]> git.hungrycats.org Git - linux/commitdiff
Btrfs: keep dropped roots in cache until transaciton commit
authorJosef Bacik <jbacik@fb.com>
Thu, 10 Sep 2015 20:22:40 +0000 (16:22 -0400)
committerZygo Blaxell <zblaxell@serenity.furryterror.org>
Wed, 28 Oct 2015 01:07:19 +0000 (21:07 -0400)
When dropping a snapshot we need to account for the qgroup changes.  If we drop
the snapshot in all one go then the backref code will fail to find blocks from
the snapshot we dropped since it won't be able to find the root in the fs root
cache.  This can lead to us failing to find refs from other roots that pointed
at blocks in the now deleted root.  To handle this we need to not remove the fs
roots from the cache until after we process the qgroup operations.  Do this by
adding dropped roots to a list on the transaction, and letting the transaction
remove the roots at the same time it drops the commit roots.  This will keep all
of the backref searching code in sync properly, and fixes a problem Mark was
seeing with snapshot delete and qgroups.  Thanks,Btrfs: keep dropped roots in
cache until transaciton commit

When dropping a snapshot we need to account for the qgroup changes.  If we drop
the snapshot in all one go then the backref code will fail to find blocks from
the snapshot we dropped since it won't be able to find the root in the fs root
cache.  This can lead to us failing to find refs from other roots that pointed
at blocks in the now deleted root.  To handle this we need to not remove the fs
roots from the cache until after we process the qgroup operations.  Do this by
adding dropped roots to a list on the transaction, and letting the transaction
remove the roots at the same time it drops the commit roots.  This will keep all
of the backref searching code in sync properly, and fixes a problem Mark was
seeing with snapshot delete and qgroups.  Thanks,

Signed-off-by: Josef Bacik <jbacik@fb.com>
(cherry picked from commit 463a422fbd2ada9c96cde735d9a1c788913c0bec)
(cherry picked from commit dac5c87cd8da83d7fdf053e06007f191cf109042)

fs/btrfs/extent-tree.c
fs/btrfs/transaction.c
fs/btrfs/transaction.h

index ef45490e16beb20106f7e4e348f92c445047e046..76af5915389bbb04d6b10aacd5211f37af26510f 100644 (file)
@@ -8594,7 +8594,7 @@ int btrfs_drop_snapshot(struct btrfs_root *root,
        }
 
        if (test_bit(BTRFS_ROOT_IN_RADIX, &root->state)) {
-               btrfs_drop_and_free_fs_root(tree_root->fs_info, root);
+               btrfs_add_dropped_root(trans, root);
        } else {
                free_extent_buffer(root->node);
                free_extent_buffer(root->commit_root);
index 6800722413530940ff78d9af6e0973722bdc042c..1b646237ad3bd4fdeece62b251c19ac2f87b934c 100644 (file)
@@ -117,6 +117,16 @@ static noinline void switch_commit_roots(struct btrfs_transaction *trans,
                        btrfs_unpin_free_ino(root);
                clear_btree_io_tree(&root->dirty_log_pages);
        }
+
+       /* We can free old roots now. */
+       spin_lock(&trans->dropped_roots_lock);
+       while (!list_empty(&trans->dropped_roots)) {
+               root = list_first_entry(&trans->dropped_roots,
+                                       struct btrfs_root, root_list);
+               list_del_init(&root->root_list);
+               btrfs_drop_and_free_fs_root(fs_info, root);
+       }
+       spin_unlock(&trans->dropped_roots_lock);
        up_write(&fs_info->commit_root_sem);
 }
 
@@ -256,9 +266,11 @@ loop:
        INIT_LIST_HEAD(&cur_trans->switch_commits);
        INIT_LIST_HEAD(&cur_trans->dirty_bgs);
        INIT_LIST_HEAD(&cur_trans->io_bgs);
+       INIT_LIST_HEAD(&cur_trans->dropped_roots);
        mutex_init(&cur_trans->cache_write_mutex);
        cur_trans->num_dirty_bgs = 0;
        spin_lock_init(&cur_trans->dirty_bgs_lock);
+       spin_lock_init(&cur_trans->dropped_roots_lock);
        list_add_tail(&cur_trans->list, &fs_info->trans_list);
        extent_io_tree_init(&cur_trans->dirty_pages,
                             fs_info->btree_inode->i_mapping);
index a458d48de78a78a9ce1503a327510c5717b7e7a5..a96b04f5e36461061b56064d717d1cbb9b1f3c10 100644 (file)
@@ -66,6 +66,7 @@ struct btrfs_transaction {
        struct list_head switch_commits;
        struct list_head dirty_bgs;
        struct list_head io_bgs;
+       struct list_head dropped_roots;
        u64 num_dirty_bgs;
 
        /*
@@ -75,6 +76,7 @@ struct btrfs_transaction {
         */
        struct mutex cache_write_mutex;
        spinlock_t dirty_bgs_lock;
+       spinlock_t dropped_roots_lock;
        struct btrfs_delayed_ref_root delayed_refs;
        int aborted;
        int dirty_bg_run;
@@ -216,4 +218,12 @@ int btrfs_transaction_in_commit(struct btrfs_fs_info *info);
 void btrfs_put_transaction(struct btrfs_transaction *transaction);
 void btrfs_apply_pending_changes(struct btrfs_fs_info *fs_info);
 
+static inline void btrfs_add_dropped_root(struct btrfs_trans_handle *trans,
+                                         struct btrfs_root *root)
+{
+       struct btrfs_transaction *cur_trans = trans->transaction;
+       spin_lock(&cur_trans->dropped_roots_lock);
+       list_add_tail(&root->root_list, &cur_trans->dropped_roots);
+       spin_unlock(&cur_trans->dropped_roots_lock);
+}
 #endif