]> asedeno.scripts.mit.edu Git - linux.git/blobdiff - fs/btrfs/inode.c
btrfs: drop unused parameter is_new from btrfs_iget
[linux.git] / fs / btrfs / inode.c
index c3f386b7cc0bd4d1b38fab14b56d1eec3c576d94..2ef5f542f58a93db12d00abae714ee85cc47301d 100644 (file)
@@ -474,6 +474,7 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
        u64 start = async_chunk->start;
        u64 end = async_chunk->end;
        u64 actual_end;
+       u64 i_size;
        int ret = 0;
        struct page **pages = NULL;
        unsigned long nr_pages;
@@ -488,7 +489,19 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
        inode_should_defrag(BTRFS_I(inode), start, end, end - start + 1,
                        SZ_16K);
 
-       actual_end = min_t(u64, i_size_read(inode), end + 1);
+       /*
+        * We need to save i_size before now because it could change in between
+        * us evaluating the size and assigning it.  This is because we lock and
+        * unlock the page in truncate and fallocate, and then modify the i_size
+        * later on.
+        *
+        * The barriers are to emulate READ_ONCE, remove that once i_size_read
+        * does that for us.
+        */
+       barrier();
+       i_size = i_size_read(inode);
+       barrier();
+       actual_end = min_t(u64, i_size, end + 1);
 again:
        will_compress = 0;
        nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
