btrfs: add ram_bytes and offset to btrfs_ordered_extent
[platform/kernel/linux-starfive.git] / fs / btrfs / inode.c
index 76e530f..5f77554 100644 (file)
@@ -66,6 +66,11 @@ struct btrfs_dio_data {
        struct extent_changeset *data_reserved;
 };
 
+struct btrfs_rename_ctx {
+       /* Output field. Stores the index number of the old directory entry. */
+       u64 index;
+};
+
 static const struct inode_operations btrfs_dir_inode_operations;
 static const struct inode_operations btrfs_symlink_inode_operations;
 static const struct inode_operations btrfs_special_inode_operations;
@@ -624,7 +629,6 @@ static noinline int compress_file_range(struct async_chunk *async_chunk)
 again:
        will_compress = 0;
        nr_pages = (end >> PAGE_SHIFT) - (start >> PAGE_SHIFT) + 1;
-       BUILD_BUG_ON((BTRFS_MAX_COMPRESSED % PAGE_SIZE) != 0);
        nr_pages = min_t(unsigned long, nr_pages,
                        BTRFS_MAX_COMPRESSED / PAGE_SIZE);
 
@@ -981,11 +985,14 @@ static int submit_one_async_extent(struct btrfs_inode *inode,
        }
        free_extent_map(em);
 
-       ret = btrfs_add_ordered_extent_compress(inode, start,   /* file_offset */
-                                       ins.objectid,           /* disk_bytenr */
-                                       async_extent->ram_size, /* num_bytes */
-                                       ins.offset,             /* disk_num_bytes */
-                                       async_extent->compress_type);
+       ret = btrfs_add_ordered_extent(inode, start,            /* file_offset */
+                                      async_extent->ram_size,  /* num_bytes */
+                                      async_extent->ram_size,  /* ram_bytes */
+                                      ins.objectid,            /* disk_bytenr */
+                                      ins.offset,              /* disk_num_bytes */
+                                      0,                       /* offset */
+                                      1 << BTRFS_ORDERED_COMPRESSED,
+                                      async_extent->compress_type);
        if (ret) {
                btrfs_drop_extent_cache(inode, start, end, 0);
                goto out_free_reserve;
@@ -1234,9 +1241,10 @@ static noinline int cow_file_range(struct btrfs_inode *inode,
                }
                free_extent_map(em);
 
-               ret = btrfs_add_ordered_extent(inode, start, ins.objectid,
-                                              ram_size, cur_alloc_size,
-                                              BTRFS_ORDERED_REGULAR);
+               ret = btrfs_add_ordered_extent(inode, start, ram_size, ram_size,
+                                              ins.objectid, cur_alloc_size, 0,
+                                              1 << BTRFS_ORDERED_REGULAR,
+                                              BTRFS_COMPRESS_NONE);
                if (ret)
                        goto out_drop_extent_cache;
 
@@ -1895,10 +1903,11 @@ out_check:
                                goto error;
                        }
                        free_extent_map(em);
-                       ret = btrfs_add_ordered_extent(inode, cur_offset,
-                                                      disk_bytenr, num_bytes,
-                                                      num_bytes,
-                                                      BTRFS_ORDERED_PREALLOC);
+                       ret = btrfs_add_ordered_extent(inode,
+                                       cur_offset, num_bytes, num_bytes,
+                                       disk_bytenr, num_bytes, 0,
+                                       1 << BTRFS_ORDERED_PREALLOC,
+                                       BTRFS_COMPRESS_NONE);
                        if (ret) {
                                btrfs_drop_extent_cache(inode, cur_offset,
                                                        cur_offset + num_bytes - 1,
@@ -1907,9 +1916,11 @@ out_check:
                        }
                } else {
                        ret = btrfs_add_ordered_extent(inode, cur_offset,
+                                                      num_bytes, num_bytes,
                                                       disk_bytenr, num_bytes,
-                                                      num_bytes,
-                                                      BTRFS_ORDERED_NOCOW);
+                                                      0,
+                                                      1 << BTRFS_ORDERED_NOCOW,
+                                                      BTRFS_COMPRESS_NONE);
                        if (ret)
                                goto error;
                }
@@ -2310,7 +2321,7 @@ void btrfs_clear_delalloc_extent(struct inode *vfs_inode,
 static blk_status_t btrfs_submit_bio_start(struct inode *inode, struct bio *bio,
                                           u64 dio_file_offset)
 {
-       return btrfs_csum_one_bio(BTRFS_I(inode), bio, 0, 0);
+       return btrfs_csum_one_bio(BTRFS_I(inode), bio, (u64)-1, false);
 }
 
 /*
@@ -2562,7 +2573,7 @@ blk_status_t btrfs_submit_data_bio(struct inode *inode, struct bio *bio,
                                          0, btrfs_submit_bio_start);
                goto out;
        } else if (!skip_sum) {
-               ret = btrfs_csum_one_bio(BTRFS_I(inode), bio, 0, 0);
+               ret = btrfs_csum_one_bio(BTRFS_I(inode), bio, (u64)-1, false);
                if (ret)
                        goto out;
        }
@@ -2870,6 +2881,7 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
        struct btrfs_key ins;
        u64 disk_num_bytes = btrfs_stack_file_extent_disk_num_bytes(stack_fi);
        u64 disk_bytenr = btrfs_stack_file_extent_disk_bytenr(stack_fi);
+       u64 offset = btrfs_stack_file_extent_offset(stack_fi);
        u64 num_bytes = btrfs_stack_file_extent_num_bytes(stack_fi);
        u64 ram_bytes = btrfs_stack_file_extent_ram_bytes(stack_fi);
        struct btrfs_drop_extents_args drop_args = { 0 };
@@ -2944,7 +2956,8 @@ static int insert_reserved_file_extent(struct btrfs_trans_handle *trans,
                goto out;
 
        ret = btrfs_alloc_reserved_file_extent(trans, root, btrfs_ino(inode),
-                                              file_pos, qgroup_reserved, &ins);
+                                              file_pos - offset,
+                                              qgroup_reserved, &ins);
 out:
        btrfs_free_path(path);
 
@@ -2970,20 +2983,20 @@ static int insert_ordered_extent_file_extent(struct btrfs_trans_handle *trans,
                                             struct btrfs_ordered_extent *oe)
 {
        struct btrfs_file_extent_item stack_fi;
-       u64 logical_len;
        bool update_inode_bytes;
+       u64 num_bytes = oe->num_bytes;
+       u64 ram_bytes = oe->ram_bytes;
 
        memset(&stack_fi, 0, sizeof(stack_fi));
        btrfs_set_stack_file_extent_type(&stack_fi, BTRFS_FILE_EXTENT_REG);
        btrfs_set_stack_file_extent_disk_bytenr(&stack_fi, oe->disk_bytenr);
        btrfs_set_stack_file_extent_disk_num_bytes(&stack_fi,
                                                   oe->disk_num_bytes);
+       btrfs_set_stack_file_extent_offset(&stack_fi, oe->offset);
        if (test_bit(BTRFS_ORDERED_TRUNCATED, &oe->flags))
-               logical_len = oe->truncated_len;
-       else
-               logical_len = oe->num_bytes;
-       btrfs_set_stack_file_extent_num_bytes(&stack_fi, logical_len);
-       btrfs_set_stack_file_extent_ram_bytes(&stack_fi, logical_len);
+               num_bytes = ram_bytes = oe->truncated_len;
+       btrfs_set_stack_file_extent_num_bytes(&stack_fi, num_bytes);
+       btrfs_set_stack_file_extent_ram_bytes(&stack_fi, ram_bytes);
        btrfs_set_stack_file_extent_compression(&stack_fi, oe->compress_type);
        /* Encryption and other encoding is reserved and all 0 */
 
@@ -4062,7 +4075,8 @@ int btrfs_update_inode_fallback(struct btrfs_trans_handle *trans,
 static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
                                struct btrfs_inode *dir,
                                struct btrfs_inode *inode,
-                               const char *name, int name_len)
+                               const char *name, int name_len,
+                               struct btrfs_rename_ctx *rename_ctx)
 {
        struct btrfs_root *root = dir->root;
        struct btrfs_fs_info *fs_info = root->fs_info;
@@ -4118,15 +4132,27 @@ static int __btrfs_unlink_inode(struct btrfs_trans_handle *trans,
                goto err;
        }
 skip_backref:
+       if (rename_ctx)
+               rename_ctx->index = index;
+
        ret = btrfs_delete_delayed_dir_index(trans, dir, index);
        if (ret) {
                btrfs_abort_transaction(trans, ret);
                goto err;
        }
 
-       btrfs_del_inode_ref_in_log(trans, root, name, name_len, inode,
-                                  dir_ino);
-       btrfs_del_dir_entries_in_log(trans, root, name, name_len, dir, index);
+       /*
+        * If we are in a rename context, we don't need to update anything in the
+        * log. That will be done later during the rename by btrfs_log_new_name().
+        * Besides that, doing it here would only cause extra unncessary btree
+        * operations on the log tree, increasing latency for applications.
+        */
+       if (!rename_ctx) {
+               btrfs_del_inode_ref_in_log(trans, root, name, name_len, inode,
+                                          dir_ino);
+               btrfs_del_dir_entries_in_log(trans, root, name, name_len, dir,
+                                            index);
+       }
 
        /*
         * If we have a pending delayed iput we could end up with the final iput
@@ -4158,7 +4184,7 @@ int btrfs_unlink_inode(struct btrfs_trans_handle *trans,
                       const char *name, int name_len)
 {
        int ret;
-       ret = __btrfs_unlink_inode(trans, dir, inode, name, name_len);
+       ret = __btrfs_unlink_inode(trans, dir, inode, name, name_len, NULL);
        if (!ret) {
                drop_nlink(&inode->vfs_inode);
                ret = btrfs_update_inode(trans, inode->root, inode);
@@ -4565,14 +4591,21 @@ out_up_write:
 static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
 {
        struct inode *inode = d_inode(dentry);
+       struct btrfs_fs_info *fs_info = BTRFS_I(inode)->root->fs_info;
        int err = 0;
        struct btrfs_trans_handle *trans;
        u64 last_unlink_trans;
 
        if (inode->i_size > BTRFS_EMPTY_DIR_SIZE)
                return -ENOTEMPTY;
-       if (btrfs_ino(BTRFS_I(inode)) == BTRFS_FIRST_FREE_OBJECTID)
+       if (btrfs_ino(BTRFS_I(inode)) == BTRFS_FIRST_FREE_OBJECTID) {
+               if (unlikely(btrfs_fs_incompat(fs_info, EXTENT_TREE_V2))) {
+                       btrfs_err(fs_info,
+                       "extent tree v2 doesn't support snapshot deletion yet");
+                       return -EOPNOTSUPP;
+               }
                return btrfs_delete_subvolume(dir, dentry);
+       }
 
        trans = __unlink_start_trans(dir);
        if (IS_ERR(trans))
@@ -4611,7 +4644,7 @@ static int btrfs_rmdir(struct inode *dir, struct dentry *dentry)
        }
 out:
        btrfs_end_transaction(trans);
-       btrfs_btree_balance_dirty(BTRFS_I(dir)->root->fs_info);
+       btrfs_btree_balance_dirty(fs_info);
 
        return err;
 }
@@ -5584,21 +5617,17 @@ static struct inode *new_simple_dir(struct super_block *s,
        return inode;
 }
 
+static_assert(BTRFS_FT_UNKNOWN == FT_UNKNOWN);
+static_assert(BTRFS_FT_REG_FILE == FT_REG_FILE);
+static_assert(BTRFS_FT_DIR == FT_DIR);
+static_assert(BTRFS_FT_CHRDEV == FT_CHRDEV);
+static_assert(BTRFS_FT_BLKDEV == FT_BLKDEV);
+static_assert(BTRFS_FT_FIFO == FT_FIFO);
+static_assert(BTRFS_FT_SOCK == FT_SOCK);
+static_assert(BTRFS_FT_SYMLINK == FT_SYMLINK);
+
 static inline u8 btrfs_inode_type(struct inode *inode)
 {
-       /*
-        * Compile-time asserts that generic FT_* types still match
-        * BTRFS_FT_* types
-        */
-       BUILD_BUG_ON(BTRFS_FT_UNKNOWN != FT_UNKNOWN);
-       BUILD_BUG_ON(BTRFS_FT_REG_FILE != FT_REG_FILE);
-       BUILD_BUG_ON(BTRFS_FT_DIR != FT_DIR);
-       BUILD_BUG_ON(BTRFS_FT_CHRDEV != FT_CHRDEV);
-       BUILD_BUG_ON(BTRFS_FT_BLKDEV != FT_BLKDEV);
-       BUILD_BUG_ON(BTRFS_FT_FIFO != FT_FIFO);
-       BUILD_BUG_ON(BTRFS_FT_SOCK != FT_SOCK);
-       BUILD_BUG_ON(BTRFS_FT_SYMLINK != FT_SYMLINK);
-
        return fs_umode_to_ftype(inode->i_mode);
 }
 
@@ -5971,14 +6000,8 @@ static int btrfs_set_inode_index_count(struct btrfs_inode *inode)
                goto out;
        ret = 0;
 
-       /*
-        * MAGIC NUMBER EXPLANATION:
-        * since we search a directory based on f_pos we have to start at 2
-        * since '.' and '..' have f_pos of 0 and 1 respectively, so everybody
-        * else has to start at 2
-        */
        if (path->slots[0] == 0) {
-               inode->index_cnt = 2;
+               inode->index_cnt = BTRFS_DIR_START_INDEX;
                goto out;
        }
 
@@ -5989,7 +6012,7 @@ static int btrfs_set_inode_index_count(struct btrfs_inode *inode)
 
        if (found_key.objectid != btrfs_ino(inode) ||
            found_key.type != BTRFS_DIR_INDEX_KEY) {
-               inode->index_cnt = 2;
+               inode->index_cnt = BTRFS_DIR_START_INDEX;
                goto out;
        }
 
@@ -6537,7 +6560,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir,
                                goto fail;
                }
                d_instantiate(dentry, inode);
-               btrfs_log_new_name(trans, BTRFS_I(inode), NULL, parent);
+               btrfs_log_new_name(trans, old_dentry, NULL, 0, parent);
        }
 
 fail:
@@ -7040,8 +7063,11 @@ static struct extent_map *btrfs_create_dio_extent(struct btrfs_inode *inode,
                if (IS_ERR(em))
                        goto out;
        }
-       ret = btrfs_add_ordered_extent_dio(inode, start, block_start, len,
-                                          block_len, type);
+       ret = btrfs_add_ordered_extent(inode, start, len, len, block_start,
+                                      block_len, 0,
+                                      (1 << type) |
+                                      (1 << BTRFS_ORDERED_DIRECT),
+                                      BTRFS_COMPRESS_NONE);
        if (ret) {
                if (em) {
                        free_extent_map(em);
@@ -7600,6 +7626,34 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
        }
 
        len = min(len, em->len - (start - em->start));
+
+       /*
+        * If we have a NOWAIT request and the range contains multiple extents
+        * (or a mix of extents and holes), then we return -EAGAIN to make the
+        * caller fallback to a context where it can do a blocking (without
+        * NOWAIT) request. This way we avoid doing partial IO and returning
+        * success to the caller, which is not optimal for writes and for reads
+        * it can result in unexpected behaviour for an application.
+        *
+        * When doing a read, because we use IOMAP_DIO_PARTIAL when calling
+        * iomap_dio_rw(), we can end up returning less data then what the caller
+        * asked for, resulting in an unexpected, and incorrect, short read.
+        * That is, the caller asked to read N bytes and we return less than that,
+        * which is wrong unless we are crossing EOF. This happens if we get a
+        * page fault error when trying to fault in pages for the buffer that is
+        * associated to the struct iov_iter passed to iomap_dio_rw(), and we
+        * have previously submitted bios for other extents in the range, in
+        * which case iomap_dio_rw() may return us EIOCBQUEUED if not all of
+        * those bios have completed by the time we get the page fault error,
+        * which we return back to our caller - we should only return EIOCBQUEUED
+        * after we have submitted bios for all the extents in the range.
+        */
+       if ((flags & IOMAP_NOWAIT) && len < length) {
+               free_extent_map(em);
+               ret = -EAGAIN;
+               goto unlock_err;
+       }
+
        if (write) {
                ret = btrfs_get_blocks_direct_write(&em, inode, dio_data,
                                                    start, len);
@@ -7803,7 +7857,7 @@ static blk_status_t btrfs_submit_bio_start_direct_io(struct inode *inode,
                                                     struct bio *bio,
                                                     u64 dio_file_offset)
 {
-       return btrfs_csum_one_bio(BTRFS_I(inode), bio, dio_file_offset, 1);
+       return btrfs_csum_one_bio(BTRFS_I(inode), bio, dio_file_offset, false);
 }
 
 static void btrfs_end_dio_bio(struct bio *bio)
@@ -7860,7 +7914,7 @@ static inline blk_status_t btrfs_submit_dio_bio(struct bio *bio,
                 * If we aren't doing async submit, calculate the csum of the
                 * bio now.
                 */
-               ret = btrfs_csum_one_bio(BTRFS_I(inode), bio, file_offset, 1);
+               ret = btrfs_csum_one_bio(BTRFS_I(inode), bio, file_offset, false);
                if (ret)
                        goto err;
        } else {
@@ -8076,8 +8130,13 @@ int btrfs_readpage(struct file *file, struct page *page)
        btrfs_lock_and_flush_ordered_range(inode, start, end, NULL);
 
        ret = btrfs_do_readpage(page, NULL, &bio_ctrl, 0, NULL);
-       if (bio_ctrl.bio)
-               ret = submit_one_bio(bio_ctrl.bio, 0, bio_ctrl.bio_flags);
+       if (bio_ctrl.bio) {
+               int ret2;
+
+               ret2 = submit_one_bio(bio_ctrl.bio, 0, bio_ctrl.bio_flags);
+               if (ret == 0)
+                       ret = ret2;
+       }
        return ret;
 }
 
@@ -9002,14 +9061,14 @@ static int btrfs_rename_exchange(struct inode *old_dir,
        struct inode *new_inode = new_dentry->d_inode;
        struct inode *old_inode = old_dentry->d_inode;
        struct timespec64 ctime = current_time(old_inode);
+       struct btrfs_rename_ctx old_rename_ctx;
+       struct btrfs_rename_ctx new_rename_ctx;
        u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
        u64 new_ino = btrfs_ino(BTRFS_I(new_inode));
        u64 old_idx = 0;
        u64 new_idx = 0;
        int ret;
        int ret2;
-       bool root_log_pinned = false;
-       bool dest_log_pinned = false;
        bool need_abort = false;
 
        /*
@@ -9112,29 +9171,6 @@ static int btrfs_rename_exchange(struct inode *old_dir,
                                BTRFS_I(new_inode), 1);
        }
 
-       /*
-        * Now pin the logs of the roots. We do it to ensure that no other task
-        * can sync the logs while we are in progress with the rename, because
-        * that could result in an inconsistency in case any of the inodes that
-        * are part of this rename operation were logged before.
-        *
-        * We pin the logs even if at this precise moment none of the inodes was
-        * logged before. This is because right after we checked for that, some
-        * other task fsyncing some other inode not involved with this rename
-        * operation could log that one of our inodes exists.
-        *
-        * We don't need to pin the logs before the above calls to
-        * btrfs_insert_inode_ref(), since those don't ever need to change a log.
-        */
-       if (old_ino != BTRFS_FIRST_FREE_OBJECTID) {
-               btrfs_pin_log_trans(root);
-               root_log_pinned = true;
-       }
-       if (new_ino != BTRFS_FIRST_FREE_OBJECTID) {
-               btrfs_pin_log_trans(dest);
-               dest_log_pinned = true;
-       }
-
        /* src is a subvolume */
        if (old_ino == BTRFS_FIRST_FREE_OBJECTID) {
                ret = btrfs_unlink_subvol(trans, old_dir, old_dentry);
@@ -9142,7 +9178,8 @@ static int btrfs_rename_exchange(struct inode *old_dir,
                ret = __btrfs_unlink_inode(trans, BTRFS_I(old_dir),
                                           BTRFS_I(old_dentry->d_inode),
                                           old_dentry->d_name.name,
-                                          old_dentry->d_name.len);
+                                          old_dentry->d_name.len,
+                                          &old_rename_ctx);
                if (!ret)
                        ret = btrfs_update_inode(trans, root, BTRFS_I(old_inode));
        }
@@ -9158,7 +9195,8 @@ static int btrfs_rename_exchange(struct inode *old_dir,
                ret = __btrfs_unlink_inode(trans, BTRFS_I(new_dir),
                                           BTRFS_I(new_dentry->d_inode),
                                           new_dentry->d_name.name,
-                                          new_dentry->d_name.len);
+                                          new_dentry->d_name.len,
+                                          &new_rename_ctx);
                if (!ret)
                        ret = btrfs_update_inode(trans, dest, BTRFS_I(new_inode));
        }
@@ -9188,46 +9226,31 @@ static int btrfs_rename_exchange(struct inode *old_dir,
        if (new_inode->i_nlink == 1)
                BTRFS_I(new_inode)->dir_index = new_idx;
 
-       if (root_log_pinned) {
-               btrfs_log_new_name(trans, BTRFS_I(old_inode), BTRFS_I(old_dir),
-                                  new_dentry->d_parent);
+       /*
+        * Now pin the logs of the roots. We do it to ensure that no other task
+        * can sync the logs while we are in progress with the rename, because
+        * that could result in an inconsistency in case any of the inodes that
+        * are part of this rename operation were logged before.
+        */
+       if (old_ino != BTRFS_FIRST_FREE_OBJECTID)
+               btrfs_pin_log_trans(root);
+       if (new_ino != BTRFS_FIRST_FREE_OBJECTID)
+               btrfs_pin_log_trans(dest);
+
+       /* Do the log updates for all inodes. */
+       if (old_ino != BTRFS_FIRST_FREE_OBJECTID)
+               btrfs_log_new_name(trans, old_dentry, BTRFS_I(old_dir),
+                                  old_rename_ctx.index, new_dentry->d_parent);
+       if (new_ino != BTRFS_FIRST_FREE_OBJECTID)
+               btrfs_log_new_name(trans, new_dentry, BTRFS_I(new_dir),
+                                  new_rename_ctx.index, old_dentry->d_parent);
+
+       /* Now unpin the logs. */
+       if (old_ino != BTRFS_FIRST_FREE_OBJECTID)
                btrfs_end_log_trans(root);
-               root_log_pinned = false;
-       }
-       if (dest_log_pinned) {
-               btrfs_log_new_name(trans, BTRFS_I(new_inode), BTRFS_I(new_dir),
-                                  old_dentry->d_parent);
+       if (new_ino != BTRFS_FIRST_FREE_OBJECTID)
                btrfs_end_log_trans(dest);
-               dest_log_pinned = false;
-       }
 out_fail:
-       /*
-        * If we have pinned a log and an error happened, we unpin tasks
-        * trying to sync the log and force them to fallback to a transaction
-        * commit if the log currently contains any of the inodes involved in
-        * this rename operation (to ensure we do not persist a log with an
-        * inconsistent state for any of these inodes or leading to any
-        * inconsistencies when replayed). If the transaction was aborted, the
-        * abortion reason is propagated to userspace when attempting to commit
-        * the transaction. If the log does not contain any of these inodes, we
-        * allow the tasks to sync it.
-        */
-       if (ret && (root_log_pinned || dest_log_pinned)) {
-               if (btrfs_inode_in_log(BTRFS_I(old_dir), fs_info->generation) ||
-                   btrfs_inode_in_log(BTRFS_I(new_dir), fs_info->generation) ||
-                   btrfs_inode_in_log(BTRFS_I(old_inode), fs_info->generation) ||
-                   btrfs_inode_in_log(BTRFS_I(new_inode), fs_info->generation))
-                       btrfs_set_log_full_commit(trans);
-
-               if (root_log_pinned) {
-                       btrfs_end_log_trans(root);
-                       root_log_pinned = false;
-               }
-               if (dest_log_pinned) {
-                       btrfs_end_log_trans(dest);
-                       dest_log_pinned = false;
-               }
-       }
        ret2 = btrfs_end_transaction(trans);
        ret = ret ? ret : ret2;
 out_notrans:
@@ -9302,11 +9325,11 @@ static int btrfs_rename(struct user_namespace *mnt_userns,
        struct btrfs_root *dest = BTRFS_I(new_dir)->root;
        struct inode *new_inode = d_inode(new_dentry);
        struct inode *old_inode = d_inode(old_dentry);
+       struct btrfs_rename_ctx rename_ctx;
        u64 index = 0;
        int ret;
        int ret2;
        u64 old_ino = btrfs_ino(BTRFS_I(old_inode));
-       bool log_pinned = false;
 
        if (btrfs_ino(BTRFS_I(new_dir)) == BTRFS_EMPTY_SUBVOL_DIR_OBJECTID)
                return -EPERM;
@@ -9411,29 +9434,11 @@ static int btrfs_rename(struct user_namespace *mnt_userns,
        if (unlikely(old_ino == BTRFS_FIRST_FREE_OBJECTID)) {
                ret = btrfs_unlink_subvol(trans, old_dir, old_dentry);
        } else {
-               /*
-                * Now pin the log. We do it to ensure that no other task can
-                * sync the log while we are in progress with the rename, as
-                * that could result in an inconsistency in case any of the
-                * inodes that are part of this rename operation were logged
-                * before.
-                *
-                * We pin the log even if at this precise moment none of the
-                * inodes was logged before. This is because right after we
-                * checked for that, some other task fsyncing some other inode
-                * not involved with this rename operation could log that one of
-                * our inodes exists.
-                *
-                * We don't need to pin the logs before the above call to
-                * btrfs_insert_inode_ref(), since that does not need to change
-                * a log.
-                */
-               btrfs_pin_log_trans(root);
-               log_pinned = true;
                ret = __btrfs_unlink_inode(trans, BTRFS_I(old_dir),
                                        BTRFS_I(d_inode(old_dentry)),
                                        old_dentry->d_name.name,
-                                       old_dentry->d_name.len);
+                                       old_dentry->d_name.len,
+                                       &rename_ctx);
                if (!ret)
                        ret = btrfs_update_inode(trans, root, BTRFS_I(old_inode));
        }
@@ -9475,12 +9480,9 @@ static int btrfs_rename(struct user_namespace *mnt_userns,
        if (old_inode->i_nlink == 1)
                BTRFS_I(old_inode)->dir_index = index;
 
-       if (log_pinned) {
-               btrfs_log_new_name(trans, BTRFS_I(old_inode), BTRFS_I(old_dir),
-                                  new_dentry->d_parent);
-               btrfs_end_log_trans(root);
-               log_pinned = false;
-       }
+       if (old_ino != BTRFS_FIRST_FREE_OBJECTID)
+               btrfs_log_new_name(trans, old_dentry, BTRFS_I(old_dir),
+                                  rename_ctx.index, new_dentry->d_parent);
 
        if (flags & RENAME_WHITEOUT) {
                ret = btrfs_whiteout_for_rename(trans, root, mnt_userns,
@@ -9492,28 +9494,6 @@ static int btrfs_rename(struct user_namespace *mnt_userns,
                }
        }
 out_fail:
-       /*
-        * If we have pinned the log and an error happened, we unpin tasks
-        * trying to sync the log and force them to fallback to a transaction
-        * commit if the log currently contains any of the inodes involved in
-        * this rename operation (to ensure we do not persist a log with an
-        * inconsistent state for any of these inodes or leading to any
-        * inconsistencies when replayed). If the transaction was aborted, the
-        * abortion reason is propagated to userspace when attempting to commit
-        * the transaction. If the log does not contain any of these inodes, we
-        * allow the tasks to sync it.
-        */
-       if (ret && log_pinned) {
-               if (btrfs_inode_in_log(BTRFS_I(old_dir), fs_info->generation) ||
-                   btrfs_inode_in_log(BTRFS_I(new_dir), fs_info->generation) ||
-                   btrfs_inode_in_log(BTRFS_I(old_inode), fs_info->generation) ||
-                   (new_inode &&
-                    btrfs_inode_in_log(BTRFS_I(new_inode), fs_info->generation)))
-                       btrfs_set_log_full_commit(trans);
-
-               btrfs_end_log_trans(root);
-               log_pinned = false;
-       }
        ret2 = btrfs_end_transaction(trans);
        ret = ret ? ret : ret2;
 out_notrans: