]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
btrfs: enable encoded read/write/send for bs > ps cases
authorQu Wenruo <wqu@suse.com>
Mon, 10 Nov 2025 22:42:01 +0000 (09:12 +1030)
committerDavid Sterba <dsterba@suse.com>
Mon, 24 Nov 2025 21:42:24 +0000 (22:42 +0100)
Since the read verification and read repair are all supporting bs > ps
without large folios now, we can enable encoded read/write/send.

Now we can relax the alignment in assert_bbio_alignment() to
min(blocksize, PAGE_SIZE).
But also add the extra blocksize based alignment check for the logical
and length of the bbio.

There is a pitfall in btrfs_add_compress_bio_folios(), which relies on
the folios passed in to meet the minimal folio order.
But now we can pass regular page sized folios in, update it to check
each folio's size instead of using the minimal folio size.

This allows btrfs_add_compress_bio_folios() to even handle folios array
with different sizes, thankfully we don't yet need to handle such crazy
situation.

Signed-off-by: Qu Wenruo <wqu@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/bio.c
fs/btrfs/compression.c
fs/btrfs/ioctl.c
fs/btrfs/send.c

index fcd28eb682471e57bc83af99fa6569ce9c5864ab..1b38e3ee0a3365c674fa6296906a0c74c18f4e5c 100644 (file)
@@ -867,21 +867,23 @@ static void assert_bbio_alignment(struct btrfs_bio *bbio)
        struct bio_vec bvec;
        struct bvec_iter iter;
        const u32 blocksize = fs_info->sectorsize;
+       const u32 alignment = min(blocksize, PAGE_SIZE);
+       const u64 logical = bbio->bio.bi_iter.bi_sector << SECTOR_SHIFT;
+       const u32 length = bbio->bio.bi_iter.bi_size;
 
-       /* Metadata has no extra bs > ps alignment requirement. */
-       if (!is_data_bbio(bbio))
-               return;
+       /* The logical and length should still be aligned to blocksize. */
+       ASSERT(IS_ALIGNED(logical, blocksize) && IS_ALIGNED(length, blocksize) &&
+              length != 0, "root=%llu inode=%llu logical=%llu length=%u",
+              btrfs_root_id(bbio->inode->root),
+              btrfs_ino(bbio->inode), logical, length);
 
        bio_for_each_bvec(bvec, &bbio->bio, iter)
-               ASSERT(IS_ALIGNED(bvec.bv_offset, blocksize) &&
-                      IS_ALIGNED(bvec.bv_len, blocksize),
+               ASSERT(IS_ALIGNED(bvec.bv_offset, alignment) &&
+                      IS_ALIGNED(bvec.bv_len, alignment),
                "root=%llu inode=%llu logical=%llu length=%u index=%u bv_offset=%u bv_len=%u",
                btrfs_root_id(bbio->inode->root),
-               btrfs_ino(bbio->inode),
-               bbio->bio.bi_iter.bi_sector << SECTOR_SHIFT,
-               bbio->bio.bi_iter.bi_size, iter.bi_idx,
-               bvec.bv_offset,
-               bvec.bv_len);
+               btrfs_ino(bbio->inode), logical, length, iter.bi_idx,
+               bvec.bv_offset, bvec.bv_len);
 #endif
 }
 
index 241a117ad7cc4b2187122c95545cd2501dc9255a..1d4c3d2e2d6c0330df8e76a12f175152d420b2ce 100644 (file)
@@ -340,21 +340,20 @@ static void end_bbio_compressed_write(struct btrfs_bio *bbio)
 
 static void btrfs_add_compressed_bio_folios(struct compressed_bio *cb)
 {
-       struct btrfs_fs_info *fs_info = cb->bbio.inode->root->fs_info;
        struct bio *bio = &cb->bbio.bio;
        u32 offset = 0;
+       unsigned int findex = 0;
 
        while (offset < cb->compressed_len) {
-               struct folio *folio;
+               struct folio *folio = cb->compressed_folios[findex];
+               u32 len = min_t(u32, cb->compressed_len - offset, folio_size(folio));
                int ret;
-               u32 len = min_t(u32, cb->compressed_len - offset,
-                               btrfs_min_folio_size(fs_info));
 
-               folio = cb->compressed_folios[offset >> (PAGE_SHIFT + fs_info->block_min_order)];
                /* Maximum compressed extent is smaller than bio size limit. */
                ret = bio_add_folio(bio, folio, len, 0);
                ASSERT(ret);
                offset += len;
+               findex++;
        }
 }
 
index 83a168613ee984337a71c6dda0fd29501a7087e0..59cef7e376a0f30d5f2f995e8645a102e90f82e1 100644 (file)
@@ -4408,10 +4408,6 @@ static int btrfs_ioctl_encoded_read(struct file *file, void __user *argp,
                goto out_acct;
        }
 
-       if (fs_info->sectorsize > PAGE_SIZE) {
-               ret = -ENOTTY;
-               goto out_acct;
-       }
        if (compat) {
 #if defined(CONFIG_64BIT) && defined(CONFIG_COMPAT)
                struct btrfs_ioctl_encoded_io_args_32 args32;
@@ -4503,7 +4499,6 @@ out_acct:
 
 static int btrfs_ioctl_encoded_write(struct file *file, void __user *argp, bool compat)
 {
-       struct btrfs_fs_info *fs_info = inode_to_fs_info(file->f_inode);
        struct btrfs_ioctl_encoded_io_args args;
        struct iovec iovstack[UIO_FASTIOV];
        struct iovec *iov = iovstack;
@@ -4517,11 +4512,6 @@ static int btrfs_ioctl_encoded_write(struct file *file, void __user *argp, bool
                goto out_acct;
        }
 
-       if (fs_info->sectorsize > PAGE_SIZE) {
-               ret = -ENOTTY;
-               goto out_acct;
-       }
-
        if (!(file->f_mode & FMODE_WRITE)) {
                ret = -EBADF;
                goto out_acct;
@@ -4803,11 +4793,6 @@ static int btrfs_uring_encoded_read(struct io_uring_cmd *cmd, unsigned int issue
                ret = -EPERM;
                goto out_acct;
        }
-       if (fs_info->sectorsize > PAGE_SIZE) {
-               ret = -ENOTTY;
-               goto out_acct;
-       }
-
        sqe_addr = u64_to_user_ptr(READ_ONCE(cmd->sqe->addr));
 
        if (issue_flags & IO_URING_F_COMPAT) {
@@ -4935,7 +4920,6 @@ out_acct:
 static int btrfs_uring_encoded_write(struct io_uring_cmd *cmd, unsigned int issue_flags)
 {
        struct file *file = cmd->file;
-       struct btrfs_fs_info *fs_info = inode_to_fs_info(file->f_inode);
        loff_t pos;
        struct kiocb kiocb;
        ssize_t ret;
@@ -4950,11 +4934,6 @@ static int btrfs_uring_encoded_write(struct io_uring_cmd *cmd, unsigned int issu
                ret = -EPERM;
                goto out_acct;
        }
-       if (fs_info->sectorsize > PAGE_SIZE) {
-               ret = -ENOTTY;
-               goto out_acct;
-       }
-
        sqe_addr = u64_to_user_ptr(READ_ONCE(cmd->sqe->addr));
 
        if (!(file->f_mode & FMODE_WRITE)) {
index 9312d74400a3f9837b47c3fa6c372ab33f27ede0..fa94105e139a3bb24c9aa6a82f01e520acb1871e 100644 (file)
@@ -5634,14 +5634,7 @@ static int send_extent_data(struct send_ctx *sctx, struct btrfs_path *path,
 
        ei = btrfs_item_ptr(leaf, path->slots[0],
                            struct btrfs_file_extent_item);
-       /*
-        * Do not go through encoded read for bs > ps cases.
-        *
-        * Encoded send is using vmallocated pages as buffer, which we can
-        * not ensure every folio is large enough to contain a block.
-        */
-       if (sctx->send_root->fs_info->sectorsize <= PAGE_SIZE &&
-           (sctx->flags & BTRFS_SEND_FLAG_COMPRESSED) &&
+       if ((sctx->flags & BTRFS_SEND_FLAG_COMPRESSED) &&
            btrfs_file_extent_compression(leaf, ei) != BTRFS_COMPRESS_NONE) {
                bool is_inline = (btrfs_file_extent_type(leaf, ei) ==
                                  BTRFS_FILE_EXTENT_INLINE);