Tuesday 6 January 2009

Diary of a Hard Disk Upgrade

I recently found myself needing to upgrade the hard disks in a few PCs to bigger and and faster ones. The thought of having to reinstall Windows from scratch an all of them made my heart sink into the pit of my stomach so I set about seeing what would be involved in "cloning" the contents of the existing disks onto the new replacements. I could have just paid for Acronis Migrate Easy (which seems to be generally well-regarded), but where's the fun in that ?! In the end, I successfully migrated a number of PCs using free software. This article describes how.

The usual disclaimers apply...this is what worked for me - if you try it and it goes wrong and you haven't taken the normal sensible precautions before embarking on an endeavour like this then please don't come crying to me.

Step 1 - Partition the new hard disk

I found it easiest to do this from Windows. I connected the new hard disk to the PC and created the partitions using the normal Disk Management tool. You will save yourself some trouble if you "match up" the partition numbers on the old and new disks (i.e. if your Windows partition is on partition #1 on the old disk, make sure it is on partition #1 on the new disk also). On some of the PCs there was a Dell diagnostics partition present (so the Windows partition was actually the second partition). More about this below.

Step 2 - Delete (or rename) the HKEY_LOCAL_MACHINE\SYSTEM\MountedDevices key in the registry

Doing this now will save you a world of pain later on. The problem is that Windows maintains a mapping of volume IDs to drive letters under this registry key

MountedDevices registry key

Here, my new drive was mounted as drive N: when I partitioned it. If I do nothing now, Windows will remount it as drive N: (instead of C:) when I later boot from it, which won't end well. If I just zap this registry key, Windows will recreate it when it next boots (although it will have forgotten about what drive letters you liked for your USB keys etc.) I guess you could just delete the entries for C: and N:...I didn't try this.

Step 3 - Reboot into Linux

I variously used Fedora Core 8 and Knoppix 5.1.1...both contained the required NTFS tools and both worked perfectly. At this stage, I have both the old and the new drives attached to the PC. I did this with various combinations to attachment from direct PATA to USB-to-PATA or USB-to-SATA converters and they all worked perfectly.

Step 4 - Dell Diagnostics Partition

One of the candidates was a Dell PC and I wanted to preserve the Dell Diagnostics partition, partly because it is a good thing to have and partly - as I mentioned above - to keep my partition numbering consistent between the old and the new drives (which saves a bunch of trouble). I did this by using the gparted utility to create a new partition on the new disk, similar in size to the original (but rounded up to an even cylinder boundary) with a system ID of 'de' (copied from the original). Then I simply did a "dump" sector-by-sector copy of the diagnostics partition from the old to the new:-

# dd if=/dev/sda1 of=/dev/sdb1 bs=32768

This worked a treat. I could then recreate my NTFS partition (again using gparted) as the second partition on the drive. It may seem that this rather wastes the effort of partitioning the disk in Step 1 above, but by doing it this way the standard Microsoft boot code is installed in the MBR. Of course, there are lots of other ways the same thing could be achieved, such as copying the MBR from the original disk to the new disk using the command

# dd if=/dev/sda of=/dev/sdb bs=512 count=1

...and then using gparted to resize the partitions accordingly. Either way, be very careful. If you manage to zap the partition table on your original disk at this stage you are going to have a seriously bad day !

The fun isn't over yet...see below !

Step 5 - Clone the NTFS parition

The next step is to clone the contents of the old NTFS partition into the new one. This is done using the aptly-named ntflsclone command:-

# ntfsclone -O /dev/sdb2 /dev/sda2

In this form, the command clones /dev/sda2 to /dev/sdb2. Once again, be careful. This command doesn't ask for any confirmation and if you get your partitions mixed up (e.g. specify them the wrong way around) it will hurt.

Step 6 - Resize the partition

At this point, all of the data is copied from the old disk to the new disk, but the filesystem on the new disk still "thinks" it is the same size as it was on the old disk. If you just reboot at this point you will find - to your dismay - that the new filesystem is no bigger than the old one, even though the partition containing the filesystem is bigger.

To fix this, we run ntfsresize on the new partition

# ntfsresize /dev/sdb2

Step 7 - Fix the number of "hidden sectors" in the NTFS Boot Sector

If the new NTFS partition doesn't start on the same sector number as the old one, you will need to adjust the number of "hidden sectors" recorded at offset 0x1C in the NTFS boot sector.

TODO: Describe using "hexedit" to complete this job

I did it a different way (kind of by accident). I wound up booting from the Windows Vista installation DVD and selecting "Repair". This located and repaired the incorrect boot sector for me automatically.

Step 8 - Insert the new disk and reboot

All going well, it will boot up exactly as before - except possibly faster - and you will miraculously have lots of available space

Step 9 - Defragment

If your original disk was heavily fragmented (which it probably was if you were running close to capacity for a good while), then the copy is still heavily fragmented. Now would be an excellent time to defragment the new partition.

Other Alternatives

In the course of my research I came across a promising tool called XXCLONE. This works a different way, being file-oriented rather than sector/block-oriented. Apparently, it copies individual files from the old to the new. As an experiment, I cloned one of the PCs using this tool rather than using the procedure described above. Initially all seemed well...I could boot from it and everything appeared to work OK. However, a few days later I was trying to install Microsoft.NET Framework 3.5 and found that it simply would not install. I can't be certain that the problem was with the method used to clone the disk, but when I went back and recloned using the Linux tools I could then install the same .NET Framework without any problems. If the problem was caused by XXCLONE it is a pity...it is very elegant and simple to use. I have sent some feedback to the developers...hopefully it will be helpful to them.


I can't claim to have worked all of this out from scratch by myself. The most useful online guide I found was Michael Dominok's at http://www.dominok.net/en/it/en.it.clonexp.html.

Finding IP addresses hidden in "ifconfig -a"

Wow...is it really over a year since my last blog post ?

Anyway, here's something which I hope will be useful.

I find it awkward to pick out my Mac's IP addresses at a glance from the output of "ifconfig -a".  Here's a command-line that makes it very easy...

[eamonn@stig ~]$ ifconfig -a | perl -ne '$interface=$1 if (/^([a-z]+[0-9]+:)/); print "$interface $1\n" if (/inet (\d+\.\d+\.\d+\.\d+)/);'

Now even the most commited command-line disciple is likely to baulk at typing all that, so I have an alias set up in ~/.bash_login.  The quotes are a little fiddly to get right, so here's the alias...

alias ipa='ifconfig -a | perl -ne '\''$interface=$1 if (/^([a-z]+[0-9]+:)/); print "$interface $1\n" if (/inet (\d+\.\d+\.\d+\.\d+)/);'\'
A slight variation of the same thing works on Linux also (with adjustments to compensate for the differences  in output format)...
alias ipa='ifconfig -a | perl -ne '\''$interface=$1 if (/^([a-z]+[0-9]+) /); print "$interface $1\n" if (/inet addr:(\d+\.\d+\.\d+\.\d+)/);'\'

I hope its useful...