aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/inode.c33
-rw-r--r--include/linux/nfs_fs.h1
-rw-r--r--include/linux/nfs_xdr.h1
3 files changed, 28 insertions, 7 deletions
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index a82f0340744f..c45bd52cc1d7 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -64,6 +64,7 @@ static void nfs_clear_inode(struct inode *);
64static void nfs_umount_begin(struct super_block *); 64static void nfs_umount_begin(struct super_block *);
65static int nfs_statfs(struct super_block *, struct kstatfs *); 65static int nfs_statfs(struct super_block *, struct kstatfs *);
66static int nfs_show_options(struct seq_file *, struct vfsmount *); 66static int nfs_show_options(struct seq_file *, struct vfsmount *);
67static void nfs_zap_acl_cache(struct inode *);
67 68
68static struct rpc_program nfs_program; 69static struct rpc_program nfs_program;
69 70
@@ -153,6 +154,7 @@ nfs_clear_inode(struct inode *inode)
153 154
154 nfs_wb_all(inode); 155 nfs_wb_all(inode);
155 BUG_ON (!list_empty(&nfsi->open_files)); 156 BUG_ON (!list_empty(&nfsi->open_files));
157 nfs_zap_acl_cache(inode);
156 cred = nfsi->cache_access.cred; 158 cred = nfsi->cache_access.cred;
157 if (cred) 159 if (cred)
158 put_rpccred(cred); 160 put_rpccred(cred);
@@ -587,9 +589,19 @@ nfs_zap_caches(struct inode *inode)
587 589
588 memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode))); 590 memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
589 if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode)) 591 if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
590 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS; 592 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
591 else 593 else
592 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS; 594 nfsi->flags |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
595}
596
597static void nfs_zap_acl_cache(struct inode *inode)
598{
599 void (*clear_acl_cache)(struct inode *);
600
601 clear_acl_cache = NFS_PROTO(inode)->clear_acl_cache;
602 if (clear_acl_cache != NULL)
603 clear_acl_cache(inode);
604 NFS_I(inode)->flags &= ~NFS_INO_INVALID_ACL;
593} 605}
594 606
595/* 607/*
@@ -789,7 +801,7 @@ nfs_setattr(struct dentry *dentry, struct iattr *attr)
789 } 801 }
790 } 802 }
791 if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0) 803 if ((attr->ia_valid & (ATTR_MODE|ATTR_UID|ATTR_GID)) != 0)
792 NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS; 804 NFS_FLAGS(inode) |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
793 nfs_end_data_update(inode); 805 nfs_end_data_update(inode);
794 unlock_kernel(); 806 unlock_kernel();
795 return error; 807 return error;
@@ -1033,6 +1045,8 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode)
1033 /* This ensures we revalidate dentries */ 1045 /* This ensures we revalidate dentries */
1034 nfsi->cache_change_attribute++; 1046 nfsi->cache_change_attribute++;
1035 } 1047 }
1048 if (flags & NFS_INO_INVALID_ACL)
1049 nfs_zap_acl_cache(inode);
1036 dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n", 1050 dfprintk(PAGECACHE, "NFS: (%s/%Ld) revalidation complete\n",
1037 inode->i_sb->s_id, 1051 inode->i_sb->s_id,
1038 (long long)NFS_FILEID(inode)); 1052 (long long)NFS_FILEID(inode));
@@ -1183,7 +1197,7 @@ int nfs_refresh_inode(struct inode *inode, struct nfs_fattr *fattr)
1183 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) 1197 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO)
1184 || inode->i_uid != fattr->uid 1198 || inode->i_uid != fattr->uid
1185 || inode->i_gid != fattr->gid) 1199 || inode->i_gid != fattr->gid)
1186 nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS; 1200 nfsi->flags |= NFS_INO_INVALID_ATTR | NFS_INO_INVALID_ACCESS | NFS_INO_INVALID_ACL;
1187 1201
1188 /* Has the link count changed? */ 1202 /* Has the link count changed? */
1189 if (inode->i_nlink != fattr->nlink) 1203 if (inode->i_nlink != fattr->nlink)
@@ -1292,16 +1306,21 @@ static int nfs_update_inode(struct inode *inode, struct nfs_fattr *fattr, unsign
1292#endif 1306#endif
1293 nfsi->change_attr = fattr->change_attr; 1307 nfsi->change_attr = fattr->change_attr;
1294 if (!data_unstable) 1308 if (!data_unstable)
1295 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS; 1309 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1296 } 1310 }
1297 1311
1298 memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime)); 1312 /* If ctime has changed we should definitely clear access+acl caches */
1313 if (!timespec_equal(&inode->i_ctime, &fattr->ctime)) {
1314 if (!data_unstable)
1315 invalid |= NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1316 memcpy(&inode->i_ctime, &fattr->ctime, sizeof(inode->i_ctime));
1317 }
1299 memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime)); 1318 memcpy(&inode->i_atime, &fattr->atime, sizeof(inode->i_atime));
1300 1319
1301 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) || 1320 if ((inode->i_mode & S_IALLUGO) != (fattr->mode & S_IALLUGO) ||
1302 inode->i_uid != fattr->uid || 1321 inode->i_uid != fattr->uid ||
1303 inode->i_gid != fattr->gid) 1322 inode->i_gid != fattr->gid)
1304 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS; 1323 invalid |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL;
1305 1324
1306 inode->i_mode = fattr->mode; 1325 inode->i_mode = fattr->mode;
1307 inode->i_nlink = fattr->nlink; 1326 inode->i_nlink = fattr->nlink;
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 0b01b96337f8..140bdf489f71 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -189,6 +189,7 @@ struct nfs_inode {
189#define NFS_INO_INVALID_DATA 0x0010 /* cached data is invalid */ 189#define NFS_INO_INVALID_DATA 0x0010 /* cached data is invalid */
190#define NFS_INO_INVALID_ATIME 0x0020 /* cached atime is invalid */ 190#define NFS_INO_INVALID_ATIME 0x0020 /* cached atime is invalid */
191#define NFS_INO_INVALID_ACCESS 0x0040 /* cached access cred invalid */ 191#define NFS_INO_INVALID_ACCESS 0x0040 /* cached access cred invalid */
192#define NFS_INO_INVALID_ACL 0x0080 /* cached acls are invalid */
192 193
193static inline struct nfs_inode *NFS_I(struct inode *inode) 194static inline struct nfs_inode *NFS_I(struct inode *inode)
194{ 195{
diff --git a/include/linux/nfs_xdr.h b/include/linux/nfs_xdr.h
index 5b45bafd9db5..cf38db59f347 100644
--- a/include/linux/nfs_xdr.h
+++ b/include/linux/nfs_xdr.h
@@ -714,6 +714,7 @@ struct nfs_rpc_ops {
714 int (*file_open) (struct inode *, struct file *); 714 int (*file_open) (struct inode *, struct file *);
715 int (*file_release) (struct inode *, struct file *); 715 int (*file_release) (struct inode *, struct file *);
716 int (*lock)(struct file *, int, struct file_lock *); 716 int (*lock)(struct file *, int, struct file_lock *);
717 void (*clear_acl_cache)(struct inode *);
717}; 718};
718 719
719/* 720/*