Zero a GPT Label Using dd

When re-using a disk with a GPT label (GUID Partition Table) it’s important to wipe the label stored on both the first and last blocks of the device.

With an MBR Partition Table it was easy enough to just nuke the beginning of the drive (adapt sdz for your drive), ala:

dd if=/dev/zero of=/dev/sdz bs=1M count=1

and be on your way.  Wouldn’t it be lovely if dd understood negative indexing and you could just say:

dd if=/dev/zero of=/dev/sdz bs=1M count=-1

and be done?   Alas, it’s not meant to be.

One way to do this is to simply use ‘dd’ to write zeroes to the entire device:

dd if=/dev/zero of=/dev/sdz bs=8M

This is entirely effective, but with today’s 2-3TB drives, this can take quite a while.  You can start it and go home for the night, but if you’re not paying attention, a dd that doesn’t finish can cause you frustration and embarrassment.  Since we only need to write 34 512-byte blocks, really what we need to do is to calculate the size of the drive and find the correct blocks to overwrite.

In the recent past, people will have told you to run fdisk, look for the cylinder/heads/sectors/clusters information, apply a mathematical transform, and plug that into ‘dd’.  Besides being a pain, fdisk doesn’t even claim to support disks over 3TB.  Before the floods, those were becoming quite common.

Fortunately, Linux’s sysfs will report a block device’s size, conveniently in 512-byte block units (though that’s not necessarily obvious in context).  For instance:

# cat /sys/block/sdz/size

shows me a 2TB disk’s actual size. I’ve looked at a 3TB disk, and fortunately (for now at least), even though the drive really uses 4k blocks, linux is still reporting in terms of 512-byte blocks.  This helps since GPT size is defined in terms of 512-byte blocks, but I wouldn’t count on sysfs to maintain this convention forever.  At some point nobody will have any 512-byte block drives and somebody will decide it’s silly to keep reporting fake block counts in sysfs.  Sanity check before blowing away drives, eh?

So, now that we know that we have the right value with the right units, it’s simply a matter of taking out the first GPT label:

/bin/dd if=/dev/zero of=/dev/sdz bs=512 count=34

and then the second (3907029168-34=3907029134):

/bin/dd if=/dev/zero of=/dev/sdz bs=512 count=34 skip=3907029134

To make sure linux understands what you’ve done here, run:

partprobe /dev/sdz

and make sure partprobe doesn’t insist upon a reboot to get the kernel straight about this (so far I haven’t found a way around this).

Verify with other partition information tools that might be relevant, e.g.:

zdb -l /dev/sdz

for ZFS.

TL;DR : for convenience, here’s a perl script that automates the above process.  Call it as:

perl /dev/sdz

or, simply:

perl sdz

As of this writing, the script simply prints commands for you to run – it’s not brave enough to run them itself.  So, check them before you run them.

10 thoughts on “Zero a GPT Label Using dd”

  1. Very helpful thanks. I had a question you may be able to help with: if I wanted to clone a drive with, say three partitions, using dd (let’s say the combined partitions are using 25% of the total drive space, hence the desire to back up on a partition-by-partition basis – to save time) could I use a similar methodology to back up the gpt boot record? Obviously instead of nuking, I’d be saving the relevant sectors and then restoring them into the same place when needed

    1. I think that would back up the GPT labels OK, but I don’t know if GPT is drive-geometry sensitive or not (i.e. would it work on another drive).

      I use ‘sfdisk –dump’ for MBR partition tables. Maybe gparted has a similar option?

  2. Thank you! I ran into some weird errors when trying to reuse some zfs disks for a new pool. I needed just this, to make zfs unaware that those disks might still be from some pool.

  3. There’s a mistake in the dd command to overwrite the second copy of the GPT label.

    You are using dd’s “skip” parameter, which “skips blocks at start of input” (so, in this case, the first 3907029134 blocks of zeroes from /dev/zero). The dd then continues to overwrite the beginning of /dev/sdz, again.

    If you substitute “seek”, then it will seek to block 3907029135 of /dev/sdz and start writing there.

    So, the command should be:

    /bin/dd if=/dev/zero of=/dev/sdz bs=512 count=34 seek=3907029134

  4. Thanks.

    There is a fix point in script.

    Replace ‘skip’ to ‘seek’ at last line in the perl script.

    The ‘skip’ operand skips blocks at start of input. The ‘seek’ operand skips blocks at start of OUTPUT.

    – print “/bin/dd if=/dev/zero of=/dev/$device bs=$BLOCK_SIZE count=$GPT_SIZE skip=$size_less_gpt\n”;
    + print “/bin/dd if=/dev/zero of=/dev/$device bs=$BLOCK_SIZE count=$GPT_SIZE seek=$size_less_gpt\n”;

  5. great article. may I suggest that in the future the author puts the TL;DR at the _beginning_ of the article since it serves as an abstract? I didn’t see it until I’d read the whole article which generally defeats the whole purpose of too long, din’t read…

  6. I’ve got a 500G SATA drive that used to be part of a 5TB hardware array. The array is gone, but I’m reusing the individual drives. If I type ‘fdisk -l’ it reports “WARNING: GPT (GUID Partition Table) detected on ‘/dev/sda’! The util fdisk doesn’t support GPT. Use GNU Parted.” I used parted to change the label to msdos, but fdisk continues to see the GPT table. It doesn’t seem to be causing any problem, I can still use fdisk or parted to create the partitions and put on a file system. Why after changing the label to msdos does fdisk still report the warning? Is this anything to worry about before I start actaully using the drive?

  7. You can also just use dd bs=512 if=/dev/zero of=/dev/sdX count=2048 seek=$((`blockdev –getsz /dev/sdX` – 2048)) to zero the last MB of a disk.
    So a quick
    does the trick of zeroing the first and last MB of a disk.

Leave a Reply
