diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-07-12 19:10:57 -0400 |
---|---|---|
committer | Anna Schumaker <Anna.Schumaker@Netapp.com> | 2017-07-19 15:28:21 -0400 |
commit | 41181886459b281ed1346369f27b3c3bb8e2dde3 (patch) | |
tree | 6e459cf7aa4d69be2022e2fa03e8136052b537d0 /fs | |
parent | e39928f942ff7a9d1cb9005423e9e35a0a4bb2e0 (diff) |
NFS: Fix another COMMIT race in pNFS
We must make sure that cinfo->ds->ncommitting is in sync with the
commit list, since it is checked as part of pnfs_commit_list().
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.c | 7 |
1 files changed, 6 insertions, 1 deletions
diff --git a/fs/nfs/pnfs_nfs.c b/fs/nfs/pnfs_nfs.c index 3e6de85faf42..7ceb86627e54 100644 --- a/fs/nfs/pnfs_nfs.c +++ b/fs/nfs/pnfs_nfs.c | |||
@@ -187,6 +187,7 @@ static void pnfs_generic_retry_commit(struct nfs_commit_info *cinfo, int idx) | |||
187 | struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; | 187 | struct pnfs_ds_commit_info *fl_cinfo = cinfo->ds; |
188 | struct pnfs_commit_bucket *bucket; | 188 | struct pnfs_commit_bucket *bucket; |
189 | struct pnfs_layout_segment *freeme; | 189 | struct pnfs_layout_segment *freeme; |
190 | struct list_head *pos; | ||
190 | LIST_HEAD(pages); | 191 | LIST_HEAD(pages); |
191 | int i; | 192 | int i; |
192 | 193 | ||
@@ -197,6 +198,8 @@ static void pnfs_generic_retry_commit(struct nfs_commit_info *cinfo, int idx) | |||
197 | continue; | 198 | continue; |
198 | freeme = bucket->clseg; | 199 | freeme = bucket->clseg; |
199 | bucket->clseg = NULL; | 200 | bucket->clseg = NULL; |
201 | list_for_each(pos, &bucket->committing) | ||
202 | cinfo->ds->ncommitting--; | ||
200 | list_splice_init(&bucket->committing, &pages); | 203 | list_splice_init(&bucket->committing, &pages); |
201 | spin_unlock(&cinfo->inode->i_lock); | 204 | spin_unlock(&cinfo->inode->i_lock); |
202 | nfs_retry_commit(&pages, freeme, cinfo, i); | 205 | nfs_retry_commit(&pages, freeme, cinfo, i); |
@@ -247,9 +250,12 @@ void pnfs_fetch_commit_bucket_list(struct list_head *pages, | |||
247 | struct nfs_commit_info *cinfo) | 250 | struct nfs_commit_info *cinfo) |
248 | { | 251 | { |
249 | struct pnfs_commit_bucket *bucket; | 252 | struct pnfs_commit_bucket *bucket; |
253 | struct list_head *pos; | ||
250 | 254 | ||
251 | bucket = &cinfo->ds->buckets[data->ds_commit_index]; | 255 | bucket = &cinfo->ds->buckets[data->ds_commit_index]; |
252 | spin_lock(&cinfo->inode->i_lock); | 256 | spin_lock(&cinfo->inode->i_lock); |
257 | list_for_each(pos, &bucket->committing) | ||
258 | cinfo->ds->ncommitting--; | ||
253 | list_splice_init(&bucket->committing, pages); | 259 | list_splice_init(&bucket->committing, pages); |
254 | data->lseg = bucket->clseg; | 260 | data->lseg = bucket->clseg; |
255 | bucket->clseg = NULL; | 261 | bucket->clseg = NULL; |
@@ -334,7 +340,6 @@ pnfs_generic_commit_pagelist(struct inode *inode, struct list_head *mds_pages, | |||
334 | } | 340 | } |
335 | } | 341 | } |
336 | out: | 342 | out: |
337 | cinfo->ds->ncommitting = 0; | ||
338 | return PNFS_ATTEMPTED; | 343 | return PNFS_ATTEMPTED; |
339 | } | 344 | } |
340 | EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist); | 345 | EXPORT_SYMBOL_GPL(pnfs_generic_commit_pagelist); |