Linux – How to fix BTRFS superblock error after resize/shrink (BTRFS: couldn’t get super buffer head for bytenr 274877906944)

btrfsddhard-disklinuxsuperblock

BTRFS RAID1 array with 2 500 GB hdds, no errors. This is the root filesystem, so there are 3 partitions on each drive: 1 = /boot (ext4), 2 = / (btrfs), 3 (swap)

/boot is ext4 because upgrading the kernel does not always work if /boot was a btrfs filesystem (new kernel installed but grub config not updated).

Now, this mirror is moved to smaller drives, the new drives are 120 GB, so the btrfs filesystem has to be resized. Resizing both btrfs partitions can be done using GParted, for example. After resizing, the MBR with the partition information can be copied from the old 500 GB drives to the new 120 GB drives (dd if=/dev/sda of=/dev/sdb bs=512 count=1), as well as the btrfs partition (dd if=/dev/sda2 of=/dev/sdb2). (Ignoring the swap partition, which would have to be moved to fit within the 120 GB.)

Although the system boots and does not have a problem with the new 120 GB drives, one error message is being logged (dmesg):

BTRFS: couldn't get super buffer head for bytenr 274877906944

And a scrub finds a "super" error (but no data errors):

"error details: super=1"

Is there a risk of data corruption due to this error?
How can this be fixed?

Since 274877906944 is 256 GB, the old btrfs partition was >256 GB and the new one is <256 GB, it seems like the system is looking for the superblock at 256 GB?

Best Answer

Warning: Don't use GParted to resize a multi-device BTRFS filesystem!

Data loss likely to happen!

Looks like GParted is the culprit. Apparently, it doesn't know how to resize multi-device btrfs filesystems and just runs btrfs filesystem resize but does not take care of each device using resize 1:49g and resize 2:49g.

This is what btrfs filesystem show said:

Total devices 2 FS bytes used 40.95GiB
devid    1 size 50.00GiB used 43.03GiB path /dev/sda2
devid    2 size 439.45GiB used 43.03GiB path /dev/sdb2

Obviously, GParted has not resized the filesystem on the second device, so Btrfs still thinks it's a 500 GB filesystem.

At some point, Btrfs would have tried to read/write data outside of the disk. This would have caused corruption, it might even have rendered the whole filesystem useless.


Fix

First, a live system was booted to reduce the risk of damage while the system is running on a filesystem that's bigger than the partition it's on.

Mount the filesystem:

mount /dev/sda2 /mnt/tmp

First shrink the second device to 50 GB - 1 GB = 49 GB to avoid rounding errors:

btrfs filesystem resize 2:49g /mnt/tmp

Resize it to fill the 50 GB partition:

btrfs filesystem resize 2:max /mnt/tmp

Check btrfs filesystem show, both devices should have the right size:

devid    1 size 50.00GiB used 43.03GiB path /dev/sda2
devid    2 size 50.00GiB used 43.03GiB path /dev/sdb2

Unmount, reboot, the error should be gone.

If nothing was damaged while the system was running in that bad state, the filesystem should be healthy now.

(Thanks to darkling who helped me fix this.)

Related Question