|
@@ -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))
|
|
|
- nfs_zap_caches(inode);
|
|
|
+ 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;
|
|
|
}
|