aboutsummaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h6
-rw-r--r--fs/ext4/page-io.c33
-rw-r--r--fs/ext4/super.c1
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
200struct ext4_io_page { 199struct 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);
2538extern void ext4_ioend_wait(struct inode *); 2537extern void ext4_ioend_wait(struct inode *);
2539extern void ext4_free_io_end(ext4_io_end_t *io); 2538extern void ext4_free_io_end(ext4_io_end_t *io);
2540extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags); 2539extern ext4_io_end_t *ext4_init_io_end(struct inode *inode, gfp_t flags);
2540extern void ext4_end_io_work(struct work_struct *work);
2541extern void ext4_io_submit(struct ext4_io_submit *io); 2541extern void ext4_io_submit(struct ext4_io_submit *io);
2542extern int ext4_bio_write_page(struct ext4_io_submit *io, 2542extern 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
162static int ext4_do_flush_completed_IO(struct inode *inode, 160static 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 */
221static void ext4_end_io_work(struct work_struct *work) 206void 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
227int ext4_flush_unwritten_io(struct inode *inode) 213int 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}