]> git.ipfire.org Git - thirdparty/linux.git/blobdiff - fs/btrfs/inode.c
btrfs: add and use helpers for reading and writing fs_info->generation
[thirdparty/linux.git] / fs / btrfs / inode.c
index 7814b9d654ce1234465bf8ad37a7890e06fd88aa..c9317c047587fe33e2a32c70d6045b3a4a8867f0 100644 (file)
@@ -71,6 +71,7 @@
 #include "super.h"
 #include "orphan.h"
 #include "backref.h"
+#include "raid-stripe-tree.h"
 
 struct btrfs_iget_args {
        u64 ino;
@@ -348,7 +349,7 @@ static void __cold btrfs_print_data_csum_error(struct btrfs_inode *inode,
 }
 
 /*
- * btrfs_inode_lock - lock inode i_rwsem based on arguments passed
+ * Lock inode i_rwsem based on arguments passed.
  *
  * ilock_flags can have the following bit set:
  *
@@ -382,7 +383,7 @@ int btrfs_inode_lock(struct btrfs_inode *inode, unsigned int ilock_flags)
 }
 
 /*
- * btrfs_inode_unlock - unock inode i_rwsem
+ * Unock inode i_rwsem.
  *
  * ilock_flags should contain the same bits set as passed to btrfs_inode_lock()
  * to decide whether the lock acquired is shared or exclusive.
@@ -573,7 +574,7 @@ static int insert_inline_extent(struct btrfs_trans_handle *trans,
                kunmap_local(kaddr);
                put_page(page);
        }
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
        btrfs_release_path(path);
 
        /*
@@ -670,7 +671,7 @@ static noinline int cow_file_range_inline(struct btrfs_inode *inode, u64 size,
        }
 
        btrfs_update_inode_bytes(inode, size, drop_args.bytes_found);
-       ret = btrfs_update_inode(trans, root, inode);
+       ret = btrfs_update_inode(trans, inode);
        if (ret && ret != -ENOSPC) {
                btrfs_abort_transaction(trans, ret);
                goto out;
@@ -1565,8 +1566,11 @@ out_unlock:
  * Phase two of compressed writeback.  This is the ordered portion of the code,
  * which only gets called in the order the work was queued.  We walk all the
  * async extents created by compress_file_range and send them down to the disk.
+ *
+ * If called with @do_free == true then it'll try to finish the work and free
+ * the work struct eventually.
  */
-static noinline void submit_compressed_extents(struct btrfs_work *work)
+static noinline void submit_compressed_extents(struct btrfs_work *work, bool do_free)
 {
        struct async_chunk *async_chunk = container_of(work, struct async_chunk,
                                                     work);
@@ -1575,6 +1579,21 @@ static noinline void submit_compressed_extents(struct btrfs_work *work)
        unsigned long nr_pages;
        u64 alloc_hint = 0;
 
+       if (do_free) {
+               struct async_chunk *async_chunk;
+               struct async_cow *async_cow;
+
+               async_chunk = container_of(work, struct async_chunk, work);
+               btrfs_add_delayed_iput(async_chunk->inode);
+               if (async_chunk->blkcg_css)
+                       css_put(async_chunk->blkcg_css);
+
+               async_cow = async_chunk->async_cow;
+               if (atomic_dec_and_test(&async_cow->num_chunks))
+                       kvfree(async_cow);
+               return;
+       }
+
        nr_pages = (async_chunk->end - async_chunk->start + PAGE_SIZE) >>
                PAGE_SHIFT;
 
@@ -1591,21 +1610,6 @@ static noinline void submit_compressed_extents(struct btrfs_work *work)
                cond_wake_up_nomb(&fs_info->async_submit_wait);
 }
 
-static noinline void async_cow_free(struct btrfs_work *work)
-{
-       struct async_chunk *async_chunk;
-       struct async_cow *async_cow;
-
-       async_chunk = container_of(work, struct async_chunk, work);
-       btrfs_add_delayed_iput(async_chunk->inode);
-       if (async_chunk->blkcg_css)
-               css_put(async_chunk->blkcg_css);
-
-       async_cow = async_chunk->async_cow;
-       if (atomic_dec_and_test(&async_cow->num_chunks))
-               kvfree(async_cow);
-}
-
 static bool run_delalloc_compressed(struct btrfs_inode *inode,
                                    struct page *locked_page, u64 start,
                                    u64 end, struct writeback_control *wbc)
@@ -1683,7 +1687,7 @@ static bool run_delalloc_compressed(struct btrfs_inode *inode,
                }
 
                btrfs_init_work(&async_chunk[i].work, compress_file_range,
-                               submit_compressed_extents, async_cow_free);
+                               submit_compressed_extents);
 
                nr_pages = DIV_ROUND_UP(cur_end - start, PAGE_SIZE);
                atomic_add(nr_pages, &fs_info->async_delalloc_pages);
