Btrfs: stop abusing current->journal_info for direct I/O
Subsystems (14)
v2 cover Btrfs: stop abusing current->journal_info for direct I/O
From: Omar Sandoval <[email protected]>
Hi,
This is a different approach from v1 [1] of this series to stop abusing current->journal_info in Btrfs. This approach unifies everything to use iocb->private instead of map_bh->b_private. Patches 1 and 5 pass the iocb to a couple of callbacks which need it. Patches 2 and 3 migrates the users of b_private to use iocb->private, and patch 4 gets rid of the b_private handling in the direct I/O code. Patch 6 cleans up Btrfs.
I'm not convinced that this is cleaner that my first approach, but it at least avoids growing the argument list to do_blockdev_direct_IO(), which was Al's complaint of v1.
Thanks!
1: https://www.spinics.net/lists/linux-btrfs/msg77859.html
Omar Sandoval (6):
fs: pass iocb to direct I/O get_block()
ext4: use iocb->private instead of bh->b_private
ocfs2: use iocb->private instead of bh->b_private
fs: stop propagating bh->b_private for direct I/O
fs: pass iocb to direct I/O submit_io()
Btrfs: stop abusing current->journal_info in btrfs_direct_IO()
fs/affs/file.c | 9 ++++++- fs/btrfs/inode.c | 36 +++++++------------------ fs/direct-io.c | 23 +++++++--------- fs/ext2/inode.c | 9 ++++++- fs/ext4/ext4.h | 2 -- fs/ext4/inode.c | 40 ++++++++++++++++------------ fs/f2fs/data.c | 5 ++-- fs/fat/inode.c | 9 ++++++- fs/gfs2/aops.c | 5 ++-- fs/hfs/inode.c | 9 ++++++- fs/hfsplus/inode.c | 9 ++++++- fs/jfs/inode.c | 9 ++++++- fs/nilfs2/inode.c | 9 ++++++- fs/ocfs2/aops.c | 39 ++++++++++++++------------- fs/ocfs2/aops.h | 64 ++++++++++++++++++++++++++++++--------------- fs/reiserfs/inode.c | 4 +-- fs/udf/inode.c | 9 ++++++- include/linux/fs.h | 17 ++++++------ 18 files changed, 187 insertions(+), 120 deletions(-)
Signature · 1 line
2.18.0
RFC PATCH v2 1/6 fs: pass iocb to direct I/O get_block()
From: Omar Sandoval <[email protected]>
Split out dio_get_block_t which is the same as get_block_t except that it takes the iocb as well, and update fs/direct-io.c and all callers to use it. This is preparation for replacing the use of bh->b_private in the direct I/O code with iocb->private.
--- fs/affs/file.c | 9 ++++++++- fs/btrfs/inode.c | 3 ++- fs/direct-io.c | 13 ++++++------- fs/ext2/inode.c | 9 ++++++++- fs/ext4/ext4.h | 2 -- fs/ext4/inode.c | 27 ++++++++++++++++++--------- fs/f2fs/data.c | 5 +++-- fs/fat/inode.c | 9 ++++++++- fs/gfs2/aops.c | 5 +++-- fs/hfs/inode.c | 9 ++++++++- fs/hfsplus/inode.c | 9 ++++++++- fs/jfs/inode.c | 9 ++++++++- fs/nilfs2/inode.c | 9 ++++++++- fs/ocfs2/aops.c | 15 +++++++++------ fs/reiserfs/inode.c | 4 ++-- fs/udf/inode.c | 9 ++++++++- include/linux/fs.h | 10 ++++++---- 17 files changed, 113 insertions(+), 43 deletions(-)
fs/affs/file.c +8 -1
@@ -389,6 +389,13 @@ static void affs_write_failed(struct address_space *mapping, loff_t to) } } +static int affs_get_block_dio (struct kiocb *iocb,struct inode *inode, +sector_t block,struct buffer_head *bh_result, +int create) +{ +return affs_get_block (inode, block, bh_result, create); +} +static ssize_t affs_direct_IO (struct kiocb *iocb,struct iov_iter *iter) {
@@ -406,7 +413,7 @@ affs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)return 0 ; } - ret =blockdev_direct_IO (iocb, inode, iter, affs_get_block); + ret =blockdev_direct_IO (iocb, inode, iter, affs_get_block_dio);if (ret <0 &&iov_iter_rw (iter) ==WRITE )affs_write_failed (mapping, offset + count);return ret;
fs/btrfs/inode.c +2 -1
@@ -7659,7 +7659,8 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,return ret; } -static int btrfs_get_blocks_direct (struct inode *inode,sector_t iblock, +static int btrfs_get_blocks_direct (struct kiocb *iocb,struct inode *inode, +sector_t iblock,struct buffer_head *bh_result,int create) {struct btrfs_fs_info *fs_info =btrfs_sb (inode->i_sb);
fs/direct-io.c +6 -7
@@ -82,7 +82,7 @@ struct dio_submit {int reap_counter;/* rate limit reaping */ sector_t final_block_in_request;/* doesn't change */ int boundary;/* prev block is at a boundary */ -get_block_t *get_block;/* block mapping function */ +dio_get_block_t *get_block;/* block mapping function */ dio_submit_t *submit_io;/* IO submition function */ loff_t logical_offset_in_bio;/* current first logical block in bio */
@@ -713,8 +713,8 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio, create =0 ; } - ret = (*sdio->get_block)(dio->inode, fs_startblk, - map_bh, create); + ret = (*sdio->get_block)(dio->iocb, dio->inode, fs_startblk, + map_bh, create);/* Store for completion */ dio->private = map_bh->b_private;
@@ -1170,7 +1170,7 @@ static inline int drop_refcount(struct dio *dio)static inline ssize_t do_blockdev_direct_IO (struct kiocb *iocb,struct inode *inode,struct block_device *bdev,struct iov_iter *iter, -get_block_t get_block,dio_iodone_t end_io, +dio_get_block_t get_block,dio_iodone_t end_io,dio_submit_t submit_io,int flags) {unsigned i_blkbits =READ_ONCE (inode->i_blkbits);
@@ -1398,9 +1398,8 @@ do_blockdev_direct_IO(struct kiocb *iocb, struct inode *inode,ssize_t __blockdev_direct_IO (struct kiocb *iocb,struct inode *inode,struct block_device *bdev,struct iov_iter *iter, -get_block_t get_block, -dio_iodone_t end_io,dio_submit_t submit_io, -int flags) +dio_get_block_t get_block,dio_iodone_t end_io, +dio_submit_t submit_io,int flags) {/* * The block device state is needed in the end to finally
fs/ext2/inode.c +8 -1
@@ -930,6 +930,13 @@ static sector_t ext2_bmap(struct address_space *mapping, sector_t block)return generic_block_bmap (mapping,block,ext2_get_block); } +static int ext2_get_block_dio (struct kiocb *iocb,struct inode *inode, +sector_t iblock,struct buffer_head *bh_result, +int create) +{ +return ext2_get_block (inode, iblock, bh_result, create); +} +static ssize_t ext2_direct_IO (struct kiocb *iocb,struct iov_iter *iter) {
@@ -940,7 +947,7 @@ ext2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)loff_t offset = iocb->ki_pos;ssize_t ret; - ret =blockdev_direct_IO (iocb, inode, iter, ext2_get_block); + ret =blockdev_direct_IO (iocb, inode, iter, ext2_get_block_dio);if (ret <0 &&iov_iter_rw (iter) ==WRITE )ext2_write_failed (mapping, offset + count);return ret;
fs/ext4/ext4.h +0 -2
@@ -2425,8 +2425,6 @@ int ext4_get_block_unwritten(struct inode *inode, sector_t iblock, struct buffer_head *bh_result, int create);int ext4_get_block (struct inode *inode,sector_t iblock,struct buffer_head *bh_result,int create); -int ext4_dio_get_block (struct inode *inode,sector_t iblock, -struct buffer_head *bh_result,int create);int ext4_da_get_block_prep (struct inode *inode,sector_t iblock,struct buffer_head *bh,int create); int ext4_walk_page_buffers(handle_t *handle,
fs/ext4/inode.c +18 -9
@@ -850,8 +850,9 @@ static int ext4_get_block_trans(struct inode *inode, sector_t iblock, }/* Get block function for DIO reads and writes to inodes without extents */ -int ext4_dio_get_block (struct inode *inode,sector_t iblock, -struct buffer_head *bh,int create) +static int ext4_dio_get_block (struct kiocb *iocb,struct inode *inode, +sector_t iblock,struct buffer_head *bh, +int create) {/* We don't expect handle for direct IO */ WARN_ON_ONCE (ext4_journal_current_handle ());
@@ -866,8 +867,11 @@ int ext4_dio_get_block(struct inode *inode, sector_t iblock,* blocks are not allocated yet. The extent will be converted to written * after IO is complete. */ -static int ext4_dio_get_block_unwritten_async (struct inode *inode, -sector_t iblock,struct buffer_head *bh_result,int create) +static int ext4_dio_get_block_unwritten_async (struct kiocb *iocb, +struct inode *inode, +sector_t iblock, +struct buffer_head *bh_result, +int create) {int ret;
@@ -905,8 +909,11 @@ static int ext4_dio_get_block_unwritten_async(struct inode *inode,* blocks are not allocated yet. The extent will be converted to written * after IO is complete by ext4_direct_IO_write(). */ -static int ext4_dio_get_block_unwritten_sync (struct inode *inode, -sector_t iblock,struct buffer_head *bh_result,int create) +static int ext4_dio_get_block_unwritten_sync (struct kiocb *iocb, +struct inode *inode, +sector_t iblock, +struct buffer_head *bh_result, +int create) {int ret;
@@ -927,8 +934,10 @@ static int ext4_dio_get_block_unwritten_sync(struct inode *inode,return ret; } -static int ext4_dio_get_block_overwrite (struct inode *inode,sector_t iblock, -struct buffer_head *bh_result,int create) +static int ext4_dio_get_block_overwrite (struct kiocb *iocb,struct inode *inode, +sector_t iblock, +struct buffer_head *bh_result, +int create) {int ret;
@@ -3663,7 +3672,7 @@ static ssize_t ext4_direct_IO_write(struct kiocb *iocb, struct iov_iter *iter)loff_t offset = iocb->ki_pos;size_t count =iov_iter_count (iter);int overwrite =0 ; -get_block_t *get_block_func =NULL ; +dio_get_block_t *get_block_func =NULL ;int dio_flags =0 ;loff_t final_size = offset + count;int orphan =0 ;
fs/f2fs/data.c +3 -2
@@ -1232,8 +1232,9 @@ static int get_data_block(struct inode *inode, sector_t iblock, NO_CHECK_TYPE); } -static int get_data_block_dio (struct inode *inode,sector_t iblock, -struct buffer_head *bh_result,int create) +static int get_data_block_dio (struct kiocb *iocb,struct inode *inode, +sector_t iblock,struct buffer_head *bh_result, +int create) { return __get_data_block(inode, iblock, bh_result, create, F2FS_GET_BLOCK_DEFAULT, NULL,
fs/fat/inode.c +8 -1
@@ -251,6 +251,13 @@ static int fat_write_end(struct file *file, struct address_space *mapping,return err; } +static int fat_get_block_dio (struct kiocb *iocb,struct inode *inode, +sector_t iblock,struct buffer_head *bh_result, +int create) +{ +return fat_get_block (inode, iblock, bh_result, create); +} +static ssize_t fat_direct_IO (struct kiocb *iocb,struct iov_iter *iter) {struct file *file = iocb->ki_filp;
@@ -279,7 +286,7 @@ static ssize_t fat_direct_IO(struct kiocb *iocb, struct iov_iter *iter)* FAT need to use the DIO_LOCKING for avoiding the race * condition of fat_get_block() and ->truncate(). */ - ret =blockdev_direct_IO (iocb, inode, iter, fat_get_block); + ret =blockdev_direct_IO (iocb, inode, iter, fat_get_block_dio);if (ret <0 &&iov_iter_rw (iter) ==WRITE )fat_write_failed (mapping, offset + count);
fs/gfs2/aops.c +3 -2
@@ -82,8 +82,9 @@ static int gfs2_get_block_noalloc(struct inode *inode, sector_t lblock,return 0 ; } -static int gfs2_get_block_direct (struct inode *inode,sector_t lblock, -struct buffer_head *bh_result,int create) +static int gfs2_get_block_direct (struct kiocb *iocb,struct inode *inode, +sector_t lblock,struct buffer_head *bh_result, +int create) {return gfs2_block_map (inode, lblock, bh_result,0 ); }
fs/hfs/inode.c +8 -1
@@ -126,6 +126,13 @@ static int hfs_releasepage(struct page *page, gfp_t mask)return res ?try_to_free_buffers (page) :0 ; } +static int hfs_get_block_dio (struct kiocb *iocb,struct inode *inode, +sector_t block,struct buffer_head *bh_result, +int create) +{ +return hfs_get_block (inode, block, bh_result, create); +} +static ssize_t hfs_direct_IO (struct kiocb *iocb,struct iov_iter *iter) {struct file *file = iocb->ki_filp;
@@ -134,7 +141,7 @@ static ssize_t hfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)size_t count =iov_iter_count (iter);ssize_t ret; - ret =blockdev_direct_IO (iocb, inode, iter, hfs_get_block); + ret =blockdev_direct_IO (iocb, inode, iter, hfs_get_block_dio);/* * In case of error extending write may have instantiated a few
fs/hfsplus/inode.c +8 -1
@@ -124,6 +124,13 @@ static int hfsplus_releasepage(struct page *page, gfp_t mask)return res ?try_to_free_buffers (page) :0 ; } +static int hfsplus_get_block_dio (struct kiocb *iocb,struct inode *inode, +sector_t iblock,struct buffer_head *bh_result, +int create) +{ +return hfsplus_get_block (inode, iblock, bh_result, create); +} +static ssize_t hfsplus_direct_IO (struct kiocb *iocb,struct iov_iter *iter) {struct file *file = iocb->ki_filp;
@@ -132,7 +139,7 @@ static ssize_t hfsplus_direct_IO(struct kiocb *iocb, struct iov_iter *iter)size_t count =iov_iter_count (iter);ssize_t ret; - ret =blockdev_direct_IO (iocb, inode, iter, hfsplus_get_block); + ret =blockdev_direct_IO (iocb, inode, iter, hfsplus_get_block_dio);/* * In case of error extending write may have instantiated a few
fs/jfs/inode.c +8 -1
@@ -332,6 +332,13 @@ static sector_t jfs_bmap(struct address_space *mapping, sector_t block)return generic_block_bmap (mapping, block, jfs_get_block); } +static int jfs_get_block_dio (struct kiocb *iocb,struct inode *ip, +sector_t lblock,struct buffer_head *bh_result, +int create) +{ +return jfs_get_block (ip, lblock, bh_result, create); +} +static ssize_t jfs_direct_IO (struct kiocb *iocb,struct iov_iter *iter) {struct file *file = iocb->ki_filp;
@@ -340,7 +347,7 @@ static ssize_t jfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)size_t count =iov_iter_count (iter);ssize_t ret; - ret =blockdev_direct_IO (iocb, inode, iter, jfs_get_block); + ret =blockdev_direct_IO (iocb, inode, iter, jfs_get_block_dio);/* * In case of error extending write may have instantiated a few
fs/nilfs2/inode.c +8 -1
@@ -300,6 +300,13 @@ static int nilfs_write_end(struct file *file, struct address_space *mapping,return err ? : copied; } +static int nilfs_get_block_dio (struct kiocb *iocb,struct inode *inode, +sector_t blkoff,struct buffer_head *bh_result, +int create) +{ +return nilfs_get_block (inode, blkoff, bh_result, create); +} +static ssize_t nilfs_direct_IO (struct kiocb *iocb,struct iov_iter *iter) {
@@ -309,7 +316,7 @@ nilfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)return 0 ;/* Needs synchronization with the cleaner */ -return blockdev_direct_IO (iocb, inode, iter, nilfs_get_block); +return blockdev_direct_IO (iocb, inode, iter, nilfs_get_block_dio); }const struct address_space_operations nilfs_aops = {
fs/ocfs2/aops.c +9 -6
@@ -134,8 +134,9 @@ static int ocfs2_symlink_get_block(struct inode *inode, sector_t iblock,return err; } -static int ocfs2_lock_get_block (struct inode *inode,sector_t iblock, -struct buffer_head *bh_result,int create) +static int ocfs2_lock_get_block (struct kiocb *iocb,struct inode *inode, +sector_t iblock,struct buffer_head *bh_result, +int create) {int ret =0 ;struct ocfs2_inode_info *oi =OCFS2_I (inode);
@@ -2143,8 +2144,9 @@ static void ocfs2_dio_free_write_ctx(struct inode *inode,* called like this: dio->get_blocks(dio->inode, fs_startblk, * fs_count, map_bh, dio->rw == WRITE); */ -static int ocfs2_dio_wr_get_block (struct inode *inode,sector_t iblock, -struct buffer_head *bh_result,int create) +static int ocfs2_dio_wr_get_block (struct kiocb *iocb,struct inode *inode, +sector_t iblock, +struct buffer_head *bh_result,int create) {struct ocfs2_super *osb =OCFS2_SB (inode->i_sb);struct ocfs2_inode_info *oi =OCFS2_I (inode);
@@ -2171,7 +2173,8 @@ static int ocfs2_dio_wr_get_block(struct inode *inode, sector_t iblock,if (pos + total_len <=i_size_read (inode)) {/* This is the fast path for re-write. */ - ret =ocfs2_lock_get_block (inode, iblock, bh_result, create); + ret =ocfs2_lock_get_block (iocb, inode, iblock, bh_result, + create);if (buffer_mapped (bh_result) && !buffer_new (bh_result) && ret ==0 )
@@ -2427,7 +2430,7 @@ static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)struct file *file = iocb->ki_filp;struct inode *inode = file->f_mapping->host;struct ocfs2_super *osb =OCFS2_SB (inode->i_sb); -get_block_t *get_block; +dio_get_block_t *get_block;/* * Fallback to buffered I/O if we see an inode without
fs/reiserfs/inode.c +2 -2
@@ -511,8 +511,8 @@ static int reiserfs_get_block_create_0(struct inode *inode, sector_t block,* This is special helper for reiserfs_get_block in case we are executing * direct_IO request. */ -static int reiserfs_get_blocks_direct_io (struct inode *inode, -sector_t iblock, +static int reiserfs_get_blocks_direct_io (struct kiocb *iocb, +struct inode *inode,sector_t iblock,struct buffer_head *bh_result,int create) {
fs/udf/inode.c +8 -1
@@ -206,6 +206,13 @@ static int udf_write_begin(struct file *file, struct address_space *mapping,return ret; } +static int udf_get_block_dio (struct kiocb *iocb,struct inode *inode, +sector_t block,struct buffer_head *bh_result, +int create) +{ +return udf_get_block (inode, block, bh_result, create); +} +static ssize_t udf_direct_IO (struct kiocb *iocb,struct iov_iter *iter) {struct file *file = iocb->ki_filp;
@@ -214,7 +221,7 @@ static ssize_t udf_direct_IO(struct kiocb *iocb, struct iov_iter *iter)size_t count =iov_iter_count (iter);ssize_t ret; - ret =blockdev_direct_IO (iocb, inode, iter, udf_get_block); + ret =blockdev_direct_IO (iocb, inode, iter, udf_get_block_dio);if (unlikely (ret <0 &&iov_iter_rw (iter) ==WRITE ))udf_write_failed (mapping, iocb->ki_pos + count);return ret;
include/linux/fs.h +6 -4
@@ -80,6 +80,9 @@ typedef __kernel_rwf_t rwf_t;struct buffer_head ;typedef int (get_block_t )(struct inode *inode,sector_t iblock,struct buffer_head *bh_result,int create); +typedef int (dio_get_block_t )(struct kiocb *iocb,struct inode *inode, +sector_t iblock,struct buffer_head *bh_result, +int create);typedef int (dio_iodone_t )(struct kiocb *iocb,loff_t offset,ssize_t bytes,void *private);
@@ -3017,14 +3020,13 @@ void dio_warn_stale_pagecache(struct file *filp);ssize_t __blockdev_direct_IO (struct kiocb *iocb,struct inode *inode,struct block_device *bdev,struct iov_iter *iter, -get_block_t get_block, -dio_iodone_t end_io,dio_submit_t submit_io, -int flags); +dio_get_block_t get_block,dio_iodone_t end_io, +dio_submit_t submit_io,int flags);static inline ssize_t blockdev_direct_IO (struct kiocb *iocb,struct inode *inode,struct iov_iter *iter, -get_block_t get_block) +dio_get_block_t get_block) {return __blockdev_direct_IO (iocb, inode, inode->i_sb->s_bdev, iter, get_block,NULL ,NULL ,DIO_LOCKING |DIO_SKIP_HOLES );
Signature · 1 line
2.18.0
RFC PATCH v2 2/6 ext4: use iocb->private instead of bh->b_private
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
As part of simplifying all of the private data passed around for direct I/O, bh->b_private will no longer be passed to dio_iodone_t. iocb is still available there, however, so convert ext4 to use it. Note that ext4_file_write_iter() also uses iocb->private, but ext4_direct_IO_write() resets it to NULL after reading it.
Also note that the comment above ext4_should_dioread_nolock() is no longer accurate. It seems that it should be possible to remove the data journaling restriction now?
--- fs/ext4/inode.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-)
fs/ext4/inode.c +4 -6
@@ -884,18 +884,16 @@ static int ext4_dio_get_block_unwritten_async(struct kiocb *iocb,/* * When doing DIO using unwritten extents, we need io_end to convert * unwritten extents to written on IO completion. We allocate io_end -* once we spot unwritten extent and store it in b_private. Generic -* DIO code keeps b_private set and furthermore passes the value to -* our completion callback in 'private' argument. +* once we spot unwritten extent and store it in iocb->private. */ if (!ret &&buffer_unwritten (bh_result)) { -if (!bh_result->b_private) { +if (!iocb->private) {ext4_io_end_t *io_end; io_end =ext4_init_io_end (inode,GFP_KERNEL );if (!io_end)return -ENOMEM ; - bh_result->b_private = io_end; + iocb->private = io_end;ext4_set_io_unwritten_flag (inode, io_end); }set_buffer_defer_completion (bh_result);
@@ -3617,7 +3615,7 @@ const struct iomap_ops ext4_iomap_ops = {static int ext4_end_io_dio (struct kiocb *iocb,loff_t offset,ssize_t size,void *private) { -ext4_io_end_t *io_end = private; +ext4_io_end_t *io_end = iocb->private;/* if not async direct IO just return */ if (!io_end)
Signature · 1 line
2.18.0
RFC PATCH v2 3/6 ocfs2: use iocb->private instead of bh->b_private
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
As part of simplifying all of the private data passed around for direct I/O, bh->b_private will no longer be passed to dio_iodone_t. Instead, filesystems should use iocb->private. ocfs2 already uses iocb->private for storing a couple of flag bits, but we can use it as a tagged pointer and hide all of the messiness in helpers.
--- fs/ocfs2/aops.c | 19 ++++++++------- fs/ocfs2/aops.h | 64 +++++++++++++++++++++++++++++++++---------------- 2 files changed, 54 insertions(+), 29 deletions(-)
fs/ocfs2/aops.c +11 -8
@@ -2104,12 +2104,13 @@ struct ocfs2_dio_write_ctxt { };static struct ocfs2_dio_write_ctxt * -ocfs2_dio_alloc_write_ctx (struct buffer_head *bh,int *alloc) +ocfs2_dio_alloc_write_ctx (struct kiocb *iocb,int *alloc) { -struct ocfs2_dio_write_ctxt *dwc =NULL ; +struct ocfs2_dio_write_ctxt *dwc; -if (bh->b_private) -return bh->b_private; + dwc =ocfs2_iocb_private (iocb); +if (dwc) +return dwc; dwc =kmalloc (sizeof (struct ocfs2_dio_write_ctxt ),GFP_NOFS );if (dwc ==NULL )
@@ -2118,7 +2119,7 @@ ocfs2_dio_alloc_write_ctx(struct buffer_head *bh, int *alloc) dwc->dw_zero_count =0 ; dwc->dw_orphaned =0 ; dwc->dw_writer_pid =task_pid_nr (current); - bh->b_private = dwc; +ocfs2_iocb_set_private (iocb, dwc); *alloc =1 ;return dwc;
@@ -2184,7 +2185,7 @@ static int ocfs2_dio_wr_get_block(struct kiocb *iocb, struct inode *inode, bh_result->b_state =0 ; } - dwc =ocfs2_dio_alloc_write_ctx (bh_result, &first_get_block); + dwc =ocfs2_dio_alloc_write_ctx (iocb, &first_get_block);if (unlikely (dwc ==NULL )) { ret = -ENOMEM ;mlog_errno (ret);
@@ -2408,6 +2409,7 @@ static int ocfs2_dio_end_io(struct kiocb *iocb,ssize_t bytes, void *private) { + struct ocfs2_dio_write_ctxt *dwc;struct inode *inode =file_inode (iocb->ki_filp);int level;int ret =0 ;
@@ -2415,8 +2417,9 @@ static int ocfs2_dio_end_io(struct kiocb *iocb,/* this io's submitter should not have unlocked this before we could */ BUG_ON (!ocfs2_iocb_is_rw_locked (iocb)); -if (bytes >0 && private) - ret =ocfs2_dio_end_io_write (inode, private, offset, bytes); + dwc =ocfs2_iocb_private (iocb); +if (bytes >0 && dwc) + ret =ocfs2_dio_end_io_write (inode, dwc, offset, bytes);ocfs2_iocb_clear_rw_locked (iocb);
fs/ocfs2/aops.h +43 -21
75 lines not on this page · raw message
Signature · 1 line
2.18.0
RFC PATCH v2 4/6 fs: stop propagating bh->b_private for direct I/O
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
Currently, the direct I/O code saves the value of bh->b_private set by the filesystem and passes it to the end_io callback. However, struct kiocb already has a ->private member which can be used for this purpose, with the added benefit of being available before get_block is called, too. The only users of the bh->b_private functionality have been converted to use iocb->private, so stop passing it around.
--- fs/direct-io.c | 7 +------ fs/ext4/inode.c | 3 +-- fs/ocfs2/aops.c | 5 +---- include/linux/fs.h | 3 +-- 4 files changed, 4 insertions(+), 14 deletions(-)
fs/direct-io.c +1 -6
@@ -122,8 +122,6 @@ struct dio {loff_t i_size;/* i_size when submitted */ dio_iodone_t *end_io;/* IO completion function */ -void *private;/* copy from map_bh.b_private */ -/* BIO completion state */ spinlock_t bio_lock;/* protects BIO fields below */ int page_errors;/* errno from get_user_pages() */
@@ -288,7 +286,7 @@ static ssize_t dio_complete(struct dio *dio, ssize_t ret, unsigned int flags)if (dio->end_io) {// XXX: ki_pos?? - err = dio->end_io (dio->iocb, offset, ret, dio->private); + err = dio->end_io (dio->iocb, offset, ret);if (err) ret = err; }
@@ -716,9 +714,6 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio, ret = (*sdio->get_block)(dio->iocb, dio->inode, fs_startblk, map_bh, create); -/* Store for completion */ - dio->private = map_bh->b_private; -if (ret ==0 &&buffer_defer_completion (map_bh)) ret =dio_set_defer_completion (dio); }
fs/ext4/inode.c +1 -2
@@ -3612,8 +3612,7 @@ const struct iomap_ops ext4_iomap_ops = { .iomap_end = ext4_iomap_end, }; -static int ext4_end_io_dio (struct kiocb *iocb,loff_t offset, -ssize_t size,void *private) +static int ext4_end_io_dio (struct kiocb *iocb,loff_t offset,ssize_t size) {ext4_io_end_t *io_end = iocb->private;
fs/ocfs2/aops.c +1 -4
@@ -2404,10 +2404,7 @@ static int ocfs2_dio_end_io_write(struct inode *inode,* particularly interested in the aio/dio case. We use the rw_lock DLM lock * to protect io on one node from truncation on another. */ -static int ocfs2_dio_end_io (struct kiocb *iocb, -loff_t offset, -ssize_t bytes, -void *private) +static int ocfs2_dio_end_io (struct kiocb *iocb,loff_t offset,ssize_t bytes) {struct ocfs2_dio_write_ctxt *dwc;struct inode *inode =file_inode (iocb->ki_filp);
include/linux/fs.h +1 -2
@@ -83,8 +83,7 @@ typedef int (get_block_t)(struct inode *inode, sector_t iblock,typedef int (dio_get_block_t )(struct kiocb *iocb,struct inode *inode,sector_t iblock,struct buffer_head *bh_result,int create); -typedef int (dio_iodone_t )(struct kiocb *iocb,loff_t offset, -ssize_t bytes,void *private); +typedef int (dio_iodone_t )(struct kiocb *iocb,loff_t offset,ssize_t bytes);#define MAY_EXEC 0x00000001#define MAY_WRITE 0x00000002
Signature · 1 line
2.18.0
RFC PATCH v2 5/6 fs: pass iocb to direct I/O submit_io()
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
Btrfs abuses current->journal_info in btrfs_direct_IO() in order to pass around some state to get_block() and submit_io(). However, iocb->private is free for Btrfs to use, we just need it passed to submit_io(). Btrfs is the only user of submit_io(), so this doesn't affect any other filesystems.
--- fs/btrfs/inode.c | 4 ++-- fs/direct-io.c | 3 ++- include/linux/fs.h | 4 ++-- 3 files changed, 6 insertions(+), 5 deletions(-)
fs/btrfs/inode.c +2 -2
@@ -8427,8 +8427,8 @@ static int btrfs_submit_direct_hook(struct btrfs_dio_private *dip)return 0 ; } -static void btrfs_submit_direct (struct bio *dio_bio,struct inode *inode, -loff_t file_offset) +static void btrfs_submit_direct (struct kiocb *iocb,struct bio *dio_bio, +struct inode *inode,loff_t file_offset) {struct btrfs_dio_private *dip =NULL ;struct bio *bio =NULL ;
fs/direct-io.c +2 -1
@@ -473,7 +473,8 @@ static inline void dio_bio_submit(struct dio *dio, struct dio_submit *sdio) dio->bio_disk = bio->bi_disk;if (sdio->submit_io) { - sdio->submit_io (bio, dio->inode, sdio->logical_offset_in_bio); + sdio->submit_io (dio->iocb, bio, dio->inode, + sdio->logical_offset_in_bio); dio->bio_cookie =BLK_QC_T_NONE ; }else dio->bio_cookie =submit_bio (bio);
include/linux/fs.h +2 -2
@@ -3003,8 +3003,8 @@ extern int generic_file_open(struct inode * inode, struct file * filp);extern int nonseekable_open (struct inode * inode,struct file * filp);#ifdef CONFIG_BLOCK -typedef void (dio_submit_t )(struct bio *bio,struct inode *inode, -loff_t file_offset); +typedef void (dio_submit_t )(struct kiocb *iocb,struct bio *bio, +struct inode *inode,loff_t file_offset);enum { /* need locking between buffered and direct access */
Signature · 1 line
2.18.0
RFC PATCH v2 6/6 Btrfs: stop abusing current->journal_info in btrfs_direct_IO()
In reply to Omar SandovalFrom: Omar Sandoval <[email protected]>
Now that we can pass around the struct btrfs_dio_data through the different callbacks generically, we don't need to shove it in current->journal_info.
--- fs/btrfs/inode.c | 29 ++++++----------------------- 1 file changed, 6 insertions(+), 23 deletions(-)
fs/btrfs/inode.c +6 -23
@@ -7654,7 +7654,6 @@ static int btrfs_get_blocks_direct_write(struct extent_map **map,WARN_ON (dio_data->reserve < len); dio_data->reserve -= len; dio_data->unsubmitted_oe_range_end = start + len; - current->journal_info = dio_data; out:return ret; }
@@ -7666,7 +7665,7 @@ static int btrfs_get_blocks_direct(struct kiocb *iocb, struct inode *inode,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 = iocb->private;u64 start = iblock << inode->i_blkbits;u64 lockstart, lockend;u64 len = bh_result->b_size;
@@ -7681,25 +7680,13 @@ static int btrfs_get_blocks_direct(struct kiocb *iocb, struct inode *inode, lockstart = start; lockend = start + len -1 ; -if (current->journal_info) { -/* -* Need to pull our outstanding extents and set journal_info to NULL so -* that anything that needs to check if there's a transaction doesn't get -* confused. -*/ - dio_data = current->journal_info; - current->journal_info =NULL ; - } -/* * If this errors out it's because we couldn't invalidate pagecache for * this range and we need to fallback to buffered. */ if (lock_extent_direct (inode, lockstart, lockend, &cached_state, - create)) { - ret = -ENOTBLK ; - goto err; - } + create)) +return -ENOTBLK ; em =btrfs_get_extent (BTRFS_I (inode),NULL ,0 , start, len,0 );if (IS_ERR (em)) {
@@ -7767,9 +7754,6 @@ static int btrfs_get_blocks_direct(struct kiocb *iocb, struct inode *inode, unlock_err:clear_extent_bit (&BTRFS_I (inode)->io_tree, lockstart, lockend, unlock_bits,1 ,0 , &cached_state); -err: -if (dio_data) - current->journal_info = dio_data;return ret; }
@@ -8470,7 +8454,7 @@ static void btrfs_submit_direct(struct kiocb *iocb, struct bio *dio_bio,* time by btrfs_direct_IO(). */ if (write) { -struct btrfs_dio_data *dio_data = current->journal_info; +struct btrfs_dio_data *dio_data = iocb->private; dio_data->unsubmitted_oe_range_end = dip->logical_offset + dip->bytes;
@@ -8612,13 +8596,13 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter)/* * We need to know how many extents we reserved so that we can * do the accounting properly if we go over the number we -* originally calculated. Abuse current->journal_info for this. +* originally calculated. */ dio_data.reserve =round_up (count, fs_info->sectorsize); dio_data.unsubmitted_oe_range_start = (u64 )offset; dio_data.unsubmitted_oe_range_end = (u64 )offset; - current->journal_info = &dio_data; + iocb->private = &dio_data;down_read (&BTRFS_I (inode)->dio_sem); }else if (test_bit (BTRFS_INODE_READDIO_NEED_LOCK , &BTRFS_I (inode)->runtime_flags)) {
@@ -8633,7 +8617,6 @@ static ssize_t btrfs_direct_IO(struct kiocb *iocb, struct iov_iter *iter) btrfs_submit_direct, flags);if (iov_iter_rw (iter) ==WRITE ) {up_read (&BTRFS_I (inode)->dio_sem); - current->journal_info =NULL ;if (ret <0 && ret != -EIOCBQUEUED ) {if (dio_data.reserve) btrfs_delalloc_release_space(inode, data_reserved,
Signature · 1 line
2.18.0