btrfs: btrfs_test_opt and friends should take a btrfs_fs_info
[linux-2.6-block.git] / fs / btrfs / inode.c
index bb62418b80232d0d4381ffea5d8555d06a3b973c..b166ee0763b6d621fc39f5f6c7bc627598767426 100644 (file)
@@ -60,6 +60,7 @@
 #include "hash.h"
 #include "props.h"
 #include "qgroup.h"
+#include "dedupe.h"
 
 struct btrfs_iget_args {
        struct btrfs_key *location;
@@ -105,8 +106,9 @@ static int btrfs_truncate(struct inode *inode);
 static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent);
 static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
-                                  u64 start, u64 end, int *page_started,
-                                  unsigned long *nr_written, int unlock);
+                                  u64 start, u64 end, u64 delalloc_end,
+                                  int *page_started, unsigned long *nr_written,
+                                  int unlock, struct btrfs_dedupe_hash *hash);
 static struct extent_map *create_pinned_em(struct inode *inode, u64 start,
                                           u64 len, u64 orig_start,
                                           u64 block_start, u64 block_len,
@@ -374,12 +376,12 @@ static inline int inode_need_compress(struct inode *inode)
        struct btrfs_root *root = BTRFS_I(inode)->root;
 
        /* force compress */
-       if (btrfs_test_opt(root, FORCE_COMPRESS))
+       if (btrfs_test_opt(root->fs_info, FORCE_COMPRESS))
                return 1;
        /* bad compression ratios */
        if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS)
                return 0;
-       if (btrfs_test_opt(root, COMPRESS) ||
+       if (btrfs_test_opt(root->fs_info, COMPRESS) ||
            BTRFS_I(inode)->flags & BTRFS_INODE_COMPRESS ||
            BTRFS_I(inode)->force_compress)
                return 1;
@@ -585,9 +587,27 @@ cont:
                        will_compress = 0;
                } else {
                        num_bytes = total_in;
+                       *num_added += 1;
+
+                       /*
+                        * The async work queues will take care of doing actual
+                        * allocation on disk for these compressed pages, and
+                        * will submit them to the elevator.
+                        */
+                       add_async_extent(async_cow, start, num_bytes,
+                                       total_compressed, pages, nr_pages_ret,
+                                       compress_type);
+
+                       if (start + num_bytes < end) {
+                               start += num_bytes;
+                               pages = NULL;
+                               cond_resched();
+                               goto again;
+                       }
+                       return;
                }
        }
-       if (!will_compress && pages) {
+       if (pages) {
                /*
                 * the compression code ran but failed to make things smaller,
                 * free any pages it allocated and our page pointer array
@@ -602,48 +622,28 @@ cont:
                nr_pages_ret = 0;
 
                /* flag the file so we don't compress in the future */
-               if (!btrfs_test_opt(root, FORCE_COMPRESS) &&
+               if (!btrfs_test_opt(root->fs_info, FORCE_COMPRESS) &&
                    !(BTRFS_I(inode)->force_compress)) {
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NOCOMPRESS;
                }
        }
-       if (will_compress) {
-               *num_added += 1;
-
-               /* the async work queues will take care of doing actual
-                * allocation on disk for these compressed pages,
-                * and will submit them to the elevator.
-                */
-               add_async_extent(async_cow, start, num_bytes,
-                                total_compressed, pages, nr_pages_ret,
-                                compress_type);
-
-               if (start + num_bytes < end) {
-                       start += num_bytes;
-                       pages = NULL;
-                       cond_resched();
-                       goto again;
-               }
-       } else {
 cleanup_and_bail_uncompressed:
-               /*
-                * No compression, but we still need to write the pages in
-                * the file we've been given so far.  redirty the locked
-                * page if it corresponds to our extent and set things up
-                * for the async work queue to run cow_file_range to do
-                * the normal delalloc dance
-                */
-               if (page_offset(locked_page) >= start &&
-                   page_offset(locked_page) <= end) {
-                       __set_page_dirty_nobuffers(locked_page);
-                       /* unlocked later on in the async handlers */
-               }
-               if (redirty)
-                       extent_range_redirty_for_io(inode, start, end);
-               add_async_extent(async_cow, start, end - start + 1,
-                                0, NULL, 0, BTRFS_COMPRESS_NONE);
-               *num_added += 1;
-       }
+       /*
+        * No compression, but we still need to write the pages in the file
+        * we've been given so far.  redirty the locked page if it corresponds
+        * to our extent and set things up for the async work queue to run
+        * cow_file_range to do the normal delalloc dance.
+        */
+       if (page_offset(locked_page) >= start &&
+           page_offset(locked_page) <= end)
+               __set_page_dirty_nobuffers(locked_page);
+               /* unlocked later on in the async handlers */
+
+       if (redirty)
+               extent_range_redirty_for_io(inode, start, end);
+       add_async_extent(async_cow, start, end - start + 1, 0, NULL, 0,
+                        BTRFS_COMPRESS_NONE);
+       *num_added += 1;
 
        return;
 
@@ -712,7 +712,10 @@ retry:
                                             async_extent->start,
                                             async_extent->start +
                                             async_extent->ram_size - 1,
-                                            &page_started, &nr_written, 0);
+                                            async_extent->start +
+                                            async_extent->ram_size - 1,
+                                            &page_started, &nr_written, 0,
+                                            NULL);
 
                        /* JDM XXX */
 
@@ -925,9 +928,9 @@ static u64 get_extent_allocation_hint(struct inode *inode, u64 start,
  */
 static noinline int cow_file_range(struct inode *inode,
                                   struct page *locked_page,
-                                  u64 start, u64 end, int *page_started,
-                                  unsigned long *nr_written,
-                                  int unlock)
+                                  u64 start, u64 end, u64 delalloc_end,
+                                  int *page_started, unsigned long *nr_written,
+                                  int unlock, struct btrfs_dedupe_hash *hash)
 {
        struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 alloc_hint = 0;
@@ -1156,7 +1159,7 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
                async_cow->start = start;
 
                if (BTRFS_I(inode)->flags & BTRFS_INODE_NOCOMPRESS &&
-                   !btrfs_test_opt(root, FORCE_COMPRESS))
+                   !btrfs_test_opt(root->fs_info, FORCE_COMPRESS))
                        cur_end = end;
                else
                        cur_end = min(end, start + SZ_512K - 1);
@@ -1418,7 +1421,8 @@ out_check:
                if (cow_start != (u64)-1) {
                        ret = cow_file_range(inode, locked_page,
                                             cow_start, found_key.offset - 1,
-                                            page_started, nr_written, 1);
+                                            end, page_started, nr_written, 1,
+                                            NULL);
                        if (ret) {
                                if (!nolock && nocow)
                                        btrfs_end_write_no_snapshoting(root);
@@ -1501,8 +1505,8 @@ out_check:
        }
 
        if (cow_start != (u64)-1) {
-               ret = cow_file_range(inode, locked_page, cow_start, end,
-                                    page_started, nr_written, 1);
+               ret = cow_file_range(inode, locked_page, cow_start, end, end,
+                                    page_started, nr_written, 1, NULL);
                if (ret)
                        goto error;
        }
