aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorJan Kara <jack@suse.cz>2013-06-04 14:21:02 -0400
committerTheodore Ts'o <tytso@mit.edu>2013-06-04 14:21:02 -0400
commit2e8fa54e3b48e4ce8c4e9ca4674ffbc973f58be5 (patch)
treeef95b6ad8bac51264484db5c37db66b8047b8bd7 /fs
parent6b523df4fb5ae281ddbc817f40504b33e6226554 (diff)
ext4: split extent conversion lists to reserved & unreserved parts
Now that we have extent conversions with reserved transaction, we have to prevent extent conversions without reserved transaction (from DIO code) to block these (as that would effectively void any transaction reservation we did). So split lists, work items, and work queues to reserved and unreserved parts. Reviewed-by: Zheng Liu <wenqing.lz@taobao.com> Signed-off-by: Jan Kara <jack@suse.cz> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
Diffstat (limited to 'fs')
-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