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

Commit 6b96724e authored by Ricardo Labiaga's avatar Ricardo Labiaga Committed by Trond Myklebust
Browse files

Revalidate caches on lock



Instead of blindly zapping the caches, attempt to revalidate them if
the server has indicated that it uses high resolution timestamps.

NFSv4 should be able to always revalidate the cache since the
protocol requires the update of the change attribute on modification of
the data.  In reality, there are servers (the Linux NFS server
for example) that do not obey this requirement and use ctime as the
basis for change attribute.  Long term, the server needs to be fixed.
At this time, and to be on the safe side, continue zapping caches if
the server indicates that it does not have a high resolution timestamp.

Signed-off-by: default avatarRicardo Labiaga <Ricardo.Labiaga@netapp.com>
Signed-off-by: default avatarTrond Myklebust <Trond.Myklebust@netapp.com>
parent 118df3d1
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -915,6 +915,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *

	server->maxfilesize = fsinfo->maxfilesize;

	server->time_delta = fsinfo->time_delta;

	/* We're airborne Set socket buffersize */
	rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
}
+16 −3
Original line number Diff line number Diff line
@@ -757,6 +757,11 @@ do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
	return status;
}

static int
is_time_granular(struct timespec *ts) {
	return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000));
}

static int
do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
{
@@ -781,13 +786,21 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
		status = do_vfs_lock(filp, fl);
	if (status < 0)
		goto out;

	/*
	 * Make sure we clear the cache whenever we try to get the lock.
	 * Revalidate the cache if the server has time stamps granular
	 * enough to detect subsecond changes.  Otherwise, clear the
	 * cache to prevent missing any changes.
	 *
	 * This makes locking act as a cache coherency point.
	 */
	nfs_sync_mapping(filp->f_mapping);
	if (!nfs_have_delegation(inode, FMODE_READ))
	if (!nfs_have_delegation(inode, FMODE_READ)) {
		if (is_time_granular(&NFS_SERVER(inode)->time_delta))
			__nfs_revalidate_inode(NFS_SERVER(inode), inode);
		else
			nfs_zap_caches(inode);
	}
out:
	return status;
}
+2 −1
Original line number Diff line number Diff line
@@ -1044,8 +1044,9 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
	res->wtmult = ntohl(*p++);
	res->dtpref = ntohl(*p++);
	p = xdr_decode_hyper(p, &res->maxfilesize);
	p = xdr_decode_time3(p, &res->time_delta);

	/* ignore time_delta and properties */
	/* ignore properties */
	res->lease_time = 0;
	return 0;
}
+1 −0
Original line number Diff line number Diff line
@@ -124,6 +124,7 @@ struct nfs_server {

	struct nfs_fsid		fsid;
	__u64			maxfilesize;	/* maximum file size */
	struct timespec		time_delta;	/* smallest time granularity */
	unsigned long		mount_time;	/* when this fs was mounted */
	dev_t			s_dev;		/* superblock dev numbers */

+1 −0
Original line number Diff line number Diff line
@@ -112,6 +112,7 @@ struct nfs_fsinfo {
	__u32			wtmult;	/* writes should be multiple of this */
	__u32			dtpref;	/* pref. readdir transfer size */
	__u64			maxfilesize;
	struct timespec		time_delta; /* server time granularity */
	__u32			lease_time; /* in seconds */
};