@@ -2235,8 +2239,7 @@ static bool should_nocow(struct btrfs_inode *inode, u64 start, u64 end)
 {
        if (inode->flags & (BTRFS_INODE_NODATACOW | BTRFS_INODE_PREALLOC)) {
                if (inode->defrag_bytes &&
-                   test_range_bit(&inode->io_tree, start, end, EXTENT_DEFRAG,
-                                  0, NULL))
+                   test_range_bit_exists(&inode->io_tree, start, end, EXTENT_DEFRAG))
                        return false;
                return true;
        }
@@ -2847,7 +2850,7 @@ int btrfs_writepage_cow_fixup(struct page *page)
        ihold(inode);
        btrfs_page_set_checked(fs_info, page, page_offset(page), PAGE_SIZE);
        get_page(page);
-       btrfs_init_work(&fixup->work, btrfs_writepage_fixup_worker, NULL, NULL);
+       btrfs_init_work(&fixup->work, btrfs_writepage_fixup_worker, NULL);
        fixup->page = page;
        fixup->inode = BTRFS_I(inode);
        btrfs_queue_work(fs_info->fixup_workers, &fixup->work);
@@ -2912,7 +2915,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
                        btrfs_item_ptr_offset(leaf, path->slots[0]),
                        sizeof(struct btrfs_file_extent_item));
 
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
        btrfs_release_path(path);
 
        /*
@@ -3070,7 +3073,7 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
                        goto out;
                }
                trans->block_rsv = &inode->block_rsv;
-               ret = btrfs_update_inode_fallback(trans, root, inode);
+               ret = btrfs_update_inode_fallback(trans, inode);
                if (ret) /* -ENOMEM or corruption */
                        btrfs_abort_transaction(trans, ret);
                goto out;
@@ -3091,6 +3094,10 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
 
        trans->block_rsv = &inode->block_rsv;
 
+       ret = btrfs_insert_raid_extent(trans, ordered_extent);
+       if (ret)
+               goto out;
+
        if (test_bit(BTRFS_ORDERED_COMPRESSED, &ordered_extent->flags))
                compress_type = ordered_extent->compress_type;
        if (test_bit(BTRFS_ORDERED_PREALLOC, &ordered_extent->flags)) {
@@ -3136,7 +3143,7 @@ int btrfs_finish_one_ordered(struct btrfs_ordered_extent *ordered_extent)
                                 &cached_state);
 
        btrfs_inode_safe_disk_i_size_write(inode, 0);
-       ret = btrfs_update_inode_fallback(trans, root, inode);
+       ret = btrfs_update_inode_fallback(trans, inode);
        if (ret) { /* -ENOMEM or corruption */
                btrfs_abort_transaction(trans, ret);
                goto out;
@@ -3224,7 +3231,8 @@ out:
 int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered)
 {
        if (btrfs_is_zoned(btrfs_sb(ordered->inode->i_sb)) &&
-           !test_bit(BTRFS_ORDERED_IOERR, &ordered->flags))
+           !test_bit(BTRFS_ORDERED_IOERR, &ordered->flags) &&
+           list_empty(&ordered->bioc_list))
                btrfs_finish_ordered_zoned(ordered);
        return btrfs_finish_one_ordered(ordered);
 }
