aboutsummaryrefslogtreecommitdiffstats
path: root/fs/nfsd
diff options
context:
space:
mode:
authorJ. Bruce Fields <bfields@citi.umich.edu>2007-02-16 04:28:30 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-16 11:14:01 -0500
commit28e05dd8457c7a7fa1c3faac169a95e0ce4b4a12 (patch)
tree850b9db205c45d82706ec283fd13de74c1516630 /fs/nfsd
parent575a6290f035b16e3301014d9b176422ec9062bb (diff)
[PATCH] knfsd: nfsd4: represent nfsv4 acl with array instead of linked list
Simplify the memory management and code a bit by representing acls with an array instead of a linked list. Signed-off-by: J. Bruce Fields <bfields@citi.umich.edu> Signed-off-by: Neil Brown <neilb@suse.de> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'fs/nfsd')
-rw-r--r--fs/nfsd/nfs4acl.c147
-rw-r--r--fs/nfsd/nfs4xdr.c43
2 files changed, 59 insertions, 131 deletions
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 6c52658e9a26..2797051cd2b4 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -128,74 +128,58 @@ struct ace_container {
128}; 128};
129 129
130static short ace2type(struct nfs4_ace *); 130static short ace2type(struct nfs4_ace *);
131static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int); 131static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
132int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t); 132 unsigned int);
133void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
133 134
134struct nfs4_acl * 135struct nfs4_acl *
135nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl, 136nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
136 unsigned int flags) 137 unsigned int flags)
137{ 138{
138 struct nfs4_acl *acl; 139 struct nfs4_acl *acl;
139 int error = -EINVAL; 140 int size = 0;
140 141
141 if ((pacl != NULL && 142 if (pacl) {
142 (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) || 143 if (posix_acl_valid(pacl) < 0)
143 (dpacl != NULL && 144 return ERR_PTR(-EINVAL);
144 (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0))) 145 size += 2*pacl->a_count;
145 goto out_err;
146
147 acl = nfs4_acl_new();
148 if (acl == NULL) {
149 error = -ENOMEM;
150 goto out_err;
151 } 146 }
152 147 if (dpacl) {
153 if (pacl != NULL) { 148 if (posix_acl_valid(dpacl) < 0)
154 error = _posix_to_nfsv4_one(pacl, acl, 149 return ERR_PTR(-EINVAL);
155 flags & ~NFS4_ACL_TYPE_DEFAULT); 150 size += 2*dpacl->a_count;
156 if (error < 0)
157 goto out_acl;
158 } 151 }
159 152
160 if (dpacl != NULL) { 153 /* Allocate for worst case: one (deny, allow) pair each: */
161 error = _posix_to_nfsv4_one(dpacl, acl, 154 acl = nfs4_acl_new(size);
162 flags | NFS4_ACL_TYPE_DEFAULT); 155 if (acl == NULL)
163 if (error < 0) 156 return ERR_PTR(-ENOMEM);
164 goto out_acl;
165 }
166 157
167 return acl; 158 if (pacl)
159 _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
168 160
169out_acl: 161 if (dpacl)
170 nfs4_acl_free(acl); 162 _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
171out_err:
172 acl = ERR_PTR(error);
173 163
174 return acl; 164 return acl;
175} 165}
176 166
177static int 167static void
178nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype, 168nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
179 uid_t owner, unsigned int flags) 169 uid_t owner, unsigned int flags)
180{ 170{
181 int error; 171 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
182
183 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
184 eflag, mask, whotype, owner); 172 eflag, mask, whotype, owner);
185 if (error < 0) 173 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
186 return error;
187 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
188 eflag, deny_mask(mask, flags), whotype, owner); 174 eflag, deny_mask(mask, flags), whotype, owner);
189 return error;
190} 175}
191 176
192/* We assume the acl has been verified with posix_acl_valid. */ 177/* We assume the acl has been verified with posix_acl_valid. */
193static int 178static void
194_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl, 179_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
195 unsigned int flags) 180 unsigned int flags)
196{ 181{
197 struct posix_acl_entry *pa, *pe, *group_owner_entry; 182 struct posix_acl_entry *pa, *pe, *group_owner_entry;
198 int error = -EINVAL;
199 u32 mask, mask_mask; 183 u32 mask, mask_mask;
200 int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ? 184 int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
201 NFS4_INHERITANCE_FLAGS : 0); 185 NFS4_INHERITANCE_FLAGS : 0);
@@ -211,23 +195,16 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
211 pa = pacl->a_entries; 195 pa = pacl->a_entries;
212 BUG_ON(pa->e_tag != ACL_USER_OBJ); 196 BUG_ON(pa->e_tag != ACL_USER_OBJ);
213 mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER); 197 mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
214 error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags); 198 nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
215 if (error < 0)
216 goto out;
217 pa++; 199 pa++;
218 200
219 while (pa->e_tag == ACL_USER) { 201 while (pa->e_tag == ACL_USER) {
220 mask = mask_from_posix(pa->e_perm, flags); 202 mask = mask_from_posix(pa->e_perm, flags);
221 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 203 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
222 eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id); 204 eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
223 if (error < 0)
224 goto out;
225 205
226 206 nfs4_acl_add_pair(acl, eflag, mask,
227 error = nfs4_acl_add_pair(acl, eflag, mask,
228 NFS4_ACL_WHO_NAMED, pa->e_id, flags); 207 NFS4_ACL_WHO_NAMED, pa->e_id, flags);
229 if (error < 0)
230 goto out;
231 pa++; 208 pa++;
232 } 209 }
233 210
@@ -238,34 +215,25 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
238 215
239 if (pacl->a_count > 3) { 216 if (pacl->a_count > 3) {
240 BUG_ON(pa->e_tag != ACL_GROUP_OBJ); 217 BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
241 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 218 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
242 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, 219 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
243 NFS4_ACL_WHO_GROUP, 0); 220 NFS4_ACL_WHO_GROUP, 0);
244 if (error < 0)
245 goto out;
246 } 221 }
247 group_owner_entry = pa; 222 group_owner_entry = pa;
248 mask = mask_from_posix(pa->e_perm, flags); 223 mask = mask_from_posix(pa->e_perm, flags);
249 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE, 224 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
250 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, 225 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
251 NFS4_ACL_WHO_GROUP, 0); 226 NFS4_ACL_WHO_GROUP, 0);
252 if (error < 0)
253 goto out;
254 pa++; 227 pa++;
255 228
256 while (pa->e_tag == ACL_GROUP) { 229 while (pa->e_tag == ACL_GROUP) {
257 mask = mask_from_posix(pa->e_perm, flags); 230 mask = mask_from_posix(pa->e_perm, flags);
258 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 231 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
259 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask, 232 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
260 NFS4_ACL_WHO_NAMED, pa->e_id); 233 NFS4_ACL_WHO_NAMED, pa->e_id);
261 if (error < 0) 234 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
262 goto out;
263
264 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
265 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask, 235 NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
266 NFS4_ACL_WHO_NAMED, pa->e_id); 236 NFS4_ACL_WHO_NAMED, pa->e_id);
267 if (error < 0)
268 goto out;
269 pa++; 237 pa++;
270 } 238 }
271 239
@@ -273,19 +241,15 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
273 241
274 pa = group_owner_entry; 242 pa = group_owner_entry;
275 mask = mask_from_posix(pa->e_perm, flags); 243 mask = mask_from_posix(pa->e_perm, flags);
276 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 244 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
277 NFS4_ACE_IDENTIFIER_GROUP | eflag, 245 NFS4_ACE_IDENTIFIER_GROUP | eflag,
278 deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0); 246 deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
279 if (error < 0)
280 goto out;
281 pa++; 247 pa++;
282 while (pa->e_tag == ACL_GROUP) { 248 while (pa->e_tag == ACL_GROUP) {
283 mask = mask_from_posix(pa->e_perm, flags); 249 mask = mask_from_posix(pa->e_perm, flags);
284 error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE, 250 nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
285 NFS4_ACE_IDENTIFIER_GROUP | eflag, 251 NFS4_ACE_IDENTIFIER_GROUP | eflag,
286 deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id); 252 deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
287 if (error < 0)
288 goto out;
289 pa++; 253 pa++;
290 } 254 }
291 255
@@ -293,10 +257,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
293 pa++; 257 pa++;
294 BUG_ON(pa->e_tag != ACL_OTHER); 258 BUG_ON(pa->e_tag != ACL_OTHER);
295 mask = mask_from_posix(pa->e_perm, flags); 259 mask = mask_from_posix(pa->e_perm, flags);
296 error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags); 260 nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
297
298out:
299 return error;
300} 261}
301 262
302static void 263static void
@@ -640,7 +601,7 @@ int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
640 if (ret) 601 if (ret)
641 goto out_estate; 602 goto out_estate;
642 ret = -EINVAL; 603 ret = -EINVAL;
643 list_for_each_entry(ace, &acl->ace_head, l_ace) { 604 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
644 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE && 605 if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
645 ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE) 606 ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
646 goto out_dstate; 607 goto out_dstate;
@@ -705,48 +666,22 @@ EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
705EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix); 666EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
706 667
707struct nfs4_acl * 668struct nfs4_acl *
708nfs4_acl_new(void) 669nfs4_acl_new(int n)
709{ 670{
710 struct nfs4_acl *acl; 671 struct nfs4_acl *acl;
711 672
712 if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL) 673 acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL);
674 if (acl == NULL)
713 return NULL; 675 return NULL;
714
715 acl->naces = 0; 676 acl->naces = 0;
716 INIT_LIST_HEAD(&acl->ace_head);
717
718 return acl; 677 return acl;
719} 678}
720 679
721void 680void
722nfs4_acl_free(struct nfs4_acl *acl)
723{
724 struct list_head *h;
725 struct nfs4_ace *ace;
726
727 if (!acl)
728 return;
729
730 while (!list_empty(&acl->ace_head)) {
731 h = acl->ace_head.next;
732 list_del(h);
733 ace = list_entry(h, struct nfs4_ace, l_ace);
734 kfree(ace);
735 }
736
737 kfree(acl);
738
739 return;
740}
741
742int
743nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask, 681nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
744 int whotype, uid_t who) 682 int whotype, uid_t who)
745{ 683{
746 struct nfs4_ace *ace; 684 struct nfs4_ace *ace = acl->aces + acl->naces;
747
748 if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
749 return -ENOMEM;
750 685
751 ace->type = type; 686 ace->type = type;
752 ace->flag = flag; 687 ace->flag = flag;
@@ -754,10 +689,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
754 ace->whotype = whotype; 689 ace->whotype = whotype;
755 ace->who = who; 690 ace->who = who;
756 691
757 list_add_tail(&ace->l_ace, &acl->ace_head);
758 acl->naces++; 692 acl->naces++;
759
760 return 0;
761} 693}
762 694
763static struct { 695static struct {
@@ -811,7 +743,6 @@ nfs4_acl_write_who(int who, char *p)
811} 743}
812 744
813EXPORT_SYMBOL(nfs4_acl_new); 745EXPORT_SYMBOL(nfs4_acl_new);
814EXPORT_SYMBOL(nfs4_acl_free);
815EXPORT_SYMBOL(nfs4_acl_add_ace); 746EXPORT_SYMBOL(nfs4_acl_add_ace);
816EXPORT_SYMBOL(nfs4_acl_get_whotype); 747EXPORT_SYMBOL(nfs4_acl_get_whotype);
817EXPORT_SYMBOL(nfs4_acl_write_who); 748EXPORT_SYMBOL(nfs4_acl_write_who);
diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c
index 0efba557fb55..fbb4af969243 100644
--- a/fs/nfsd/nfs4xdr.c
+++ b/fs/nfsd/nfs4xdr.c
@@ -273,42 +273,42 @@ nfsd4_decode_fattr(struct nfsd4_compoundargs *argp, u32 *bmval, struct iattr *ia
273 iattr->ia_valid |= ATTR_SIZE; 273 iattr->ia_valid |= ATTR_SIZE;
274 } 274 }
275 if (bmval[0] & FATTR4_WORD0_ACL) { 275 if (bmval[0] & FATTR4_WORD0_ACL) {
276 int nace, i; 276 int nace;
277 struct nfs4_ace ace; 277 struct nfs4_ace *ace;
278 278
279 READ_BUF(4); len += 4; 279 READ_BUF(4); len += 4;
280 READ32(nace); 280 READ32(nace);
281 281
282 *acl = nfs4_acl_new(); 282 if (nace > NFS4_ACL_MAX)
283 return nfserr_resource;
284
285 *acl = nfs4_acl_new(nace);
283 if (*acl == NULL) { 286 if (*acl == NULL) {
284 host_err = -ENOMEM; 287 host_err = -ENOMEM;
285 goto out_nfserr; 288 goto out_nfserr;
286 } 289 }
287 defer_free(argp, (void (*)(const void *))nfs4_acl_free, *acl); 290 defer_free(argp, kfree, *acl);
288 291
289 for (i = 0; i < nace; i++) { 292 (*acl)->naces = nace;
293 for (ace = (*acl)->aces; ace < (*acl)->aces + nace; ace++) {
290 READ_BUF(16); len += 16; 294 READ_BUF(16); len += 16;
291 READ32(ace.type); 295 READ32(ace->type);
292 READ32(ace.flag); 296 READ32(ace->flag);
293 READ32(ace.access_mask); 297 READ32(ace->access_mask);
294 READ32(dummy32); 298 READ32(dummy32);
295 READ_BUF(dummy32); 299 READ_BUF(dummy32);
296 len += XDR_QUADLEN(dummy32) << 2; 300 len += XDR_QUADLEN(dummy32) << 2;
297 READMEM(buf, dummy32); 301 READMEM(buf, dummy32);
298 ace.whotype = nfs4_acl_get_whotype(buf, dummy32); 302 ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
299 host_err = 0; 303 host_err = 0;
300 if (ace.whotype != NFS4_ACL_WHO_NAMED) 304 if (ace->whotype != NFS4_ACL_WHO_NAMED)
301 ace.who = 0; 305 ace->who = 0;
302 else if (ace.flag & NFS4_ACE_IDENTIFIER_GROUP) 306 else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
303 host_err = nfsd_map_name_to_gid(argp->rqstp, 307 host_err = nfsd_map_name_to_gid(argp->rqstp,
304 buf, dummy32, &ace.who); 308 buf, dummy32, &ace->who);
305 else 309 else
306 host_err = nfsd_map_name_to_uid(argp->rqstp, 310 host_err = nfsd_map_name_to_uid(argp->rqstp,
307 buf, dummy32, &ace.who); 311 buf, dummy32, &ace->who);
308 if (host_err)
309 goto out_nfserr;
310 host_err = nfs4_acl_add_ace(*acl, ace.type, ace.flag,
311 ace.access_mask, ace.whotype, ace.who);
312 if (host_err) 312 if (host_err)
313 goto out_nfserr; 313 goto out_nfserr;
314 } 314 }
@@ -1596,7 +1596,6 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1596 } 1596 }
1597 if (bmval0 & FATTR4_WORD0_ACL) { 1597 if (bmval0 & FATTR4_WORD0_ACL) {
1598 struct nfs4_ace *ace; 1598 struct nfs4_ace *ace;
1599 struct list_head *h;
1600 1599
1601 if (acl == NULL) { 1600 if (acl == NULL) {
1602 if ((buflen -= 4) < 0) 1601 if ((buflen -= 4) < 0)
@@ -1609,9 +1608,7 @@ nfsd4_encode_fattr(struct svc_fh *fhp, struct svc_export *exp,
1609 goto out_resource; 1608 goto out_resource;
1610 WRITE32(acl->naces); 1609 WRITE32(acl->naces);
1611 1610
1612 list_for_each(h, &acl->ace_head) { 1611 for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
1613 ace = list_entry(h, struct nfs4_ace, l_ace);
1614
1615 if ((buflen -= 4*3) < 0) 1612 if ((buflen -= 4*3) < 0)
1616 goto out_resource; 1613 goto out_resource;
1617 WRITE32(ace->type); 1614 WRITE32(ace->type);
@@ -1821,7 +1818,7 @@ out_acl:
1821 status = nfs_ok; 1818 status = nfs_ok;
1822 1819
1823out: 1820out:
1824 nfs4_acl_free(acl); 1821 kfree(acl);
1825 if (fhp == &tempfh) 1822 if (fhp == &tempfh)
1826 fh_put(&tempfh); 1823 fh_put(&tempfh);
1827 return status; 1824 return status;