2012-03-05 16:09:24 +01:00
|
|
|
#!/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 {
|
2012-04-06 13:43:24 +02:00
|
|
|
$size=`blockdev --getsize64 "$dev"`;
|
2012-03-05 16:09:24 +01:00
|
|
|
}
|
|
|
|
sysopen(F, $dev, O_EXCL | O_RDWR) or die("Cannot open $dev exclusively: $!");
|
|
|
|
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");
|
2012-04-06 13:43:24 +02:00
|
|
|
if (!-b $dev) {
|
|
|
|
system("fsync \'$dev\'");
|
|
|
|
} else {
|
|
|
|
system("blockdev --flushbufs \'$dev\'");
|
|
|
|
}
|