Using dd on disks with different sector sizes

I would like to move a partition to a new drive. The old drive has a sector size of 512 bytes while the new one has a sector size of 4096 bytes. I tried doing a dd of the full disk, but that failed because the partition on the old drive was not aligned to 4K boundaries. So instead I created a partition from scratch on the new drive using fdisk, then copied that partition between disks using dd. Finally, I expanded the filesystem on the new drive using resize2fs. This appears to have worked, as I can mount the new partition (read-only so far) and view files, and fsck says it is clean.

But I still have lingering doubts about whether this is a safe thing to do. For example, does the FS care about the sector size in a way that would break things by doing this, or is it shielded from that by the VFS layer or HD itself?


Solution 1:

You haven't told us what was the dd command that you tried initially which failed. However, I spent a bit of time checking the source code of dd command (from coreutils package) and looks like we had a problem here.

1852   /* Some devices require alignment on a sector or page boundary
1853      (e.g. character disk devices).  Align the input buffer to a
1854      page boundary to cover all bases.  Note that due to the swab
1855      algorithm, we must have at least one byte in the page before
1856      the input buffer;  thus we allocate 2 pages of slop in the
1857      real buffer.  8k above the blocksize shouldn't bother anyone.
1858 
1859      The page alignment is necessary on any Linux kernel that supports
1860      either the SGI raw I/O patch or Steven Tweedies raw I/O patch.
1861      It is necessary when accessing raw (i.e. character special) disk
1862      devices on Unixware or other SVR4-derived system.  */

If you give the error message, I can do a further search. But to me, this is where we got hit. That is aligning 512 byte page boundary with a 4 KiB page boundary doesn't seem right.

Now, coming to the second part, did you create the partition of the second drive (with fdisk) as 512 byte size. However, the sector size advertised by most modern disks to OS is 1 MiB that is 4096 KiB.

In the function update_sector_offset of fdisk.c you will see

/*
             * Align the begin of partitions to:
             *
             * a) topology
             *  a2) alignment offset
             *  a1) or physical sector (minimal_io_size, aka "grain")
             *
             * b) or default to 1MiB (2048 sectrors, Windows Vista default)
             *
             * c) or for very small devices use 1 phy.sector
             */
            sector_t x = 0;

            if (fdisk_dev_has_topology(cxt)) {
                    if (cxt->alignment_offset)
                            x = cxt->alignment_offset;
                    else if (cxt->io_size > 2048 * 512)
                            x = cxt->io_size;
            }
            /* default to 1MiB */
            if (!x)
                    x = 2048 * 512;

            sector_offset = x / cxt->sector_size;

*cxt is the descriptor to the fdisk struct.

So, this part is not clear to me. That is, if your new disk advertised the sector size as 4096 KiB or 512 bytes.

Now, coming to the last part.

No, filesystems don't actually care about sector size. And as long as the block size is 4 KiB, things should be fine, because, since virtual page size (in mm context) is 4 KiB, the mmaped IO needs to be aligned with that. In my laptop, the block size and physical sector size is the same.

$ sudo blockdev --getpbsz /dev/sda
[sudo] password for chakraborty: 
4096

$ sudo blockdev --getbsz /dev/sda
4096

IO happens in context of block size, not sector size. If due to physical sector size FS encounters any problem, I would be very surprised. However, VFS doesn't come that far. VFS is between application issuing IO and the actual filesystem. What we are discussing is below VFS layer.