diff options
author | Peng Tao <tao.peng@primarydata.com> | 2015-04-09 23:02:16 +0800 |
---|---|---|
committer | Trond Myklebust <trond.myklebust@primarydata.com> | 2015-04-23 15:05:18 -0400 |
commit | 1ccbad9f9f9bd36db26a10f0b17fbaf12b3ae93a (patch) | |
tree | 6bf27072c4383cffc77e15c553d6b294394a472e /fs/nfs/direct.c | |
parent | ea96d1ecbe4fcb1df487d99309d3157b4ff5fc02 (diff) | |
download | linux-stable-1ccbad9f9f9bd36db26a10f0b17fbaf12b3ae93a.tar.gz linux-stable-1ccbad9f9f9bd36db26a10f0b17fbaf12b3ae93a.tar.bz2 linux-stable-1ccbad9f9f9bd36db26a10f0b17fbaf12b3ae93a.zip |
nfs: fix DIO good bytes calculation
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>
Cc: <stable@vger.kernel.org> # v3.19+
Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r-- | fs/nfs/direct.c | 29 |
1 files changed, 17 insertions, 12 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c index 018a06a062bd..e97a67e40b48 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; + } } /* |