aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorDave Chinner <dchinner@redhat.com>2014-06-06 01:59:59 -0400
committerDave Chinner <david@fromorbit.com>2014-06-06 01:59:59 -0400
commit1f6d64829db78a7e1d63e15c9f48f0a5d2b5a679 (patch)
treeaa4692eeb903340f84953001667e5c03c53d309c /fs/xfs
parentd6d211db37e75de2ddc3a4f979038c40df7cc79c (diff)
xfs: block allocation work needs to be kswapd aware
Upon memory pressure, kswapd calls xfs_vm_writepage() from shrink_page_list(). This can result in delayed allocation occurring and that gets deferred to the the allocation workqueue. The allocation then runs outside kswapd context, which means if it needs memory (and it does to demand page metadata from disk) it can block in shrink_inactive_list() waiting for IO congestion. These blocking waits are normally avoiding in kswapd context, so under memory pressure writeback from kswapd can be arbitrarily delayed by memory reclaim. To avoid this, pass the kswapd context to the allocation being done by the workqueue, so that memory reclaim understands correctly that the work is being done for kswapd and therefore it is not blocked and does not delay memory reclaim. To avoid issues with int->char conversion of flag fields (as noticed in v1 of this patch) convert the flag fields in the struct xfs_bmalloca to bool types. pahole indicates these variables are still single byte variables, so no extra space is consumed by this change. cc: <stable@vger.kernel.org> Reported-by: Tetsuo Handa <penguin-kernel@I-love.SAKURA.ne.jp> Signed-off-by: Dave Chinner <dchinner@redhat.com> Reviewed-by: Christoph Hellwig <hch@lst.de> Signed-off-by: Dave Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_bmap_util.c16
-rw-r--r--fs/xfs/xfs_bmap_util.h13
2 files changed, 20 insertions, 9 deletions
diff --git a/fs/xfs/xfs_bmap_util.c b/fs/xfs/xfs_bmap_util.c
index 296160b8e78c..47a9daa7b4e6 100644
--- a/fs/xfs/xfs_bmap_util.c
+++ b/fs/xfs/xfs_bmap_util.c
@@ -258,14 +258,23 @@ xfs_bmapi_allocate_worker(
258 struct xfs_bmalloca *args = container_of(work, 258 struct xfs_bmalloca *args = container_of(work,
259 struct xfs_bmalloca, work); 259 struct xfs_bmalloca, work);
260 unsigned long pflags; 260 unsigned long pflags;
261 unsigned long new_pflags = PF_FSTRANS;
261 262
262 /* we are in a transaction context here */ 263 /*
263 current_set_flags_nested(&pflags, PF_FSTRANS); 264 * we are in a transaction context here, but may also be doing work
265 * in kswapd context, and hence we may need to inherit that state
266 * temporarily to ensure that we don't block waiting for memory reclaim
267 * in any way.
268 */
269 if (args->kswapd)
270 new_pflags |= PF_MEMALLOC | PF_SWAPWRITE | PF_KSWAPD;
271
272 current_set_flags_nested(&pflags, new_pflags);
264 273
265 args->result = __xfs_bmapi_allocate(args); 274 args->result = __xfs_bmapi_allocate(args);
266 complete(args->done); 275 complete(args->done);
267 276
268 current_restore_flags_nested(&pflags, PF_FSTRANS); 277 current_restore_flags_nested(&pflags, new_pflags);
269} 278}
270 279
271/* 280/*
@@ -284,6 +293,7 @@ xfs_bmapi_allocate(
284 293
285 294
286 args->done = &done; 295 args->done = &done;
296 args->kswapd = current_is_kswapd();
287 INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker); 297 INIT_WORK_ONSTACK(&args->work, xfs_bmapi_allocate_worker);
288 queue_work(xfs_alloc_wq, &args->work); 298 queue_work(xfs_alloc_wq, &args->work);
289 wait_for_completion(&done); 299 wait_for_completion(&done);
diff --git a/fs/xfs/xfs_bmap_util.h b/fs/xfs/xfs_bmap_util.h
index 935ed2b24edf..075f72232a64 100644
--- a/fs/xfs/xfs_bmap_util.h
+++ b/fs/xfs/xfs_bmap_util.h
@@ -50,12 +50,13 @@ struct xfs_bmalloca {
50 xfs_extlen_t total; /* total blocks needed for xaction */ 50 xfs_extlen_t total; /* total blocks needed for xaction */
51 xfs_extlen_t minlen; /* minimum allocation size (blocks) */ 51 xfs_extlen_t minlen; /* minimum allocation size (blocks) */
52 xfs_extlen_t minleft; /* amount must be left after alloc */ 52 xfs_extlen_t minleft; /* amount must be left after alloc */
53 char eof; /* set if allocating past last extent */ 53 bool eof; /* set if allocating past last extent */
54 char wasdel; /* replacing a delayed allocation */ 54 bool wasdel; /* replacing a delayed allocation */
55 char userdata;/* set if is user data */ 55 bool userdata;/* set if is user data */
56 char aeof; /* allocated space at eof */ 56 bool aeof; /* allocated space at eof */
57 char conv; /* overwriting unwritten extents */ 57 bool conv; /* overwriting unwritten extents */
58 char stack_switch; 58 bool stack_switch;
59 bool kswapd; /* allocation in kswapd context */
59 int flags; 60 int flags;
60 struct completion *done; 61 struct completion *done;
61 struct work_struct work; 62 struct work_struct work;