aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNick Piggin <npiggin@kernel.dk>2011-01-07 01:49:59 -0500
committerNick Piggin <npiggin@kernel.dk>2011-01-07 01:50:29 -0500
commit1e1743ebe35ec7e3c1fa732408358fbc614cbbe5 (patch)
tree9654cd50bb29a4c5ccc498b9b08cc385288bc854
parentb74c79e99389cd79b31fcc08f82c24e492e63c7e (diff)
fs: provide simple rcu-walk generic_check_acl implementation
This simple implementation just checks for no ACLs on the inode, and if so, then the rcu-walk may proceed, otherwise fail it. This could easily be extended to put acls under RCU and check them under seqlock, if need be. But this implementation is enough to show the rcu-walk aware permissions code for path lookups is working, and will handle cases where there are no ACLs or ACLs in just the final element. This patch implicity converts tmpfs to rcu-aware permission check. Subsequent patches onvert ext*, xfs, and, btrfs. Each of these uses acl/permission code in a different way, so convert them all to provide templates and proof of concept. Signed-off-by: Nick Piggin <npiggin@kernel.dk>
-rw-r--r--fs/generic_acl.c22
-rw-r--r--include/linux/posix_acl.h19
2 files changed, 31 insertions, 10 deletions
diff --git a/fs/generic_acl.c b/fs/generic_acl.c
index 62800428213..06c48a89183 100644
--- a/fs/generic_acl.c
+++ b/fs/generic_acl.c
@@ -192,16 +192,18 @@ generic_acl_chmod(struct inode *inode)
192int 192int
193generic_check_acl(struct inode *inode, int mask, unsigned int flags) 193generic_check_acl(struct inode *inode, int mask, unsigned int flags)
194{ 194{
195 struct posix_acl *acl; 195 if (flags & IPERM_FLAG_RCU) {
196 196 if (!negative_cached_acl(inode, ACL_TYPE_ACCESS))
197 if (flags & IPERM_FLAG_RCU) 197 return -ECHILD;
198 return -ECHILD; 198 } else {
199 199 struct posix_acl *acl;
200 acl = get_cached_acl(inode, ACL_TYPE_ACCESS); 200
201 if (acl) { 201 acl = get_cached_acl(inode, ACL_TYPE_ACCESS);
202 int error = posix_acl_permission(inode, acl, mask); 202 if (acl) {
203 posix_acl_release(acl); 203 int error = posix_acl_permission(inode, acl, mask);
204 return error; 204 posix_acl_release(acl);
205 return error;
206 }
205 } 207 }
206 return -EAGAIN; 208 return -EAGAIN;
207} 209}
diff --git a/include/linux/posix_acl.h b/include/linux/posix_acl.h
index 67608161df6..d68283a898b 100644
--- a/include/linux/posix_acl.h
+++ b/include/linux/posix_acl.h
@@ -108,6 +108,25 @@ static inline struct posix_acl *get_cached_acl(struct inode *inode, int type)
108 return acl; 108 return acl;
109} 109}
110 110
111static inline int negative_cached_acl(struct inode *inode, int type)
112{
113 struct posix_acl **p, *acl;
114 switch (type) {
115 case ACL_TYPE_ACCESS:
116 p = &inode->i_acl;
117 break;
118 case ACL_TYPE_DEFAULT:
119 p = &inode->i_default_acl;
120 break;
121 default:
122 BUG();
123 }
124 acl = ACCESS_ONCE(*p);
125 if (acl)
126 return 0;
127 return 1;
128}
129
111static inline void set_cached_acl(struct inode *inode, 130static inline void set_cached_acl(struct inode *inode,
112 int type, 131 int type,
113 struct posix_acl *acl) 132 struct posix_acl *acl)