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>
This commit is contained in:
parent
a0e265bc78
commit
e14bebf6de
@ -523,20 +523,6 @@ try_again:
|
|||||||
total_bytes = head->wb_bytes;
|
total_bytes = head->wb_bytes;
|
||||||
for (subreq = head->wb_this_page; subreq != head;
|
for (subreq = head->wb_this_page; subreq != head;
|
||||||
subreq = subreq->wb_this_page) {
|
subreq = subreq->wb_this_page) {
|
||||||
/*
|
|
||||||
* Subrequests are always contiguous, non overlapping
|
|
||||||
* and in order - but may be repeated (mirrored writes).
|
|
||||||
*/
|
|
||||||
if (subreq->wb_offset == (head->wb_offset + total_bytes)) {
|
|
||||||
/* keep track of how many bytes this group covers */
|
|
||||||
total_bytes += subreq->wb_bytes;
|
|
||||||
} else if (WARN_ON_ONCE(subreq->wb_offset < head->wb_offset ||
|
|
||||||
((subreq->wb_offset + subreq->wb_bytes) >
|
|
||||||
(head->wb_offset + total_bytes)))) {
|
|
||||||
nfs_unroll_locks_and_wait(inode, head, subreq);
|
|
||||||
return ERR_PTR(-EIO);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!nfs_lock_request(subreq)) {
|
if (!nfs_lock_request(subreq)) {
|
||||||
/* releases page group bit lock and
|
/* releases page group bit lock and
|
||||||
* inode spin lock and all references */
|
* inode spin lock and all references */
|
||||||
@ -548,6 +534,20 @@ try_again:
|
|||||||
|
|
||||||
return ERR_PTR(ret);
|
return ERR_PTR(ret);
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* Subrequests are always contiguous, non overlapping
|
||||||
|
* and in order - but may be repeated (mirrored writes).
|
||||||
|
*/
|
||||||
|
if (subreq->wb_offset == (head->wb_offset + total_bytes)) {
|
||||||
|
/* keep track of how many bytes this group covers */
|
||||||
|
total_bytes += subreq->wb_bytes;
|
||||||
|
} else if (WARN_ON_ONCE(subreq->wb_offset < head->wb_offset ||
|
||||||
|
((subreq->wb_offset + subreq->wb_bytes) >
|
||||||
|
(head->wb_offset + total_bytes)))) {
|
||||||
|
nfs_unlock_request(subreq);
|
||||||
|
nfs_unroll_locks_and_wait(inode, head, subreq);
|
||||||
|
return ERR_PTR(-EIO);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now that all requests are locked, make sure they aren't on any list.
|
/* Now that all requests are locked, make sure they aren't on any list.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user