fs: btrfs: Do not fail when all root_backups are empty
authorYevgeny Popovych <yevgenyp@pointgrab.com>
Mon, 11 Jun 2018 11:14:33 +0000 (14:14 +0300)
committerTom Rini <trini@konsulko.com>
Mon, 18 Jun 2018 18:43:12 +0000 (14:43 -0400)
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 <yevgenyp@pointgrab.com>
Cc: Marek Behun <marek.behun@nic.cz>
Cc: Sergey Struzh <sergeys@pointgrab.com>
fs/btrfs/btrfs.h
fs/btrfs/super.c

index 27d78837c54105aaddc0361f633abd16eb39c30e..986d078679784bd3e143c834e96ebba8ad15a930 100644 (file)
@@ -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;
index ad6641f3148eb75673dc852094375e4e1084dd2d..e680caa56a4d0a8063072ca60acf9780a325a558 100644 (file)
 
 #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;
        }