[PATCH] NFS: Add hooks to allow common NFS attribute code to clear cached acls
authorTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 22 Jun 2005 17:16:22 +0000 (17:16 +0000)
committerTrond Myklebust <Trond.Myklebust@netapp.com>
Wed, 22 Jun 2005 20:07:09 +0000 (16:07 -0400)
Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
fs/nfs/inode.c
include/linux/nfs_fs.h
include/linux/nfs_xdr.h

index a82f0340744f5efdbff4e166a9cad55cc301cff5..c45bd52cc1d70d3624a7ec0a9a7e833d659da01a 100644 (file)
@@ -64,6 +64,7 @@ static void nfs_clear_inode(struct inode *);
 static void nfs_umount_begin(struct super_block *);
 static int  nfs_statfs(struct super_block *, struct kstatfs *);
 static int  nfs_show_options(struct seq_file *, struct vfsmount *);
+static void nfs_zap_acl_cache(struct inode *);
 
 static struct rpc_program      nfs_program;
 
@@ -153,6 +154,7 @@ nfs_clear_inode(struct inode *inode)
 
        nfs_wb_all(inode);
        BUG_ON (!list_empty(&nfsi->open_files));
+       nfs_zap_acl_cache(inode);
        cred = nfsi->cache_access.cred;
        if (cred)
                put_rpccred(cred);
@@ -587,9 +589,19 @@ nfs_zap_caches(struct inode *inode)
 
        memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
        if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
-               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS;
+               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
        else
-               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+               nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+}
+
+static void nfs_zap_acl_cache(struct inode *inode)
+{
+       void (*clear_acl_cache)(struct inode *);
+
+       clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
+       if (clear_acl_cache != NULL)
+               clear_acl_cache(inode);
+       NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL;
 }
 
 /*
@@ -789,7 +801,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
                }
        }
        if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
-               NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS;
+               NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
        nfs_end_data_update(inode);
        unlock_kernel();
        return error;
@@ -1033,6 +1045,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
                /* This ensures we revalidate dentries */
                nfsi->cache_change_attribute++;
        }
+       if (flags & NFS_INO_INVALID_ACL)
+               nfs_zap_acl_cache(inode);
        dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
                inode->i_sb->s_id,
                (long long)NFS_FILEID(inode));
@@ -1183,7 +1197,7 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
        if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
                        || inode->i_uid != fattr->uid
                        || inode->i_gid != fattr->gid)
-               nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS;
+               nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
 
        /* Has the link count changed? */
        if (inode->i_nlink != fattr->nlink)
@@ -1292,16 +1306,21 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
 #endif
                nfsi->change_attr = fattr->change_attr;
                if (!data_unstable)
-                       invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS;
+                       invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
        }
 
-       memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+       /* If ctime has changed we should definitely clear access+acl caches */
+       if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
+               if (!data_unstable)
+                       invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
+               memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
+       }
        memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
 
        if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) ||
            inode->i_uid != fattr->uid ||
            inode->i_gid != fattr->gid)
-               invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS;
+               invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
 
        inode->i_mode = fattr->mode;
        inode->i_nlink = fattr->nlink;
index 0b01b96337f80003a7220bbb124b3c5692476074..140bdf489f71399920df95c29d9c202e62df7019 100644 (file)
@@ -189,6 +189,7 @@ struct nfs_inode {
 #define NFS_INO_INVALID_DATA   0x0010          /* cached data is invalid */
 #define NFS_INO_INVALID_ATIME  0x0020          /* cached atime is invalid */
 #define NFS_INO_INVALID_ACCESS 0x0040          /* cached access cred invalid */
+#define NFS_INO_INVALID_ACL    0x0080          /* cached acls are invalid */
 
 static inline struct nfs_inode *NFS_I(struct inode *inode)
 {
index 5b45bafd9db5b98a7824e3e817a04e28c98c0ea0..cf38db59f34731efeb695bc52d70d8ed19827d0a 100644 (file)
@@ -714,6 +714,7 @@ struct nfs_rpc_ops {
        int     (*file_open)   (struct inode *, struct file *);
        int     (*file_release) (struct inode *, struct file *);
        int     (*lock)(struct file *, int, struct file_lock *);
+       void    (*clear_acl_cache)(struct inode *);
 };
 
 /*