aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/nfs/nfs3acl.c100
-rw-r--r--fs/nfs/nfs3proc.c1
-rw-r--r--include/linux/nfs_fs.h11
3 files changed, 97 insertions, 15 deletions
diff --git a/fs/nfs/nfs3acl.c b/fs/nfs/nfs3acl.c
index 89b6468700e7..451112ff9aa4 100644
--- a/fs/nfs/nfs3acl.c
+++ b/fs/nfs/nfs3acl.c
@@ -113,6 +113,69 @@ int nfs3_removexattr(struct dentry *dentry, const char *name)
113 return nfs3_proc_setacl(inode, type, NULL); 113 return nfs3_proc_setacl(inode, type, NULL);
114} 114}
115 115
116static void __nfs3_forget_cached_acls(struct nfs_inode *nfsi)
117{
118 if (nfsi->acl_access != ERR_PTR(-EAGAIN)) {
119 posix_acl_release(nfsi->acl_access);
120 nfsi->acl_access = ERR_PTR(-EAGAIN);
121 }
122 if (nfsi->acl_default != ERR_PTR(-EAGAIN)) {
123 posix_acl_release(nfsi->acl_default);
124 nfsi->acl_default = ERR_PTR(-EAGAIN);
125 }
126}
127
128void nfs3_forget_cached_acls(struct inode *inode)
129{
130 dprintk("NFS: nfs3_forget_cached_acls(%s/%ld)\n", inode->i_sb->s_id,
131 inode->i_ino);
132 spin_lock(&inode->i_lock);
133 __nfs3_forget_cached_acls(NFS_I(inode));
134 spin_unlock(&inode->i_lock);
135}
136
137static struct posix_acl *nfs3_get_cached_acl(struct inode *inode, int type)
138{
139 struct nfs_inode *nfsi = NFS_I(inode);
140 struct posix_acl *acl = ERR_PTR(-EAGAIN);
141
142 spin_lock(&inode->i_lock);
143 switch(type) {
144 case ACL_TYPE_ACCESS:
145 acl = nfsi->acl_access;
146 break;
147
148 case ACL_TYPE_DEFAULT:
149 acl = nfsi->acl_default;
150 break;
151
152 default:
153 return ERR_PTR(-EINVAL);
154 }
155 if (acl == ERR_PTR(-EAGAIN))
156 acl = ERR_PTR(-EAGAIN);
157 else
158 acl = posix_acl_dup(acl);
159 spin_unlock(&inode->i_lock);
160 dprintk("NFS: nfs3_get_cached_acl(%s/%ld, %d) = %p\n", inode->i_sb->s_id,
161 inode->i_ino, type, acl);
162 return acl;
163}
164
165static void nfs3_cache_acls(struct inode *inode, struct posix_acl *acl,
166 struct posix_acl *dfacl)
167{
168 struct nfs_inode *nfsi = NFS_I(inode);
169
170 dprintk("nfs3_cache_acls(%s/%ld, %p, %p)\n", inode->i_sb->s_id,
171 inode->i_ino, acl, dfacl);
172 spin_lock(&inode->i_lock);
173 __nfs3_forget_cached_acls(NFS_I(inode));
174 nfsi->acl_access = posix_acl_dup(acl);
175 nfsi->acl_default = posix_acl_dup(dfacl);
176 spin_unlock(&inode->i_lock);
177}
178
116struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type) 179struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
117{ 180{
118 struct nfs_server *server = NFS_SERVER(inode); 181 struct nfs_server *server = NFS_SERVER(inode);
@@ -126,26 +189,32 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
126 struct nfs3_getaclres res = { 189 struct nfs3_getaclres res = {
127 .fattr = &fattr, 190 .fattr = &fattr,
128 }; 191 };
129 struct posix_acl *acl = NULL; 192 struct posix_acl *acl;
130 int status, count; 193 int status, count;
131 194
132 if (!nfs_server_capable(inode, NFS_CAP_ACLS)) 195 if (!nfs_server_capable(inode, NFS_CAP_ACLS))
133 return ERR_PTR(-EOPNOTSUPP); 196 return ERR_PTR(-EOPNOTSUPP);
134 197
135 switch (type) { 198 status = nfs_revalidate_inode(server, inode);
136 case ACL_TYPE_ACCESS: 199 if (status < 0)
137 args.mask = NFS_ACLCNT|NFS_ACL; 200 return ERR_PTR(status);
138 break; 201 acl = nfs3_get_cached_acl(inode, type);
139 202 if (acl != ERR_PTR(-EAGAIN))
140 case ACL_TYPE_DEFAULT: 203 return acl;
141 if (!S_ISDIR(inode->i_mode)) 204 acl = NULL;
142 return NULL; 205
143 args.mask = NFS_DFACLCNT|NFS_DFACL; 206 /*
144 break; 207 * Only get the access acl when explicitly requested: We don't
145 208 * need it for access decisions, and only some applications use
146 default: 209 * it. Applications which request the access acl first are not
147 return ERR_PTR(-EINVAL); 210 * penalized from this optimization.
148 } 211 */
212 if (type == ACL_TYPE_ACCESS)
213 args.mask |= NFS_ACLCNT|NFS_ACL;
214 if (S_ISDIR(inode->i_mode))
215 args.mask |= NFS_DFACLCNT|NFS_DFACL;
216 if (args.mask == 0)
217 return NULL;
149 218
150 dprintk("NFS call getacl\n"); 219 dprintk("NFS call getacl\n");
151 status = rpc_call(server->client_acl, ACLPROC3_GETACL, 220 status = rpc_call(server->client_acl, ACLPROC3_GETACL,
@@ -180,6 +249,7 @@ struct posix_acl *nfs3_proc_getacl(struct inode *inode, int type)
180 res.acl_access = NULL; 249 res.acl_access = NULL;
181 } 250 }
182 } 251 }
252 nfs3_cache_acls(inode, res.acl_access, res.acl_default);
183 253
184 switch(type) { 254 switch(type) {
185 case ACL_TYPE_ACCESS: 255 case ACL_TYPE_ACCESS:
diff --git a/fs/nfs/nfs3proc.c b/fs/nfs/nfs3proc.c
index a9ddc196224d..7851569b31c6 100644
--- a/fs/nfs/nfs3proc.c
+++ b/fs/nfs/nfs3proc.c
@@ -882,4 +882,5 @@ struct nfs_rpc_ops nfs_v3_clientops = {
882 .file_open = nfs_open, 882 .file_open = nfs_open,
883 .file_release = nfs_release, 883 .file_release = nfs_release,
884 .lock = nfs3_proc_lock, 884 .lock = nfs3_proc_lock,
885 .clear_acl_cache = nfs3_forget_cached_acls,
885}; 886};
diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h
index 7662c5131b47..4ceac9ddac93 100644
--- a/include/linux/nfs_fs.h
+++ b/include/linux/nfs_fs.h
@@ -91,6 +91,8 @@ struct nfs_open_context {
91 */ 91 */
92struct nfs_delegation; 92struct nfs_delegation;
93 93
94struct posix_acl;
95
94/* 96/*
95 * nfs fs inode data in memory 97 * nfs fs inode data in memory
96 */ 98 */
@@ -144,6 +146,10 @@ struct nfs_inode {
144 atomic_t data_updates; 146 atomic_t data_updates;
145 147
146 struct nfs_access_entry cache_access; 148 struct nfs_access_entry cache_access;
149#ifdef CONFIG_NFS_V3_ACL
150 struct posix_acl *acl_access;
151 struct posix_acl *acl_default;
152#endif
147 153
148 /* 154 /*
149 * This is the cookie verifier used for NFSv3 readdir 155 * This is the cookie verifier used for NFSv3 readdir
@@ -480,6 +486,7 @@ extern int nfs3_proc_setacl(struct inode *inode, int type,
480 struct posix_acl *acl); 486 struct posix_acl *acl);
481extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode, 487extern int nfs3_proc_set_default_acl(struct inode *dir, struct inode *inode,
482 mode_t mode); 488 mode_t mode);
489extern void nfs3_forget_cached_acls(struct inode *inode);
483#else 490#else
484static inline int nfs3_proc_set_default_acl(struct inode *dir, 491static inline int nfs3_proc_set_default_acl(struct inode *dir,
485 struct inode *inode, 492 struct inode *inode,
@@ -487,6 +494,10 @@ static inline int nfs3_proc_set_default_acl(struct inode *dir,
487{ 494{
488 return 0; 495 return 0;
489} 496}
497
498static inline void nfs3_forget_cached_acls(struct inode *inode)
499{
500}
490#endif /* CONFIG_NFS_V3_ACL */ 501#endif /* CONFIG_NFS_V3_ACL */
491 502
492/* 503/*