aboutsummaryrefslogtreecommitdiffstats
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
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>
-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/*