]> Pileus Git - ~andy/linux/blobdiff - fs/btrfs/relocation.c
SELinux: remove avd from slow_avc_audit()
[~andy/linux] / fs / btrfs / relocation.c
index 8c1aae2c845d49960fe352c809033f1bdf5ffb74..017281dbb2a71f6a0c51f4f8cc52cf9e651f2fd0 100644 (file)
@@ -326,6 +326,19 @@ static struct rb_node *tree_search(struct rb_root *root, u64 bytenr)
        return NULL;
 }
 
+void backref_tree_panic(struct rb_node *rb_node, int errno,
+                                         u64 bytenr)
+{
+
+       struct btrfs_fs_info *fs_info = NULL;
+       struct backref_node *bnode = rb_entry(rb_node, struct backref_node,
+                                             rb_node);
+       if (bnode->root)
+               fs_info = bnode->root->fs_info;
+       btrfs_panic(fs_info, errno, "Inconsistency in backref cache "
+                   "found at offset %llu\n", (unsigned long long)bytenr);
+}
+
 /*
  * walk up backref nodes until reach node presents tree root
  */
@@ -452,7 +465,8 @@ static void update_backref_node(struct backref_cache *cache,
        rb_erase(&node->rb_node, &cache->rb_root);
        node->bytenr = bytenr;
        rb_node = tree_insert(&cache->rb_root, node->bytenr, &node->rb_node);
-       BUG_ON(rb_node);
+       if (rb_node)
+               backref_tree_panic(rb_node, -EEXIST, bytenr);
 }
 
 /*
@@ -999,7 +1013,8 @@ next:
        if (!cowonly) {
                rb_node = tree_insert(&cache->rb_root, node->bytenr,
                                      &node->rb_node);
-               BUG_ON(rb_node);
+               if (rb_node)
+                       backref_tree_panic(rb_node, -EEXIST, node->bytenr);
                list_add_tail(&node->lower, &cache->leaves);
        }
 
@@ -1034,7 +1049,9 @@ next:
                if (!cowonly) {
                        rb_node = tree_insert(&cache->rb_root, upper->bytenr,
                                              &upper->rb_node);
-                       BUG_ON(rb_node);
+                       if (rb_node)
+                               backref_tree_panic(rb_node, -EEXIST,
+                                                  upper->bytenr);
                }
 
                list_add_tail(&edge->list[UPPER], &upper->lower);
@@ -1180,7 +1197,8 @@ static int clone_backref_node(struct btrfs_trans_handle *trans,
 
        rb_node = tree_insert(&cache->rb_root, new_node->bytenr,
                              &new_node->rb_node);
-       BUG_ON(rb_node);
+       if (rb_node)
+               backref_tree_panic(rb_node, -EEXIST, new_node->bytenr);
 
        if (!new_node->lowest) {
                list_for_each_entry(new_edge, &new_node->lower, list[UPPER]) {
@@ -1203,14 +1221,15 @@ fail:
 /*
  * helper to add 'address of tree root -> reloc tree' mapping
  */
-static int __add_reloc_root(struct btrfs_root *root)
+static int __must_check __add_reloc_root(struct btrfs_root *root)
 {
        struct rb_node *rb_node;
        struct mapping_node *node;
        struct reloc_control *rc = root->fs_info->reloc_ctl;
 
        node = kmalloc(sizeof(*node), GFP_NOFS);
-       BUG_ON(!node);
+       if (!node)
+               return -ENOMEM;
 
        node->bytenr = root->node->start;
        node->data = root;
@@ -1219,7 +1238,12 @@ static int __add_reloc_root(struct btrfs_root *root)
        rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
                              node->bytenr, &node->rb_node);
        spin_unlock(&rc->reloc_root_tree.lock);
-       BUG_ON(rb_node);
+       if (rb_node) {
+               kfree(node);
+               btrfs_panic(root->fs_info, -EEXIST, "Duplicate root found "
+                           "for start=%llu while inserting into relocation "
+                           "tree\n");
+       }
 
        list_add_tail(&root->root_list, &rc->reloc_roots);
        return 0;
@@ -1252,7 +1276,8 @@ static int __update_reloc_root(struct btrfs_root *root, int del)
                rb_node = tree_insert(&rc->reloc_root_tree.rb_root,
                                      node->bytenr, &node->rb_node);
                spin_unlock(&rc->reloc_root_tree.lock);
