diff options
author | Christoph Hellwig <hch@infradead.org> | 2009-09-11 03:47:56 -0400 |
---|---|---|
committer | Jens Axboe <jens.axboe@oracle.com> | 2009-09-16 09:16:18 -0400 |
commit | f0fad8a530e7cbad5f686dbca3079d1a626a3882 (patch) | |
tree | 8e2260cd493a9088c6523dcd0a9f00e34d34a328 /fs | |
parent | 1fe06ad89255c211fe100d7f690d10b161398df8 (diff) |
writeback: merely wakeup flusher thread if work allocation fails for WB_SYNC_NONE
Since it's an opportunistic writeback and not a data integrity action,
don't punt to blocking writeback. Just wakeup the thread and it will
flush old data.
Acked-by: Jan Kara <jack@suse.cz>
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/fs-writeback.c | 46 |
1 files changed, 14 insertions, 32 deletions
diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index 628235cf44b5..783ed44c7cfe 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c | |||
@@ -75,13 +75,6 @@ static inline void bdi_work_init(struct bdi_work *work, | |||
75 | work->state = WS_USED; | 75 | work->state = WS_USED; |
76 | } | 76 | } |
77 | 77 | ||
78 | static inline void bdi_work_init_on_stack(struct bdi_work *work, | ||
79 | struct writeback_control *wbc) | ||
80 | { | ||
81 | bdi_work_init(work, wbc); | ||
82 | work->state |= WS_ONSTACK; | ||
83 | } | ||
84 | |||
85 | /** | 78 | /** |
86 | * writeback_in_progress - determine whether there is writeback in progress | 79 | * writeback_in_progress - determine whether there is writeback in progress |
87 | * @bdi: the device's backing_dev_info structure. | 80 | * @bdi: the device's backing_dev_info structure. |
@@ -207,34 +200,23 @@ static struct bdi_work *bdi_alloc_work(struct writeback_control *wbc) | |||
207 | 200 | ||
208 | void bdi_start_writeback(struct writeback_control *wbc) | 201 | void bdi_start_writeback(struct writeback_control *wbc) |
209 | { | 202 | { |
210 | const bool must_wait = wbc->sync_mode == WB_SYNC_ALL; | 203 | /* |
211 | struct bdi_work work_stack, *work = NULL; | 204 | * WB_SYNC_NONE is opportunistic writeback. If this allocation fails, |
212 | 205 | * bdi_queue_work() will wake up the thread and flush old data. This | |
213 | if (!must_wait) | 206 | * should ensure some amount of progress in freeing memory. |
214 | work = bdi_alloc_work(wbc); | 207 | */ |
208 | if (wbc->sync_mode != WB_SYNC_ALL) { | ||
209 | struct bdi_work *w = bdi_alloc_work(wbc); | ||
215 | 210 | ||
216 | if (!work) { | 211 | bdi_queue_work(wbc->bdi, w); |
217 | work = &work_stack; | 212 | } else { |
218 | bdi_work_init_on_stack(work, wbc); | 213 | struct bdi_work work; |
219 | } | ||
220 | 214 | ||
221 | bdi_queue_work(wbc->bdi, work); | 215 | bdi_work_init(&work, wbc); |
216 | work.state |= WS_ONSTACK; | ||
222 | 217 | ||
223 | /* | 218 | bdi_queue_work(wbc->bdi, &work); |
224 | * If the sync mode is WB_SYNC_ALL, block waiting for the work to | 219 | bdi_wait_on_work_clear(&work); |
225 | * complete. If not, we only need to wait for the work to be started, | ||
226 | * if we allocated it on-stack. We use the same mechanism, if the | ||
227 | * wait bit is set in the bdi_work struct, then threads will not | ||
228 | * clear pending until after they are done. | ||
229 | * | ||
230 | * Note that work == &work_stack if must_wait is true, so we don't | ||
231 | * need to do call_rcu() here ever, since the completion path will | ||
232 | * have done that for us. | ||
233 | */ | ||
234 | if (must_wait || work == &work_stack) { | ||
235 | bdi_wait_on_work_clear(work); | ||
236 | if (work != &work_stack) | ||
237 | call_rcu(&work->rcu_head, bdi_work_free); | ||
238 | } | 220 | } |
239 | } | 221 | } |
240 | 222 | ||