diff options
author | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-07-17 11:11:49 -0400 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2017-08-15 11:54:46 -0400 |
commit | e14bebf6de11a4b8476cf2b0a75bf7c3e69112d5 (patch) | |
tree | d6d22e8c6a213ceb8d9e93565df99cf99fdba503 /fs/nfs/write.c | |
parent | a0e265bc78010d2d831a968d4cea3c40a0efac8b (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.c | 24 |
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. |