Skip to content

Commit

Permalink
nfs: fix DIO good bytes calculation
Browse files Browse the repository at this point in the history
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 5fadeb4("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>
  • Loading branch information
Peng Tao authored and Trond Myklebust committed Apr 23, 2015
1 parent ea96d1e commit 1ccbad9
Showing 1 changed file with 17 additions and 12 deletions.
29 changes: 17 additions & 12 deletions fs/nfs/direct.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
}

/*
Expand Down

0 comments on commit 1ccbad9

Please sign in to comment.