aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfs/nfs3acl.c
diff options
context:
space:
mode:
authorAndreas Gruenbacher <agruen@suse.de>2005-06-22 13:16:27 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2005-06-22 16:07:25 -0400
commit5c6a9f7d92291c832d47e792ed1fafa44acb066e (patch)
treec67e62e0b46c22b061d5eb2b28ef702bdf2afa0d /fs/nfs/nfs3acl.c
parent055ffbea0596942579b0dae71d5dab78de8135f6 (diff)
[PATCH] NFS: Cache the NFSv3 acls.
Attach acls to inodes in the icache to avoid unnecessary GETACL RPC round-trips. As long as the client doesn't retrieve any acls itself, only the default acls of exiting directories and the default and access acls of new directories will end up in the cache, which preserves some memory compared to always caching the access and default acl of all files. Signed-off-by: Andreas Gruenbacher <agruen@suse.de> Acked-by: Olaf Kirch <okir@suse.de> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
Diffstat (limited to 'fs/nfs/nfs3acl.c')
-rw-r--r--fs/nfs/nfs3acl.c100
1 files changed, 85 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: