btrfs: allocate dio_data on stack
authorChristoph Hellwig <hch@lst.de>
Thu, 5 May 2022 20:11:12 +0000 (15:11 -0500)
committerDavid Sterba <dsterba@suse.com>
Mon, 16 May 2022 15:17:32 +0000 (17:17 +0200)
Make use of the new iomap_iter->private field to avoid a memory
allocation per iomap range.

Reviewed-by: Nikolay Borisov <nborisov@suse.com>
Signed-off-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: David Sterba <dsterba@suse.com>
Signed-off-by: David Sterba <dsterba@suse.com>
fs/btrfs/inode.c

index 954e91b..9848a5a 100644 (file)
@@ -7546,10 +7546,11 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
                loff_t length, unsigned int flags, struct iomap *iomap,
                struct iomap *srcmap)
 {
+       struct iomap_iter *iter = container_of(iomap, struct iomap_iter, iomap);
        struct btrfs_fs_info *fs_info = btrfs_sb(inode->i_sb);
        struct extent_map *em;
        struct extent_state *cached_state = NULL;
-       struct btrfs_dio_data *dio_data = NULL;
+       struct btrfs_dio_data *dio_data = iter->private;
        u64 lockstart, lockend;
        const bool write = !!(flags & IOMAP_WRITE);
        int ret = 0;
@@ -7595,17 +7596,7 @@ static int btrfs_dio_iomap_begin(struct inode *inode, loff_t start,
                }
        }
 
-       if (flags & IOMAP_NOWAIT) {
-               dio_data = kzalloc(sizeof(*dio_data), GFP_NOWAIT);
-               if (!dio_data)
-                       return -EAGAIN;
-       } else {
-               dio_data = kzalloc(sizeof(*dio_data), GFP_NOFS);
-               if (!dio_data)
-                       return -ENOMEM;
-       }
-
-       iomap->private = dio_data;
+       memset(dio_data, 0, sizeof(*dio_data));
 
        /*
         * We always try to allocate data space and must do it before locking
@@ -7769,23 +7760,22 @@ err:
                extent_changeset_free(dio_data->data_reserved);
        }
 
-       kfree(dio_data);
-
        return ret;
 }
 
 static int btrfs_dio_iomap_end(struct inode *inode, loff_t pos, loff_t length,
                ssize_t written, unsigned int flags, struct iomap *iomap)
 {
-       int ret = 0;
-       struct btrfs_dio_data *dio_data = iomap->private;
+       struct iomap_iter *iter = container_of(iomap, struct iomap_iter, iomap);
+       struct btrfs_dio_data *dio_data = iter->private;
        size_t submitted = dio_data->submitted;
        const bool write = !!(flags & IOMAP_WRITE);
+       int ret = 0;
 
        if (!write && (iomap->type == IOMAP_HOLE)) {
                /* If reading from a hole, unlock and return */
                unlock_extent(&BTRFS_I(inode)->io_tree, pos, pos + length - 1);
-               goto out;
+               return 0;
        }
 
        if (submitted < length) {
@@ -7802,10 +7792,6 @@ static int btrfs_dio_iomap_end(struct inode *inode, loff_t pos, loff_t length,
 
        if (write)
                extent_changeset_free(dio_data->data_reserved);
-out:
-       kfree(dio_data);
-       iomap->private = NULL;
-
        return ret;
 }
 
@@ -8041,7 +8027,7 @@ static void btrfs_submit_direct(const struct iomap_iter *iter,
        int ret;
        blk_status_t status;
        struct btrfs_io_geometry geom;
-       struct btrfs_dio_data *dio_data = iter->iomap.private;
+       struct btrfs_dio_data *dio_data = iter->private;
        struct extent_map *em = NULL;
 
        dip = btrfs_create_dio_private(dio_bio, inode, file_offset);
@@ -8166,8 +8152,10 @@ static const struct iomap_dio_ops btrfs_dio_ops = {
 
 ssize_t btrfs_dio_rw(struct kiocb *iocb, struct iov_iter *iter, size_t done_before)
 {
+       struct btrfs_dio_data data;
+
        return iomap_dio_rw(iocb, iter, &btrfs_dio_iomap_ops, &btrfs_dio_ops,
-                           IOMAP_DIO_PARTIAL, NULL, done_before);
+                           IOMAP_DIO_PARTIAL, &data, done_before);
 }
 
 static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,