On 26.03.2018 11:27, Anand Jain wrote:
> During the mkfs.btrfs -b <blockcount> btrfs_prepare_device() zeros all
> the superblock bytenr locations only if the bytenr is below the
> blockcount. The problem with this is that if the BTRFS is recreated
> with a smaller size then we will leave the stale superblock in the disk
> which shall confuse the recovery. As shown in the test case below.
> 
>  mkfs.btrfs -qf /dev/mapper/vg-lv
>  mkfs.btrfs -qf -b1G /dev/mapper/vg-lv
>  btrfs in dump-super -a /dev/mapper/vg-lv | grep '.fsid|superblock:'
> 
>  superblock: bytenr=65536, device=/dev/mapper/vg-lv
>  dev_item.fsid                ebc67d01-7fc5-43f0-90b4-d1925002551e [match]
>  superblock: bytenr=67108864, device=/dev/mapper/vg-lv
>  dev_item.fsid                ebc67d01-7fc5-43f0-90b4-d1925002551e [match]
>  superblock: bytenr=274877906944, device=/dev/mapper/vg-lv
>  dev_item.fsid                b97a9206-593b-4933-a424-c6a6ee23fe7c [match]
> 
> So if we find a valid superblock zero it even if it's beyond the
> blockcount.
> 
> Signed-off-by: Anand Jain <anand.j...@oracle.com>
> ---
>  utils.c | 35 +++++++++++++++++++++++++++++++++++
>  1 file changed, 35 insertions(+)
> 
> diff --git a/utils.c b/utils.c
> index e9cb3a82fda6..6a9408b06e73 100644
> --- a/utils.c
> +++ b/utils.c
> @@ -365,6 +365,41 @@ int btrfs_prepare_device(int fd, const char *file, u64 
> *block_count_ret,
>               return 1;
>       }
>  
> +     /*
> +      * Check for the BTRFS SB copies up until btrfs_device_size() and zero
> +      * it. So that kernel (or user for the manual recovery) don't have to
> +      * confuse with the stale SB copy during recovery.
> +      */
> +     if (block_count != btrfs_device_size(fd, &st)) {
> +             for (i = 1; i < BTRFS_SUPER_MIRROR_MAX; i++) {
> +                     struct btrfs_super_block *disk_super;
> +                     char buf[BTRFS_SUPER_INFO_SIZE];
> +                     disk_super = (struct btrfs_super_block *)buf;
> +
> +                     /* Already zeroed above */
> +                     if (btrfs_sb_offset(i) < block_count)
> +                             continue;
> +
> +                     /* Beyond actual disk size */
> +                     if (btrfs_sb_offset(i) >= btrfs_device_size(fd, &st))
> +                             continue;
> +
> +                     /* Does not contain any stale SB */
> +                     if (btrfs_read_dev_super(fd, disk_super,
> +                                              btrfs_sb_offset(i), 0))
> +                             continue;
> +
> +                     ret = zero_dev_clamped(fd, btrfs_sb_offset(i),
> +                                             BTRFS_SUPER_INFO_SIZE,
> +                                             btrfs_device_size(fd, &st));
> +                     if (ret < 0) {
> +                             error("failed to zero device '%s' bytenr %llu: 
> %s",
> +                                     file, btrfs_sb_offset(i), 
> strerror(-ret));
> +                             return 1;
> +                     }
> +             }
> +     }
> +

I told you this code can be made a lot simpler, simply by modifying the
last argument passed to zero_dev_clamped. I even posted the resulting
diff which was just 3 lines changed.

I agree that it's a good idea to wipe all available superblock when we
use -b. However I don't agree with your approach - it adds a loop, it
adds a bunch of checks and makes the complexity orders of magnitude
higher than it could be. So I'm asking again - is there any inherent
benefit which I'm missing in your newly added 35 lines of code against
just passing the block device to zero_dev_clamped and letting the
existing logic take care of everything?

>       *block_count_ret = block_count;
>       return 0;
>  }
> 
--
To unsubscribe from this list: send the line "unsubscribe linux-btrfs" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to