Commit 3aeba064 authored by Trond Myklebust's avatar Trond Myklebust Committed by Linus Torvalds

[PATCH] A basic NFSv4 client for 2.5.x

This is a nontrivial change to the NFS client.

NFSv4 defines a new file attribute, change_attr.  This is a per-file
opaque quantity returned by the server, whose value is required to
change whenever the file is modified.  If it exists, we want to use
it for all cache consistency checks in nfs_refresh_inode().  Some
operations also return a "pre-operation" value of the change_attr;
we want to take this into account too.

First, define flags
  NFS_ATTR_FATTR_V4 - indicates that the 'struct nfs_fattr' is an
                      NFSv4 fattr, so the change_attr field is valid
  NFS_ATTR_PRE_CHANGE - indicates that the server returned a pre-operation
                      change_attr, so the pre_change_attr field is valid

Second, change nfs_refresh_inode() so that the caches are invalidated
if there is a change_attr mismatch.  Exception: If the pre_change_attr
tells us that the mismatch was caused by our operation, then do not
invalidate the caches.

This patch should leave the logic in nfs_refresh_inode() unchanged
if neither of the new flags are set.
parent 61e6f975
...@@ -716,6 +716,8 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr) ...@@ -716,6 +716,8 @@ __nfs_fhget(struct super_block *sb, struct nfs_fh *fh, struct nfs_fattr *fattr)
inode->i_mtime = nfs_time_to_secs(new_mtime); inode->i_mtime = nfs_time_to_secs(new_mtime);
NFS_MTIME_UPDATE(inode) = fattr->timestamp; NFS_MTIME_UPDATE(inode) = fattr->timestamp;
NFS_CACHE_ISIZE(inode) = new_size; NFS_CACHE_ISIZE(inode) = new_size;
if (fattr->valid & NFS_ATTR_FATTR_V4)
NFS_CHANGE_ATTR(inode) = fattr->change_attr;
inode->i_size = new_isize; inode->i_size = new_isize;
inode->i_mode = fattr->mode; inode->i_mode = fattr->mode;
inode->i_nlink = fattr->nlink; inode->i_nlink = fattr->nlink;
...@@ -1067,12 +1069,25 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1067,12 +1069,25 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
invalid = 1; invalid = 1;
} }
if ((fattr->valid & NFS_ATTR_FATTR_V4)
&& NFS_CHANGE_ATTR(inode) != fattr->change_attr) {
#ifdef NFS_DEBUG_VERBOSE
printk(KERN_DEBUG "NFS: change_attr change on %s/%ld\n",
inode->i_sb->s_id, inode->i_ino);
#endif
invalid = 1;
}
/* Check Weak Cache Consistency data. /* Check Weak Cache Consistency data.
* If size and mtime match the pre-operation values, we can * If size and mtime match the pre-operation values, we can
* assume that any attribute changes were caused by our NFS * assume that any attribute changes were caused by our NFS
* operation, so there's no need to invalidate the caches. * operation, so there's no need to invalidate the caches.
*/ */
if ((fattr->valid & NFS_ATTR_WCC) if ((fattr->valid & NFS_ATTR_PRE_CHANGE)
&& NFS_CHANGE_ATTR(inode) == fattr->pre_change_attr) {
invalid = 0;
}
else if ((fattr->valid & NFS_ATTR_WCC)
&& NFS_CACHE_ISIZE(inode) == fattr->pre_size && NFS_CACHE_ISIZE(inode) == fattr->pre_size
&& NFS_CACHE_MTIME(inode) == fattr->pre_mtime) { && NFS_CACHE_MTIME(inode) == fattr->pre_mtime) {
invalid = 0; invalid = 0;
...@@ -1110,6 +1125,9 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr) ...@@ -1110,6 +1125,9 @@ __nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
} }
} }
if (fattr->valid & NFS_ATTR_FATTR_V4)
NFS_CHANGE_ATTR(inode) = fattr->change_attr;
inode->i_mode = fattr->mode; inode->i_mode = fattr->mode;
inode->i_nlink = fattr->nlink; inode->i_nlink = fattr->nlink;
inode->i_uid = fattr->uid; inode->i_uid = fattr->uid;
......
...@@ -144,6 +144,7 @@ struct nfs_inode { ...@@ -144,6 +144,7 @@ struct nfs_inode {
__u64 read_cache_isize; __u64 read_cache_isize;
unsigned long attrtimeo; unsigned long attrtimeo;
unsigned long attrtimeo_timestamp; unsigned long attrtimeo_timestamp;
__u64 change_attr; /* v4 only */
/* /*
* Timestamp that dates the change made to read_cache_mtime. * Timestamp that dates the change made to read_cache_mtime.
...@@ -208,6 +209,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode) ...@@ -208,6 +209,7 @@ static inline struct nfs_inode *NFS_I(struct inode *inode)
#define NFS_CACHE_CTIME(inode) (NFS_I(inode)->read_cache_ctime) #define NFS_CACHE_CTIME(inode) (NFS_I(inode)->read_cache_ctime)
#define NFS_CACHE_MTIME(inode) (NFS_I(inode)->read_cache_mtime) #define NFS_CACHE_MTIME(inode) (NFS_I(inode)->read_cache_mtime)
#define NFS_CACHE_ISIZE(inode) (NFS_I(inode)->read_cache_isize) #define NFS_CACHE_ISIZE(inode) (NFS_I(inode)->read_cache_isize)
#define NFS_CHANGE_ATTR(inode) (NFS_I(inode)->change_attr)
#define NFS_NEXTSCAN(inode) (NFS_I(inode)->nextscan) #define NFS_NEXTSCAN(inode) (NFS_I(inode)->nextscan)
#define NFS_CACHEINV(inode) \ #define NFS_CACHEINV(inode) \
do { \ do { \
......
...@@ -35,12 +35,16 @@ struct nfs_fattr { ...@@ -35,12 +35,16 @@ struct nfs_fattr {
__u64 atime; __u64 atime;
__u64 mtime; __u64 mtime;
__u64 ctime; __u64 ctime;
__u64 change_attr; /* NFSv4 change attribute */
__u64 pre_change_attr;/* pre-op NFSv4 change attribute */
unsigned long timestamp; unsigned long timestamp;
}; };
#define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */ #define NFS_ATTR_WCC 0x0001 /* pre-op WCC data */
#define NFS_ATTR_FATTR 0x0002 /* post-op attributes */ #define NFS_ATTR_FATTR 0x0002 /* post-op attributes */
#define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */ #define NFS_ATTR_FATTR_V3 0x0004 /* NFSv3 attributes */
#define NFS_ATTR_FATTR_V4 0x0008
#define NFS_ATTR_PRE_CHANGE 0x0010
/* /*
* Info on the file system * Info on the file system
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment