aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorTrond Myklebust <trond.myklebust@primarydata.com>2016-07-24 11:46:06 -0400
committerTrond Myklebust <trond.myklebust@primarydata.com>2016-07-24 16:16:38 -0400
commitecebb80bf3ee8c5f3172f00bb17ba55f9e3ae24f (patch)
tree32d5c42f2e3358342549f3991241a4ca253b2363 /fs/nfs
parent13bede18de41e2cfe8f67c1cd8b6d10be42ef473 (diff)
pNFS: Always update the layout barrier seqid on LAYOUTGET
Currently, pnfs_set_layout_stateid() will update the layout sequence id barrier only if the stateid itself is newer than the current layout stateid. However in a situation where multiple LAYOUTGET calls and a LAYOUTRETURN raced, it is entirely possible for one of the LAYOUTGET to set the current stateid to something newer than the LAYOUTRETURN that needs to set the barrier. The fix is to allow the "update_barrier" flag to force a check as to whether or not the barrier needs to be updated. Signed-off-by: Trond Myklebust <trond.myklebust@primarydata.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/pnfs.c27
1 files changed, 14 insertions, 13 deletions
diff --git a/fs/nfs/pnfs.c b/fs/nfs/pnfs.c
index eef844785bc6..85c3e7b47ddb 100644
--- a/fs/nfs/pnfs.c
+++ b/fs/nfs/pnfs.c
@@ -761,24 +761,25 @@ void
761pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new, 761pnfs_set_layout_stateid(struct pnfs_layout_hdr *lo, const nfs4_stateid *new,
762 bool update_barrier) 762 bool update_barrier)
763{ 763{
764 u32 oldseq, newseq, new_barrier; 764 u32 oldseq, newseq, new_barrier = 0;
765 bool empty = !pnfs_layout_is_valid(lo); 765 bool invalid = !pnfs_layout_is_valid(lo);
766 766
767 oldseq = be32_to_cpu(lo->plh_stateid.seqid); 767 oldseq = be32_to_cpu(lo->plh_stateid.seqid);
768 newseq = be32_to_cpu(new->seqid); 768 newseq = be32_to_cpu(new->seqid);
769 if (empty || pnfs_seqid_is_newer(newseq, oldseq)) { 769 if (invalid || pnfs_seqid_is_newer(newseq, oldseq)) {
770 nfs4_stateid_copy(&lo->plh_stateid, new); 770 nfs4_stateid_copy(&lo->plh_stateid, new);
771 if (update_barrier) { 771 /*
772 new_barrier = be32_to_cpu(new->seqid); 772 * Because of wraparound, we want to keep the barrier
773 } else { 773 * "close" to the current seqids.
774 /* Because of wraparound, we want to keep the barrier 774 */
775 * "close" to the current seqids. 775 new_barrier = newseq - atomic_read(&lo->plh_outstanding);
776 */
777 new_barrier = newseq - atomic_read(&lo->plh_outstanding);
778 }
779 if (empty || pnfs_seqid_is_newer(new_barrier, lo->plh_barrier))
780 lo->plh_barrier = new_barrier;
781 } 776 }
777 if (update_barrier)
778 new_barrier = be32_to_cpu(new->seqid);
779 else if (new_barrier == 0)
780 return;
781 if (invalid || pnfs_seqid_is_newer(new_barrier, lo->plh_barrier))
782 lo->plh_barrier = new_barrier;
782} 783}
783 784
784static bool 785static bool