summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@monkey.org>2016-06-17 22:48:24 +0200
committerAnna Schumaker <Anna.Schumaker@Netapp.com>2016-06-24 18:01:00 +0200
commit5e3a98883e7ebdd1440f829a9e9dd5c3d2c5903b (patch)
tree71716567b64b5e73b59d7a96a480caac1061e5c6 /fs
parentnfs4: Fix potential use after free of state in nfs4_do_reclaim. (diff)
downloadlinux-5e3a98883e7ebdd1440f829a9e9dd5c3d2c5903b.tar.xz
linux-5e3a98883e7ebdd1440f829a9e9dd5c3d2c5903b.zip
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>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/pnfs_nfs.c12
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,
}
/* Helper function for pnfs_generic_commit_pagelist to catch an empty
- * page list. This can happen when two commits race. */
+ * page list. This can happen when two commits race.
+ *
+ * This must be called instead of nfs_init_commit - call one or the other, but
+ * not both!
+ */
static bool
pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages,
struct nfs_commit_data *data,
@@ -256,7 +260,11 @@ pnfs_generic_commit_cancel_empty_pagelist(struct list_head *pages,
if (list_empty(pages)) {
if (atomic_dec_and_test(&cinfo->mds->rpcs_out))
wake_up_atomic_t(&cinfo->mds->rpcs_out);
- nfs_commitdata_release(data);
+ /* don't call nfs_commitdata_release - it tries to put
+ * the open_context which is not acquired until nfs_init_commit
+ * which has not been called on @data */
+ WARN_ON_ONCE(data->context);
+ nfs_commit_free(data);
return true;
}