OSDN Git Service

NFS: Avoid writeback threads getting stuck in mempool_alloc()
authorTrond Myklebust <trond.myklebust@hammerspace.com>
Mon, 21 Mar 2022 17:48:36 +0000 (13:48 -0400)
committerTrond Myklebust <trond.myklebust@hammerspace.com>
Tue, 22 Mar 2022 19:52:56 +0000 (15:52 -0400)
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>
fs/nfs/pagelist.c
fs/nfs/write.c

index ad7f83d..3156db5 100644 (file)
@@ -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);
index ef47e37..e864ac8 100644 (file)
@@ -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;
 }