• Nikolay Borisov's avatar
    btrfs: Streamline btrfs_fs_info::backup_root_index semantics · 6ef108dd
    Nikolay Borisov authored
    The backup_root_index member stores the index at which the backup root
    should be saved upon next transaction commit. However, there is a
    small deviation from this behavior in the form of a check in
    backup_super_roots which checks if current root generation equals to the
    generation of the previous root. This can trigger in the following
    scenario:
    
    slot0: gen-2
    slot1: gen-1
    slot2: gen
    slot3: unused
    
    Now suppose slot3 (which is also the root specified in the super block)
    is corrupted hence init_tree_roots chooses to use the backup root at
    slot2, meaning read_backup_root will read slot2 and assign the
    superblock generation to gen-1. Despite this backup_root_index will
    point at slot3 because its init happens in init_backup_root_slot, long
    before any parsing of the backup roots occur. Then on next transaction
    start, gen-1 will be incremented by 1 making the root's generation
    equal gen. Subsequently, on transaction commit the following check
    triggers:
    
      if (btrfs_backup_tree_root_gen(root_backup) ==
               btrfs_header_generation(info->tree_root->node))
    
    This causes the 'next_backup', which is the index at which the backup is
    going to be written to, to set to last_backup, which will be slot2.
    
    All of this is a very confusing way of expressing the following
    invariant:
    
     Always write a backup root at the index following the last used backup
     root.
    
    This commit streamlines this logic by setting backup_root_index to the
    next index after the one used for mount.
    Signed-off-by: default avatarNikolay Borisov <nborisov@suse.com>
    Reviewed-by: default avatarDavid Sterba <dsterba@suse.com>
    Signed-off-by: default avatarDavid Sterba <dsterba@suse.com>
    6ef108dd
disk-io.c 124 KB