summaryrefslogtreecommitdiff
path: root/fs/nfsd/nfs4acl.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/nfsd/nfs4acl.c')
-rw-r--r--fs/nfsd/nfs4acl.c147
1 files changed, 39 insertions, 108 deletions
diff --git a/fs/nfsd/nfs4acl.c b/fs/nfsd/nfs4acl.c
index 6c52658e9a2..2797051cd2b 100644
--- a/fs/nfsd/nfs4acl.c
+++ b/fs/nfsd/nfs4acl.c
@@ -128,74 +128,58 @@ struct ace_container {
};
static short ace2type(struct nfs4_ace *);
-static int _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *, unsigned int);
-int nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
+static void _posix_to_nfsv4_one(struct posix_acl *, struct nfs4_acl *,
+ unsigned int);
+void nfs4_acl_add_ace(struct nfs4_acl *, u32, u32, u32, int, uid_t);
struct nfs4_acl *
nfs4_acl_posix_to_nfsv4(struct posix_acl *pacl, struct posix_acl *dpacl,
unsigned int flags)
{
struct nfs4_acl *acl;
- int error = -EINVAL;
+ int size = 0;
- if ((pacl != NULL &&
- (posix_acl_valid(pacl) < 0 || pacl->a_count == 0)) ||
- (dpacl != NULL &&
- (posix_acl_valid(dpacl) < 0 || dpacl->a_count == 0)))
- goto out_err;
-
- acl = nfs4_acl_new();
- if (acl == NULL) {
- error = -ENOMEM;
- goto out_err;
+ if (pacl) {
+ if (posix_acl_valid(pacl) < 0)
+ return ERR_PTR(-EINVAL);
+ size += 2*pacl->a_count;
}
-
- if (pacl != NULL) {
- error = _posix_to_nfsv4_one(pacl, acl,
- flags & ~NFS4_ACL_TYPE_DEFAULT);
- if (error < 0)
- goto out_acl;
+ if (dpacl) {
+ if (posix_acl_valid(dpacl) < 0)
+ return ERR_PTR(-EINVAL);
+ size += 2*dpacl->a_count;
}
- if (dpacl != NULL) {
- error = _posix_to_nfsv4_one(dpacl, acl,
- flags | NFS4_ACL_TYPE_DEFAULT);
- if (error < 0)
- goto out_acl;
- }
+ /* Allocate for worst case: one (deny, allow) pair each: */
+ acl = nfs4_acl_new(size);
+ if (acl == NULL)
+ return ERR_PTR(-ENOMEM);
- return acl;
+ if (pacl)
+ _posix_to_nfsv4_one(pacl, acl, flags & ~NFS4_ACL_TYPE_DEFAULT);
-out_acl:
- nfs4_acl_free(acl);
-out_err:
- acl = ERR_PTR(error);
+ if (dpacl)
+ _posix_to_nfsv4_one(dpacl, acl, flags | NFS4_ACL_TYPE_DEFAULT);
return acl;
}
-static int
+static void
nfs4_acl_add_pair(struct nfs4_acl *acl, int eflag, u32 mask, int whotype,
uid_t owner, unsigned int flags)
{
- int error;
-
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
eflag, mask, whotype, owner);
- if (error < 0)
- return error;
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
eflag, deny_mask(mask, flags), whotype, owner);
- return error;
}
/* We assume the acl has been verified with posix_acl_valid. */
-static int
+static void
_posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
unsigned int flags)
{
struct posix_acl_entry *pa, *pe, *group_owner_entry;
- int error = -EINVAL;
u32 mask, mask_mask;
int eflag = ((flags & NFS4_ACL_TYPE_DEFAULT) ?
NFS4_INHERITANCE_FLAGS : 0);
@@ -211,23 +195,16 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
pa = pacl->a_entries;
BUG_ON(pa->e_tag != ACL_USER_OBJ);
mask = mask_from_posix(pa->e_perm, flags | NFS4_ACL_OWNER);
- error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
- if (error < 0)
- goto out;
+ nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_OWNER, 0, flags);
pa++;
while (pa->e_tag == ACL_USER) {
mask = mask_from_posix(pa->e_perm, flags);
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
eflag, mask_mask, NFS4_ACL_WHO_NAMED, pa->e_id);
- if (error < 0)
- goto out;
-
- error = nfs4_acl_add_pair(acl, eflag, mask,
+ nfs4_acl_add_pair(acl, eflag, mask,
NFS4_ACL_WHO_NAMED, pa->e_id, flags);
- if (error < 0)
- goto out;
pa++;
}
@@ -238,34 +215,25 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
if (pacl->a_count > 3) {
BUG_ON(pa->e_tag != ACL_GROUP_OBJ);
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
NFS4_ACL_WHO_GROUP, 0);
- if (error < 0)
- goto out;
}
group_owner_entry = pa;
mask = mask_from_posix(pa->e_perm, flags);
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
NFS4_ACL_WHO_GROUP, 0);
- if (error < 0)
- goto out;
pa++;
while (pa->e_tag == ACL_GROUP) {
mask = mask_from_posix(pa->e_perm, flags);
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
NFS4_ACE_IDENTIFIER_GROUP | eflag, mask_mask,
NFS4_ACL_WHO_NAMED, pa->e_id);
- if (error < 0)
- goto out;
-
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE,
NFS4_ACE_IDENTIFIER_GROUP | eflag, mask,
NFS4_ACL_WHO_NAMED, pa->e_id);
- if (error < 0)
- goto out;
pa++;
}
@@ -273,19 +241,15 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
pa = group_owner_entry;
mask = mask_from_posix(pa->e_perm, flags);
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
NFS4_ACE_IDENTIFIER_GROUP | eflag,
deny_mask(mask, flags), NFS4_ACL_WHO_GROUP, 0);
- if (error < 0)
- goto out;
pa++;
while (pa->e_tag == ACL_GROUP) {
mask = mask_from_posix(pa->e_perm, flags);
- error = nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
+ nfs4_acl_add_ace(acl, NFS4_ACE_ACCESS_DENIED_ACE_TYPE,
NFS4_ACE_IDENTIFIER_GROUP | eflag,
deny_mask(mask, flags), NFS4_ACL_WHO_NAMED, pa->e_id);
- if (error < 0)
- goto out;
pa++;
}
@@ -293,10 +257,7 @@ _posix_to_nfsv4_one(struct posix_acl *pacl, struct nfs4_acl *acl,
pa++;
BUG_ON(pa->e_tag != ACL_OTHER);
mask = mask_from_posix(pa->e_perm, flags);
- error = nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
-
-out:
- return error;
+ nfs4_acl_add_pair(acl, eflag, mask, NFS4_ACL_WHO_EVERYONE, 0, flags);
}
static void
@@ -640,7 +601,7 @@ int nfs4_acl_nfsv4_to_posix(struct nfs4_acl *acl, struct posix_acl **pacl,
if (ret)
goto out_estate;
ret = -EINVAL;
- list_for_each_entry(ace, &acl->ace_head, l_ace) {
+ for (ace = acl->aces; ace < acl->aces + acl->naces; ace++) {
if (ace->type != NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE &&
ace->type != NFS4_ACE_ACCESS_DENIED_ACE_TYPE)
goto out_dstate;
@@ -705,48 +666,22 @@ EXPORT_SYMBOL(nfs4_acl_posix_to_nfsv4);
EXPORT_SYMBOL(nfs4_acl_nfsv4_to_posix);
struct nfs4_acl *
-nfs4_acl_new(void)
+nfs4_acl_new(int n)
{
struct nfs4_acl *acl;
- if ((acl = kmalloc(sizeof(*acl), GFP_KERNEL)) == NULL)
+ acl = kmalloc(sizeof(*acl) + n*sizeof(struct nfs4_ace), GFP_KERNEL);
+ if (acl == NULL)
return NULL;
-
acl->naces = 0;
- INIT_LIST_HEAD(&acl->ace_head);
-
return acl;
}
void
-nfs4_acl_free(struct nfs4_acl *acl)
-{
- struct list_head *h;
- struct nfs4_ace *ace;
-
- if (!acl)
- return;
-
- while (!list_empty(&acl->ace_head)) {
- h = acl->ace_head.next;
- list_del(h);
- ace = list_entry(h, struct nfs4_ace, l_ace);
- kfree(ace);
- }
-
- kfree(acl);
-
- return;
-}
-
-int
nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
int whotype, uid_t who)
{
- struct nfs4_ace *ace;
-
- if ((ace = kmalloc(sizeof(*ace), GFP_KERNEL)) == NULL)
- return -ENOMEM;
+ struct nfs4_ace *ace = acl->aces + acl->naces;
ace->type = type;
ace->flag = flag;
@@ -754,10 +689,7 @@ nfs4_acl_add_ace(struct nfs4_acl *acl, u32 type, u32 flag, u32 access_mask,
ace->whotype = whotype;
ace->who = who;
- list_add_tail(&ace->l_ace, &acl->ace_head);
acl->naces++;
-
- return 0;
}
static struct {
@@ -811,7 +743,6 @@ nfs4_acl_write_who(int who, char *p)
}
EXPORT_SYMBOL(nfs4_acl_new);
-EXPORT_SYMBOL(nfs4_acl_free);
EXPORT_SYMBOL(nfs4_acl_add_ace);
EXPORT_SYMBOL(nfs4_acl_get_whotype);
EXPORT_SYMBOL(nfs4_acl_write_who);