mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-05 18:39:59 +00:00
NFS: Fix I/O request leakages
commitf57dcf4c72
upstream. When we fail to add the request to the I/O queue, we currently leave it to the caller to free the failed request. However since some of the requests that fail are actually created by nfs_pageio_add_request() itself, and are not passed back the caller, this leads to a leakage issue, which can again cause page locks to leak. This commit addresses the leakage by freeing the created requests on error, using desc->pg_completion_ops->error_cleanup() Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com> Fixes:a7d42ddb30
("nfs: add mirroring support to pgio layer") Cc: stable@vger.kernel.org # v4.0:c18b96a1b8
: nfs: clean up rest of reqs Cc: stable@vger.kernel.org # v4.0:d600ad1f2b
: NFS41: pop some layoutget Cc: stable@vger.kernel.org # v4.0+ Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
00648da11e
commit
d6bce5aed4
1 changed files with 21 additions and 5 deletions
|
@ -988,6 +988,17 @@ static void nfs_pageio_doio(struct nfs_pageio_descriptor *desc)
|
|||
}
|
||||
}
|
||||
|
||||
static void
|
||||
nfs_pageio_cleanup_request(struct nfs_pageio_descriptor *desc,
|
||||
struct nfs_page *req)
|
||||
{
|
||||
LIST_HEAD(head);
|
||||
|
||||
nfs_list_remove_request(req);
|
||||
nfs_list_add_request(req, &head);
|
||||
desc->pg_completion_ops->error_cleanup(&head);
|
||||
}
|
||||
|
||||
/**
|
||||
* nfs_pageio_add_request - Attempt to coalesce a request into a page list.
|
||||
* @desc: destination io descriptor
|
||||
|
@ -1025,10 +1036,8 @@ static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
|
|||
nfs_page_group_unlock(req);
|
||||
desc->pg_moreio = 1;
|
||||
nfs_pageio_doio(desc);
|
||||
if (desc->pg_error < 0)
|
||||
return 0;
|
||||
if (mirror->pg_recoalesce)
|
||||
return 0;
|
||||
if (desc->pg_error < 0 || mirror->pg_recoalesce)
|
||||
goto out_cleanup_subreq;
|
||||
/* retry add_request for this subreq */
|
||||
nfs_page_group_lock(req);
|
||||
continue;
|
||||
|
@ -1061,6 +1070,10 @@ static int __nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
|
|||
desc->pg_error = PTR_ERR(subreq);
|
||||
nfs_page_group_unlock(req);
|
||||
return 0;
|
||||
out_cleanup_subreq:
|
||||
if (req != subreq)
|
||||
nfs_pageio_cleanup_request(desc, subreq);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nfs_do_recoalesce(struct nfs_pageio_descriptor *desc)
|
||||
|
@ -1168,11 +1181,14 @@ int nfs_pageio_add_request(struct nfs_pageio_descriptor *desc,
|
|||
if (nfs_pgio_has_mirroring(desc))
|
||||
desc->pg_mirror_idx = midx;
|
||||
if (!nfs_pageio_add_request_mirror(desc, dupreq))
|
||||
goto out_failed;
|
||||
goto out_cleanup_subreq;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
out_cleanup_subreq:
|
||||
if (req != dupreq)
|
||||
nfs_pageio_cleanup_request(desc, dupreq);
|
||||
out_failed:
|
||||
/* remember fatal errors */
|
||||
if (nfs_error_is_fatal(desc->pg_error))
|
||||
|
|
Loading…
Reference in a new issue