@@ -1561,8 +1565,8 @@ static int run_delalloc_range(struct inode *inode, struct page *locked_page,
                ret = run_delalloc_nocow(inode, locked_page, start, end,
                                         page_started, 0, nr_written);
        } else if (!inode_need_compress(inode)) {
-               ret = cow_file_range(inode, locked_page, start, end,
-                                     page_started, nr_written, 1);
+               ret = cow_file_range(inode, locked_page, start, end, end,
+                                     page_started, nr_written, 1, NULL);
        } else {
                set_bit(BTRFS_INODE_HAS_ASYNC_EXTENT,
                        &BTRFS_I(inode)->runtime_flags);
@@ -1822,6 +1826,10 @@ static void btrfs_clear_bit_hook(struct inode *inode,
 /*
  * extent_io.c merge_bio_hook, this must check the chunk tree to make sure
  * we don't create bios that span stripes or chunks
+ *
+ * return 1 if page cannot be merged to bio
+ * return 0 if page can be merged to bio
+ * return error otherwise
  */
 int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset,
                         size_t size, struct bio *bio,
@@ -1840,8 +1848,8 @@ int btrfs_merge_bio_hook(int rw, struct page *page, unsigned long offset,
        map_length = length;
        ret = btrfs_map_block(root->fs_info, rw, logical,
                              &map_length, NULL, 0);
-       /* Will always return 0 with map_multi == NULL */
-       BUG_ON(ret < 0);
+       if (ret < 0)
+               return ret;
        if (map_length < length + size)
                return 1;
        return 0;
@@ -4558,6 +4566,7 @@ delete:
                        BUG_ON(ret);
                        if (btrfs_should_throttle_delayed_refs(trans, root))
                                btrfs_async_run_delayed_refs(root,
+                                                            trans->transid,
                                        trans->delayed_ref_updates * 2, 0);
                        if (be_nice) {
                                if (truncate_space_check(trans, root,
@@ -5158,11 +5167,18 @@ void btrfs_evict_inode(struct inode *inode)
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_block_rsv *rsv, *global_rsv;
        int steal_from_global = 0;
-       u64 min_size = btrfs_calc_trunc_metadata_size(root, 1);
+       u64 min_size;
        int ret;
 
        trace_btrfs_inode_evict(inode);
 
+       if (!root) {
+               kmem_cache_free(btrfs_inode_cachep, BTRFS_I(inode));
+               return;
+       }
+
+       min_size = btrfs_calc_trunc_metadata_size(root, 1);
+
        evict_inode_truncate_pages(inode);
 
        if (inode->i_nlink &&
@@ -5263,7 +5279,7 @@ void btrfs_evict_inode(struct inode *inode)
                if (steal_from_global) {
                        if (!btrfs_check_space_for_delayed_refs(trans, root))
                                ret = btrfs_block_rsv_migrate(global_rsv, rsv,
-                                                             min_size);
+                                                             min_size, 0);
                        else
                                ret = -ENOSPC;
                }
@@ -5757,6 +5773,7 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
        int name_len;
        int is_curr = 0;        /* ctx->pos points to the current index? */
        bool emitted;
+       bool put = false;
 
        /* FIXME, use a real flag for deciding about the key type */
        if (root->fs_info->tree_root == root)
@@ -5774,7 +5791,8 @@ static int btrfs_real_readdir(struct file *file, struct dir_context *ctx)
        if (key_type == BTRFS_DIR_INDEX_KEY) {
                INIT_LIST_HEAD(&ins_list);
                INIT_LIST_HEAD(&del_list);
-               btrfs_get_delayed_items(inode, &ins_list, &del_list);
+               put = btrfs_readdir_get_delayed_items(inode, &ins_list,
+                                                     &del_list);
        }
 
        key.type = key_type;
@@ -5921,8 +5939,8 @@ next:
 nopos:
        ret = 0;
 err:
-       if (key_type == BTRFS_DIR_INDEX_KEY)
-               btrfs_put_delayed_items(&ins_list, &del_list);
+       if (put)
+               btrfs_readdir_put_delayed_items(inode, &ins_list, &del_list);
        btrfs_free_path(path);
        return ret;
 }
@@ -6237,9 +6255,9 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans,
        btrfs_inherit_iflags(inode, dir);
 
        if (S_ISREG(mode)) {
-               if (btrfs_test_opt(root, NODATASUM))
+               if (btrfs_test_opt(root->fs_info, NODATASUM))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATASUM;
-               if (btrfs_test_opt(root, NODATACOW))
+               if (btrfs_test_opt(root->fs_info, NODATACOW))
                        BTRFS_I(inode)->flags |= BTRFS_INODE_NODATACOW |
                                BTRFS_INODE_NODATASUM;
        }
@@ -8582,13 +8600,13 @@ out:
        return retval;
 }
 
-static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
-                              loff_t offset)
+static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_dio_data dio_data = { 0 };
+       loff_t offset = iocb->ki_pos;
        size_t count = 0;
        int flags = 0;
        bool wakeup = true;
@@ -8648,7 +8666,7 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter,
 
        ret = __blockdev_direct_IO(iocb, inode,
                                   BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
-                                  iter, offset, btrfs_get_blocks_direct, NULL,
+                                  iter, btrfs_get_blocks_direct, NULL,
                                   btrfs_submit_direct, flags);
        if (iov_iter_rw(iter) == WRITE) {
                current->journal_info = NULL;
@@ -9113,7 +9131,7 @@ static int btrfs_truncate(struct inode *inode)
 
        /* Migrate the slack space for the truncate to our reserve */
        ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv, rsv,
-                                     min_size);
+                                     min_size, 0);
        BUG_ON(ret);
 
        /*
@@ -9153,7 +9171,7 @@ static int btrfs_truncate(struct inode *inode)
                }
 
                ret = btrfs_block_rsv_migrate(&root->fs_info->trans_block_rsv,
-                                             rsv, min_size);
+                                             rsv, min_size, 0);
                BUG_ON(ret);    /* shouldn't happen */
                trans->block_rsv = rsv;
        }
@@ -9174,7 +9192,6 @@ static int btrfs_truncate(struct inode *inode)
                ret = btrfs_end_transaction(trans, root);
                btrfs_btree_balance_dirty(root);
        }
