From d146a7b9c6200c7a84a15208f0c06e0ab60890dd Mon Sep 17 00:00:00 2001 From: Yevgeny Popovych Date: Mon, 11 Jun 2018 14:14:33 +0300 Subject: [PATCH] fs: btrfs: Do not fail when all root_backups are empty This is the case when reading freshly created filesystem. The error message is like the following: btrfs_read_superblock: No valid root_backup found! Since the data from super_roots/root_backups is not actually used - decided to rework btrfs_newest_root_backup() into btrfs_check_super_roots() that will only check if super_roots array is valid and correctly handle empty scenario. As a result: * btrfs_read_superblock() now only checks if super_roots array is valid; the case when it is empty is considered OK. * removed root_backup pointer from btrfs_info, which would be NULL in case of empty super_roots. * btrfs_read_superblock() verifies number of devices from the superblock itself, not newest root_backup. Signed-off-by: Yevgeny Popovych Cc: Marek Behun Cc: Sergey Struzh --- fs/btrfs/btrfs.h | 1 - fs/btrfs/super.c | 30 ++++++++++++++++++++++-------- 2 files changed, 22 insertions(+), 9 deletions(-) diff --git a/fs/btrfs/btrfs.h b/fs/btrfs/btrfs.h index 27d7883..986d078 100644 --- a/fs/btrfs/btrfs.h +++ b/fs/btrfs/btrfs.h @@ -13,7 +13,6 @@ struct btrfs_info { struct btrfs_super_block sb; - struct btrfs_root_backup *root_backup; struct btrfs_root tree_root; struct btrfs_root fs_root; diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c index ad6641f..e680caa 100644 --- a/fs/btrfs/super.c +++ b/fs/btrfs/super.c @@ -15,18 +15,34 @@ #define BTRFS_SUPER_INFO_SIZE 4096 -static int btrfs_newest_root_backup(struct btrfs_super_block *sb) +/* + * checks if a valid root backup is present. + * considers the case when all root backups empty valid. + * returns -1 in case of invalid root backup and 0 for valid. + */ +static int btrfs_check_super_roots(struct btrfs_super_block *sb) { struct btrfs_root_backup *root_backup; int i, newest = -1; + int num_empty = 0; for (i = 0; i < BTRFS_NUM_BACKUP_ROOTS; ++i) { root_backup = sb->super_roots + i; + + if (root_backup->tree_root == 0 && root_backup->tree_root_gen == 0) + num_empty++; + if (root_backup->tree_root_gen == sb->generation) newest = i; } - return newest; + if (num_empty == BTRFS_NUM_BACKUP_ROOTS) { + return 0; + } else if (newest >= 0) { + return 0; + } + + return -1; } static inline int is_power_of_2(u64 x) @@ -166,7 +182,7 @@ int btrfs_read_superblock(void) char raw_sb[BTRFS_SUPER_INFO_SIZE]; struct btrfs_super_block *sb = (struct btrfs_super_block *) raw_sb; u64 dev_total_bytes; - int i, root_backup_idx; + int i; dev_total_bytes = (u64) btrfs_part_info->size * btrfs_part_info->blksz; @@ -211,17 +227,15 @@ int btrfs_read_superblock(void) return -1; } - root_backup_idx = btrfs_newest_root_backup(&btrfs_info.sb); - if (root_backup_idx < 0) { + if (btrfs_check_super_roots(&btrfs_info.sb)) { printf("%s: No valid root_backup found!\n", __func__); return -1; } - btrfs_info.root_backup = btrfs_info.sb.super_roots + root_backup_idx; - if (btrfs_info.root_backup->num_devices != 1) { + if (btrfs_info.sb.num_devices != 1) { printf("%s: Unsupported number of devices (%lli). This driver " "only supports filesystem on one device.\n", __func__, - btrfs_info.root_backup->num_devices); + btrfs_info.sb.num_devices); return -1; }