diff options
author | Christoph Hellwig <hch@infradead.org> | 2013-09-04 09:04:39 -0400 |
---|---|---|
committer | Al Viro <viro@zeniv.linux.org.uk> | 2013-09-04 09:23:46 -0400 |
commit | 7b7a8665edd8db733980389b098530f9e4f630b2 (patch) | |
tree | 968d570a9f0c4d861226aefed2f5f97a131c8d53 /fs/super.c | |
parent | 4b6ccca701ef5977d0ffbc2c932430dea88b38b6 (diff) |
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>
Diffstat (limited to 'fs/super.c')
-rw-r--r-- | fs/super.c | 18 |
1 files changed, 9 insertions, 9 deletions
diff --git a/fs/super.c b/fs/super.c index 68307c029228..5536a95186e2 100644 --- a/fs/super.c +++ b/fs/super.c | |||
@@ -152,15 +152,9 @@ static struct super_block *alloc_super(struct file_system_type *type, int flags) | |||
152 | static const struct super_operations default_op; | 152 | static const struct super_operations default_op; |
153 | 153 | ||
154 | if (s) { | 154 | if (s) { |
155 | if (security_sb_alloc(s)) { | 155 | if (security_sb_alloc(s)) |
156 | /* | 156 | goto out_free_sb; |
157 | * We cannot call security_sb_free() without | 157 | |
158 | * security_sb_alloc() succeeding. So bail out manually | ||
159 | */ | ||
160 | kfree(s); | ||
161 | s = NULL; | ||
162 | goto out; | ||
163 | } | ||
164 | #ifdef CONFIG_SMP | 158 | #ifdef CONFIG_SMP |
165 | s->s_files = alloc_percpu(struct list_head); | 159 | s->s_files = alloc_percpu(struct list_head); |
166 | if (!s->s_files) | 160 | if (!s->s_files) |
@@ -228,6 +222,7 @@ err_out: | |||
228 | free_percpu(s->s_files); | 222 | free_percpu(s->s_files); |
229 | #endif | 223 | #endif |
230 | destroy_sb_writers(s); | 224 | destroy_sb_writers(s); |
225 | out_free_sb: | ||
231 | kfree(s); | 226 | kfree(s); |
232 | s = NULL; | 227 | s = NULL; |
233 | goto out; | 228 | goto out; |
@@ -414,6 +409,11 @@ void generic_shutdown_super(struct super_block *sb) | |||
414 | 409 | ||
415 | evict_inodes(sb); | 410 | evict_inodes(sb); |
416 | 411 | ||
412 | if (sb->s_dio_done_wq) { | ||
413 | destroy_workqueue(sb->s_dio_done_wq); | ||
414 | sb->s_dio_done_wq = NULL; | ||
415 | } | ||
416 | |||
417 | if (sop->put_super) | 417 | if (sop->put_super) |
418 | sop->put_super(sb); | 418 | sop->put_super(sb); |
419 | 419 | ||