-
 out:
        btrfs_free_block_rsv(root, rsv);
 
@@ -9383,25 +9400,25 @@ int btrfs_init_cachep(void)
 
        btrfs_trans_handle_cachep = kmem_cache_create("btrfs_trans_handle",
                        sizeof(struct btrfs_trans_handle), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL);
        if (!btrfs_trans_handle_cachep)
                goto fail;
 
        btrfs_transaction_cachep = kmem_cache_create("btrfs_transaction",
                        sizeof(struct btrfs_transaction), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_TEMPORARY | SLAB_MEM_SPREAD, NULL);
        if (!btrfs_transaction_cachep)
                goto fail;
 
        btrfs_path_cachep = kmem_cache_create("btrfs_path",
                        sizeof(struct btrfs_path), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_MEM_SPREAD, NULL);
        if (!btrfs_path_cachep)
                goto fail;
 
        btrfs_free_space_cachep = kmem_cache_create("btrfs_free_space",
                        sizeof(struct btrfs_free_space), 0,
-                       SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, NULL);
+                       SLAB_MEM_SPREAD, NULL);
        if (!btrfs_free_space_cachep)
                goto fail;
 
@@ -10513,10 +10530,10 @@ static const struct inode_operations btrfs_dir_inode_operations = {
        .symlink        = btrfs_symlink,
        .setattr        = btrfs_setattr,
        .mknod          = btrfs_mknod,
-       .setxattr       = btrfs_setxattr,
+       .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = btrfs_removexattr,
+       .removexattr    = generic_removexattr,
        .permission     = btrfs_permission,
        .get_acl        = btrfs_get_acl,
        .set_acl        = btrfs_set_acl,
@@ -10534,7 +10551,7 @@ static const struct inode_operations btrfs_dir_ro_inode_operations = {
 static const struct file_operations btrfs_dir_file_operations = {
        .llseek         = generic_file_llseek,
        .read           = generic_read_dir,
-       .iterate        = btrfs_real_readdir,
+       .iterate_shared = btrfs_real_readdir,
        .unlocked_ioctl = btrfs_ioctl,
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = btrfs_compat_ioctl,
@@ -10590,10 +10607,10 @@ static const struct address_space_operations btrfs_symlink_aops = {
 static const struct inode_operations btrfs_file_inode_operations = {
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
-       .setxattr       = btrfs_setxattr,
+       .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = btrfs_removexattr,
+       .removexattr    = generic_removexattr,
        .permission     = btrfs_permission,
        .fiemap         = btrfs_fiemap,
        .get_acl        = btrfs_get_acl,
@@ -10604,10 +10621,10 @@ static const struct inode_operations btrfs_special_inode_operations = {
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
-       .setxattr       = btrfs_setxattr,
+       .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = btrfs_removexattr,
+       .removexattr    = generic_removexattr,
        .get_acl        = btrfs_get_acl,
        .set_acl        = btrfs_set_acl,
        .update_time    = btrfs_update_time,
@@ -10618,10 +10635,10 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
        .getattr        = btrfs_getattr,
        .setattr        = btrfs_setattr,
        .permission     = btrfs_permission,
-       .setxattr       = btrfs_setxattr,
+       .setxattr       = generic_setxattr,
        .getxattr       = generic_getxattr,
        .listxattr      = btrfs_listxattr,
-       .removexattr    = btrfs_removexattr,
+       .removexattr    = generic_removexattr,
        .update_time    = btrfs_update_time,
 };