diff options
author | Jan Kara <jack@suse.cz> | 2013-01-28 09:43:46 -0500 |
---|---|---|
committer | Theodore Ts'o <tytso@mit.edu> | 2013-01-28 09:43:46 -0500 |
commit | 84c17543ab5685d950da73209df0ecda26e72d3b (patch) | |
tree | c7f2025fa8bcc209168d171c825060ff95a2be97 /fs/ext4 | |
parent | fe089c77f1466c74f0f19ad2475b1630216b8b19 (diff) |
ext4: move work from io_end to inode
It does not make much sense to have struct work in ext4_io_end_t
because we always use it for only one ext4_io_end_t per inode (the
first one in the i_completed_io list). So just move the structure to
inode itself. This also allows for a small simplification in
processing io_end structures.
Signed-off-by: Jan Kara <jack@suse.cz>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs/ext4')
-rw-r--r-- | fs/ext4/ext4.h | 6 | ||||
-rw-r--r-- | fs/ext4/page-io.c | 33 | ||||
-rw-r--r-- | fs/ext4/super.c | 1 |
3 files changed, 13 insertions, 27 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index 0ccda0c9682e..d93393eb5f2d 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h | |||
@@ -194,8 +194,7 @@ struct mpage_da_data { | |||
194 | */ | 194 | */ |
195 | #define EXT4_IO_END_UNWRITTEN 0x0001 | 195 | #define EXT4_IO_END_UNWRITTEN 0x0001 |
196 | #define EXT4_IO_END_ERROR 0x0002 | 196 | #define EXT4_IO_END_ERROR 0x0002 |
197 | #define EXT4_IO_END_QUEUED 0x0004 | 197 | #define EXT4_IO_END_DIRECT 0x0004 |
198 | #define EXT4_IO_END_DIRECT 0x0008 | ||
199 | 198 | ||
200 | struct ext4_io_page { | 199 | struct ext4_io_page { |
201 | struct page *p_page; | 200 | struct page *p_page; |
@@ -217,7 +216,6 @@ typedef struct ext4_io_end { | |||
217 | unsigned int flag; /* unwritten or not */ | 216 | unsigned int flag; /* unwritten or not */ |
218 | loff_t offset; /* offset in the file */ | 217 | loff_t offset; /* offset in the file */ |
219 | ssize_t size; /* size of the extent */ | 218 | ssize_t size; /* size of the extent */ |
220 | struct work_struct work; /* data work queue */ | ||
221 | struct kiocb *iocb; /* iocb struct for AIO */ | 219 | struct kiocb *iocb; /* iocb struct for AIO */ |
222 | int result; /* error value for AIO */ | 220 | int result; /* error value for AIO */ |
223 | int num_io_pages; /* for writepages() */ | 221 | int num_io_pages; /* for writepages() */ |
@@ -929,6 +927,7 @@ struct ext4_inode_info { | |||
929 | spinlock_t i_completed_io_lock; | 927 | spinlock_t i_completed_io_lock; |
930 | atomic_t i_ioend_count; /* Number of outstanding io_end structs */ | 928 | atomic_t i_ioend_count; /* Number of outstanding io_end structs */ |
931 | atomic_t i_unwritten; /* Nr. of inflight conversions pending */ | 929 | atomic_t i_unwritten; /* Nr. of inflight conversions pending */ |
930 | struct work_struct i_unwritten_work; /* deferred extent conversion */ | ||
932 | 931 | ||
933 | spinlock_t i_block_reservation_lock; | 932 | spinlock_t i_block_reservation_lock; |
934 | 933 | ||
@@ -2538,6 +2537,7 @@ extern void ext4_exit_pageio(void); | |||
2538 | extern void ext4_ioend_wait(struct inode *); | 2537 | extern void ext4_ioend_wait(struct inode *); |
2539 | extern void ext4_free_io_end(ext4_io_end_t *io); | 2538 | extern void ext4_free_io_end(ext4_io_end_t *io); |
2540 | extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags); | 2539 | extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags); |
2540 | extern void ext4_end_io_work(struct work_struct *work); | ||
2541 | extern void ext4_io_submit(struct ext4_io_submit *io); | 2541 | extern void ext4_io_submit(struct ext4_io_submit *io); |
2542 | extern int ext4_bio_write_page(struct ext4_io_submit *io, | 2542 | extern int ext4_bio_write_page(struct ext4_io_submit *io, |
2543 | struct page *page, | 2543 | struct page *page, |
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 05795f10e55a..a0290176ee75 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c | |||
@@ -151,16 +151,13 @@ void ext4_add_complete_io(ext4_io_end_t *io_end) | |||
151 | wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; | 151 | wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq; |
152 | 152 | ||
153 | spin_lock_irqsave(&ei->i_completed_io_lock, flags); | 153 | spin_lock_irqsave(&ei->i_completed_io_lock, flags); |
154 | if (list_empty(&ei->i_completed_io_list)) { | 154 | if (list_empty(&ei->i_completed_io_list)) |
155 | io_end->flag |= EXT4_IO_END_QUEUED; | 155 | queue_work(wq, &ei->i_unwritten_work); |
156 | queue_work(wq, &io_end->work); | ||
157 | } | ||
158 | list_add_tail(&io_end->list, &ei->i_completed_io_list); | 156 | list_add_tail(&io_end->list, &ei->i_completed_io_list); |
159 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); | 157 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); |
160 | } | 158 | } |
161 | 159 | ||
162 | static int ext4_do_flush_completed_IO(struct inode *inode, | 160 | static int ext4_do_flush_completed_IO(struct inode *inode) |
163 | ext4_io_end_t *work_io) | ||
164 | { | 161 | { |
165 | ext4_io_end_t *io; | 162 | ext4_io_end_t *io; |
166 | struct list_head unwritten, complete, to_free; | 163 | struct list_head unwritten, complete, to_free; |
@@ -191,19 +188,7 @@ static int ext4_do_flush_completed_IO(struct inode *inode, | |||
191 | while (!list_empty(&complete)) { | 188 | while (!list_empty(&complete)) { |
192 | io = list_entry(complete.next, ext4_io_end_t, list); | 189 | io = list_entry(complete.next, ext4_io_end_t, list); |
193 | io->flag &= ~EXT4_IO_END_UNWRITTEN; | 190 | io->flag &= ~EXT4_IO_END_UNWRITTEN; |
194 | /* end_io context can not be destroyed now because it still | 191 | list_move(&io->list, &to_free); |
195 | * used by queued worker. Worker thread will destroy it later */ | ||
196 | if (io->flag & EXT4_IO_END_QUEUED) | ||
197 | list_del_init(&io->list); | ||
198 | else | ||
199 | list_move(&io->list, &to_free); | ||
200 | } | ||
201 | /* If we are called from worker context, it is time to clear queued | ||
202 | * flag, and destroy it's end_io if it was converted already */ | ||
203 | if (work_io) { | ||
204 | work_io->flag &= ~EXT4_IO_END_QUEUED; | ||
205 | if (!(work_io->flag & EXT4_IO_END_UNWRITTEN)) | ||
206 | list_add_tail(&work_io->list, &to_free); | ||
207 | } | 192 | } |
208 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); | 193 | spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); |
209 | 194 | ||
@@ -218,10 +203,11 @@ static int ext4_do_flush_completed_IO(struct inode *inode, | |||
218 | /* | 203 | /* |
219 | * work on completed aio dio IO, to convert unwritten extents to extents | 204 | * work on completed aio dio IO, to convert unwritten extents to extents |
220 | */ | 205 | */ |
221 | static void ext4_end_io_work(struct work_struct *work) | 206 | void ext4_end_io_work(struct work_struct *work) |
222 | { | 207 | { |
223 | ext4_io_end_t *io = container_of(work, ext4_io_end_t, work); | 208 | struct ext4_inode_info *ei = container_of(work, struct ext4_inode_info, |
224 | ext4_do_flush_completed_IO(io->inode, io); | 209 | i_unwritten_work); |
210 | ext4_do_flush_completed_IO(&ei->vfs_inode); | ||
225 | } | 211 | } |
226 | 212 | ||
227 | int ext4_flush_unwritten_io(struct inode *inode) | 213 | int ext4_flush_unwritten_io(struct inode *inode) |
@@ -229,7 +215,7 @@ int ext4_flush_unwritten_io(struct inode *inode) | |||
229 | int ret; | 215 | int ret; |
230 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) && | 216 | WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) && |
231 | !(inode->i_state & I_FREEING)); | 217 | !(inode->i_state & I_FREEING)); |
232 | ret = ext4_do_flush_completed_IO(inode, NULL); | 218 | ret = ext4_do_flush_completed_IO(inode); |
233 | ext4_unwritten_wait(inode); | 219 | ext4_unwritten_wait(inode); |
234 | return ret; | 220 | return ret; |
235 | } | 221 | } |
@@ -240,7 +226,6 @@ ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags) | |||
240 | if (io) { | 226 | if (io) { |
241 | atomic_inc(&EXT4_I(inode)->i_ioend_count); | 227 | atomic_inc(&EXT4_I(inode)->i_ioend_count); |
242 | io->inode = inode; | 228 | io->inode = inode; |
243 | INIT_WORK(&io->work, ext4_end_io_work); | ||
244 | INIT_LIST_HEAD(&io->list); | 229 | INIT_LIST_HEAD(&io->list); |
245 | } | 230 | } |
246 | return io; | 231 | return io; |
diff --git a/fs/ext4/super.c b/fs/ext4/super.c index d5d336bd2180..dc0fb7b942cf 100644 --- a/fs/ext4/super.c +++ b/fs/ext4/super.c | |||
@@ -960,6 +960,7 @@ static struct inode *ext4_alloc_inode(struct super_block *sb) | |||
960 | ei->i_datasync_tid = 0; | 960 | ei->i_datasync_tid = 0; |
961 | atomic_set(&ei->i_ioend_count, 0); | 961 | atomic_set(&ei->i_ioend_count, 0); |
962 | atomic_set(&ei->i_unwritten, 0); | 962 | atomic_set(&ei->i_unwritten, 0); |
963 | INIT_WORK(&ei->i_unwritten_work, ext4_end_io_work); | ||
963 | 964 | ||
964 | return &ei->vfs_inode; | 965 | return &ei->vfs_inode; |
965 | } | 966 | } |