aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/direct.c
diff options
context:
space:
mode:
authorPeng Tao <tao.peng@primarydata.com>2015-01-18 23:41:16 -0500
committerTom Haynes <loghyr@primarydata.com>2015-02-03 14:06:52 -0500
commit5fadeb47dcc5c30d4b6cf481b4a78689eab59443 (patch)
tree61144dbb7c04d5ddae49174c122ef1c686712b06 /fs/nfs/direct.c
parentaa8a45ee974dfe3ffe290daaf5db457afae56fde (diff)
nfs: count DIO good bytes correctly with mirroring
When resending to MDS, we might resend multiple mirroring requests to MDS. As a result, nfs_direct_good_bytes() ends up counting bytes multiple times, causing application to get wrong return results in read/write syscalls. Fix it by tracking start of a dreq and checking the range of pgio header. Cc: Weston Andros Adamson <dros@primarydata.com> Signed-off-by: Peng Tao <tao.peng@primarydata.com>
Diffstat (limited to 'fs/nfs/direct.c')
-rw-r--r--fs/nfs/direct.c12
1 files changed, 8 insertions, 4 deletions
diff --git a/fs/nfs/direct.c b/fs/nfs/direct.c
index 4fad6b727eb4..3715b4957abc 100644
--- a/fs/nfs/direct.c
+++ b/fs/nfs/direct.c
@@ -88,6 +88,7 @@ struct nfs_direct_req {
88 88
89 ssize_t count, /* bytes actually processed */ 89 ssize_t count, /* bytes actually processed */
90 bytes_left, /* bytes left to be sent */ 90 bytes_left, /* bytes left to be sent */
91 io_start, /* start of IO */
91 error; /* any reported error */ 92 error; /* any reported error */
92 struct completion completion; /* wait for i/o completion */ 93 struct completion completion; /* wait for i/o completion */
93 94
@@ -130,10 +131,11 @@ nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr)
130 131
131 WARN_ON_ONCE(hdr->pgio_mirror_idx >= dreq->mirror_count); 132 WARN_ON_ONCE(hdr->pgio_mirror_idx >= dreq->mirror_count);
132 133
133 dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes; 134 count = dreq->mirrors[hdr->pgio_mirror_idx].count;
134 135 if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) {
135 if (hdr->pgio_mirror_idx == 0) 136 count = hdr->io_start + hdr->good_bytes - dreq->io_start;
136 dreq->count += hdr->good_bytes; 137 dreq->mirrors[hdr->pgio_mirror_idx].count = count;
138 }
137 139
138 /* update the dreq->count by finding the minimum agreed count from all 140 /* update the dreq->count by finding the minimum agreed count from all
139 * mirrors */ 141 * mirrors */
@@ -594,6 +596,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
594 596
595 dreq->inode = inode; 597 dreq->inode = inode;
596 dreq->bytes_left = count; 598 dreq->bytes_left = count;
599 dreq->io_start = pos;
597 dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); 600 dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
598 l_ctx = nfs_get_lock_context(dreq->ctx); 601 l_ctx = nfs_get_lock_context(dreq->ctx);
599 if (IS_ERR(l_ctx)) { 602 if (IS_ERR(l_ctx)) {
@@ -1002,6 +1005,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
1002 1005
1003 dreq->inode = inode; 1006 dreq->inode = inode;
1004 dreq->bytes_left = count; 1007 dreq->bytes_left = count;
1008 dreq->io_start = pos;
1005 dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp)); 1009 dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
1006 l_ctx = nfs_get_lock_context(dreq->ctx); 1010 l_ctx = nfs_get_lock_context(dreq->ctx);
1007 if (IS_ERR(l_ctx)) { 1011 if (IS_ERR(l_ctx)) {