NFS: Fix a COMMIT race in pNFS
authorTrond Myklebust <trond.myklebust@primarydata.com>
Wed, 12 Jul 2017 23:10:56 +0000 (19:10 -0400)
committerAnna Schumaker <Anna.Schumaker@Netapp.com>
Wed, 19 Jul 2017 19:28:21 +0000 (15:28 -0400)
We must make sure that cinfo->ds->nwritten is in sync with the
commit list, since it is checked as part of pnfs_scan_commit_lists().

Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Signed-off-by: Anna Schumaker <Anna.Schumaker@Netapp.com>
fs/nfs/pnfs_nfs.c

index d40755a0984bbb0942e96aee388ed50fe7629a6e..3e6de85faf428d175cc5cb3c49e0cb21c9ac559f 100644 (file)
@@ -159,13 +159,18 @@ void pnfs_generic_recover_commit_reqs(struct list_head *dst,
 {
        struct pnfs_commit_bucket *b;
        struct pnfs_layout_segment *freeme;
+       int nwritten;
        int i;
 
        lockdep_assert_held(&cinfo->inode->i_lock);
 restart:
        for (i = 0, b = cinfo->ds->buckets; i < cinfo->ds->nbuckets; i++, b++) {
-               if (pnfs_generic_transfer_commit_list(&b->written, dst,
-                                                     cinfo, 0)) {
+               nwritten = pnfs_generic_transfer_commit_list(&b->written,
+                               dst, cinfo, 0);
+               if (!nwritten)
+                       continue;
+               cinfo->ds->nwritten -= nwritten;
+               if (list_empty(&b->written)) {
                        freeme = b->wlseg;
                        b->wlseg = NULL;
                        spin_unlock(&cinfo->inode->i_lock);
@@ -174,7 +179,6 @@ restart:
                        goto restart;
                }
        }
-       cinfo->ds->nwritten = 0;
 }
 EXPORT_SYMBOL_GPL(pnfs_generic_recover_commit_reqs);