diff options
author | Benjamin Coddington <bcodding@redhat.com> | 2017-04-19 10:11:33 -0400 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2017-05-25 09:44:48 -0400 |
commit | f2b6f508c5417bc5f2a5a30268b5b75ae3b4a754 (patch) | |
tree | c09b8aea1a247f53d1022b88f8022b23c4aab309 /fs | |
parent | a8c35e5c88def2c07cd0ff1aca1af2b06363b293 (diff) |
NFS: Use GFP_NOIO for two allocations in writeback
commit ae97aa524ef495b6276fd26f5d5449fb22975d7c upstream.
Prevent a deadlock that can occur if we wait on allocations
that try to write back our pages.
Signed-off-by: Benjamin Coddington <bcodding@redhat.com>
Fixes: 00bfa30abe869 ("NFS: Create a common pgio_alloc and pgio_release...")
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r-- | fs/nfs/pagelist.c | 15 |
1 files changed, 11 insertions, 4 deletions
diff --git a/fs/nfs/pagelist.c b/fs/nfs/pagelist.c index 965db474f4b0..142a74f3c59b 100644 --- a/fs/nfs/pagelist.c +++ b/fs/nfs/pagelist.c | |||
@@ -29,13 +29,14 @@ | |||
29 | static struct kmem_cache *nfs_page_cachep; | 29 | static struct kmem_cache *nfs_page_cachep; |
30 | static const struct rpc_call_ops nfs_pgio_common_ops; | 30 | static const struct rpc_call_ops nfs_pgio_common_ops; |
31 | 31 | ||
32 | static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount) | 32 | static bool nfs_pgarray_set(struct nfs_page_array *p, unsigned int pagecount, |
33 | gfp_t gfp_flags) | ||
33 | { | 34 | { |
34 | p->npages = pagecount; | 35 | p->npages = pagecount; |
35 | if (pagecount <= ARRAY_SIZE(p->page_array)) | 36 | if (pagecount <= ARRAY_SIZE(p->page_array)) |
36 | p->pagevec = p->page_array; | 37 | p->pagevec = p->page_array; |
37 | else { | 38 | else { |
38 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), GFP_KERNEL); | 39 | p->pagevec = kcalloc(pagecount, sizeof(struct page *), gfp_flags); |
39 | if (!p->pagevec) | 40 | if (!p->pagevec) |
40 | p->npages = 0; | 41 | p->npages = 0; |
41 | } | 42 | } |
@@ -681,6 +682,7 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
681 | { | 682 | { |
682 | struct nfs_pgio_mirror *new; | 683 | struct nfs_pgio_mirror *new; |
683 | int i; | 684 | int i; |
685 | gfp_t gfp_flags = GFP_KERNEL; | ||
684 | 686 | ||
685 | desc->pg_moreio = 0; | 687 | desc->pg_moreio = 0; |
686 | desc->pg_inode = inode; | 688 | desc->pg_inode = inode; |
@@ -700,8 +702,10 @@ void nfs_pageio_init(struct nfs_pageio_descriptor *desc, | |||
700 | if (pg_ops->pg_get_mirror_count) { | 702 | if (pg_ops->pg_get_mirror_count) { |
701 | /* until we have a request, we don't have an lseg and no | 703 | /* until we have a request, we don't have an lseg and no |
702 | * idea how many mirrors there will be */ | 704 | * idea how many mirrors there will be */ |
705 | if (desc->pg_rw_ops->rw_mode == FMODE_WRITE) | ||
706 | gfp_flags = GFP_NOIO; | ||
703 | new = kcalloc(NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX, | 707 | new = kcalloc(NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX, |
704 | sizeof(struct nfs_pgio_mirror), GFP_KERNEL); | 708 | sizeof(struct nfs_pgio_mirror), gfp_flags); |
705 | desc->pg_mirrors_dynamic = new; | 709 | desc->pg_mirrors_dynamic = new; |
706 | desc->pg_mirrors = new; | 710 | desc->pg_mirrors = new; |
707 | 711 | ||
@@ -755,9 +759,12 @@ int nfs_generic_pgio(struct nfs_pageio_descriptor *desc, | |||
755 | struct list_head *head = &mirror->pg_list; | 759 | struct list_head *head = &mirror->pg_list; |
756 | struct nfs_commit_info cinfo; | 760 | struct nfs_commit_info cinfo; |
757 | unsigned int pagecount, pageused; | 761 | unsigned int pagecount, pageused; |
762 | gfp_t gfp_flags = GFP_KERNEL; | ||
758 | 763 | ||
759 | pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); | 764 | pagecount = nfs_page_array_len(mirror->pg_base, mirror->pg_count); |
760 | if (!nfs_pgarray_set(&hdr->page_array, pagecount)) { | 765 | if (desc->pg_rw_ops->rw_mode == FMODE_WRITE) |
766 | gfp_flags = GFP_NOIO; | ||
767 | if (!nfs_pgarray_set(&hdr->page_array, pagecount, gfp_flags)) { | ||
761 | nfs_pgio_error(hdr); | 768 | nfs_pgio_error(hdr); |
762 | desc->pg_error = -ENOMEM; | 769 | desc->pg_error = -ENOMEM; |
763 | return desc->pg_error; | 770 | return desc->pg_error; |