direct-io: Implement generic deferred AIO completions
Add support to the core direct-io code to defer AIO completions to user context using a workqueue. This replaces opencoded and less efficient code in XFS and ext4 (we save a memory allocation for each direct IO) and will be needed to properly support O_(D)SYNC for AIO. The communication between the filesystem and the direct I/O code requires a new buffer head flag, which is a bit ugly but not avoidable until the direct I/O code stops abusing the buffer_head structure for communicating with the filesystems. Currently this creates a per-superblock unbound workqueue for these completions, which is taken from an earlier patch by Jan Kara. I'm not really convinced about this use and would prefer a "normal" global workqueue with a high concurrency limit, but this needs further discussion. JK: Fixed ext4 part, dynamic allocation of the workqueue. Signed-off-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
This commit is contained in:
committed by
Al Viro
parent
4b6ccca701
commit
7b7a8665ed
@ -180,7 +180,6 @@ struct ext4_map_blocks {
|
||||
* Flags for ext4_io_end->flags
|
||||
*/
|
||||
#define EXT4_IO_END_UNWRITTEN 0x0001
|
||||
#define EXT4_IO_END_DIRECT 0x0002
|
||||
|
||||
/*
|
||||
* For converting uninitialized extents on a work queue. 'handle' is used for
|
||||
@ -196,8 +195,6 @@ typedef struct ext4_io_end {
|
||||
unsigned int flag; /* unwritten or not */
|
||||
loff_t offset; /* offset in the file */
|
||||
ssize_t size; /* size of the extent */
|
||||
struct kiocb *iocb; /* iocb struct for AIO */
|
||||
int result; /* error value for AIO */
|
||||
atomic_t count; /* reference counter */
|
||||
} ext4_io_end_t;
|
||||
|
||||
@ -900,11 +897,9 @@ struct ext4_inode_info {
|
||||
* Completed IOs that need unwritten extents handling and don't have
|
||||
* transaction reserved
|
||||
*/
|
||||
struct list_head i_unrsv_conversion_list;
|
||||
atomic_t i_ioend_count; /* Number of outstanding io_end structs */
|
||||
atomic_t i_unwritten; /* Nr. of inflight conversions pending */
|
||||
struct work_struct i_rsv_conversion_work;
|
||||
struct work_struct i_unrsv_conversion_work;
|
||||
|
||||
spinlock_t i_block_reservation_lock;
|
||||
|
||||
@ -1276,8 +1271,6 @@ struct ext4_sb_info {
|
||||
struct flex_groups *s_flex_groups;
|
||||
ext4_group_t s_flex_groups_allocated;
|
||||
|
||||
/* workqueue for unreserved extent convertions (dio) */
|
||||
struct workqueue_struct *unrsv_conversion_wq;
|
||||
/* workqueue for reserved extent conversions (buffered io) */
|
||||
struct workqueue_struct *rsv_conversion_wq;
|
||||
|
||||
@ -1340,9 +1333,6 @@ static inline void ext4_set_io_unwritten_flag(struct inode *inode,
|
||||
struct ext4_io_end *io_end)
|
||||
{
|
||||
if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
|
||||
/* Writeback has to have coversion transaction reserved */
|
||||
WARN_ON(EXT4_SB(inode->i_sb)->s_journal && !io_end->handle &&
|
||||
!(io_end->flag & EXT4_IO_END_DIRECT));
|
||||
io_end->flag |= EXT4_IO_END_UNWRITTEN;
|
||||
atomic_inc(&EXT4_I(inode)->i_unwritten);
|
||||
}
|
||||
@ -2716,7 +2706,6 @@ extern void ext4_put_io_end_defer(ext4_io_end_t *io_end);
|
||||
extern void ext4_io_submit_init(struct ext4_io_submit *io,
|
||||
struct writeback_control *wbc);
|
||||
extern void ext4_end_io_rsv_work(struct work_struct *work);
|
||||
extern void ext4_end_io_unrsv_work(struct work_struct *work);
|
||||
extern void ext4_io_submit(struct ext4_io_submit *io);
|
||||
extern int ext4_bio_write_page(struct ext4_io_submit *io,
|
||||
struct page *page,
|
||||
|
Reference in New Issue
Block a user