History

writeback: Generalize and expose wb_completion

wb_completion is used to track writeback completions. We want to use it from memcg side for foreign inode flushes. This patch updates it to remember the target waitq instead of assuming bdi->wb_waitq and expose it outside of fs-writeback.c.

Tejun Heo committed 7 years ago

Commit 5b9cce41 parent 38b4e093 files · +36 −33Browse files

Unified · Split

3 files
  1. fs/fs-writeback.c +14 −33
  2. include/linux/backing-dev-defs.h +20 −0
  3. include/linux/backing-dev.h +2 −0
fs/fs-writeback.c+14−33
@@ -36,10 +36,6 @@ · 35 unmodified lines
3636 */
3737 #define MIN_WRITEBACK_PAGES (4096UL >> (PAGE_SHIFT - 10))
3838
39−struct wb_completion {
40− atomic_t cnt;
41−};
42−
4339 /*
4440 * Passed into wb_writeback(), essentially a subset of writeback_control
4541 */
@@ -60,19 +56,6 @@ struct wb_writeback_work { · 14 unmodified lines
6056 struct wb_completion *done; /* set if the caller waits */
6157 };
6258
63−/*
64− * If one wants to wait for one or more wb_writeback_works, each work's
65− * ->done should be set to a wb_completion defined using the following
66− * macro. Once all work items are issued with wb_queue_work(), the caller
67− * can wait for the completion of all using wb_wait_for_completion(). Work
68− * items which are waited upon aren't freed automatically on completion.
69− */
70−#define DEFINE_WB_COMPLETION_ONSTACK(cmpl) \
71− struct wb_completion cmpl = { \
72− .cnt = ATOMIC_INIT(1), \
73− }
74−
75−
7659 /*
7760 * If an inode is constantly having its pages dirtied, but then the
7861 * updates stop dirtytime_expire_interval seconds in the past, it's
@@ -182,7 +165,7 @@ static void finish_writeback_work(struct bdi_writeback *wb, · 103 unmodified lines
182165 if (work->auto_free)
183166 kfree(work);
184167 if (done && atomic_dec_and_test(&done->cnt))
185− wake_up_all(&wb->bdi->wb_waitq);
168+ wake_up_all(done->waitq);
186169 }
187170
188171 static void wb_queue_work(struct bdi_writeback *wb,
@@ -206,20 +189,18 @@ static void wb_queue_work(struct bdi_writeback *wb, · 17 unmodified lines
206189
207190 /**
208191 * wb_wait_for_completion - wait for completion of bdi_writeback_works
209− * @bdi: bdi work items were issued to
210192 * @done: target wb_completion
211193 *
212194 * Wait for one or more work items issued to @bdi with their ->done field
213− * set to @done, which should have been defined with
214− * DEFINE_WB_COMPLETION_ONSTACK(). This function returns after all such
215− * work items are completed. Work items which are waited upon aren't freed
195+ * set to @done, which should have been initialized with
196+ * DEFINE_WB_COMPLETION(). This function returns after all such work items
197+ * are completed. Work items which are waited upon aren't freed
216198 * automatically on completion.
217199 */
218−static void wb_wait_for_completion(struct backing_dev_info *bdi,
219− struct wb_completion *done)
200+void wb_wait_for_completion(struct wb_completion *done)
220201 {
221202 atomic_dec(&done->cnt); /* put down the initial count */
222− wait_event(bdi->wb_waitq, !atomic_read(&done->cnt));
203+ wait_event(*done->waitq, !atomic_read(&done->cnt));
223204 }
224205
225206 #ifdef CONFIG_CGROUP_WRITEBACK
@@ -854,7 +835,7 @@ static void bdi_split_work_to_wbs(struct backing_dev_info *bdi, · 628 unmodified lines
854835 restart:
855836 rcu_read_lock();
856837 list_for_each_entry_continue_rcu(wb, &bdi->wb_list, bdi_node) {
857− DEFINE_WB_COMPLETION_ONSTACK(fallback_work_done);
838+ DEFINE_WB_COMPLETION(fallback_work_done, bdi);
858839 struct wb_writeback_work fallback_work;
859840 struct wb_writeback_work *work;
860841 long nr_pages;
@@ -901,7 +882,7 @@ restart: · 40 unmodified lines
901882 last_wb = wb;
902883
903884 rcu_read_unlock();
904− wb_wait_for_completion(bdi, &fallback_work_done);
885+ wb_wait_for_completion(&fallback_work_done);
905886 goto restart;
906887 }
907888 rcu_read_unlock();
@@ -2373,7 +2354,8 @@ static void wait_sb_inodes(struct super_block *sb) · 1465 unmodified lines
23732354 static void __writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr,
23742355 enum wb_reason reason, bool skip_if_busy)
23752356 {
2376− DEFINE_WB_COMPLETION_ONSTACK(done);
2357+ struct backing_dev_info *bdi = sb->s_bdi;
2358+ DEFINE_WB_COMPLETION(done, bdi);
23772359 struct wb_writeback_work work = {
23782360 .sb = sb,
23792361 .sync_mode = WB_SYNC_NONE,
@@ -2382,14 +2364,13 @@ static void __writeback_inodes_sb_nr(struct super_block *sb, unsigned long nr, · 2 unmodified lines
23822364 .nr_pages = nr,
23832365 .reason = reason,
23842366 };
2385− struct backing_dev_info *bdi = sb->s_bdi;
23862367
23872368 if (!bdi_has_dirty_io(bdi) || bdi == &noop_backing_dev_info)
23882369 return;
23892370 WARN_ON(!rwsem_is_locked(&sb->s_umount));
23902371
23912372 bdi_split_work_to_wbs(sb->s_bdi, &work, skip_if_busy);
2392− wb_wait_for_completion(bdi, &done);
2373+ wb_wait_for_completion(&done);
23932374 }
23942375
23952376 /**
@@ -2451,7 +2432,8 @@ EXPORT_SYMBOL(try_to_writeback_inodes_sb); · 55 unmodified lines
24512432 */
24522433 void sync_inodes_sb(struct super_block *sb)
24532434 {
2454− DEFINE_WB_COMPLETION_ONSTACK(done);
2435+ struct backing_dev_info *bdi = sb->s_bdi;
2436+ DEFINE_WB_COMPLETION(done, bdi);
24552437 struct wb_writeback_work work = {
24562438 .sb = sb,
24572439 .sync_mode = WB_SYNC_ALL,
@@ -2461,7 +2443,6 @@ void sync_inodes_sb(struct super_block *sb) · 3 unmodified lines
24612443 .reason = WB_REASON_SYNC,
24622444 .for_sync = 1,
24632445 };
2464− struct backing_dev_info *bdi = sb->s_bdi;
24652446
24662447 /*
24672448 * Can't skip on !bdi_has_dirty() because we should wait for !dirty
@@ -2475,7 +2456,7 @@ void sync_inodes_sb(struct super_block *sb) · 7 unmodified lines
24752456 /* protect against inode wb switch, see inode_switch_wbs_work_fn() */
24762457 bdi_down_write_wb_switch_rwsem(bdi);
24772458 bdi_split_work_to_wbs(bdi, &work, false);
2478− wb_wait_for_completion(bdi, &done);
2459+ wb_wait_for_completion(&done);
24792460 bdi_up_write_wb_switch_rwsem(bdi);
24802461
24812462 wait_sb_inodes(sb);
include/linux/backing-dev-defs.h+20−0
@@ -67,6 +67,26 @@ enum wb_reason { · 66 unmodified lines
6767 WB_REASON_MAX,
6868 };
6969
70+struct wb_completion {
71+ atomic_t cnt;
72+ wait_queue_head_t *waitq;
73+};
74+
75+#define __WB_COMPLETION_INIT(_waitq) \
76+ (struct wb_completion){ .cnt = ATOMIC_INIT(1), .waitq = (_waitq) }
77+
78+/*
79+ * If one wants to wait for one or more wb_writeback_works, each work's
80+ * ->done should be set to a wb_completion defined using the following
81+ * macro. Once all work items are issued with wb_queue_work(), the caller
82+ * can wait for the completion of all using wb_wait_for_completion(). Work
83+ * items which are waited upon aren't freed automatically on completion.
84+ */
85+#define WB_COMPLETION_INIT(bdi) __WB_COMPLETION_INIT(&(bdi)->wb_waitq)
86+
87+#define DEFINE_WB_COMPLETION(cmpl, bdi) \
88+ struct wb_completion cmpl = WB_COMPLETION_INIT(bdi)
89+
7090 /*
7191 * For cgroup writeback, multiple wb's may map to the same blkcg. Those
7292 * wb's can operate mostly independently but should share the congested
include/linux/backing-dev.h+2−0
@@ -44,6 +44,8 @@ void wb_start_background_writeback(struct bdi_writeback *wb); · 43 unmodified lines
4444 void wb_workfn(struct work_struct *work);
4545 void wb_wakeup_delayed(struct bdi_writeback *wb);
4646
47+void wb_wait_for_completion(struct wb_completion *done);
48+
4749 extern spinlock_t bdi_lock;
4850 extern struct list_head bdi_list;
4951

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t