btrfs: Remove root argument from cow_file_range_inline
[sfrench/cifs-2.6.git] / fs / btrfs / inode.c
index a79299a89b7d0285328e29cecaaff51ff82c5be7..ce65acafe7bb75b4306bd4fcd34ee0e59f1077f0 100644 (file)
@@ -58,7 +58,6 @@
 #include "free-space-cache.h"
 #include "inode-map.h"
 #include "backref.h"
-#include "hash.h"
 #include "props.h"
 #include "qgroup.h"
 #include "dedupe.h"
@@ -102,7 +101,7 @@ static const unsigned char btrfs_type_by_mode[S_IFMT >> S_SHIFT] = {
 };
 
 static int btrfs_setsize(struct inode *inode, struct iattr *attr);
-static int btrfs_truncate(struct inode *inode);
+static int btrfs_truncate(struct inode *inode, bool skip_writeback);
 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,
@@ -277,12 +276,12 @@ fail:
  * does the checks required to make sure the data is small enough
  * to fit as an inline extent.
  */
-static noinline int cow_file_range_inline(struct btrfs_root *root,
-                                         struct inode *inode, u64 start,
+static noinline int cow_file_range_inline(struct inode *inode, u64 start,
                                          u64 end, size_t compressed_size,
                                          int compress_type,
                                          struct page **compressed_pages)
 {
+       struct btrfs_root *root = BTRFS_I(inode)->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_trans_handle *trans;
        u64 isize = i_size_read(inode);
@@ -458,7 +457,6 @@ static noinline void compress_file_range(struct inode *inode,
                                        int *num_added)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
-       struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 blocksize = fs_info->sectorsize;
        u64 actual_end;
        u64 isize = i_size_read(inode);
@@ -580,11 +578,11 @@ cont:
                        /* we didn't compress the entire range, try
                         * to make an uncompressed inline extent.
                         */
-                       ret = cow_file_range_inline(root, inode, start, end,
-                                           0, BTRFS_COMPRESS_NONE, NULL);
+                       ret = cow_file_range_inline(inode, start, end, 0,
+                                                   BTRFS_COMPRESS_NONE, NULL);
                } else {
                        /* try making a compressed inline extent */
-                       ret = cow_file_range_inline(root, inode, start, end,
+                       ret = cow_file_range_inline(inode, start, end,
                                                    total_compressed,
                                                    compress_type, pages);
                }
@@ -961,7 +959,6 @@ static noinline int cow_file_range(struct inode *inode,
        u64 alloc_hint = 0;
        u64 num_bytes;
        unsigned long ram_size;
-       u64 disk_num_bytes;
        u64 cur_alloc_size = 0;
        u64 blocksize = fs_info->sectorsize;
        struct btrfs_key ins;
@@ -979,14 +976,14 @@ static noinline int cow_file_range(struct inode *inode,
 
        num_bytes = ALIGN(end - start + 1, blocksize);
        num_bytes = max(blocksize,  num_bytes);
-       disk_num_bytes = num_bytes;
+       ASSERT(num_bytes <= btrfs_super_total_bytes(fs_info->super_copy));
 
        inode_should_defrag(BTRFS_I(inode), start, end, num_bytes, SZ_64K);
 
        if (start == 0) {
                /* lets try to make an inline extent */
-               ret = cow_file_range_inline(root, inode, start, end, 0,
-                                       BTRFS_COMPRESS_NONE, NULL);
+               ret = cow_file_range_inline(inode, start, end, 0,
+                                           BTRFS_COMPRESS_NONE, NULL);
                if (ret == 0) {
                        /*
                         * We use DO_ACCOUNTING here because we need the
@@ -1010,15 +1007,12 @@ static noinline int cow_file_range(struct inode *inode,
                }
        }
 
-       BUG_ON(disk_num_bytes >
-              btrfs_super_total_bytes(fs_info->super_copy));
-
        alloc_hint = get_extent_allocation_hint(inode, start, num_bytes);
        btrfs_drop_extent_cache(BTRFS_I(inode), start,
                        start + num_bytes - 1, 0);
 
-       while (disk_num_bytes > 0) {
-               cur_alloc_size = disk_num_bytes;
+       while (num_bytes > 0) {
+               cur_alloc_size = num_bytes;
                ret = btrfs_reserve_extent(root, cur_alloc_size, cur_alloc_size,
                                           fs_info->sectorsize, 0, alloc_hint,
                                           &ins, 1, 1);
@@ -1082,11 +1076,10 @@ static noinline int cow_file_range(struct inode *inode,
                                             delalloc_end, locked_page,
                                             EXTENT_LOCKED | EXTENT_DELALLOC,
                                             page_ops);
-               if (disk_num_bytes < cur_alloc_size)
-                       disk_num_bytes = 0;
+               if (num_bytes < cur_alloc_size)
+                       num_bytes = 0;
                else
-                       disk_num_bytes -= cur_alloc_size;
-               num_bytes -= cur_alloc_size;
+                       num_bytes -= cur_alloc_size;
                alloc_hint = ins.objectid + ins.offset;
                start += cur_alloc_size;
                extent_reserved = false;
@@ -1262,6 +1255,8 @@ static noinline int csum_exist_in_range(struct btrfs_fs_info *fs_info,
                list_del(&sums->list);
                kfree(sums);
        }
+       if (ret < 0)
+               return ret;
        return 1;
 }
 
@@ -1394,10 +1389,23 @@ next_slot:
                                goto out_check;
                        if (btrfs_extent_readonly(fs_info, disk_bytenr))
                                goto out_check;
-                       if (btrfs_cross_ref_exist(root, ino,
-                                                 found_key.offset -
-                                                 extent_offset, disk_bytenr))
+                       ret = btrfs_cross_ref_exist(root, ino,
+                                                   found_key.offset -
+                                                   extent_offset, disk_bytenr);
+                       if (ret) {
+                               /*
+                                * ret could be -EIO if the above fails to read
+                                * metadata.
+                                */
+                               if (ret < 0) {
+                                       if (cow_start != (u64)-1)
+                                               cur_offset = cow_start;
+                                       goto error;
+                               }
+
+                               WARN_ON_ONCE(nolock);
                                goto out_check;
+                       }
                        disk_bytenr += extent_offset;
                        disk_bytenr += cur_offset - found_key.offset;
                        num_bytes = min(end + 1, extent_end) - cur_offset;
@@ -1415,10 +1423,22 @@ next_slot:
                         * this ensure that csum for a given extent are
                         * either valid or do not exist.
                         */
-                       if (csum_exist_in_range(fs_info, disk_bytenr,
-                                               num_bytes)) {
+                       ret = csum_exist_in_range(fs_info, disk_bytenr,
+                                                 num_bytes);
+                       if (ret) {
                                if (!nolock)
                                        btrfs_end_write_no_snapshotting(root);
+
+                               /*
+                                * ret could be -EIO if the above fails to read
+                                * metadata.
+                                */
+                               if (ret < 0) {
+                                       if (cow_start != (u64)-1)
+                                               cur_offset = cow_start;
+                                       goto error;
+                               }
+                               WARN_ON_ONCE(nolock);
                                goto out_check;
                        }
                        if (!btrfs_inc_nocow_writers(fs_info, disk_bytenr)) {
@@ -2043,12 +2063,15 @@ static noinline int add_pending_csums(struct btrfs_trans_handle *trans,
                             struct inode *inode, struct list_head *list)
 {
        struct btrfs_ordered_sum *sum;
+       int ret;
 
        list_for_each_entry(sum, list, list) {
                trans->adding_csums = true;
-               btrfs_csum_file_blocks(trans,
+               ret = btrfs_csum_file_blocks(trans,
                       BTRFS_I(inode)->root->fs_info->csum_root, sum);
                trans->adding_csums = false;
+               if (ret)
+                       return ret;
        }
        return 0;
 }
@@ -3062,7 +3085,11 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                goto out;
        }
 
-       add_pending_csums(trans, inode, &ordered_extent->list);
+       ret = add_pending_csums(trans, inode, &ordered_extent->list);
+       if (ret) {
+               btrfs_abort_transaction(trans, ret);
+               goto out;
+       }
 
        btrfs_ordered_update_i_size(inode, 0, ordered_extent);
        ret = btrfs_update_inode_fallback(trans, root, inode);
@@ -3240,6 +3267,16 @@ static int btrfs_readpage_end_io_hook(struct btrfs_io_bio *io_bio,
                                      start, (size_t)(end - start + 1));
 }
 
+/*
+ * btrfs_add_delayed_iput - perform a delayed iput on @inode
+ *
+ * @inode: The inode we want to perform iput on
+ *
+ * This function uses the generic vfs_inode::i_count to track whether we should
+ * just decrement it (in case it's > 1) or if this is the last iput then link
+ * the inode to the delayed iput machinery. Delayed iputs are processed at
+ * transaction commit time/superblock commit/cleaner kthread.
+ */
 void btrfs_add_delayed_iput(struct inode *inode)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
@@ -3249,12 +3286,8 @@ void btrfs_add_delayed_iput(struct inode *inode)
                return;
 
        spin_lock(&fs_info->delayed_iput_lock);
-       if (binode->delayed_iput_count == 0) {
-               ASSERT(list_empty(&binode->delayed_iput));
-               list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs);
-       } else {
-               binode->delayed_iput_count++;
-       }
+       ASSERT(list_empty(&binode->delayed_iput));
+       list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs);
        spin_unlock(&fs_info->delayed_iput_lock);
 }
 
@@ -3267,13 +3300,7 @@ void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info)
 
                inode = list_first_entry(&fs_info->delayed_iputs,
                                struct btrfs_inode, delayed_iput);
-               if (inode->delayed_iput_count) {
-                       inode->delayed_iput_count--;
-                       list_move_tail(&inode->delayed_iput,
-                                       &fs_info->delayed_iputs);
-               } else {
-                       list_del_init(&inode->delayed_iput);
-               }
+               list_del_init(&inode->delayed_iput);
                spin_unlock(&fs_info->delayed_iput_lock);
                iput(&inode->vfs_inode);
                spin_lock(&fs_info->delayed_iput_lock);
@@ -3353,14 +3380,6 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans,
                        return -ENOMEM;
        }
 
-       spin_lock(&root->orphan_lock);
-       if (!root->orphan_block_rsv) {
-               root->orphan_block_rsv = block_rsv;
-       } else if (block_rsv) {
-               btrfs_free_block_rsv(fs_info, block_rsv);
-               block_rsv = NULL;
-       }
-
        if (!test_and_set_bit(BTRFS_INODE_HAS_ORPHAN_ITEM,
                              &inode->runtime_flags)) {
 #if 0
@@ -3375,12 +3394,23 @@ int btrfs_orphan_add(struct btrfs_trans_handle *trans,
                        insert = 1;
 #endif
                insert = 1;
-               atomic_inc(&root->orphan_inodes);
        }
 
        if (!test_and_set_bit(BTRFS_INODE_ORPHAN_META_RESERVED,
                              &inode->runtime_flags))
                reserve = 1;
+
+       spin_lock(&root->orphan_lock);
+       /* If someone has created ->orphan_block_rsv, be happy to use it. */
+       if (!root->orphan_block_rsv) {
+               root->orphan_block_rsv = block_rsv;
+       } else if (block_rsv) {
+               btrfs_free_block_rsv(fs_info, block_rsv);
+               block_rsv = NULL;
+       }
+
+       if (insert)
+               atomic_inc(&root->orphan_inodes);
        spin_unlock(&root->orphan_lock);
 
        /* grab metadata reservation from transaction handle */
@@ -3637,7 +3667,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                                goto out;
                        }
 
-                       ret = btrfs_truncate(inode);
+                       ret = btrfs_truncate(inode, false);
                        if (ret)
                                btrfs_orphan_del(NULL, BTRFS_I(inode));
                } else {
@@ -5123,7 +5153,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
                inode_dio_wait(inode);
                btrfs_inode_resume_unlocked_dio(BTRFS_I(inode));
 
-               ret = btrfs_truncate(inode);
+               ret = btrfs_truncate(inode, newsize == oldsize);
                if (ret && inode->i_nlink) {
                        int err;
 
@@ -8291,13 +8321,13 @@ static void btrfs_end_dio_bio(struct bio *bio)
                err = dip->subio_endio(dip->inode, btrfs_io_bio(bio), err);
 
        if (err) {
-               dip->errors = 1;
-
                /*
-                * before atomic variable goto zero, we must make sure
-                * dip->errors is perceived to be set.
+                * We want to perceive the errors flag being set before
+                * decrementing the reference count. We don't need a barrier
+                * since atomic operations with a return value are fully
+                * ordered as per atomic_t.txt
                 */
-               smp_mb__before_atomic();
+               dip->errors = 1;
        }
 
        /* if there are more bios still pending for this dio, just exit */
@@ -8485,10 +8515,11 @@ submit:
 out_err:
        dip->errors = 1;
        /*
-        * before atomic variable goto zero, we must
-        * make sure dip->errors is perceived to be set.
+        * Before atomic variable goto zero, we must  make sure dip->errors is
+        * perceived to be set. This ordering is ensured by the fact that an
+        * atomic operations with a return value are fully ordered as per
+        * atomic_t.txt
         */
-       smp_mb__before_atomic();
        if (atomic_dec_and_test(&dip->pending_bios))
                bio_io_error(dip->orig_bio);
 
@@ -9104,7 +9135,7 @@ out_noreserve:
        return ret;
 }
 
-static int btrfs_truncate(struct inode *inode)
+static int btrfs_truncate(struct inode *inode, bool skip_writeback)
 {
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -9115,10 +9146,12 @@ static int btrfs_truncate(struct inode *inode)
        u64 mask = fs_info->sectorsize - 1;
        u64 min_size = btrfs_calc_trunc_metadata_size(fs_info, 1);
 
-       ret = btrfs_wait_ordered_range(inode, inode->i_size & (~mask),
-                                      (u64)-1);
-       if (ret)
-               return ret;
+       if (!skip_writeback) {
+               ret = btrfs_wait_ordered_range(inode, inode->i_size & (~mask),
+                                              (u64)-1);
+               if (ret)
+                       return ret;
+       }
 
        /*
         * Yes ladies and gentlemen, this is indeed ugly.  The fact is we have
@@ -9328,7 +9361,6 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        ei->dir_index = 0;
        ei->last_unlink_trans = 0;
        ei->last_log_commit = 0;
-       ei->delayed_iput_count = 0;
 
        spin_lock_init(&ei->lock);
        ei->outstanding_extents = 0;
@@ -9448,7 +9480,7 @@ static void init_once(void *foo)
        inode_init_once(&ei->vfs_inode);
 }
 
-void btrfs_destroy_cachep(void)
+void __cold btrfs_destroy_cachep(void)
 {
        /*
         * Make sure all delayed rcu free inodes are flushed before we