@@ -3282,7 +3290,7 @@ bool btrfs_data_csum_ok(struct btrfs_bio *bbio, struct btrfs_device *dev,
 
        if (btrfs_is_data_reloc_root(inode->root) &&
            test_range_bit(&inode->io_tree, file_offset, end, EXTENT_NODATASUM,
-                          1, NULL)) {
+                          NULL)) {
                /* Skip the range without csum for data reloc inode */
                clear_extent_bits(&inode->io_tree, file_offset, end,
                                  EXTENT_NODATASUM);
@@ -3306,7 +3314,7 @@ zeroit:
 }
 
 /*
- * btrfs_add_delayed_iput - perform a delayed iput on @inode
+ * Perform a delayed iput on @inode.
  *
  * @inode: The inode we want to perform iput on
  *
@@ -3792,7 +3800,7 @@ cache_index:
         * This is required for both inode re-read from disk and delayed inode
         * in delayed_nodes_tree.
         */
-       if (BTRFS_I(inode)->last_trans == fs_info->generation)
+       if (BTRFS_I(inode)->last_trans == btrfs_get_fs_generation(fs_info))
                set_bit(BTRFS_INODE_NEEDS_FULL_SYNC,
                        &BTRFS_I(inode)->runtime_flags);
 
@@ -3957,8 +3965,7 @@ static void fill_inode_item(struct btrfs_trans_handle *trans,
  * copy everything in the in-memory inode into the btree.
  */
 static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root,
-                               struct btrfs_inode *inode)
+                                           struct btrfs_inode *inode)
 {
        struct btrfs_inode_item *inode_item;
        struct btrfs_path *path;
@@ -3969,7 +3976,7 @@ static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans,
        if (!path)
                return -ENOMEM;
 
-       ret = btrfs_lookup_inode(trans, root, path, &inode->location, 1);
+       ret = btrfs_lookup_inode(trans, inode->root, path, &inode->location, 1);
        if (ret) {
                if (ret > 0)
                        ret = -ENOENT;
@@ -3981,7 +3988,7 @@ static noinline int btrfs_update_inode_item(struct btrfs_trans_handle *trans,
                                    struct btrfs_inode_item);
 
        fill_inode_item(trans, leaf, inode_item, &inode->vfs_inode);
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
        btrfs_set_inode_last_trans(trans, inode);
        ret = 0;
 failed:
@@ -3992,10 +3999,10 @@ failed:
 /*
  * copy everything in the in-memory inode into the btree.
  */
-noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root,
-                               struct btrfs_inode *inode)
+int btrfs_update_inode(struct btrfs_trans_handle *trans,
+                      struct btrfs_inode *inode)
 {
+       struct btrfs_root *root = inode->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
        int ret;
 
@@ -4011,23 +4018,23 @@ noinline int btrfs_update_inode(struct btrfs_trans_handle *trans,
            && !test_bit(BTRFS_FS_LOG_RECOVERING, &fs_info->flags)) {
                btrfs_update_root_times(trans, root);
 
-               ret = btrfs_delayed_update_inode(trans, root, inode);
+               ret = btrfs_delayed_update_inode(trans, inode);
                if (!ret)
                        btrfs_set_inode_last_trans(trans, inode);
                return ret;
        }
 
-       return btrfs_update_inode_item(trans, root, inode);
+       return btrfs_update_inode_item(trans, inode);
 }
 
 int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
-                               struct btrfs_root *root, struct btrfs_inode *inode)
+                               struct btrfs_inode *inode)
 {
        int ret;
 
-       ret = btrfs_update_inode(trans, root, inode);
+       ret = btrfs_update_inode(trans, inode);
        if (ret == -ENOSPC)
-               return btrfs_update_inode_item(trans, root, inode);
+               return btrfs_update_inode_item(trans, inode);
        return ret;
 }
 
