diff options
author | Weston Andros Adamson <dros@monkey.org> | 2016-06-17 16:48:24 -0400 |
---|---|---|
committer | Sasha Levin <sasha.levin@oracle.com> | 2016-07-10 20:20:05 -0400 |
commit | eba391c749fe8a47aea9de2e78fadc02434b5417 (patch) | |
tree | 9e24f4d6e86bd22d59d66bbeba3a92c5cf7ac264 /fs/nfs | |
parent | 691c507ec01fa0cab2a9cfb5bd4398ddd5480a8a (diff) | |
download | linux-rt-eba391c749fe8a47aea9de2e78fadc02434b5417.tar.gz |
pnfs_nfs: fix _cancel_empty_pagelist
[ Upstream commit 5e3a98883e7ebdd1440f829a9e9dd5c3d2c5903b ]
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>
Signed-off-by: Sasha Levin <sasha.levin@oracle.com>
Diffstat (limited to 'fs/nfs')
-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 8bd645a1913b..19c1bcf70e3e 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; } |