aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/write.c
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2017-07-17 11:11:49 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2017-08-15 11:54:46 -0400
commite14bebf6de11a4b8476cf2b0a75bf7c3e69112d5 (patch)
treed6d22e8c6a213ceb8d9e93565df99cf99fdba503 /fs/nfs/write.c
parenta0e265bc78010d2d831a968d4cea3c40a0efac8b (diff)
NFS: Don't check request offset and size without holding a lock
Request offsets and sizes are not guaranteed to be stable unless you are holding the request locked. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/write.c')
-rw-r--r--fs/nfs/write.c24
1 files changed, 12 insertions, 12 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index c940e615f5dc..84b6818e5278 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -523,6 +523,17 @@ try_again:
523 total_bytes = head->wb_bytes; 523 total_bytes = head->wb_bytes;
524 for (subreq = head->wb_this_page; subreq != head; 524 for (subreq = head->wb_this_page; subreq != head;
525 subreq = subreq->wb_this_page) { 525 subreq = subreq->wb_this_page) {
526 if (!nfs_lock_request(subreq)) {
527 /* releases page group bit lock and
528 * inode spin lock and all references */
529 ret = nfs_unroll_locks_and_wait(inode, head,
530 subreq);
531
532 if (ret == 0)
533 goto try_again;
534
535 return ERR_PTR(ret);
536 }
526 /* 537 /*
527 * Subrequests are always contiguous, non overlapping 538 * Subrequests are always contiguous, non overlapping
528 * and in order - but may be repeated (mirrored writes). 539 * and in order - but may be repeated (mirrored writes).
@@ -533,21 +544,10 @@ try_again:
533 } else if (WARN_ON_ONCE(subreq->wb_offset < head->wb_offset || 544 } else if (WARN_ON_ONCE(subreq->wb_offset < head->wb_offset ||
534 ((subreq->wb_offset + subreq->wb_bytes) > 545 ((subreq->wb_offset + subreq->wb_bytes) >
535 (head->wb_offset + total_bytes)))) { 546 (head->wb_offset + total_bytes)))) {
547 nfs_unlock_request(subreq);
536 nfs_unroll_locks_and_wait(inode, head, subreq); 548 nfs_unroll_locks_and_wait(inode, head, subreq);
537 return ERR_PTR(-EIO); 549 return ERR_PTR(-EIO);
538 } 550 }
539
540 if (!nfs_lock_request(subreq)) {
541 /* releases page group bit lock and
542 * inode spin lock and all references */
543 ret = nfs_unroll_locks_and_wait(inode, head,
544 subreq);
545
546 if (ret == 0)
547 goto try_again;
548
549 return ERR_PTR(ret);
550 }
551 } 551 }
552 552
553 /* Now that all requests are locked, make sure they aren't on any list. 553 /* Now that all requests are locked, make sure they aren't on any list.