@@ -4134,7 +4141,7 @@ err:
        inode_inc_iversion(&dir->vfs_inode);
        inode_set_ctime_current(&inode->vfs_inode);
        dir->vfs_inode.i_mtime = inode_set_ctime_current(&dir->vfs_inode);
-       ret = btrfs_update_inode(trans, root, dir);
+       ret = btrfs_update_inode(trans, dir);
 out:
        return ret;
 }
@@ -4148,7 +4155,7 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
        ret = __btrfs_unlink_inode(trans, dir, inode, name, NULL);
        if (!ret) {
                drop_nlink(&inode->vfs_inode);
-               ret = btrfs_update_inode(trans, inode->root, inode);
+               ret = btrfs_update_inode(trans, inode);
        }
        return ret;
 }
@@ -4307,7 +4314,7 @@ static int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
        btrfs_i_size_write(dir, dir->vfs_inode.i_size - fname.disk_name.len * 2);
        inode_inc_iversion(&dir->vfs_inode);
        dir->vfs_inode.i_mtime = inode_set_ctime_current(&dir->vfs_inode);
-       ret = btrfs_update_inode_fallback(trans, root, dir);
+       ret = btrfs_update_inode_fallback(trans, dir);
        if (ret)
                btrfs_abort_transaction(trans, ret);
 out:
@@ -4641,7 +4648,8 @@ out_notrans:
 }
 
 /*
- * btrfs_truncate_block - read, zero a chunk and write a block
+ * Read, zero a chunk and write a block.
+ *
  * @inode - inode that we're zeroing
  * @from - the offset to start zeroing
  * @len - the length to zero, 0 to zero the entire range respective to the
@@ -4791,9 +4799,9 @@ out:
        return ret;
 }
 
-static int maybe_insert_hole(struct btrfs_root *root, struct btrfs_inode *inode,
-                            u64 offset, u64 len)
+static int maybe_insert_hole(struct btrfs_inode *inode, u64 offset, u64 len)
 {
+       struct btrfs_root *root = inode->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
        struct btrfs_trans_handle *trans;
        struct btrfs_drop_extents_args drop_args = { 0 };
@@ -4833,7 +4841,7 @@ static int maybe_insert_hole(struct btrfs_root *root, struct btrfs_inode *inode,
                btrfs_abort_transaction(trans, ret);
        } else {
                btrfs_update_inode_bytes(inode, 0, drop_args.bytes_found);
-               btrfs_update_inode(trans, root, inode);
+               btrfs_update_inode(trans, inode);
        }
        btrfs_end_transaction(trans);
        return ret;
@@ -4889,8 +4897,7 @@ int btrfs_cont_expand(struct btrfs_inode *inode, loff_t oldsize, loff_t size)
                if (!test_bit(EXTENT_FLAG_PREALLOC, &em->flags)) {
                        struct extent_map *hole_em;
 
-                       err = maybe_insert_hole(root, inode, cur_offset,
-                                               hole_size);
+                       err = maybe_insert_hole(inode, cur_offset, hole_size);
                        if (err)
                                break;
 
@@ -4916,7 +4923,7 @@ int btrfs_cont_expand(struct btrfs_inode *inode, loff_t oldsize, loff_t size)
                        hole_em->orig_block_len = 0;
                        hole_em->ram_bytes = hole_size;
                        hole_em->compress_type = BTRFS_COMPRESS_NONE;
-                       hole_em->generation = fs_info->generation;
+                       hole_em->generation = btrfs_get_fs_generation(fs_info);
 
                        err = btrfs_replace_extent_map_range(inode, hole_em, true);
                        free_extent_map(hole_em);
@@ -4984,7 +4991,7 @@ static int btrfs_setsize(struct inode *inode, struct iattr *attr)
                i_size_write(inode, newsize);
                btrfs_inode_safe_disk_i_size_write(BTRFS_I(inode), 0);
                pagecache_isize_extended(inode, oldsize, newsize);
-               ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
+               ret = btrfs_update_inode(trans, BTRFS_I(inode));
                btrfs_drew_write_unlock(&root->snapshot_lock);
                btrfs_end_transaction(trans);
        } else {
@@ -6000,15 +6007,15 @@ static int btrfs_dirty_inode(struct btrfs_inode *inode)
        if (IS_ERR(trans))
                return PTR_ERR(trans);
 
-       ret = btrfs_update_inode(trans, root, inode);
-       if (ret && (ret == -ENOSPC || ret == -EDQUOT)) {
+       ret = btrfs_update_inode(trans, inode);
+       if (ret == -ENOSPC || ret == -EDQUOT) {
                /* whoops, lets try again with the full transaction */
                btrfs_end_transaction(trans);
                trans = btrfs_start_transaction(root, 1);
                if (IS_ERR(trans))
                        return PTR_ERR(trans);
 
