aboutsummaryrefslogtreecommitdiff
path: root/fs
diff options
context:
space:
mode:
authorPeng Tao <tao.peng@primarydata.com>2015-04-09 23:02:16 +0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2015-05-06 22:04:06 +0200
commitdcd8d0c80e86b8821c5a453b5bf782328d8580e1 (patch)
tree4c06987b4944b6d218a41301fd3b478cf0470a98 /fs
parentc59908b7a9d4b76f72367f055559663e1da274fc (diff)
nfs: fix DIO good bytes calculation
commit 1ccbad9f9f9bd36db26a10f0b17fbaf12b3ae93a upstream. For direct read that has IO size larger than rsize, we'll split it into several READ requests and nfs_direct_good_bytes() would count completed bytes incorrectly by eating last zero count reply. Fix it by handling mirror and non-mirror cases differently such that we only count mirrored writes differently. This fixes 5fadeb47("nfs: count DIO good bytes correctly with mirroring"). Reported-by: Jean Spector <jean@primarydata.com> Signed-off-by: Peng Tao <tao.peng@primarydata.com> Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'fs')
-rw-r--r--fs/nfs/direct.c29
1 files changed, 17 insertions, 12 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index e907c8cf732e..5e451a75132d 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -131,20 +131,25 @@ nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr)
WARN_ON_ONCE(hdr->pgio_mirror_idx >= dreq->mirror_count);
- count = dreq->mirrors[hdr->pgio_mirror_idx].count;
- if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) {
- count = hdr->io_start + hdr->good_bytes - dreq->io_start;
- dreq->mirrors[hdr->pgio_mirror_idx].count = count;
- }
-
- /* update the dreq->count by finding the minimum agreed count from all
- * mirrors */
- count = dreq->mirrors[0].count;
+ if (dreq->mirror_count == 1) {
+ dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes;
+ dreq->count += hdr->good_bytes;
+ } else {
+ /* mirrored writes */
+ count = dreq->mirrors[hdr->pgio_mirror_idx].count;
+ if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) {
+ count = hdr->io_start + hdr->good_bytes - dreq->io_start;
+ dreq->mirrors[hdr->pgio_mirror_idx].count = count;
+ }
+ /* update the dreq->count by finding the minimum agreed count from all
+ * mirrors */
+ count = dreq->mirrors[0].count;
- for (i = 1; i < dreq->mirror_count; i++)
- count = min(count, dreq->mirrors[i].count);
+ for (i = 1; i < dreq->mirror_count; i++)
+ count = min(count, dreq->mirrors[i].count);
- dreq->count = count;
+ dreq->count = count;
+ }
}
/*