Swapping Raid Disks – Part 3 Something crazy with dd

Ok so in earlier parts of this series i showed how i migrated two raid partitions of a disk i wanted to use exclusively for data.  The original disk topology looked as follows

Disk /dev/sda: 243031 cylinders, 255 heads, 63 sectors/track

Units = cylinders of 8225280 bytes, blocks of 1024 bytes, counting from 0

Device Boot Start End #cyls #blocks Id System
/dev/sda1   0+ 45689- 45690- 367001600 fd Linux raid autodetect
/dev/sda2 * 45689+ 45702- 13- 102400 fd Linux raid autodetect
/dev/sda3   45702+ 243031- 197329- 1585042432 83 Linux
/dev/sda4   0 - 0 0 0 Empty

/dev/sda1 & /dev/sda2 have now been migrated away and can be reclaimed   The problem is i dont want 3 separate partitions i just want one partitions which will include  all the space.   For the benefit of the reader. The disk is a 1.8 TB disk; the first 2 partitions take up 300GB and the last partitions takes up 1.5TB of data.  I want to end up with one partitions that contains 1.8TB and i don’t want to delete any of the data on the data partitions (about 90%) used.

I want to resize an ext2/3/4 partition so i my first port of call is resize2fs.  I know that i can change the disk topology and get resize2fs to grow the disk;  however i have never had to grow a disk backwards, so off to the man pages.  It didn’t take long before you see a pretty big warning

“make sure you create it with the same starting disk cylinder as before! Otherwise, the resize operation will certainly not work, and you may lose your entire filesystem”

Ok so it looks like resize2fs is out unless i can first move the sdc3 partition to the beginning of the disk.  hanging around in irc i had a lot of people telling me to give (g)parted a go, although most where sceptical if it was possible at all.  I took a look at (g)parted however as far as i can tell all (g)parted is only able to copy a partitions from one location two another.  If i had 1.5TB avalible space at the beginning of the disk i would have been able to copy /dev/sdc3, change the last cylinder, resiz2fs and everything would be sorted.  however As mentioned we only had 300GB avalible.

The night was getting late and the hacker in me started to consider some more exotic, dangerous and some would say down right stupid solutions.  I eventually arrived at dd.  I thought perhaps i could just to something like

dd if=/dev/sdc3 of=/dev/sdc bs=1M conv=noerror

In theory this would create on block device /dev/sdc3 containing the file system on /dev/sdc3.  The obvious problem here is that dd will start over writing the beginning of /dev/sdc3 before it has finished copying all of the data from /dev/sdc3.  Would this work? I figured in theory dd would read the partition table into memory, pick the two start positions and continue the copy process until it reaches the end of /sdv/sdc3.  It would neither know or care that we, or more accurately it, was overwriting the beginning of /dev/sdc3

At this point i should but if the a disclaimer




Ok that out of the way i gave it a go and to my supprise it seem to have worked. If you are doing this on a remote machine i strongly recommend you use tmux or screen, if the dd is interrupted you have almost certainly lost your data.

[root@server ~]$ df -h | grep sdc
/dev/sdc3 1.5T 1.4T 98G 94% /data/disk1
[root@server ~]$ umount /dev/sdc3
[root@server ~]$ dd if=/dev/sdc3 of=/dev/sdc bs=1M conv=noerror
[root@server ~]$ mount /dev/sdc /data/disk1
[root@server ~]$ df -h | grep sdc
/dev/sdc 1.5T 1.4T 98G 94% /data/disk1
[root@server ~]$ umount /dev/sdc
[root@server ~]$ e2fsck -f /dev/sdc
[root@server ~]$ resize2fs /dev/sdc
[root@server ~]$ mount /dev/sdc /data/disk1
[root@server ~]$ df -h | grep sdc
/dev/sdc              1.8T  1.4T  462G  75% /data/disk1

So there we are looks like it wasn’t so insane after all. Comments most welcome

UPDATE: I had a problem mounting the new disk via its UUID.  tune2fs -l showed the same UUID which was present in /etc/fstab;  However using the mount command didn’t work.

[root@server ~]# tune2fs -l /dev/sdd | grep UUID
Filesystem UUID:          67966bfd-92b5-47b8-a545-277a4bea8be5
[root@server ~]# grep 67966bfd-92b5-47b8-a545-277a4bea8be5 /etc/fstab 
UUID=67966bfd-92b5-47b8-a545-277a4bea8be5 /data/disk2             ext4    noatime,nodiratime,nodelalloc        1 2
[root@server ~]# mount /data/disk2/
mount: special device UUID=67966bfd-92b5-47b8-a545-277a4bea8be5 does not exist

I have fixed this by doing running the following steps, not sure which one fixed it will test on the next system

[root@server ~]# cd /dev/disk/by-uuid/
[root@server ~]# ln -sv ../../sdd 67966bfd-92b5-47b8-a545-277a4bea8be5
[root@server ~]# mount /data/disk2/
[root@server ~]# umount /data/disk2/
[root@server ~]# rm 67966bfd-92b5-47b8-a545-277a4bea8be5
[root@server ~]# blockdev --rereadpt /dev/sdd
[root@server ~]# partprobe /dev/sdd
[root@server ~]# mount /data/disk2/

Also note that this server hasn’t been rebooted yet. Will update after it has.

Edit: System rebooted without issue, haven’t re-tested the mounting by uuid (or i don’t remember the results :)). however i preformed this procedure a couple of times without issue

6 Responses to “Swapping Raid Disks – Part 3 Something crazy with dd”

  1. 1 joosteto
    November 7, 2012 at 9:36 am

    So you end up with a partition-less /dev/sdc (I mean, running fdisk /dev/sdc now gives errors)?

    I wonder if something like this would have worked (and resulted in a disk with one partition):
    – use fdisk to delete partitions 2&3, and resize partition 1 to cover hole disk
    – dd if=/dev/sdc1 of=/dev/sdc1 bs=8225280 skip=45702 count=197329

    • November 7, 2012 at 8:46 pm

      Hello Joosteto,

      thats correct i ended up with one block device with no partition table. I think it would have been possible to do what you suggest however you would need to do it in the opposite order to what you suggest. i.e.

      * dd if=/dev/sdc1 of=/dev/sdc1 bs=8225280 skip=45702 count=197329
      * Fdisk /dev/sdc delete partition 2 & 3 and set the last cylinder of partition 1 to the last cylinder of the disk
      * run resize2fs /dev/sdc1

      In my case the disk will only ever have one partition so having it configured without a partition table is fine

      Edit: here is the output of fdisk
      Command (m for help): p

      Disk /dev/sdc: 1999.0 GB, 1998998994944 bytes
      255 heads, 63 sectors/track, 243031 cylinders
      Units = cylinders of 16065 * 512 = 8225280 bytes
      Sector size (logical/physical): 512 bytes / 512 bytes
      I/O size (minimum/optimal): 512 bytes / 512 bytes
      Disk identifier: 0xffa4d850

      Device Boot Start End Blocks Id System

  2. July 28, 2013 at 10:43 am

    Good day! This is my first visit to your blog! We are a collection of
    volunteers and starting a new project in a community in
    the same niche. Your blog provided us valuable information to work on.
    You have done a marvellous job!

  3. September 4, 2014 at 11:48 pm

    Simply wish to say your article is as astonishing.
    The clarity for your publish is just excellent and i can assume you are a professional on this subject.
    Fine with your permission allow me to take hold
    of your RSS feed to keep updated with coming near near post.
    Thanks a million and please continue the enjoyable work.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: