Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux...
authorLinus Torvalds <torvalds@linux-foundation.org>
Sun, 17 Mar 2013 18:04:14 +0000 (11:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sun, 17 Mar 2013 18:04:14 +0000 (11:04 -0700)
Pull btrfs fixes from Chris Mason:
 "Eric's rcu barrier patch fixes a long standing problem with our
  unmount code hanging on to devices in workqueue helpers.  Liu Bo
  nailed down a difficult assertion for in-memory extent mappings."

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/mason/linux-btrfs:
  Btrfs: fix warning of free_extent_map
  Btrfs: fix warning when creating snapshots
  Btrfs: return as soon as possible when edquot happens
  Btrfs: return EIO if we have extent tree corruption
  btrfs: use rcu_barrier() to wait for bdev puts at unmount
  Btrfs: remove btrfs_try_spin_lock
  Btrfs: get better concurrency for snapshot-aware defrag work

fs/btrfs/extent-tree.c
fs/btrfs/file.c
fs/btrfs/inode.c
fs/btrfs/locking.h
fs/btrfs/qgroup.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c

index 3e074dab2d57a3e39ad16538f7a51bfde8e4ed91..9ac2eca681ebb09c605612dd563bc4417e4fc587 100644 (file)
@@ -1467,8 +1467,11 @@ int lookup_inline_extent_backref(struct btrfs_trans_handle *trans,
        if (ret && !insert) {
                err = -ENOENT;
                goto out;
+       } else if (ret) {
+               err = -EIO;
+               WARN_ON(1);
+               goto out;
        }
-       BUG_ON(ret); /* Corruption */
 
        leaf = path->nodes[0];
        item_size = btrfs_item_size_nr(leaf, path->slots[0]);
index af1d0605a5c1e74b3f30392d4e28c0faf34400ad..5b4ea5f55b8f47d0bf9a90992dd9da2d33880e14 100644 (file)
@@ -591,6 +591,7 @@ void btrfs_drop_extent_cache(struct inode *inode, u64 start, u64 end,
                }
                compressed = test_bit(EXTENT_FLAG_COMPRESSED, &em->flags);
                clear_bit(EXTENT_FLAG_PINNED, &em->flags);
+               clear_bit(EXTENT_FLAG_LOGGING, &flags);
                remove_extent_mapping(em_tree, em);
                if (no_splits)
                        goto next;
index d1470adca8f87aafa6a028995eeac0e91ee781db..ca1b767d51f760672f8de72c48efbf3df8e58a75 100644 (file)
@@ -2312,6 +2312,7 @@ again:
        key.type = BTRFS_EXTENT_DATA_KEY;
        key.offset = start;
 
+       path->leave_spinning = 1;
        if (merge) {
                struct btrfs_file_extent_item *fi;
                u64 extent_len;
@@ -2368,6 +2369,7 @@ again:
 
        btrfs_mark_buffer_dirty(leaf);
        inode_add_bytes(inode, len);
+       btrfs_release_path(path);
 
        ret = btrfs_inc_extent_ref(trans, root, new->bytenr,
                        new->disk_len, 0,
@@ -2381,6 +2383,7 @@ again:
        ret = 1;
 out_free_path:
        btrfs_release_path(path);
+       path->leave_spinning = 0;
        btrfs_end_transaction(trans, root);
 out_unlock:
        unlock_extent_cached(&BTRFS_I(inode)->io_tree, lock_start, lock_end,
index ca52681e5f4049c45f2a228a3f8237ca23815772..b81e0e9a48941891681eef385d10d071f6cbe51b 100644 (file)
@@ -26,7 +26,6 @@
 
 void btrfs_tree_lock(struct extent_buffer *eb);
 void btrfs_tree_unlock(struct extent_buffer *eb);
-int btrfs_try_spin_lock(struct extent_buffer *eb);
 
 void btrfs_tree_read_lock(struct extent_buffer *eb);
 void btrfs_tree_read_unlock(struct extent_buffer *eb);
index aee4b1cc3d988ccc0dbde615000d07bcf5d35051..5471e47d6559eafeb36e55035cb427710c5ee4ba 100644 (file)
@@ -1525,21 +1525,23 @@ int btrfs_qgroup_reserve(struct btrfs_root *root, u64 num_bytes)
 
                if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_RFER) &&
                    qg->reserved + qg->rfer + num_bytes >
-                   qg->max_rfer)
+                   qg->max_rfer) {
                        ret = -EDQUOT;
+                       goto out;
+               }
 
                if ((qg->lim_flags & BTRFS_QGROUP_LIMIT_MAX_EXCL) &&
                    qg->reserved + qg->excl + num_bytes >
-                   qg->max_excl)
+                   qg->max_excl) {
                        ret = -EDQUOT;
+                       goto out;
+               }
 
                list_for_each_entry(glist, &qg->groups, next_group) {
                        ulist_add(ulist, glist->group->qgroupid,
                                  (uintptr_t)glist->group, GFP_ATOMIC);
                }
        }
-       if (ret)
-               goto out;
 
        /*
         * no limits exceeded, now record the reservation into all qgroups
index 9250b9c4f01e1b826e25414e6ace942487e2ccca..50767bbaad6c6bfeb40e4d0e815446effd5392b3 100644 (file)
@@ -625,14 +625,13 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_trans_release_metadata(trans, root);
        trans->block_rsv = NULL;
-       /*
-        * the same root has to be passed to start_transaction and
-        * end_transaction. Subvolume quota depends on this.
-        */
-       WARN_ON(trans->root != root);
 
        if (trans->qgroup_reserved) {
-               btrfs_qgroup_free(root, trans->qgroup_reserved);
+               /*
+                * the same root has to be passed here between start_transaction
+                * and end_transaction. Subvolume quota depends on this.
+                */
+               btrfs_qgroup_free(trans->root, trans->qgroup_reserved);
                trans->qgroup_reserved = 0;
        }
 
index 6b9cff42265d06e5b26a7ed53684a5551675a930..5989a92236f7f1b578ec3ccf88078bb69c1093d3 100644 (file)
@@ -684,6 +684,12 @@ int btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
                __btrfs_close_devices(fs_devices);
                free_fs_devices(fs_devices);
        }
+       /*
+        * Wait for rcu kworkers under __btrfs_close_devices
+        * to finish all blkdev_puts so device is really
+        * free when umount is done.
+        */
+       rcu_barrier();
        return ret;
 }