Patch "NFSv4: Fix up mirror allocation" has been added to the 4.12-stable tree
Subsystems (2)
This is a note to let you know that I've just added the patch titled
NFSv4: Fix up mirror allocation
to the 4.12-stable tree which can be found at:
http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary
The filename of the patch is:
nfsv4-fix-up-mirror-allocation.patch
and it can be found in the queue-4.12 subdirectory.
If you, or anyone else, feels it should not be added to the stable tree, please let <[email protected]> know about it.
Quoted 1 line
From
14abcb0bf59a30cf65a74f6c6f53974cd7224bc6Mon Sep 17 00:00:00 2001
From: Trond Myklebust <[email protected]>
Date: Sat, 19 Aug 2017 10:10:34 -0400
Subject: NFSv4: Fix up mirror allocation
From: Trond Myklebust <[email protected]>
commit 14abcb0bf59a30cf65a74f6c6f53974cd7224bc6 upstream.
There are a number of callers of nfs_pageio_complete() that want to continue using the nfs_pageio_descriptor without needing to call nfs_pageio_init() again. Examples include nfs_pageio_resend() and nfs_pageio_cond_complete().
The problem is that nfs_pageio_complete() also calls nfs_pageio_cleanup_mirroring(), which frees up the array of mirrors. This can lead to writeback errors, in the next call to nfs_pageio_setup_mirroring().
Fix by simply moving the allocation of the mirrors to nfs_pageio_setup_mirroring().
--- fs/nfs/pagelist.c | 73 ++++++++++++++++++++++++++++-------------------------- 1 file changed, 39 insertions(+), 34 deletions(-)
fs/nfs/pagelist.c +39 -34
@@ -697,9 +697,6 @@ void nfs_pageio_init(struct nfs_pageio_d int io_flags, gfp_t gfp_flags) { -struct nfs_pgio_mirror *new; -int i; - desc->pg_moreio =0 ; desc->pg_inode = inode; desc->pg_ops = pg_ops;
@@ -715,21 +712,9 @@ void nfs_pageio_init(struct nfs_pageio_d desc->pg_mirror_count =1 ; desc->pg_mirror_idx =0 ; -if (pg_ops->pg_get_mirror_count) { -/* until we have a request, we don't have an lseg and no -* idea how many mirrors there will be */ - new =kcalloc (NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX , -sizeof (struct nfs_pgio_mirror ), gfp_flags); - desc->pg_mirrors_dynamic = new; - desc->pg_mirrors = new; - -for (i =0 ; i <NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX ; i++) -nfs_pageio_mirror_init (&desc->pg_mirrors[i], bsize); - }else { - desc->pg_mirrors_dynamic =NULL ; - desc->pg_mirrors = desc->pg_mirrors_static; -nfs_pageio_mirror_init (&desc->pg_mirrors[0 ], bsize); - } + desc->pg_mirrors_dynamic =NULL ; + desc->pg_mirrors = desc->pg_mirrors_static; +nfs_pageio_mirror_init (&desc->pg_mirrors[0 ], bsize); }EXPORT_SYMBOL_GPL (nfs_pageio_init);
@@ -848,32 +833,52 @@ static int nfs_generic_pg_pgios(struct nreturn ret; } +static struct nfs_pgio_mirror * +nfs_pageio_alloc_mirrors (struct nfs_pageio_descriptor *desc, +unsigned int mirror_count) +{ +struct nfs_pgio_mirror *ret; +unsigned int i; + +kfree (desc->pg_mirrors_dynamic); + desc->pg_mirrors_dynamic =NULL ; +if (mirror_count ==1 ) +return desc->pg_mirrors_static; + ret =kmalloc_array (mirror_count,sizeof (*ret),GFP_NOFS ); +if (ret !=NULL ) { +for (i =0 ; i < mirror_count; i++) +nfs_pageio_mirror_init (&ret[i], desc->pg_bsize); + desc->pg_mirrors_dynamic = ret; + } +return ret; +} +/* * nfs_pageio_setup_mirroring - determine if mirroring is to be used * by calling the pg_get_mirror_count op */ -static int nfs_pageio_setup_mirroring (struct nfs_pageio_descriptor *pgio, +static void nfs_pageio_setup_mirroring (struct nfs_pageio_descriptor *pgio,struct nfs_page *req) { -int mirror_count =1 ; - -if (!pgio->pg_ops->pg_get_mirror_count) -return 0 ; +unsigned int mirror_count =1 ; - mirror_count = pgio->pg_ops->pg_get_mirror_count (pgio, req); - -if (pgio->pg_error <0 ) -return pgio->pg_error; - -if (!mirror_count || mirror_count >NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX ) -return -EINVAL ; +if (pgio->pg_ops->pg_get_mirror_count) + mirror_count = pgio->pg_ops->pg_get_mirror_count (pgio, req); +if (mirror_count == pgio->pg_mirror_count || pgio->pg_error <0 ) +return ; -if (WARN_ON_ONCE (!pgio->pg_mirrors_dynamic)) -return -EINVAL ; +if (!mirror_count || mirror_count >NFS_PAGEIO_DESCRIPTOR_MIRROR_MAX ) { + pgio->pg_error = -EINVAL ; +return ; + } + pgio->pg_mirrors =nfs_pageio_alloc_mirrors (pgio, mirror_count); +if (pgio->pg_mirrors ==NULL ) { + pgio->pg_error = -ENOMEM ; + pgio->pg_mirrors = pgio->pg_mirrors_static; + mirror_count =1 ; + } pgio->pg_mirror_count = mirror_count; - -return 0 ; }/*
Patches currently in stable-queue which might be from [email protected] are
queue-4.12/nfsv4-fix-up-mirror-allocation.patch queue-4.12/nfs-fix-2-use-after-free-issues-in-the-i-o-code.patch queue-4.12/nfs-sync-the-correct-byte-range-during-synchronous-writes.patch