aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorWeston Andros Adamson <dros@primarydata.com>2014-09-05 16:34:29 -0400
committerTom Haynes <loghyr@primarydata.com>2015-02-03 14:06:44 -0500
commit309a1d65b11de24d172f7dbbc21583ebd649c912 (patch)
tree3f01d1ddf35fc8b2b27f4468e3bfa7862588ff8a /fs/nfs
parent180bb5ec06ce3a95dccc751fbf6bf11d3003da98 (diff)
nfs: handle overlapping reqs in lock_and_join
This is needed for mirrored DS support, where multuple requests cover the same range. Signed-off-by: Weston Andros Adamson <dros@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/write.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/fs/nfs/write.c b/fs/nfs/write.c
index 8800bd3b235d..e9974574b19a 100644
--- a/fs/nfs/write.c
+++ b/fs/nfs/write.c
@@ -473,13 +473,18 @@ try_again:
473 do { 473 do {
474 /* 474 /*
475 * Subrequests are always contiguous, non overlapping 475 * Subrequests are always contiguous, non overlapping
476 * and in order. If not, it's a programming error. 476 * and in order - but may be repeated (mirrored writes).
477 */ 477 */
478 WARN_ON_ONCE(subreq->wb_offset != 478 if (subreq->wb_offset == (head->wb_offset + total_bytes)) {
479 (head->wb_offset + total_bytes)); 479 /* keep track of how many bytes this group covers */
480 480 total_bytes += subreq->wb_bytes;
481 /* keep track of how many bytes this group covers */ 481 } else if (WARN_ON_ONCE(subreq->wb_offset < head->wb_offset ||
482 total_bytes += subreq->wb_bytes; 482 ((subreq->wb_offset + subreq->wb_bytes) >
483 (head->wb_offset + total_bytes)))) {
484 nfs_page_group_unlock(head);
485 spin_unlock(&inode->i_lock);
486 return ERR_PTR(-EIO);
487 }
483 488
484 if (!nfs_lock_request(subreq)) { 489 if (!nfs_lock_request(subreq)) {
485 /* releases page group bit lock and 490 /* releases page group bit lock and