mirror of
https://github.com/torvalds/linux.git
synced 2026-03-08 06:04:44 +01:00
NFS/localio: prevent direct reclaim recursion into NFS via nfs_writepages
LOCALIO is an NFS loopback mount optimization that avoids using the network for READ, WRITE and COMMIT if the NFS client and server are determined to be on the same system. But because LOCALIO is still fundamentally "just NFS loopback mount" it is susceptible to recursion deadlock via direct reclaim, e.g.: NFS LOCALIO down to XFS and then back into NFS via nfs_writepages. Fix LOCALIO's potential for direct reclaim deadlock by ensuring that all its page cache allocations are done from GFP_NOFS context. Thanks to Ben Coddington for pointing out commitad22c7a043("xfs: prevent stack overflows from page cache allocation"). Reported-by: John Cagle <john.cagle@hammerspace.com> Tested-by: Allen Lu <allen.lu@hammerspace.com> Suggested-by: Benjamin Coddington <bcodding@hammerspace.com> Fixes:70ba381e1a("nfs: add LOCALIO support") Signed-off-by: Mike Snitzer <snitzer@hammerspace.com> Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com>
This commit is contained in:
parent
5fcd95831d
commit
67435d2d8a
1 changed files with 15 additions and 0 deletions
|
|
@ -291,6 +291,18 @@ nfs_local_open_fh(struct nfs_client *clp, const struct cred *cred,
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(nfs_local_open_fh);
|
||||
|
||||
/*
|
||||
* Ensure all page cache allocations are done from GFP_NOFS context to
|
||||
* prevent direct reclaim recursion back into NFS via nfs_writepages.
|
||||
*/
|
||||
static void
|
||||
nfs_local_mapping_set_gfp_nofs_context(struct address_space *m)
|
||||
{
|
||||
gfp_t gfp_mask = mapping_gfp_mask(m);
|
||||
|
||||
mapping_set_gfp_mask(m, (gfp_mask & ~(__GFP_FS)));
|
||||
}
|
||||
|
||||
static void
|
||||
nfs_local_iocb_free(struct nfs_local_kiocb *iocb)
|
||||
{
|
||||
|
|
@ -315,6 +327,7 @@ nfs_local_iocb_alloc(struct nfs_pgio_header *hdr,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
nfs_local_mapping_set_gfp_nofs_context(file->f_mapping);
|
||||
init_sync_kiocb(&iocb->kiocb, file);
|
||||
|
||||
iocb->hdr = hdr;
|
||||
|
|
@ -1000,6 +1013,8 @@ nfs_local_run_commit(struct file *filp, struct nfs_commit_data *data)
|
|||
end = LLONG_MAX;
|
||||
}
|
||||
|
||||
nfs_local_mapping_set_gfp_nofs_context(filp->f_mapping);
|
||||
|
||||
dprintk("%s: commit %llu - %llu\n", __func__, start, end);
|
||||
return vfs_fsync_range(filp, start, end, 0);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue