aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/ext4/ext4.h25
-rw-r--r--fs/ext4/page-io.c65
-rw-r--r--fs/ext4/super.c38
3 files changed, 88 insertions, 40 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 8de219b758fb..b69a733b5b42 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -887,12 +887,22 @@ struct ext4_inode_info {
887 qsize_t i_reserved_quota; 887 qsize_t i_reserved_quota;
888#endif 888#endif
889 889
890 /* completed IOs that might need unwritten extents handling */ 890 /* Lock protecting lists below */
891 struct list_head i_completed_io_list;
892 spinlock_t i_completed_io_lock; 891 spinlock_t i_completed_io_lock;
892 /*
893 * Completed IOs that need unwritten extents handling and have
894 * transaction reserved
895 */
896 struct list_head i_rsv_conversion_list;
897 /*
898 * Completed IOs that need unwritten extents handling and don't have
899 * transaction reserved
900 */
901 struct list_head i_unrsv_conversion_list;
893 atomic_t i_ioend_count; /* Number of outstanding io_end structs */ 902 atomic_t i_ioend_count; /* Number of outstanding io_end structs */
894 atomic_t i_unwritten; /* Nr. of inflight conversions pending */ 903 atomic_t i_unwritten; /* Nr. of inflight conversions pending */
895 struct work_struct i_unwritten_work; /* deferred extent conversion */ 904 struct work_struct i_rsv_conversion_work;
905 struct work_struct i_unrsv_conversion_work;
896 906
897 spinlock_t i_block_reservation_lock; 907 spinlock_t i_block_reservation_lock;
898 908
@@ -1264,8 +1274,10 @@ struct ext4_sb_info {
1264 struct flex_groups *s_flex_groups; 1274 struct flex_groups *s_flex_groups;
1265 ext4_group_t s_flex_groups_allocated; 1275 ext4_group_t s_flex_groups_allocated;
1266 1276
1267 /* workqueue for dio unwritten */ 1277 /* workqueue for unreserved extent convertions (dio) */
1268 struct workqueue_struct *dio_unwritten_wq; 1278 struct workqueue_struct *unrsv_conversion_wq;
1279 /* workqueue for reserved extent conversions (buffered io) */
1280 struct workqueue_struct *rsv_conversion_wq;
1269 1281
1270 /* timer for periodic error stats printing */ 1282 /* timer for periodic error stats printing */
1271 struct timer_list s_err_report; 1283 struct timer_list s_err_report;
@@ -2646,7 +2658,8 @@ extern int ext4_put_io_end(ext4_io_end_t *io_end);
2646extern void ext4_put_io_end_defer(ext4_io_end_t *io_end); 2658extern void ext4_put_io_end_defer(ext4_io_end_t *io_end);
2647extern void ext4_io_submit_init(struct ext4_io_submit *io, 2659extern void ext4_io_submit_init(struct ext4_io_submit *io,
2648 struct writeback_control *wbc); 2660 struct writeback_control *wbc);
2649extern void ext4_end_io_work(struct work_struct *work); 2661extern void ext4_end_io_rsv_work(struct work_struct *work);
2662extern void ext4_end_io_unrsv_work(struct work_struct *work);
2650extern void ext4_io_submit(struct ext4_io_submit *io); 2663extern void ext4_io_submit(struct ext4_io_submit *io);
2651extern int ext4_bio_write_page(struct ext4_io_submit *io, 2664extern int ext4_bio_write_page(struct ext4_io_submit *io,
2652 struct page *page, 2665 struct page *page,
diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c
index 5f20bc481041..bcdfd6bdde06 100644
--- a/fs/ext4/page-io.c
+++ b/fs/ext4/page-io.c
@@ -58,8 +58,10 @@ void ext4_ioend_shutdown(struct inode *inode)
58 * We need to make sure the work structure is finished being 58 * We need to make sure the work structure is finished being
59 * used before we let the inode get destroyed. 59 * used before we let the inode get destroyed.
60 */ 60 */
61 if (work_pending(&EXT4_I(inode)->i_unwritten_work)) 61 if (work_pending(&EXT4_I(inode)->i_rsv_conversion_work))
62 cancel_work_sync(&EXT4_I(inode)->i_unwritten_work); 62 cancel_work_sync(&EXT4_I(inode)->i_rsv_conversion_work);
63 if (work_pending(&EXT4_I(inode)->i_unrsv_conversion_work))
64 cancel_work_sync(&EXT4_I(inode)->i_unrsv_conversion_work);
63} 65}
64 66
65static void ext4_release_io_end(ext4_io_end_t *io_end) 67static void ext4_release_io_end(ext4_io_end_t *io_end)
@@ -114,20 +116,17 @@ static int ext4_end_io(ext4_io_end_t *io)
114 return ret; 116 return ret;
115} 117}
116 118
117static void dump_completed_IO(struct inode *inode) 119static void dump_completed_IO(struct inode *inode, struct list_head *head)
118{ 120{
119#ifdef EXT4FS_DEBUG 121#ifdef EXT4FS_DEBUG
120 struct list_head *cur, *before, *after; 122 struct list_head *cur, *before, *after;
121 ext4_io_end_t *io, *io0, *io1; 123 ext4_io_end_t *io, *io0, *io1;
122 124
123 if (list_empty(&EXT4_I(inode)->i_completed_io_list)) { 125 if (list_empty(head))
124 ext4_debug("inode %lu completed_io list is empty\n",
125 inode->i_ino);
126 return; 126 return;
127 }
128 127
129 ext4_debug("Dump inode %lu completed_io list\n", inode->i_ino); 128 ext4_debug("Dump inode %lu completed io list\n", inode->i_ino);
130 list_for_each_entry(io, &EXT4_I(inode)->i_completed_io_list, list) { 129 list_for_each_entry(io, head, list) {
131 cur = &io->list; 130 cur = &io->list;
132 before = cur->prev; 131 before = cur->prev;
133 io0 = container_of(before, ext4_io_end_t, list); 132 io0 = container_of(before, ext4_io_end_t, list);
@@ -148,16 +147,23 @@ static void ext4_add_complete_io(ext4_io_end_t *io_end)
148 unsigned long flags; 147 unsigned long flags;
149 148
150 BUG_ON(!(io_end->flag & EXT4_IO_END_UNWRITTEN)); 149 BUG_ON(!(io_end->flag & EXT4_IO_END_UNWRITTEN));
151 wq = EXT4_SB(io_end->inode->i_sb)->dio_unwritten_wq;
152
153 spin_lock_irqsave(&ei->i_completed_io_lock, flags); 150 spin_lock_irqsave(&ei->i_completed_io_lock, flags);
154 if (list_empty(&ei->i_completed_io_list)) 151 if (io_end->handle) {
155 queue_work(wq, &ei->i_unwritten_work); 152 wq = EXT4_SB(io_end->inode->i_sb)->rsv_conversion_wq;
156 list_add_tail(&io_end->list, &ei->i_completed_io_list); 153 if (list_empty(&ei->i_rsv_conversion_list))
154 queue_work(wq, &ei->i_rsv_conversion_work);
155 list_add_tail(&io_end->list, &ei->i_rsv_conversion_list);
156 } else {
157 wq = EXT4_SB(io_end->inode->i_sb)->unrsv_conversion_wq;
158 if (list_empty(&ei->i_unrsv_conversion_list))
159 queue_work(wq, &ei->i_unrsv_conversion_work);
160 list_add_tail(&io_end->list, &ei->i_unrsv_conversion_list);
161 }
157 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); 162 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
158} 163}
159 164
160static int ext4_do_flush_completed_IO(struct inode *inode) 165static int ext4_do_flush_completed_IO(struct inode *inode,
166 struct list_head *head)
161{ 167{
162 ext4_io_end_t *io; 168 ext4_io_end_t *io;
163 struct list_head unwritten; 169 struct list_head unwritten;
@@ -166,8 +172,8 @@ static int ext4_do_flush_completed_IO(struct inode *inode)
166 int err, ret = 0; 172 int err, ret = 0;
167 173
168 spin_lock_irqsave(&ei->i_completed_io_lock, flags); 174 spin_lock_irqsave(&ei->i_completed_io_lock, flags);
169 dump_completed_IO(inode); 175 dump_completed_IO(inode, head);
170 list_replace_init(&ei->i_completed_io_list, &unwritten); 176 list_replace_init(head, &unwritten);
171 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); 177 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
172 178
173 while (!list_empty(&unwritten)) { 179 while (!list_empty(&unwritten)) {
@@ -183,21 +189,34 @@ static int ext4_do_flush_completed_IO(struct inode *inode)
183} 189}
184 190
185/* 191/*
186 * work on completed aio dio IO, to convert unwritten extents to extents 192 * work on completed IO, to convert unwritten extents to extents
187 */ 193 */
188void ext4_end_io_work(struct work_struct *work) 194void ext4_end_io_rsv_work(struct work_struct *work)
189{ 195{
190 struct ext4_inode_info *ei = container_of(work, struct ext4_inode_info, 196 struct ext4_inode_info *ei = container_of(work, struct ext4_inode_info,
191 i_unwritten_work); 197 i_rsv_conversion_work);
192 ext4_do_flush_completed_IO(&ei->vfs_inode); 198 ext4_do_flush_completed_IO(&ei->vfs_inode, &ei->i_rsv_conversion_list);
199}
200
201void ext4_end_io_unrsv_work(struct work_struct *work)
202{
203 struct ext4_inode_info *ei = container_of(work, struct ext4_inode_info,
204 i_unrsv_conversion_work);
205 ext4_do_flush_completed_IO(&ei->vfs_inode, &ei->i_unrsv_conversion_list);
193} 206}
194 207
195int ext4_flush_unwritten_io(struct inode *inode) 208int ext4_flush_unwritten_io(struct inode *inode)
196{ 209{
197 int ret; 210 int ret, err;
211
198 WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) && 212 WARN_ON_ONCE(!mutex_is_locked(&inode->i_mutex) &&
199 !(inode->i_state & I_FREEING)); 213 !(inode->i_state & I_FREEING));
200 ret = ext4_do_flush_completed_IO(inode); 214 ret = ext4_do_flush_completed_IO(inode,
215 &EXT4_I(inode)->i_rsv_conversion_list);
216 err = ext4_do_flush_completed_IO(inode,
217 &EXT4_I(inode)->i_unrsv_conversion_list);
218 if (!ret)
219 ret = err;
201 ext4_unwritten_wait(inode); 220 ext4_unwritten_wait(inode);
202 return ret; 221 return ret;
203} 222}
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index eac4d3081ba4..7c8e1713e203 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -750,8 +750,10 @@ static void ext4_put_super(struct super_block *sb)
750 ext4_unregister_li_request(sb); 750 ext4_unregister_li_request(sb);
751 dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED); 751 dquot_disable(sb, -1, DQUOT_USAGE_ENABLED | DQUOT_LIMITS_ENABLED);
752 752
753 flush_workqueue(sbi->dio_unwritten_wq); 753 flush_workqueue(sbi->unrsv_conversion_wq);
754 destroy_workqueue(sbi->dio_unwritten_wq); 754 flush_workqueue(sbi->rsv_conversion_wq);
755 destroy_workqueue(sbi->unrsv_conversion_wq);
756 destroy_workqueue(sbi->rsv_conversion_wq);
755 757
756 if (sbi->s_journal) { 758 if (sbi->s_journal) {
757 err = jbd2_journal_destroy(sbi->s_journal); 759 err = jbd2_journal_destroy(sbi->s_journal);
@@ -859,13 +861,15 @@ static struct inode *ext4_alloc_inode(struct super_block *sb)
859 ei->i_reserved_quota = 0; 861 ei->i_reserved_quota = 0;
860#endif 862#endif
861 ei->jinode = NULL; 863 ei->jinode = NULL;
862 INIT_LIST_HEAD(&ei->i_completed_io_list); 864 INIT_LIST_HEAD(&ei->i_rsv_conversion_list);
865 INIT_LIST_HEAD(&ei->i_unrsv_conversion_list);
863 spin_lock_init(&ei->i_completed_io_lock); 866 spin_lock_init(&ei->i_completed_io_lock);
864 ei->i_sync_tid = 0; 867 ei->i_sync_tid = 0;
865 ei->i_datasync_tid = 0; 868 ei->i_datasync_tid = 0;
866 atomic_set(&ei->i_ioend_count, 0); 869 atomic_set(&ei->i_ioend_count, 0);
867 atomic_set(&ei->i_unwritten, 0); 870 atomic_set(&ei->i_unwritten, 0);
868 INIT_WORK(&ei->i_unwritten_work, ext4_end_io_work); 871 INIT_WORK(&ei->i_rsv_conversion_work, ext4_end_io_rsv_work);
872 INIT_WORK(&ei->i_unrsv_conversion_work, ext4_end_io_unrsv_work);
869 873
870 return &ei->vfs_inode; 874 return &ei->vfs_inode;
871} 875}
@@ -3936,12 +3940,20 @@ no_journal:
3936 * The maximum number of concurrent works can be high and 3940 * The maximum number of concurrent works can be high and
3937 * concurrency isn't really necessary. Limit it to 1. 3941 * concurrency isn't really necessary. Limit it to 1.
3938 */ 3942 */
3939 EXT4_SB(sb)->dio_unwritten_wq = 3943 EXT4_SB(sb)->rsv_conversion_wq =
3940 alloc_workqueue("ext4-dio-unwritten", WQ_MEM_RECLAIM | WQ_UNBOUND, 1); 3944 alloc_workqueue("ext4-rsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
3941 if (!EXT4_SB(sb)->dio_unwritten_wq) { 3945 if (!EXT4_SB(sb)->rsv_conversion_wq) {
3942 printk(KERN_ERR "EXT4-fs: failed to create DIO workqueue\n"); 3946 printk(KERN_ERR "EXT4-fs: failed to create workqueue\n");
3943 ret = -ENOMEM; 3947 ret = -ENOMEM;
3944 goto failed_mount_wq; 3948 goto failed_mount4;
3949 }
3950
3951 EXT4_SB(sb)->unrsv_conversion_wq =
3952 alloc_workqueue("ext4-unrsv-conversion", WQ_MEM_RECLAIM | WQ_UNBOUND, 1);
3953 if (!EXT4_SB(sb)->unrsv_conversion_wq) {
3954 printk(KERN_ERR "EXT4-fs: failed to create workqueue\n");
3955 ret = -ENOMEM;
3956 goto failed_mount4;
3945 } 3957 }
3946 3958
3947 /* 3959 /*
@@ -4095,7 +4107,10 @@ failed_mount4a:
4095 sb->s_root = NULL; 4107 sb->s_root = NULL;
4096failed_mount4: 4108failed_mount4:
4097 ext4_msg(sb, KERN_ERR, "mount failed"); 4109 ext4_msg(sb, KERN_ERR, "mount failed");
4098 destroy_workqueue(EXT4_SB(sb)->dio_unwritten_wq); 4110 if (EXT4_SB(sb)->rsv_conversion_wq)
4111 destroy_workqueue(EXT4_SB(sb)->rsv_conversion_wq);
4112 if (EXT4_SB(sb)->unrsv_conversion_wq)
4113 destroy_workqueue(EXT4_SB(sb)->unrsv_conversion_wq);
4099failed_mount_wq: 4114failed_mount_wq:
4100 if (sbi->s_journal) { 4115 if (sbi->s_journal) {
4101 jbd2_journal_destroy(sbi->s_journal); 4116 jbd2_journal_destroy(sbi->s_journal);
@@ -4541,7 +4556,8 @@ static int ext4_sync_fs(struct super_block *sb, int wait)
4541 struct ext4_sb_info *sbi = EXT4_SB(sb); 4556 struct ext4_sb_info *sbi = EXT4_SB(sb);
4542 4557
4543 trace_ext4_sync_fs(sb, wait); 4558 trace_ext4_sync_fs(sb, wait);
4544 flush_workqueue(sbi->dio_unwritten_wq); 4559 flush_workqueue(sbi->rsv_conversion_wq);
4560 flush_workqueue(sbi->unrsv_conversion_wq);
4545 /* 4561 /*
4546 * Writeback quota in non-journalled quota case - journalled quota has 4562 * Writeback quota in non-journalled quota case - journalled quota has
4547 * no dirty dquots 4563 * no dirty dquots