NFSv4: Ensure change attribute returned by GETATTR callback conforms to spec
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Tue, 3 Jan 2006 08:55:37 +0000 (09:55 +0100)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Fri, 6 Jan 2006 19:58:51 +0000 (14:58 -0500)
 According to RFC3530 we're supposed to cache the change attribute
 at the time the client receives a write delegation.
 If the inode is clean, a CB_GETATTR callback by the server to the
 client is supposed to return the cached change attribute.
 If, OTOH, the inode is dirty, the client should bump the cached
 change attribute by 1.

Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/callback_proc.c
fs/nfs/delegation.c
fs/nfs/delegation.h

index 65f1e19e4d19f6f16eb0e3c9660c86d294016add..462cfceb50c508574378fd83d587112a89419809 100644 (file)
@@ -35,7 +35,9 @@ unsigned nfs4_callback_getattr(struct cb_getattrargs *args, struct cb_getattrres
        if (delegation == NULL || (delegation->type & FMODE_WRITE) == 0)
                goto out_iput;
        res->size = i_size_read(inode);
-       res->change_attr = NFS_CHANGE_ATTR(inode);
+       res->change_attr = delegation->change_attr;
+       if (nfsi->npages != 0)
+               res->change_attr++;
        res->ctime = inode->i_ctime;
        res->mtime = inode->i_mtime;
        res->bitmap[0] = (FATTR4_WORD0_CHANGE|FATTR4_WORD0_SIZE) &
index 75dfb1c717a0dcea68d9ee65e3233a216700a5b4..d2ee09b38ceea36e5b2c22d7273e564de7e40f16 100644 (file)
@@ -131,6 +131,7 @@ int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct
                        sizeof(delegation->stateid.data));
        delegation->type = res->delegation_type;
        delegation->maxsize = res->maxsize;
+       delegation->change_attr = nfsi->change_attr;
        delegation->cred = get_rpccred(cred);
        delegation->inode = inode;
 
index fbc50ec271c54f51a2e36750d89139f67c3aac93..7a0b2bfce771225016fde49829eded19e47f2869 100644 (file)
@@ -21,6 +21,7 @@ struct nfs_delegation {
 #define NFS_DELEGATION_NEED_RECLAIM 1
        long flags;
        loff_t maxsize;
+       __u64 change_attr;
 };
 
 int nfs_inode_set_delegation(struct inode *inode, struct rpc_cred *cred, struct nfs_openres *res);