From: Zach Brown <zab@xxxxxxxxx> This adds a helper function which allocates and initializes the dio structure. We'll be calling this from another entry point like __blockdev_direct_IO() in an upcoming patch. Signed-off-by: Dave Kleikamp <dave.kleikamp@xxxxxxxxxx> Cc: Zach Brown <zab@xxxxxxxxx> --- fs/direct-io.c | 68 ++++++++++++++++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 26 deletions(-) diff --git a/fs/direct-io.c b/fs/direct-io.c index 21a1412..1fbb4ab 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -1096,6 +1096,47 @@ static int dio_aligned(unsigned long offset, unsigned *blkbits, return 1; } +static struct dio *dio_alloc_init(int flags, int rw, struct kiocb *iocb, + struct inode *inode, dio_iodone_t end_io, + loff_t end) +{ + struct dio *dio; + + dio = kmem_cache_alloc(dio_cache, GFP_KERNEL); + if (!dio) + return NULL; + + /* + * Believe it or not, zeroing out the page array caused a .5% + * performance regression in a database benchmark. So, we take + * care to only zero out what's needed. + */ + memset(dio, 0, offsetof(struct dio, pages)); + + dio->flags = flags; + /* + * For file extending writes updating i_size before data + * writeouts complete can expose uninitialized blocks. So + * even for AIO, we need to wait for i/o to complete before + * returning in this case. + */ + dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) && + (end > i_size_read(inode))); + + dio->inode = inode; + dio->rw = rw; + + dio->end_io = end_io; + + dio->iocb = iocb; + dio->i_size = i_size_read(inode); + + spin_lock_init(&dio->bio_lock); + dio->refcount = 1; + + return dio; +} + /* * This is a library function for use by filesystem drivers. * @@ -1158,18 +1199,11 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, if (rw == READ && end == offset) return 0; - dio = kmem_cache_alloc(dio_cache, GFP_KERNEL); + dio = dio_alloc_init(flags, rw, iocb, inode, end_io, end); retval = -ENOMEM; if (!dio) goto out; - /* - * Believe it or not, zeroing out the page array caused a .5% - * performance regression in a database benchmark. So, we take - * care to only zero out what's needed. - */ - memset(dio, 0, offsetof(struct dio, pages)); - dio->flags = flags; if (dio->flags & DIO_LOCKING) { if (rw == READ) { struct address_space *mapping = @@ -1193,35 +1227,17 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, */ atomic_inc(&inode->i_dio_count); - /* - * For file extending writes updating i_size before data - * writeouts complete can expose uninitialized blocks. So - * even for AIO, we need to wait for i/o to complete before - * returning in this case. - */ - dio->is_async = !is_sync_kiocb(iocb) && !((rw & WRITE) && - (end > i_size_read(inode))); - retval = 0; - dio->inode = inode; - dio->rw = rw; sdio.blkbits = blkbits; sdio.blkfactor = inode->i_blkbits - blkbits; sdio.block_in_file = offset >> blkbits; sdio.get_block = get_block; - dio->end_io = end_io; sdio.submit_io = submit_io; sdio.final_block_in_bio = -1; sdio.next_block_for_io = -1; - dio->iocb = iocb; - dio->i_size = i_size_read(inode); - - spin_lock_init(&dio->bio_lock); - dio->refcount = 1; - /* * In case of non-aligned buffers, we may need 2 more * pages since we need to zero out first and last block. -- 1.7.9.2 -- To unsubscribe from this list: send the line "unsubscribe linux-fsdevel" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html