Wednesday, November 16, 2011

Migrating to a new SSD without data loss

I have a Samsung N150 netbook that came with Windows 7 preinstalled on a 250GB hard disk.  I created a bunch of new ext4 partitions on this disk and was running Kubuntu on it.  I almost never used Windows, but I had kept it on the disk anyway.  Last week I thought of upgrading to an SSD, and bought a 240GB SSD.  This post is to document how I copied over the Windows installation and recovery partition to the SSD before swapping the disks.

I connected the SSD to my computer using an USB interface and ran sudo fdisk -l to see the partition tables of both disks.
% sudo fdisk -l

Disk /dev/sda: 250.1 GB, 250059350016 bytes
255 heads, 63 sectors/track, 30401 cylinders, total 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xd937cf59

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048    31459327    15728640   27  Hidden NTFS WinRE
/dev/sda2   *    31459328    31664127      102400    7  HPFS/NTFS/exFAT
/dev/sda3        31664128   232622079   100478976    7  HPFS/NTFS/exFAT
/dev/sda4       232624126   488394751   127885313    5  Extended
/dev/sda5       480397312   488394751     3998720   82  Linux swap / Solaris
/dev/sda6       232624128   291215359    29295616   83  Linux
/dev/sda7       291217408   480391167    94586880   83  Linux

Partition table entries are not in disk order

Disk /dev/sdb: 240.1 GB, 240057409536 bytes
255 heads, 63 sectors/track, 29185 cylinders, total 468862128 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00045231

   Device Boot      Start         End      Blocks   Id  System
/dev/sda is the original hard disk that came with the laptop, and /dev/sdb, which is empty currently, is the new SSD.  I have to clone the first 3 partitions (/dev/sda1, /dev/sda2, and /dev/sda3) bit-by-bit to retain all the preinstalled stuff — this includes Windows 7 installation and the recovery partition.  Replicating the Windows partitions is the tricky part, so this post will describe that in detail.  Copying data from Linux partitions can be done with a simple rsync.

The first step is to create partitions on the new disk that resemble the old disk.  I followed the fdisk guide of TLDP and created the first 3 partitions.  Now fdisk -l shows this configuration:
% sudo fdisk -l      

Disk /dev/sda: 250.1 GB, 250059350016 bytes
255 heads, 63 sectors/track, 30401 cylinders, total 488397168 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0xd937cf59

   Device Boot      Start         End      Blocks   Id  System
/dev/sda1            2048    31459327    15728640   27  Hidden NTFS WinRE
/dev/sda2   *    31459328    31664127      102400    7  HPFS/NTFS/exFAT
/dev/sda3        31664128   232622079   100478976    7  HPFS/NTFS/exFAT
/dev/sda4       232624126   488394751   127885313    5  Extended
/dev/sda5       480397312   488394751     3998720   82  Linux swap / Solaris
/dev/sda6       232624128   291215359    29295616   83  Linux
/dev/sda7       291217408   480391167    94586880   83  Linux

Partition table entries are not in disk order

Disk /dev/sdb: 240.1 GB, 240057409536 bytes
255 heads, 63 sectors/track, 29185 cylinders, total 468862128 sectors
Units = sectors of 1 * 512 = 512 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Disk identifier: 0x00045231

   Device Boot      Start         End      Blocks   Id  System
/dev/sdb1            2048    31459327    15728640   27  Hidden NTFS WinRE
/dev/sdb2   *    31459328    31664127      102400    7  HPFS/NTFS/exFAT
/dev/sdb3        31664128   232622079   100478976    7  HPFS/NTFS/exFAT
The partitions in the new disk are of the same size and same type as in the old one.  /dev/sdb2 is bootable as is /dev/sda2.  (It won’t boot yet though, since the disk has no OS yet.)  Now to copy the data bits over.  I first unmounted all three partitions.  This is critical because changing data underneath when it’s being copied over is a darn good recipe for data corruption.

dd is the low-level data copying utility I used to clone the partitions.  Copying the data over was as simple as running these commands one by one.  (Swapping if and of can result in wiping out all data from the old partition.  dd cannot even know if you’re passing wrong arguments to it.)
% sudo dd if=/dev/sda1 of=/dev/sdb1 conv=notrunc
% sudo dd if=/dev/sda2 of=/dev/sdb2 conv=notrunc
% sudo dd if=/dev/sda3 of=/dev/sdb3 conv=notrunc

Copying can be painfully slow since we are moving hundreds of GBs around.  Blog O’ Matty has a post that shows how to find status of a running dd command.  Essentially you’d send SIGUSR1 signal to the dd process and it’d print the current status of the transfer.  One of the commenters suggests running sudo pkill -SIGUSR1 dd so that you don’t have to think about process IDs.

Once this was done, I installed Kubuntu on the SSD using the standard installation process, and everything went just fine.  Windows doesn’t boot probably because it thinks mine is a pirated copy.  (Shows an error saying some ‘important’ hardware has gone missing.)  But I can boot into the recovery partition, so I can restore factory settings to get Windows running again when I want it.

I restored all my installed software from the package selection list I had already generated.  That’s it... the computer is exactly like it was before with all my programs and configuration.

Saturday, November 12, 2011

Tweaking stack size of Linux processes to reduce swapping

Since upgrading to Kubuntu 11.10, my laptop has been slow.  Slow because it’s been accessing the hard disk a lot.  I incidentally opened system monitor yesterday and found that more than 1GB of swapping space was in use although only about 1.1GB of the total 2GB RAM was in use.  That doesn’t sound right.  The computer shouldn’t swap when about half of the RAM is unused.

My friend Abhay had once told me about thread stack size configuration of Linux (Unix?) processes.  This configuration specifies how much RAM is given to each thread for its stack.  I ran the following command to see how much was the current stack size:
% ulimit -s
8192
That’s 8192KB allocated for each thread.  With some Googling around I figured this was a huge number.  Windows allocates only 1MB by default.  For a machine that’s low on RAM like mine, 8MB for stack is ludicrous.  I decided to make it 2MB instead.  Unsurprisingly, I wasn’t the first to try to do something like this; a thread on LinuxQuestions.org explained that I can edit /etc/security/limits.conf to set the default size.

I added the following lines to my /etc/security/limits.conf:
* soft stack 2048
* hard stack 2048
(Only root can modify this file; you’ll need to use sudo.)  To apply the configuration changes I restarted the machine.  After restarting, now my machine is using about 1.4GB of RAM and about 80MB of swap.  No need to mention, everything is fast as it used be.