aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs
diff options
context:
space:
mode:
authorRicardo Labiaga <Ricardo.Labiaga@netapp.com>2010-10-12 19:30:05 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-10-24 17:59:56 -0400
commit6b96724e507fecc3e6440e86426fe4f44359ed66 (patch)
tree5b38131405301f4dd536a11f44ff0d5e6785d266 /fs/nfs
parent118df3d17f11733b294ea2cd988d56ee376ef9fd (diff)
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: Ricardo Labiaga <Ricardo.Labiaga@netapp.com> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs')
-rw-r--r--fs/nfs/client.c2
-rw-r--r--fs/nfs/file.c19
-rw-r--r--fs/nfs/nfs3xdr.c3
3 files changed, 20 insertions, 4 deletions
diff --git a/fs/nfs/client.c b/fs/nfs/client.c
index da2f2f024a4d..a63bce8d0596 100644
--- a/fs/nfs/client.c
+++ b/fs/nfs/client.c
@@ -915,6 +915,8 @@ static void nfs_server_set_fsinfo(struct nfs_server *server, struct nfs_fsinfo *
915 915
916 server->maxfilesize = fsinfo->maxfilesize; 916 server->maxfilesize = fsinfo->maxfilesize;
917 917
918 server->time_delta = fsinfo->time_delta;
919
918 /* We're airborne Set socket buffersize */ 920 /* We're airborne Set socket buffersize */
919 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100); 921 rpc_setbufsize(server->client, server->wsize + 100, server->rsize + 100);
920} 922}
diff --git a/fs/nfs/file.c b/fs/nfs/file.c
index 39672b731736..c3f2477c16c1 100644
--- a/fs/nfs/file.c
+++ b/fs/nfs/file.c
@@ -758,6 +758,11 @@ do_unlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
758} 758}
759 759
760static int 760static int
761is_time_granular(struct timespec *ts) {
762 return ((ts->tv_sec == 0) && (ts->tv_nsec <= 1000));
763}
764
765static int
761do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local) 766do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
762{ 767{
763 struct inode *inode = filp->f_mapping->host; 768 struct inode *inode = filp->f_mapping->host;
@@ -781,13 +786,21 @@ do_setlk(struct file *filp, int cmd, struct file_lock *fl, int is_local)
781 status = do_vfs_lock(filp, fl); 786 status = do_vfs_lock(filp, fl);
782 if (status < 0) 787 if (status < 0)
783 goto out; 788 goto out;
789
784 /* 790 /*
785 * Make sure we clear the cache whenever we try to get the lock. 791 * Revalidate the cache if the server has time stamps granular
792 * enough to detect subsecond changes. Otherwise, clear the
793 * cache to prevent missing any changes.
794 *
786 * This makes locking act as a cache coherency point. 795 * This makes locking act as a cache coherency point.
787 */ 796 */
788 nfs_sync_mapping(filp->f_mapping); 797 nfs_sync_mapping(filp->f_mapping);
789 if (!nfs_have_delegation(inode, FMODE_READ)) 798 if (!nfs_have_delegation(inode, FMODE_READ)) {
790 nfs_zap_caches(inode); 799 if (is_time_granular(&NFS_SERVER(inode)->time_delta))
800 __nfs_revalidate_inode(NFS_SERVER(inode), inode);
801 else
802 nfs_zap_caches(inode);
803 }
791out: 804out:
792 return status; 805 return status;
793} 806}
diff --git a/fs/nfs/nfs3xdr.c b/fs/nfs/nfs3xdr.c
index 31a44df40aea..d9a5e832c257 100644
--- a/fs/nfs/nfs3xdr.c
+++ b/fs/nfs/nfs3xdr.c
@@ -1044,8 +1044,9 @@ nfs3_xdr_fsinfores(struct rpc_rqst *req, __be32 *p, struct nfs_fsinfo *res)
1044 res->wtmult = ntohl(*p++); 1044 res->wtmult = ntohl(*p++);
1045 res->dtpref = ntohl(*p++); 1045 res->dtpref = ntohl(*p++);
1046 p = xdr_decode_hyper(p, &res->maxfilesize); 1046 p = xdr_decode_hyper(p, &res->maxfilesize);
1047 p = xdr_decode_time3(p, &res->time_delta);
1047 1048
1048 /* ignore time_delta and properties */ 1049 /* ignore properties */
1049 res->lease_time = 0; 1050 res->lease_time = 0;
1050 return 0; 1051 return 0;
1051} 1052}