From: Jens Axboe Date: Sun, 21 Apr 2013 04:27:25 +0000 (-0700) Subject: fs: only inc/dec inode->i_dio_count for file systems X-Git-Url: https://git.kernel.dk/?a=commitdiff_plain;h=refs%2Fheads%2Faio-dio;p=linux-2.6-block.git fs: only inc/dec inode->i_dio_count for file systems We don't need truncate protection for block devices, so add a flag bypassing this cache line dirtying for every IO. Signed-off-by: Jens Axboe --- diff --git a/fs/block_dev.c b/fs/block_dev.c index aae187a7f94a..00a6f9efce51 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -164,7 +164,8 @@ blkdev_direct_IO(int rw, struct kiocb *iocb, const struct iovec *iov, struct inode *inode = file->f_mapping->host; return __blockdev_direct_IO(rw, iocb, inode, I_BDEV(inode), iov, offset, - nr_segs, blkdev_get_block, NULL, NULL, 0); + nr_segs, blkdev_get_block, NULL, NULL, + DIO_IGNORE_TRUNCATE); } int __sync_blockdev(struct block_device *bdev, int wait) diff --git a/fs/direct-io.c b/fs/direct-io.c index 9e639f0edf5c..f66555cdf203 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -266,7 +266,11 @@ static ssize_t dio_complete(struct dio *dio, loff_t offset, ssize_t ret, bool is dio->end_io(dio->iocb, offset, transferred, dio->private, ret, is_async); } else { - inode_dio_done(dio->inode); + if (dio->flags & DIO_IGNORE_TRUNCATE) + __inode_dio_done(dio->inode); + else + inode_dio_done(dio->inode); + if (is_async) aio_complete(dio->iocb, ret, 0); } @@ -1125,9 +1129,12 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode, } /* - * Will be decremented at I/O completion time. + * Will be decremented at I/O completion time. For a block device + * we don't need to protect against truncate, so don't increment + * the inode direct IO count. */ - atomic_inc(&inode->i_dio_count); + if (!(dio->flags & DIO_IGNORE_TRUNCATE)) + atomic_inc(&inode->i_dio_count); /* * For file extending writes updating i_size before data diff --git a/fs/inode.c b/fs/inode.c index a898b3d43ccf..6878ba8979ff 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -1883,6 +1883,11 @@ void inode_dio_wait(struct inode *inode) } EXPORT_SYMBOL(inode_dio_wait); +void __inode_dio_done(struct inode *inode) +{ + wake_up_bit(&inode->i_state, __I_DIO_WAKEUP); +} + /* * inode_dio_done - signal finish of a direct I/O requests * @inode: inode the direct I/O happens on @@ -1893,6 +1898,6 @@ EXPORT_SYMBOL(inode_dio_wait); void inode_dio_done(struct inode *inode) { if (atomic_dec_and_test(&inode->i_dio_count)) - wake_up_bit(&inode->i_state, __I_DIO_WAKEUP); + __inode_dio_done(inode); } EXPORT_SYMBOL(inode_dio_done); diff --git a/include/linux/fs.h b/include/linux/fs.h index 2c28271ab9d4..db36094768ea 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -2433,6 +2433,9 @@ enum { /* filesystem does not support filling holes */ DIO_SKIP_HOLES = 0x02, + + /* inode/fs/bdev does not need truncate protection */ + DIO_IGNORE_TRUNCATE = 0x04, }; void dio_end_io(struct bio *bio, int error); @@ -2453,6 +2456,7 @@ static inline ssize_t blockdev_direct_IO(int rw, struct kiocb *iocb, #endif void inode_dio_wait(struct inode *inode); +void __inode_dio_done(struct inode *inode); void inode_dio_done(struct inode *inode); extern const struct file_operations generic_ro_fops;