Commit c704ecb2 authored by Dave Chinner's avatar Dave Chinner Committed by Chandan Babu R

xfs: place the CIL under nofs allocation context

This is core code that needs to run in low memory conditions and
can be triggered from memory reclaim. While it runs in a workqueue,
it really shouldn't be recursing back into the filesystem during
any memory allocation it needs to function.
Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatar"Darrick J. Wong" <djwong@kernel.org>
Signed-off-by: default avatarChandan Babu R <chandanbabu@kernel.org>
parent 2c1e31ed
...@@ -100,7 +100,7 @@ xlog_cil_ctx_alloc(void) ...@@ -100,7 +100,7 @@ xlog_cil_ctx_alloc(void)
{ {
struct xfs_cil_ctx *ctx; struct xfs_cil_ctx *ctx;
ctx = kzalloc(sizeof(*ctx), GFP_NOFS | __GFP_NOFAIL); ctx = kzalloc(sizeof(*ctx), GFP_KERNEL | __GFP_NOFAIL);
INIT_LIST_HEAD(&ctx->committing); INIT_LIST_HEAD(&ctx->committing);
INIT_LIST_HEAD(&ctx->busy_extents.extent_list); INIT_LIST_HEAD(&ctx->busy_extents.extent_list);
INIT_LIST_HEAD(&ctx->log_items); INIT_LIST_HEAD(&ctx->log_items);
...@@ -1116,11 +1116,18 @@ xlog_cil_cleanup_whiteouts( ...@@ -1116,11 +1116,18 @@ xlog_cil_cleanup_whiteouts(
* same sequence twice. If we get a race between multiple pushes for the same * same sequence twice. If we get a race between multiple pushes for the same
* sequence they will block on the first one and then abort, hence avoiding * sequence they will block on the first one and then abort, hence avoiding
* needless pushes. * needless pushes.
*
* This runs from a workqueue so it does not inherent any specific memory
* allocation context. However, we do not want to block on memory reclaim
* recursing back into the filesystem because this push may have been triggered
* by memory reclaim itself. Hence we really need to run under full GFP_NOFS
* contraints here.
*/ */
static void static void
xlog_cil_push_work( xlog_cil_push_work(
struct work_struct *work) struct work_struct *work)
{ {
unsigned int nofs_flags = memalloc_nofs_save();
struct xfs_cil_ctx *ctx = struct xfs_cil_ctx *ctx =
container_of(work, struct xfs_cil_ctx, push_work); container_of(work, struct xfs_cil_ctx, push_work);
struct xfs_cil *cil = ctx->cil; struct xfs_cil *cil = ctx->cil;
...@@ -1334,12 +1341,14 @@ xlog_cil_push_work( ...@@ -1334,12 +1341,14 @@ xlog_cil_push_work(
spin_unlock(&log->l_icloglock); spin_unlock(&log->l_icloglock);
xlog_cil_cleanup_whiteouts(&whiteouts); xlog_cil_cleanup_whiteouts(&whiteouts);
xfs_log_ticket_ungrant(log, ticket); xfs_log_ticket_ungrant(log, ticket);
memalloc_nofs_restore(nofs_flags);
return; return;
out_skip: out_skip:
up_write(&cil->xc_ctx_lock); up_write(&cil->xc_ctx_lock);
xfs_log_ticket_put(new_ctx->ticket); xfs_log_ticket_put(new_ctx->ticket);
kfree(new_ctx); kfree(new_ctx);
memalloc_nofs_restore(nofs_flags);
return; return;
out_abort_free_ticket: out_abort_free_ticket:
...@@ -1348,6 +1357,7 @@ xlog_cil_push_work( ...@@ -1348,6 +1357,7 @@ xlog_cil_push_work(
if (!ctx->commit_iclog) { if (!ctx->commit_iclog) {
xfs_log_ticket_ungrant(log, ctx->ticket); xfs_log_ticket_ungrant(log, ctx->ticket);
xlog_cil_committed(ctx); xlog_cil_committed(ctx);
memalloc_nofs_restore(nofs_flags);
return; return;
} }
spin_lock(&log->l_icloglock); spin_lock(&log->l_icloglock);
...@@ -1356,6 +1366,7 @@ xlog_cil_push_work( ...@@ -1356,6 +1366,7 @@ xlog_cil_push_work(
/* Not safe to reference ctx now! */ /* Not safe to reference ctx now! */
spin_unlock(&log->l_icloglock); spin_unlock(&log->l_icloglock);
xfs_log_ticket_ungrant(log, ticket); xfs_log_ticket_ungrant(log, ticket);
memalloc_nofs_restore(nofs_flags);
} }
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment