Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 630458e7 authored by J. Bruce Fields's avatar J. Bruce Fields
Browse files

nfsd4: factor ctime into change attribute



Factoring ctime into the nfsv4 change attribute gives us better
properties than just i_version alone.

Eventually we'll likely also expose this (as opposed to raw i_version)
to userspace, at which point we'll want to move it to a common helper,
called from either userspace or individual filesystems.  For now, nfsd
is the only user.

Signed-off-by: default avatarJ. Bruce Fields <bfields@redhat.com>
parent 35a30fc3
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -260,7 +260,7 @@ void fill_post_wcc(struct svc_fh *fhp)
		printk("nfsd: inode locked twice during operation.\n");

	err = fh_getattr(fhp, &fhp->fh_post_attr);
	fhp->fh_post_change = d_inode(fhp->fh_dentry)->i_version;
	fhp->fh_post_change = nfsd4_change_attribute(d_inode(fhp->fh_dentry));
	if (err) {
		fhp->fh_post_saved = false;
		/* Grab the ctime anyway - set_change_info might use it */
+1 −1
Original line number Diff line number Diff line
@@ -1973,7 +1973,7 @@ static __be32 *encode_change(__be32 *p, struct kstat *stat, struct inode *inode,
		*p++ = cpu_to_be32(convert_to_wallclock(exp->cd->flush_time));
		*p++ = 0;
	} else if (IS_I_VERSION(inode)) {
		p = xdr_encode_hyper(p, inode->i_version);
		p = xdr_encode_hyper(p, nfsd4_change_attribute(inode));
	} else {
		*p++ = cpu_to_be32(stat->ctime.tv_sec);
		*p++ = cpu_to_be32(stat->ctime.tv_nsec);
+23 −1
Original line number Diff line number Diff line
@@ -240,6 +240,28 @@ fh_clear_wcc(struct svc_fh *fhp)
	fhp->fh_pre_saved = false;
}

/*
 * We could use i_version alone as the change attribute.  However,
 * i_version can go backwards after a reboot.  On its own that doesn't
 * necessarily cause a problem, but if i_version goes backwards and then
 * is incremented again it could reuse a value that was previously used
 * before boot, and a client who queried the two values might
 * incorrectly assume nothing changed.
 *
 * By using both ctime and the i_version counter we guarantee that as
 * long as time doesn't go backwards we never reuse an old value.
 */
static inline u64 nfsd4_change_attribute(struct inode *inode)
{
	u64 chattr;

	chattr =  inode->i_ctime.tv_sec;
	chattr <<= 30;
	chattr += inode->i_ctime.tv_nsec;
	chattr += inode->i_version;
	return chattr;
}

/*
 * Fill in the pre_op attr for the wcc data
 */
@@ -253,7 +275,7 @@ fill_pre_wcc(struct svc_fh *fhp)
		fhp->fh_pre_mtime = inode->i_mtime;
		fhp->fh_pre_ctime = inode->i_ctime;
		fhp->fh_pre_size  = inode->i_size;
		fhp->fh_pre_change = inode->i_version;
		fhp->fh_pre_change = nfsd4_change_attribute(inode);
		fhp->fh_pre_saved = true;
	}
}