btrfs: fix memory leak in qgroup accounting
[linux-2.6-microblaze.git] / fs / btrfs / qgroup.c
index 3ad1516..39fc8c3 100644 (file)
@@ -1811,7 +1811,7 @@ static int qgroup_trace_extent_swap(struct btrfs_trans_handle* trans,
                btrfs_item_key_to_cpu(dst_path->nodes[dst_level], &key, 0);
 
        /* For src_path */
-       extent_buffer_get(src_eb);
+       atomic_inc(&src_eb->refs);
        src_path->nodes[root_level] = src_eb;
        src_path->slots[root_level] = dst_path->slots[root_level];
        src_path->locks[root_level] = 0;
@@ -2067,7 +2067,7 @@ static int qgroup_trace_subtree_swap(struct btrfs_trans_handle *trans,
                goto out;
        }
        /* For dst_path */
-       extent_buffer_get(dst_eb);
+       atomic_inc(&dst_eb->refs);
        dst_path->nodes[level] = dst_eb;
        dst_path->slots[level] = 0;
        dst_path->locks[level] = 0;
@@ -2126,7 +2126,7 @@ int btrfs_qgroup_trace_subtree(struct btrfs_trans_handle *trans,
         * walk back up the tree (adjusting slot pointers as we go)
         * and restart the search process.
         */
-       extent_buffer_get(root_eb); /* For path */
+       atomic_inc(&root_eb->refs);     /* For path */
        path->nodes[root_level] = root_eb;
        path->slots[root_level] = 0;
        path->locks[root_level] = 0; /* so release_path doesn't try to unlock */
@@ -2423,8 +2423,12 @@ int btrfs_qgroup_account_extent(struct btrfs_trans_handle *trans, u64 bytenr,
        u64 nr_old_roots = 0;
        int ret = 0;
 
+       /*
+        * If quotas get disabled meanwhile, the resouces need to be freed and
+        * we can't just exit here.
+        */
        if (!test_bit(BTRFS_FS_QUOTA_ENABLED, &fs_info->flags))
-               return 0;
+               goto out_free;
 
        if (new_roots) {
                if (!maybe_fs_roots(new_roots))
@@ -3232,12 +3236,12 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
                if (!(fs_info->qgroup_flags &
                      BTRFS_QGROUP_STATUS_FLAG_RESCAN)) {
                        btrfs_warn(fs_info,
-                       "qgroup rescan init failed, qgroup is not enabled");
+                       "qgroup rescan init failed, qgroup rescan is not queued");
                        ret = -EINVAL;
                } else if (!(fs_info->qgroup_flags &
                             BTRFS_QGROUP_STATUS_FLAG_ON)) {
                        btrfs_warn(fs_info,
-                       "qgroup rescan init failed, qgroup rescan is not queued");
+                       "qgroup rescan init failed, qgroup is not enabled");
                        ret = -EINVAL;
                }
 
@@ -3277,10 +3281,7 @@ qgroup_rescan_init(struct btrfs_fs_info *fs_info, u64 progress_objectid,
        spin_unlock(&fs_info->qgroup_lock);
        mutex_unlock(&fs_info->qgroup_rescan_lock);
 
-       memset(&fs_info->qgroup_rescan_work, 0,
-              sizeof(fs_info->qgroup_rescan_work));
        btrfs_init_work(&fs_info->qgroup_rescan_work,
-                       btrfs_qgroup_rescan_helper,
                        btrfs_qgroup_rescan_worker, NULL, NULL);
        return 0;
 }
@@ -3826,7 +3827,7 @@ out:
  */
 int btrfs_qgroup_add_swapped_blocks(struct btrfs_trans_handle *trans,
                struct btrfs_root *subvol_root,
-               struct btrfs_block_group_cache *bg,
+               struct btrfs_block_group *bg,
                struct extent_buffer *subvol_parent, int subvol_slot,
                struct extent_buffer *reloc_parent, int reloc_slot,
                u64 last_snapshot)