| From c550d122035eb92c59efcc7e89e66d8793bd4914 Mon Sep 17 00:00:00 2001 |
| From: Sasha Levin <sashal@kernel.org> |
| Date: Mon, 21 Mar 2022 13:48:36 -0400 |
| Subject: NFS: Avoid writeback threads getting stuck in mempool_alloc() |
| |
| From: Trond Myklebust <trond.myklebust@hammerspace.com> |
| |
| [ Upstream commit 0bae835b63c53f86cdc524f5962e39409585b22c ] |
| |
| In a low memory situation, allow the NFS writeback code to fail without |
| getting stuck in infinite loops in mempool_alloc(). |
| |
| Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> |
| Signed-off-by: Sasha Levin <sashal@kernel.org> |
| --- |
| fs/nfs/pagelist.c | 10 +++++----- |
| fs/nfs/write.c | 10 ++++++++-- |
| 2 files changed, 13 insertions(+), 7 deletions(-) |
| |
| diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c |
| index 815d63080245..9157dd19b8b4 100644 |
| --- a/fs/nfs/pagelist.c |
| +++ b/fs/nfs/pagelist.c |
| @@ -90,10 +90,10 @@ void nfs_set_pgio_error(struct nfs_pgio_header *hdr, int error, loff_t pos) |
| } |
| } |
| |
| -static inline struct nfs_page * |
| -nfs_page_alloc(void) |
| +static inline struct nfs_page *nfs_page_alloc(void) |
| { |
| - struct nfs_page *p = kmem_cache_zalloc(nfs_page_cachep, GFP_KERNEL); |
| + struct nfs_page *p = |
| + kmem_cache_zalloc(nfs_page_cachep, nfs_io_gfp_mask()); |
| if (p) |
| INIT_LIST_HEAD(&p->wb_list); |
| return p; |
| @@ -892,7 +892,7 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, |
| struct nfs_commit_info cinfo; |
| struct nfs_page_array *pg_array = &hdr->page_array; |
| unsigned int pagecount, pageused; |
| - gfp_t gfp_flags = GFP_KERNEL; |
| + gfp_t gfp_flags = nfs_io_gfp_mask(); |
| |
| pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); |
| pg_array->npages = pagecount; |
| @@ -979,7 +979,7 @@ nfs_pageio_alloc_mirrors(struct nfs_pageio_descriptor *desc, |
| desc->pg_mirrors_dynamic = NULL; |
| if (mirror_count == 1) |
| return desc->pg_mirrors_static; |
| - ret = kmalloc_array(mirror_count, sizeof(*ret), GFP_KERNEL); |
| + ret = kmalloc_array(mirror_count, sizeof(*ret), nfs_io_gfp_mask()); |
| if (ret != NULL) { |
| for (i = 0; i < mirror_count; i++) |
| nfs_pageio_mirror_init(&ret[i], desc->pg_bsize); |
| diff --git a/fs/nfs/write.c b/fs/nfs/write.c |
| index 8eb7466182ac..fdaca2a55f36 100644 |
| --- a/fs/nfs/write.c |
| +++ b/fs/nfs/write.c |
| @@ -94,9 +94,15 @@ EXPORT_SYMBOL_GPL(nfs_commit_free); |
| |
| static struct nfs_pgio_header *nfs_writehdr_alloc(void) |
| { |
| - struct nfs_pgio_header *p = mempool_alloc(nfs_wdata_mempool, GFP_KERNEL); |
| + struct nfs_pgio_header *p; |
| |
| - memset(p, 0, sizeof(*p)); |
| + p = kmem_cache_zalloc(nfs_wdata_cachep, nfs_io_gfp_mask()); |
| + if (!p) { |
| + p = mempool_alloc(nfs_wdata_mempool, GFP_NOWAIT); |
| + if (!p) |
| + return NULL; |
| + memset(p, 0, sizeof(*p)); |
| + } |
| p->rw_mode = FMODE_WRITE; |
| return p; |
| } |
| -- |
| 2.35.1 |
| |