-               BUG_ON(rb_node);
+               if (rb_node)
+                       backref_tree_panic(rb_node, -EEXIST, node->bytenr);
        } else {
                list_del_init(&root->root_list);
                kfree(node);
@@ -1334,6 +1359,7 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
        struct btrfs_root *reloc_root;
        struct reloc_control *rc = root->fs_info->reloc_ctl;
        int clear_rsv = 0;
+       int ret;
 
        if (root->reloc_root) {
                reloc_root = root->reloc_root;
@@ -1353,7 +1379,8 @@ int btrfs_init_reloc_root(struct btrfs_trans_handle *trans,
        if (clear_rsv)
                trans->block_rsv = NULL;
 
-       __add_reloc_root(reloc_root);
+       ret = __add_reloc_root(reloc_root);
+       BUG_ON(ret < 0);
        root->reloc_root = reloc_root;
        return 0;
 }
@@ -1577,15 +1604,14 @@ int replace_file_extents(struct btrfs_trans_handle *trans,
                                WARN_ON(!IS_ALIGNED(end, root->sectorsize));
                                end--;
                                ret = try_lock_extent(&BTRFS_I(inode)->io_tree,
-                                                     key.offset, end,
-                                                     GFP_NOFS);
+                                                     key.offset, end);
                                if (!ret)
                                        continue;
 
                                btrfs_drop_extent_cache(inode, key.offset, end,
                                                        1);
                                unlock_extent(&BTRFS_I(inode)->io_tree,
-                                             key.offset, end, GFP_NOFS);
+                                             key.offset, end);
                        }
                }
 
@@ -1956,9 +1982,9 @@ static int invalidate_extent_cache(struct btrfs_root *root,
                }
 
                /* the lock_extent waits for readpage to complete */
-               lock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+               lock_extent(&BTRFS_I(inode)->io_tree, start, end);
                btrfs_drop_extent_cache(inode, start, end, 1);
-               unlock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+               unlock_extent(&BTRFS_I(inode)->io_tree, start, end);
        }
        return 0;
 }
@@ -2246,7 +2272,8 @@ again:
                } else {
                        list_del_init(&reloc_root->root_list);
                }
-               btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1);
+               ret = btrfs_drop_snapshot(reloc_root, rc->block_rsv, 0, 1);
+               BUG_ON(ret < 0);
        }
 
        if (found) {
@@ -2862,12 +2889,12 @@ int prealloc_file_extent_cluster(struct inode *inode,
                else
                        end = cluster->end - offset;
 
-               lock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+               lock_extent(&BTRFS_I(inode)->io_tree, start, end);
                num_bytes = end + 1 - start;
                ret = btrfs_prealloc_file_range(inode, 0, start,
                                                num_bytes, num_bytes,
                                                end + 1, &alloc_hint);
-               unlock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+               unlock_extent(&BTRFS_I(inode)->io_tree, start, end);
                if (ret)
                        break;
                nr++;
@@ -2899,7 +2926,7 @@ int setup_extent_mapping(struct inode *inode, u64 start, u64 end,
        em->bdev = root->fs_info->fs_devices->latest_bdev;
        set_bit(EXTENT_FLAG_PINNED, &em->flags);
 
-       lock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+       lock_extent(&BTRFS_I(inode)->io_tree, start, end);
        while (1) {
                write_lock(&em_tree->lock);
                ret = add_extent_mapping(em_tree, em);
@@ -2910,7 +2937,7 @@ int setup_extent_mapping(struct inode *inode, u64 start, u64 end,
                }
                btrfs_drop_extent_cache(inode, start, end, 0);
        }
-       unlock_extent(&BTRFS_I(inode)->io_tree, start, end, GFP_NOFS);
+       unlock_extent(&BTRFS_I(inode)->io_tree, start, end);
        return ret;
 }
 
@@ -2990,8 +3017,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                page_start = (u64)page->index << PAGE_CACHE_SHIFT;
                page_end = page_start + PAGE_CACHE_SIZE - 1;
 
-               lock_extent(&BTRFS_I(inode)->io_tree,
-                           page_start, page_end, GFP_NOFS);
+               lock_extent(&BTRFS_I(inode)->io_tree, page_start, page_end);
 
                set_page_extent_mapped(page);
 
@@ -3007,7 +3033,7 @@ static int relocate_file_extent_cluster(struct inode *inode,
                set_page_dirty(page);
 
                unlock_extent(&BTRFS_I(inode)->io_tree,
-                             page_start, page_end, GFP_NOFS);
+                             page_start, page_end);
                unlock_page(page);
                page_cache_release(page);
 
@@ -3154,7 +3180,8 @@ static int add_tree_block(struct reloc_control *rc,
        block->key_ready = 0;
 
        rb_node = tree_insert(blocks, block->bytenr, &block->rb_node);
-       BUG_ON(rb_node);
+       if (rb_node)
+               backref_tree_panic(rb_node, -EEXIST, block->bytenr);
 
        return 0;
 }
@@ -3426,7 +3453,9 @@ static int find_data_references(struct reloc_control *rc,
                        block->key_ready = 1;
                        rb_node = tree_insert(blocks, block->bytenr,
                                              &block->rb_node);
-                       BUG_ON(rb_node);
+                       if (rb_node)
+                               backref_tree_panic(rb_node, -EEXIST,
+                                                  block->bytenr);
                }
                if (counted)
                        added = 1;
@@ -4073,10 +4102,11 @@ out:
 static noinline_for_stack int mark_garbage_root(struct btrfs_root *root)
 {
        struct btrfs_trans_handle *trans;
-       int ret;
+       int ret, err;
 
        trans = btrfs_start_transaction(root->fs_info->tree_root, 0);
-       BUG_ON(IS_ERR(trans));
+       if (IS_ERR(trans))
+               return PTR_ERR(trans);
 
        memset(&root->root_item.drop_progress, 0,
                sizeof(root->root_item.drop_progress));
@@ -4084,11 +4114,11 @@ static noinline_for_stack int mark_garbage_root(struct btrfs_root *root)
        btrfs_set_root_refs(&root->root_item, 0);
        ret = btrfs_update_root(trans, root->fs_info->tree_root,
                                &root->root_key, &root->root_item);
-       BUG_ON(ret);
 
-       ret = btrfs_end_transaction(trans, root->fs_info->tree_root);
-       BUG_ON(ret);
-       return 0;
+       err = btrfs_end_transaction(trans, root->fs_info->tree_root);
+       if (err)
+               return err;
+       return ret;
 }
 
 /*
@@ -4156,7 +4186,11 @@ int btrfs_recover_relocation(struct btrfs_root *root)
                                        err = ret;
                                        goto out;
                                }
-                               mark_garbage_root(reloc_root);
+                               ret = mark_garbage_root(reloc_root);
+                               if (ret < 0) {
+                                       err = ret;
+                                       goto out;
+                               }
                        }
                }
 
@@ -4202,13 +4236,19 @@ int btrfs_recover_relocation(struct btrfs_root *root)
 
                fs_root = read_fs_root(root->fs_info,
                                       reloc_root->root_key.offset);
-               BUG_ON(IS_ERR(fs_root));
+               if (IS_ERR(fs_root)) {
+                       err = PTR_ERR(fs_root);
+                       goto out_free;
+               }
 
-               __add_reloc_root(reloc_root);
+               err = __add_reloc_root(reloc_root);
+               BUG_ON(err < 0); /* -ENOMEM or logic error */
                fs_root->reloc_root = reloc_root;
        }
 
-       btrfs_commit_transaction(trans, rc->extent_root);
+       err = btrfs_commit_transaction(trans, rc->extent_root);
+       if (err)
+               goto out_free;
 
        merge_reloc_roots(rc);
 
@@ -4218,7 +4258,7 @@ int btrfs_recover_relocation(struct btrfs_root *root)
        if (IS_ERR(trans))
                err = PTR_ERR(trans);
        else
-               btrfs_commit_transaction(trans, rc->extent_root);
+               err = btrfs_commit_transaction(trans, rc->extent_root);
 out_free:
        kfree(rc);
 out:
@@ -4267,6 +4307,8 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len)
        disk_bytenr = file_pos + BTRFS_I(inode)->index_cnt;
        ret = btrfs_lookup_csums_range(root->fs_info->csum_root, disk_bytenr,
                                       disk_bytenr + len - 1, &list, 0);
+       if (ret)
+               goto out;
 
        while (!list_empty(&list)) {
                sums = list_entry(list.next, struct btrfs_ordered_sum, list);
@@ -4284,6 +4326,7 @@ int btrfs_reloc_clone_csums(struct inode *inode, u64 file_pos, u64 len)
 
                btrfs_add_ordered_sum(inode, ordered, sums);
        }
+out:
        btrfs_put_ordered_extent(ordered);
        return ret;
 }
@@ -4380,7 +4423,7 @@ void btrfs_reloc_pre_snapshot(struct btrfs_trans_handle *trans,
  * called after snapshot is created. migrate block reservation
  * and create reloc root for the newly created snapshot
  */
-void btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
+int btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
                               struct btrfs_pending_snapshot *pending)
 {
        struct btrfs_root *root = pending->root;
@@ -4390,7 +4433,7 @@ void btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
        int ret;
 
        if (!root->reloc_root)
-               return;
+               return 0;
 
        rc = root->fs_info->reloc_ctl;
        rc->merging_rsv_size += rc->nodes_relocated;
@@ -4399,18 +4442,21 @@ void btrfs_reloc_post_snapshot(struct btrfs_trans_handle *trans,
                ret = btrfs_block_rsv_migrate(&pending->block_rsv,
                                              rc->block_rsv,
                                              rc->nodes_relocated);
-               BUG_ON(ret);
+               if (ret)
+                       return ret;
        }
 
        new_root = pending->snap;
        reloc_root = create_reloc_root(trans, root->reloc_root,
                                       new_root->root_key.objectid);
+       if (IS_ERR(reloc_root))
+               return PTR_ERR(reloc_root);
 
-       __add_reloc_root(reloc_root);
+       ret = __add_reloc_root(reloc_root);
+       BUG_ON(ret < 0);
        new_root->reloc_root = reloc_root;
 
-       if (rc->create_reloc_tree) {
+       if (rc->create_reloc_tree)
                ret = clone_backref_node(trans, rc, root, reloc_root);
-               BUG_ON(ret);
-       }
+       return ret;
 }