@@ -1255,10 +1268,8 @@ static int cow_file_range_async(struct inode *inode, struct page *locked_page,
                async_chunk[i].write_flags = write_flags;
                INIT_LIST_HEAD(&async_chunk[i].extents);
 
-               btrfs_init_work(&async_chunk[i].work,
-                               btrfs_delalloc_helper,
-                               async_cow_start, async_cow_submit,
-                               async_cow_free);
+               btrfs_init_work(&async_chunk[i].work, async_cow_start,
+                               async_cow_submit, async_cow_free);
 
                nr_pages = DIV_ROUND_UP(cur_end - start, PAGE_SIZE);
                atomic_add(nr_pages, &fs_info->async_delalloc_pages);
@@ -2247,8 +2258,7 @@ int btrfs_writepage_cow_fixup(struct page *page, u64 start, u64 end)
 
        SetPageChecked(page);
        get_page(page);
-       btrfs_init_work(&fixup->work, btrfs_fixup_helper,
-                       btrfs_writepage_fixup_worker, NULL, NULL);
+       btrfs_init_work(&fixup->work, btrfs_writepage_fixup_worker, NULL, NULL);
        fixup->page = page;
        btrfs_queue_work(fs_info->fixup_workers, &fixup->work);
        return -EBUSY;
@@ -2662,7 +2672,7 @@ static noinline int relink_extent_backref(struct btrfs_path *path,
        key.type = BTRFS_INODE_ITEM_KEY;
        key.offset = 0;
 
-       inode = btrfs_iget(fs_info->sb, &key, root, NULL);
+       inode = btrfs_iget(fs_info->sb, &key, root);
        if (IS_ERR(inode)) {
                srcu_read_unlock(&fs_info->subvol_srcu, index);
                return 0;
@@ -3241,7 +3251,6 @@ void btrfs_writepage_endio_finish_ordered(struct page *page, u64 start,
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_ordered_extent *ordered_extent = NULL;
        struct btrfs_workqueue *wq;
-       btrfs_work_func_t func;
 
        trace_btrfs_writepage_end_io_hook(page, start, end, uptodate);
 
@@ -3250,16 +3259,12 @@ void btrfs_writepage_endio_finish_ordered(struct page *page, u64 start,
                                            end - start + 1, uptodate))
                return;
 
-       if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
+       if (btrfs_is_free_space_inode(BTRFS_I(inode)))
                wq = fs_info->endio_freespace_worker;
-               func = btrfs_freespace_write_helper;
-       } else {
+       else
                wq = fs_info->endio_write_workers;
-               func = btrfs_endio_write_helper;
-       }
 
-       btrfs_init_work(&ordered_extent->work, func, finish_ordered_fn, NULL,
-                       NULL);
+       btrfs_init_work(&ordered_extent->work, finish_ordered_fn, NULL, NULL);
        btrfs_queue_work(wq, &ordered_extent->work);
 }
 
@@ -3518,7 +3523,7 @@ int btrfs_orphan_cleanup(struct btrfs_root *root)
                found_key.objectid = found_key.offset;
                found_key.type = BTRFS_INODE_ITEM_KEY;
                found_key.offset = 0;
-               inode = btrfs_iget(fs_info->sb, &found_key, root, NULL);
+               inode = btrfs_iget(fs_info->sb, &found_key, root);
                ret = PTR_ERR_OR_ZERO(inode);
                if (ret && ret != -ENOENT)
                        goto out;
@@ -5737,12 +5742,14 @@ static struct inode *btrfs_iget_locked(struct super_block *s,
        return inode;
 }
 
-/* Get an inode object given its location and corresponding root.
- * Returns in *is_new if the inode was read from disk
+/*
+ * Get an inode object given its location and corresponding root.
+ * Path can be preallocated to prevent recursing back to iget through
+ * allocator. NULL is also valid but may require an additional allocation
+ * later.
  */
 struct inode *btrfs_iget_path(struct super_block *s, struct btrfs_key *location,
-                             struct btrfs_root *root, int *new,
-                             struct btrfs_path *path)
+                             struct btrfs_root *root, struct btrfs_path *path)
 {
        struct inode *inode;
 
@@ -5757,8 +5764,6 @@ struct inode *btrfs_iget_path(struct super_block *s, struct btrfs_key *location,
                if (!ret) {
                        inode_tree_add(inode);
                        unlock_new_inode(inode);
-                       if (new)
-                               *new = 1;
                } else {
                        iget_failed(inode);
                        /*
@@ -5776,9 +5781,9 @@ struct inode *btrfs_iget_path(struct super_block *s, struct btrfs_key *location,
 }
 
 struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location,
-                        struct btrfs_root *root, int *new)
+                        struct btrfs_root *root)
 {
-       return btrfs_iget_path(s, location, root, new, NULL);
+       return btrfs_iget_path(s, location, root, NULL);
 }
 
 static struct inode *new_simple_dir(struct super_block *s,
@@ -5844,7 +5849,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
                return ERR_PTR(ret);
 
        if (location.type == BTRFS_INODE_ITEM_KEY) {
-               inode = btrfs_iget(dir->i_sb, &location, root, NULL);
+               inode = btrfs_iget(dir->i_sb, &location, root);
                if (IS_ERR(inode))
                        return inode;
 
@@ -5869,7 +5874,7 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
                else
                        inode = new_simple_dir(dir->i_sb, &location, sub_root);
        } else {
-               inode = btrfs_iget(dir->i_sb, &location, sub_root, NULL);
+               inode = btrfs_iget(dir->i_sb, &location, sub_root);
        }
        srcu_read_unlock(&fs_info->subvol_srcu, index);
 
@@ -8198,18 +8203,14 @@ static void __endio_write_update_ordered(struct inode *inode,
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct btrfs_ordered_extent *ordered = NULL;
        struct btrfs_workqueue *wq;
-       btrfs_work_func_t func;
        u64 ordered_offset = offset;
        u64 ordered_bytes = bytes;
        u64 last_offset;
 
-       if (btrfs_is_free_space_inode(BTRFS_I(inode))) {
+       if (btrfs_is_free_space_inode(BTRFS_I(inode)))
                wq = fs_info->endio_freespace_worker;
-               func = btrfs_freespace_write_helper;
-       } else {
+       else
                wq = fs_info->endio_write_workers;
-               func = btrfs_endio_write_helper;
-       }
 
        while (ordered_offset < offset + bytes) {
                last_offset = ordered_offset;
@@ -8217,9 +8218,8 @@ static void __endio_write_update_ordered(struct inode *inode,
                                                           &ordered_offset,
                                                           ordered_bytes,
                                                           uptodate)) {
-                       btrfs_init_work(&ordered->work, func,
-                                       finish_ordered_fn,
-                                       NULL, NULL);
+                       btrfs_init_work(&ordered->work, finish_ordered_fn, NULL,
+                                       NULL);
                        btrfs_queue_work(wq, &ordered->work);
                }
                /*
@@ -9731,6 +9731,18 @@ static int btrfs_rename_exchange(struct inode *old_dir,
                        commit_transaction = true;
        }
        if (commit_transaction) {
+               /*
+                * We may have set commit_transaction when logging the new name
+                * in the destination root, in which case we left the source
+                * root context in the list of log contextes. So make sure we
+                * remove it to avoid invalid memory accesses, since the context
+                * was allocated in our stack frame.
+                */
+               if (sync_log_root) {
+                       mutex_lock(&root->log_mutex);
+                       list_del_init(&ctx_root.list);
+                       mutex_unlock(&root->log_mutex);
+               }
                ret = btrfs_commit_transaction(trans);
        } else {
                int ret2;
@@ -9744,6 +9756,9 @@ static int btrfs_rename_exchange(struct inode *old_dir,
        if (old_ino == BTRFS_FIRST_FREE_OBJECTID)
                up_read(&fs_info->subvol_sem);
 
+       ASSERT(list_empty(&ctx_root.list));
+       ASSERT(list_empty(&ctx_dest.list));
+
        return ret;
 }
 
@@ -10088,8 +10103,7 @@ static struct btrfs_delalloc_work *btrfs_alloc_delalloc_work(struct inode *inode
        init_completion(&work->completion);
        INIT_LIST_HEAD(&work->list);
        work->inode = inode;
-       btrfs_init_work(&work->work, btrfs_flush_delalloc_helper,
-                       btrfs_run_delalloc_work, NULL, NULL);
+       btrfs_init_work(&work->work, btrfs_run_delalloc_work, NULL, NULL);
 
        return work;
 }