nfsd: simplify fh_verify access checks
[safe/jmp/linux-2.6] / fs / btrfs / tree-defrag.c
index b17693f..b10eacd 100644 (file)
 #include "transaction.h"
 #include "locking.h"
 
+/* defrag all the leaves in a given btree.  If cache_only == 1, don't read
+ * things from disk, otherwise read all the leaves and try to get key order to
+ * better reflect disk order
+ */
+
 int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
                        struct btrfs_root *root, int cache_only)
 {
@@ -32,10 +37,13 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
        int wret;
        int level;
        int orig_level;
-       int i;
        int is_extent = 0;
        int next_key_ret = 0;
        u64 last_ret = 0;
+       u64 min_trans = 0;
+
+       if (cache_only)
+               goto out;
 
        if (root->fs_info->extent_root == root) {
                /*
@@ -43,10 +51,6 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
                 * we can't defrag the extent root without deadlock
                 */
                goto out;
-#if 0
-               mutex_lock(&root->fs_info->alloc_mutex);
-               is_extent = 1;
-#endif
        }
 
        if (root->ref_cows == 0 && !is_extent)
@@ -62,14 +66,15 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
        level = btrfs_header_level(root->node);
        orig_level = level;
 
-       if (level == 0) {
+       if (level == 0)
                goto out;
-       }
+
        if (root->defrag_progress.objectid == 0) {
                struct extent_buffer *root_node;
                u32 nritems;
 
                root_node = btrfs_lock_root_node(root);
+               btrfs_set_lock_blocking(root_node);
                nritems = btrfs_header_nritems(root_node);
                root->defrag_max.objectid = 0;
                /* from above we know this is not a leaf */
@@ -82,8 +87,19 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
                memcpy(&key, &root->defrag_progress, sizeof(key));
        }
 
-       path->lowest_level = 1;
        path->keep_locks = 1;
+       if (cache_only)
+               min_trans = root->defrag_trans_start;
+
+       ret = btrfs_search_forward(root, &key, NULL, path,
+                                  cache_only, min_trans);
+       if (ret < 0)
+               goto out;
+       if (ret > 0) {
+               ret = 0;
+               goto out;
+       }
+       btrfs_release_path(root, path);
        wret = btrfs_search_slot(trans, root, &key, path, 0, 1);
 
        if (wret < 0) {
@@ -95,7 +111,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
                goto out;
        }
        path->slots[1] = btrfs_header_nritems(path->nodes[1]);
-       next_key_ret = btrfs_find_next_key(root, path, &key, 1);
+       next_key_ret = btrfs_find_next_key(root, path, &key, 1, cache_only,
+                                          min_trans);
        ret = btrfs_realloc_node(trans, root,
                                 path->nodes[1], 0,
                                 cache_only, &last_ret,
@@ -106,23 +123,8 @@ int btrfs_defrag_leaves(struct btrfs_trans_handle *trans,
                ret = -EAGAIN;
        }
 
-       for (i = 1; i < BTRFS_MAX_LEVEL; i++) {
-               if (path->locks[i]) {
-                       btrfs_tree_unlock(path->nodes[i]);
-                       path->locks[i] = 0;
-               }
-               if (path->nodes[i]) {
-                       free_extent_buffer(path->nodes[i]);
-                       path->nodes[i] = NULL;
-               }
-       }
-       if (is_extent)
-               btrfs_extent_post_op(trans, root);
-
+       btrfs_release_path(root, path);
 out:
-       if (is_extent)
-               mutex_unlock(&root->fs_info->alloc_mutex);
-
        if (path)
                btrfs_free_path(path);
        if (ret == -EAGAIN) {
@@ -138,6 +140,7 @@ done:
        if (ret != -EAGAIN) {
                memset(&root->defrag_progress, 0,
                       sizeof(root->defrag_progress));
+               root->defrag_trans_start = trans->transid;
        }
        return ret;
 }