diff options
author | Weston Andros Adamson <dros@monkey.org> | 2016-06-17 16:48:24 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2016-06-24 12:01:00 -0400 |
commit | 5e3a98883e7ebdd1440f829a9e9dd5c3d2c5903b (patch) | |
tree | 71716567b64b5e73b59d7a96a480caac1061e5c6 | |
parent | cea7f829d3ea6e87a67220bc417260b858e278ff (diff) |
pnfs_nfs: fix _cancel_empty_pagelist
pnfs_generic_commit_cancel_empty_pagelist calls nfs_commitdata_release,
but that is wrong: nfs_commitdata_release puts the open context, something
that isn't valid until nfs_init_commit is called, which is never the case
when pnfs_generic_commit_cancel_empty_pagelist is called.
This was introduced in "nfs: avoid race that crashes nfs_init_commit".
Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
Cc: stable@vger.kernel.org
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
-rw-r--r-- | fs/nfs/pnfs_nfs.c | 12 |
1 files changed, 10 insertions, 2 deletions
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index 0dfc476da3e1..b38e3c0dc790 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
@@ -247,7 +247,11 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages, | |||
247 | } | 247 | } |
248 | 248 | ||
249 | /* Helper function for pnfs_generic_commit_pagelist to catch an empty | 249 | /* Helper function for pnfs_generic_commit_pagelist to catch an empty |
250 | * page list. This can happen when two commits race. */ | 250 | * page list. This can happen when two commits race. |
251 | * | ||
252 | * This must be called instead of nfs_init_commit - call one or the other, but | ||
253 | * not both! | ||
254 | */ | ||
251 | static bool | 255 | static bool |
252 | pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, | 256 | pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, |
253 | struct nfs_commit_data *data, | 257 | struct nfs_commit_data *data, |
@@ -256,7 +260,11 @@ pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages, | |||
256 | if (list_empty(pages)) { | 260 | if (list_empty(pages)) { |
257 | if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) | 261 | if (atomic_dec_and_test(&cinfo->mds->rpcs_out)) |
258 | wake_up_atomic_t(&cinfo->mds->rpcs_out); | 262 | wake_up_atomic_t(&cinfo->mds->rpcs_out); |
259 | nfs_commitdata_release(data); | 263 | /* don't call nfs_commitdata_release - it tries to put |
264 | * the open_context which is not acquired until nfs_init_commit | ||
265 | * which has not been called on @data */ | ||
266 | WARN_ON_ONCE(data->context); | ||
267 | nfs_commit_free(data); | ||
260 | return true; | 268 | return true; |
261 | } | 269 | } |
262 | 270 | ||