#!/usr/bin/perl # clear btrfs signature from a device use Fcntl; use constant BTRFS_SUPER_INFO_OFFSET => 64 * 1024; use constant BTRFS_SUPER_INFO_SIZE => 4096; use constant BTRFS_SUPER_MIRROR_MAX => 3; use constant BTRFS_SUPER_MIRROR_SHIFT => 12; use constant BTRFS_MAGIC => "_BHRfS_M"; use constant BTRFS_DEAD => '_BHRf$_M'; sub btrfs_sb_offset($) { my $mirror =$_[0]; my $start = 16 * 1024; if ($mirror>0) { return $start << (BTRFS_SUPER_MIRROR_SHIFT * $mirror); } return BTRFS_SUPER_INFO_OFFSET; } my $dbg=1; my $savesb=0; # main my $dev=$ARGV[0]; my $size; if(!-b $dev) { print("Not a block device: $dev\n"); $size=(stat($dev))[7]; } else { $size=`blkdev --getsize64 "$dev"`; } sysopen(F, $dev, O_EXCL | O_RDWR) or die("Cannot open $dev exclusively: $!"); sysseek(F, 0, 2); $size=tell(F); print("Device size: $size\n") if($dbg); for(my $i=0;$i<6;$i++) { my $off=btrfs_sb_offset($i); if($off > $size) { print("Offset for SB $i beyond EOF\n") if($dbg); last; } print("Offset $i is $off\n") if($dbg); sysseek(F, $off, 0); sysread(F, $buf, BTRFS_SUPER_INFO_SIZE); if($savesb) { open(Q,">SB$i"); print Q ($buf); close(Q); } my $sbmagic=substr($buf, 0x40, length(BTRFS_MAGIC)); print("SB magic: $sbmagic\n") if($dbg); if(BTRFS_MAGIC eq $sbmagic) { print("Found a valid signature of superblock $i\n"); sysseek(F, $off + 0x40, 0); print("Clearing...\n"); syswrite(F, BTRFS_DEAD, length(BTRFS_DEAD)); } elsif(BTRFS_DEAD eq $sbmagic) { print("Found a signature of a dead superblock $i\n"); } else { print("Superblock $i does not look like a btrfs one\n"); } } close(F); print("Syncing dev\n"); system("fsync \'$dev\'");