-               ret = btrfs_update_inode(trans, root, inode);
+               ret = btrfs_update_inode(trans, inode);
        }
        btrfs_end_transaction(trans);
        if (inode->delayed_node)
@@ -6310,7 +6317,7 @@ int btrfs_create_new_inode(struct btrfs_trans_handle *trans,
                }
        }
 
-       btrfs_mark_buffer_dirty(path->nodes[0]);
+       btrfs_mark_buffer_dirty(trans, path->nodes[0]);
        /*
         * We don't need the path anymore, plus inheriting properties, adding
         * ACLs, security xattrs, orphan item or adding the link, will result in
@@ -6447,7 +6454,7 @@ int btrfs_add_link(struct btrfs_trans_handle *trans,
                parent_inode->vfs_inode.i_mtime =
                        inode_set_ctime_current(&parent_inode->vfs_inode);
 
-       ret = btrfs_update_inode(trans, root, parent_inode);
+       ret = btrfs_update_inode(trans, parent_inode);
        if (ret)
                btrfs_abort_transaction(trans, ret);
        return ret;
@@ -6598,7 +6605,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
        } else {
                struct dentry *parent = dentry->d_parent;
 
-               err = btrfs_update_inode(trans, root, BTRFS_I(inode));
+               err = btrfs_update_inode(trans, BTRFS_I(inode));
                if (err)
                        goto fail;
                if (inode->i_nlink == 1) {
@@ -7103,8 +7110,7 @@ noinline int can_nocow_extent(struct inode *inode, u64 offset, u64 *len,
 
                range_end = round_up(offset + nocow_args.num_bytes,
                                     root->fs_info->sectorsize) - 1;
-               ret = test_range_bit(io_tree, offset, range_end,
-                                    EXTENT_DELALLOC, 0, NULL);
+               ret = test_range_bit_exists(io_tree, offset, range_end, EXTENT_DELALLOC);
                if (ret) {
                        ret = -EAGAIN;
                        goto out;
@@ -8005,11 +8011,11 @@ static void btrfs_invalidate_folio(struct folio *folio, size_t offset,
                                         EXTENT_LOCKED | EXTENT_DO_ACCOUNTING |
                                         EXTENT_DEFRAG, &cached_state);
 
-               spin_lock_irq(&inode->ordered_tree.lock);
+               spin_lock_irq(&inode->ordered_tree_lock);
                set_bit(BTRFS_ORDERED_TRUNCATED, &ordered->flags);
                ordered->truncated_len = min(ordered->truncated_len,
                                             cur - ordered->file_offset);
-               spin_unlock_irq(&inode->ordered_tree.lock);
+               spin_unlock_irq(&inode->ordered_tree_lock);
 
                /*
                 * If the ordered extent has finished, we're safe to delete all
@@ -8339,7 +8345,7 @@ static int btrfs_truncate(struct btrfs_inode *inode, bool skip_writeback)
                if (ret != -ENOSPC && ret != -EAGAIN)
                        break;
 
-               ret = btrfs_update_inode(trans, root, inode);
+               ret = btrfs_update_inode(trans, inode);
                if (ret)
                        break;
 
@@ -8392,7 +8398,7 @@ static int btrfs_truncate(struct btrfs_inode *inode, bool skip_writeback)
                int ret2;
 
                trans->block_rsv = &fs_info->trans_block_rsv;
-               ret2 = btrfs_update_inode(trans, root, inode);
+               ret2 = btrfs_update_inode(trans, inode);
                if (ret2 && !ret)
                        ret = ret2;
 
@@ -8491,7 +8497,9 @@ struct inode *btrfs_alloc_inode(struct super_block *sb)
        extent_io_tree_init(fs_info, &ei->file_extent_tree,
                            IO_TREE_INODE_FILE_EXTENT);
        mutex_init(&ei->log_mutex);
-       btrfs_ordered_inode_tree_init(&ei->ordered_tree);
+       spin_lock_init(&ei->ordered_tree_lock);
+       ei->ordered_tree = RB_ROOT;
+       ei->ordered_tree_last = NULL;
        INIT_LIST_HEAD(&ei->delalloc_inodes);
        INIT_LIST_HEAD(&ei->delayed_iput);
        RB_CLEAR_NODE(&ei->rb_node);
@@ -8823,7 +8831,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
                                           BTRFS_I(old_dentry->d_inode),
                                           old_name, &old_rename_ctx);
                if (!ret)
-                       ret = btrfs_update_inode(trans, root, BTRFS_I(old_inode));
+                       ret = btrfs_update_inode(trans, BTRFS_I(old_inode));
        }
        if (ret) {
                btrfs_abort_transaction(trans, ret);
@@ -8838,7 +8846,7 @@ static int btrfs_rename_exchange(struct inode *old_dir,
                                           BTRFS_I(new_dentry->d_inode),
                                           new_name, &new_rename_ctx);
                if (!ret)
-                       ret = btrfs_update_inode(trans, dest, BTRFS_I(new_inode));
+                       ret = btrfs_update_inode(trans, BTRFS_I(new_inode));
        }
        if (ret) {
                btrfs_abort_transaction(trans, ret);
@@ -9083,7 +9091,7 @@ static int btrfs_rename(struct mnt_idmap *idmap,
                                           BTRFS_I(d_inode(old_dentry)),
                                           &old_fname.disk_name, &rename_ctx);
                if (!ret)
-                       ret = btrfs_update_inode(trans, root, BTRFS_I(old_inode));
+                       ret = btrfs_update_inode(trans, BTRFS_I(old_inode));
        }
        if (ret) {
                btrfs_abort_transaction(trans, ret);
@@ -9208,7 +9216,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_run_delalloc_work, NULL, NULL);
+       btrfs_init_work(&work->work, btrfs_run_delalloc_work, NULL);
 
        return work;
 }
@@ -9446,7 +9454,7 @@ static int btrfs_symlink(struct mnt_idmap *idmap, struct inode *dir,
 
        ptr = btrfs_file_extent_inline_start(ei);
        write_extent_buffer(leaf, symname, ptr, name_len);
-       btrfs_mark_buffer_dirty(leaf);
+       btrfs_mark_buffer_dirty(trans, leaf);
        btrfs_free_path(path);
 
        d_instantiate_new(dentry, inode);
@@ -9639,7 +9647,7 @@ next:
                        btrfs_inode_safe_disk_i_size_write(BTRFS_I(inode), 0);
                }
 
-               ret = btrfs_update_inode(trans, root, BTRFS_I(inode));
+               ret = btrfs_update_inode(trans, BTRFS_I(inode));
 
                if (ret) {
                        btrfs_abort_transaction(trans, ret);