diff options
author | Peng Tao <tao.peng@primarydata.com> | 2015-01-18 23:41:16 -0500 |
---|---|---|
committer | Tom Haynes <loghyr@primarydata.com> | 2015-02-03 14:06:52 -0500 |
commit | 5fadeb47dcc5c30d4b6cf481b4a78689eab59443 (patch) | |
tree | 61144dbb7c04d5ddae49174c122ef1c686712b06 /fs/nfs/direct.c | |
parent | aa8a45ee974dfe3ffe290daaf5db457afae56fde (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.c | 12 |
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)) { |