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>
Bu işleme şunda yer alıyor:

işlemeyi yapan:
Al Viro

ebeveyn
4b6ccca701
işleme
7b7a8665ed
@@ -762,9 +762,7 @@ static void ext4_put_super(struct super_block *sb)
|
||||
ext4_unregister_li_request(sb);
|
||||
dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
|
||||
|
||||
flush_workqueue(sbi->unrsv_conversion_wq);
|
||||
flush_workqueue(sbi->rsv_conversion_wq);
|
||||
destroy_workqueue(sbi->unrsv_conversion_wq);
|
||||
destroy_workqueue(sbi->rsv_conversion_wq);
|
||||
|
||||
if (sbi->s_journal) {
|
||||
@@ -875,14 +873,12 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
|
||||
#endif
|
||||
ei->jinode = NULL;
|
||||
INIT_LIST_HEAD(&ei->i_rsv_conversion_list);
|
||||
INIT_LIST_HEAD(&ei->i_unrsv_conversion_list);
|
||||
spin_lock_init(&ei->i_completed_io_lock);
|
||||
ei->i_sync_tid = 0;
|
||||
ei->i_datasync_tid = 0;
|
||||
atomic_set(&ei->i_ioend_count, 0);
|
||||
atomic_set(&ei->i_unwritten, 0);
|
||||
INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
|
||||
INIT_WORK(&ei->i_unrsv_conversion_work, ext4_end_io_unrsv_work);
|
||||
|
||||
return &ei->vfs_inode;
|
||||
}
|
||||
@@ -3954,14 +3950,6 @@ no_journal:
|
||||
goto failed_mount4;
|
||||
}
|
||||
|
||||
EXT4_SB(sb)->unrsv_conversion_wq =
|
||||
alloc_workqueue("ext4-unrsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
|
||||
if (!EXT4_SB(sb)->unrsv_conversion_wq) {
|
||||
printk(KERN_ERR "EXT4-fs: failed to create workqueue\n");
|
||||
ret = -ENOMEM;
|
||||
goto failed_mount4;
|
||||
}
|
||||
|
||||
/*
|
||||
* The jbd2_journal_load will have done any necessary log recovery,
|
||||
* so we can safely mount the rest of the filesystem now.
|
||||
@@ -4115,8 +4103,6 @@ failed_mount4:
|
||||
ext4_msg(sb, KERN_ERR, "mount failed");
|
||||
if (EXT4_SB(sb)->rsv_conversion_wq)
|
||||
destroy_workqueue(EXT4_SB(sb)->rsv_conversion_wq);
|
||||
if (EXT4_SB(sb)->unrsv_conversion_wq)
|
||||
destroy_workqueue(EXT4_SB(sb)->unrsv_conversion_wq);
|
||||
failed_mount_wq:
|
||||
if (sbi->s_journal) {
|
||||
jbd2_journal_destroy(sbi->s_journal);
|
||||
@@ -4564,7 +4550,6 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
|
||||
|
||||
trace_ext4_sync_fs(sb, wait);
|
||||
flush_workqueue(sbi->rsv_conversion_wq);
|
||||
flush_workqueue(sbi->unrsv_conversion_wq);
|
||||
/*
|
||||
* Writeback quota in non-journalled quota case - journalled quota has
|
||||
* no dirty dquots
|
||||
@@ -4600,7 +4585,6 @@ static int ext4_sync_fs_nojournal(struct super_block *sb, int wait)
|
||||
|
||||
trace_ext4_sync_fs(sb, wait);
|
||||
flush_workqueue(EXT4_SB(sb)->rsv_conversion_wq);
|
||||
flush_workqueue(EXT4_SB(sb)->unrsv_conversion_wq);
|
||||
dquot_writeback_dquots(sb, -1);
|
||||
if (wait && test_opt(sb, BARRIER))
|
||||
ret = blkdev_issue_flush(sb->s_bdev, GFP_KERNEL, NULL);
|
||||
|
Yeni konuda referans
Bir kullanıcı engelle