Skip to content

Commit 5fadeb4

Browse files
Peng TaoTom Haynes
authored andcommitted
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>
1 parent aa8a45e commit 5fadeb4

File tree

1 file changed

+8
-4
lines changed

1 file changed

+8
-4
lines changed

fs/nfs/direct.c

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct nfs_direct_req {
8888

8989
ssize_t count, /* bytes actually processed */
9090
bytes_left, /* bytes left to be sent */
91+
io_start, /* start of IO */
9192
error; /* any reported error */
9293
struct completion completion; /* wait for i/o completion */
9394

@@ -130,10 +131,11 @@ nfs_direct_good_bytes(struct nfs_direct_req *dreq, struct nfs_pgio_header *hdr)
130131

131132
WARN_ON_ONCE(hdr->pgio_mirror_idx >= dreq->mirror_count);
132133

133-
dreq->mirrors[hdr->pgio_mirror_idx].count += hdr->good_bytes;
134-
135-
if (hdr->pgio_mirror_idx == 0)
136-
dreq->count += hdr->good_bytes;
134+
count = dreq->mirrors[hdr->pgio_mirror_idx].count;
135+
if (count + dreq->io_start < hdr->io_start + hdr->good_bytes) {
136+
count = hdr->io_start + hdr->good_bytes - dreq->io_start;
137+
dreq->mirrors[hdr->pgio_mirror_idx].count = count;
138+
}
137139

138140
/* update the dreq->count by finding the minimum agreed count from all
139141
* mirrors */
@@ -594,6 +596,7 @@ ssize_t nfs_file_direct_read(struct kiocb *iocb, struct iov_iter *iter,
594596

595597
dreq->inode = inode;
596598
dreq->bytes_left = count;
599+
dreq->io_start = pos;
597600
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
598601
l_ctx = nfs_get_lock_context(dreq->ctx);
599602
if (IS_ERR(l_ctx)) {
@@ -1002,6 +1005,7 @@ ssize_t nfs_file_direct_write(struct kiocb *iocb, struct iov_iter *iter,
10021005

10031006
dreq->inode = inode;
10041007
dreq->bytes_left = count;
1008+
dreq->io_start = pos;
10051009
dreq->ctx = get_nfs_open_context(nfs_file_open_context(iocb->ki_filp));
10061010
l_ctx = nfs_get_lock_context(dreq->ctx);
10071011
if (IS_ERR(l_ctx)) {

0 commit comments

Comments
 (0)