ace->flag = eflag;
                        ace->access_mask = deny_mask_from_posix(deny, flags);
                        ace->whotype = NFS4_ACL_WHO_NAMED;
-                       ace->who = pa->e_id;
+                       ace->who_uid = pa->e_uid;
                        ace++;
                        acl->naces++;
                }
                ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
                                                   flags);
                ace->whotype = NFS4_ACL_WHO_NAMED;
-               ace->who = pa->e_id;
+               ace->who_uid = pa->e_uid;
                ace++;
                acl->naces++;
                pa++;
                ace->access_mask = mask_from_posix(pa->e_perm & pas.mask,
                                                   flags);
                ace->whotype = NFS4_ACL_WHO_NAMED;
-               ace->who = pa->e_id;
+               ace->who_gid = pa->e_gid;
                ace++;
                acl->naces++;
                pa++;
                        ace->flag = eflag | NFS4_ACE_IDENTIFIER_GROUP;
                        ace->access_mask = deny_mask_from_posix(deny, flags);
                        ace->whotype = NFS4_ACL_WHO_NAMED;
-                       ace->who = pa->e_id;
+                       ace->who_gid = pa->e_gid;
                        ace++;
                        acl->naces++;
                }
        acl->naces++;
 }
 
+static bool
+pace_gt(struct posix_acl_entry *pace1, struct posix_acl_entry *pace2)
+{
+       if (pace1->e_tag != pace2->e_tag)
+               return pace1->e_tag > pace2->e_tag;
+       if (pace1->e_tag == ACL_USER)
+               return uid_gt(pace1->e_uid, pace2->e_uid);
+       if (pace1->e_tag == ACL_GROUP)
+               return gid_gt(pace1->e_gid, pace2->e_gid);
+       return false;
+}
+
 static void
 sort_pacl_range(struct posix_acl *pacl, int start, int end) {
        int sorted = 0, i;
        while (!sorted) {
                sorted = 1;
                for (i = start; i < end; i++) {
-                       if (pacl->a_entries[i].e_id
-                                       > pacl->a_entries[i+1].e_id) {
+                       if (pace_gt(&pacl->a_entries[i],
+                                   &pacl->a_entries[i+1])) {
                                sorted = 0;
                                tmp = pacl->a_entries[i];
                                pacl->a_entries[i] = pacl->a_entries[i+1];
 };
 
 struct posix_user_ace_state {
-       uid_t uid;
+       union {
+               kuid_t uid;
+               kgid_t gid;
+       };
        struct posix_ace_state perms;
 };
 
        if (error)
                goto out_err;
        low_mode_from_nfs4(state->owner.allow, &pace->e_perm, flags);
-       pace->e_id = ACL_UNDEFINED_ID;
 
        for (i=0; i < state->users->n; i++) {
                pace++;
                        goto out_err;
                low_mode_from_nfs4(state->users->aces[i].perms.allow,
                                        &pace->e_perm, flags);
-               pace->e_id = state->users->aces[i].uid;
+               pace->e_uid = state->users->aces[i].uid;
                add_to_mask(state, &state->users->aces[i].perms);
        }
 
        if (error)
                goto out_err;
        low_mode_from_nfs4(state->group.allow, &pace->e_perm, flags);
-       pace->e_id = ACL_UNDEFINED_ID;
        add_to_mask(state, &state->group);
 
        for (i=0; i < state->groups->n; i++) {
                        goto out_err;
                low_mode_from_nfs4(state->groups->aces[i].perms.allow,
                                        &pace->e_perm, flags);
-               pace->e_id = state->groups->aces[i].uid;
+               pace->e_gid = state->groups->aces[i].gid;
                add_to_mask(state, &state->groups->aces[i].perms);
        }
 
        pace++;
        pace->e_tag = ACL_MASK;
        low_mode_from_nfs4(state->mask.allow, &pace->e_perm, flags);
-       pace->e_id = ACL_UNDEFINED_ID;
 
        pace++;
        pace->e_tag = ACL_OTHER;
        if (error)
                goto out_err;
        low_mode_from_nfs4(state->other.allow, &pace->e_perm, flags);
-       pace->e_id = ACL_UNDEFINED_ID;
 
        return pacl;
 out_err:
        astate->deny |= mask & ~astate->allow;
 }
 
-static int find_uid(struct posix_acl_state *state, struct posix_ace_state_array *a, uid_t uid)
+static int find_uid(struct posix_acl_state *state, kuid_t uid)
 {
+       struct posix_ace_state_array *a = state->users;
        int i;
 
        for (i = 0; i < a->n; i++)
-               if (a->aces[i].uid == uid)
+               if (uid_eq(a->aces[i].uid, uid))
                        return i;
        /* Not found: */
        a->n++;
        return i;
 }
 
+static int find_gid(struct posix_acl_state *state, kgid_t gid)
+{
+       struct posix_ace_state_array *a = state->groups;
+       int i;
+
+       for (i = 0; i < a->n; i++)
+               if (gid_eq(a->aces[i].gid, gid))
+                       return i;
+       /* Not found: */
+       a->n++;
+       a->aces[i].gid = gid;
+       a->aces[i].perms.allow = state->everyone.allow;
+       a->aces[i].perms.deny  = state->everyone.deny;
+
+       return i;
+}
+
 static void deny_bits_array(struct posix_ace_state_array *a, u32 mask)
 {
        int i;
                }
                break;
        case ACL_USER:
-               i = find_uid(state, state->users, ace->who);
+               i = find_uid(state, ace->who_uid);
                if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
                        allow_bits(&state->users->aces[i].perms, mask);
                } else {
                }
                break;
        case ACL_GROUP:
-               i = find_uid(state, state->groups, ace->who);
+               i = find_gid(state, ace->who_gid);
                if (ace->type == NFS4_ACE_ACCESS_ALLOWED_ACE_TYPE) {
                        allow_bits(&state->groups->aces[i].perms, mask);
                } else {
 
                        ace->whotype = nfs4_acl_get_whotype(buf, dummy32);
                        status = nfs_ok;
                        if (ace->whotype != NFS4_ACL_WHO_NAMED)
-                               ace->who = 0;
+                               ;
                        else if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
                                status = nfsd_map_name_to_gid(argp->rqstp,
-                                               buf, dummy32, &ace->who);
+                                               buf, dummy32, &ace->who_gid);
                        else
                                status = nfsd_map_name_to_uid(argp->rqstp,
-                                               buf, dummy32, &ace->who);
+                                               buf, dummy32, &ace->who_uid);
                        if (status)
                                return status;
                }
 }
 
 static __be32
-nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
+nfsd4_encode_name(struct svc_rqst *rqstp, int whotype, kuid_t uid, kgid_t gid,
                        __be32 **p, int *buflen)
 {
        int status;
                return nfserr_resource;
        if (whotype != NFS4_ACL_WHO_NAMED)
                status = nfs4_acl_write_who(whotype, (u8 *)(*p + 1));
-       else if (group)
-               status = nfsd_map_gid_to_name(rqstp, id, (u8 *)(*p + 1));
+       else if (gid_valid(gid))
+               status = nfsd_map_gid_to_name(rqstp, gid, (u8 *)(*p + 1));
        else
-               status = nfsd_map_uid_to_name(rqstp, id, (u8 *)(*p + 1));
+               status = nfsd_map_uid_to_name(rqstp, uid, (u8 *)(*p + 1));
        if (status < 0)
                return nfserrno(status);
        *p = xdr_encode_opaque(*p, NULL, status);
 }
 
 static inline __be32
-nfsd4_encode_user(struct svc_rqst *rqstp, uid_t uid, __be32 **p, int *buflen)
+nfsd4_encode_user(struct svc_rqst *rqstp, kuid_t user, __be32 **p, int *buflen)
 {
-       return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, uid, 0, p, buflen);
+       return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, user, INVALID_GID,
+                                p, buflen);
 }
 
 static inline __be32
-nfsd4_encode_group(struct svc_rqst *rqstp, uid_t gid, __be32 **p, int *buflen)
+nfsd4_encode_group(struct svc_rqst *rqstp, kgid_t group, __be32 **p, int *buflen)
 {
-       return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, gid, 1, p, buflen);
+       return nfsd4_encode_name(rqstp, NFS4_ACL_WHO_NAMED, INVALID_UID, group,
+                                p, buflen);
 }
 
 static inline __be32
-nfsd4_encode_aclname(struct svc_rqst *rqstp, int whotype, uid_t id, int group,
+nfsd4_encode_aclname(struct svc_rqst *rqstp, struct nfs4_ace *ace,
                __be32 **p, int *buflen)
 {
-       return nfsd4_encode_name(rqstp, whotype, id, group, p, buflen);
+       kuid_t uid = INVALID_UID;
+       kgid_t gid = INVALID_GID;
+
+       if (ace->whotype == NFS4_ACL_WHO_NAMED) {
+               if (ace->flag & NFS4_ACE_IDENTIFIER_GROUP)
+                       gid = ace->who_gid;
+               else
+                       uid = ace->who_uid;
+       }
+       return nfsd4_encode_name(rqstp, ace->whotype, uid, gid, p, buflen);
 }
 
 #define WORD0_ABSENT_FS_ATTRS (FATTR4_WORD0_FS_LOCATIONS | FATTR4_WORD0_FSID | \
                        WRITE32(ace->type);
                        WRITE32(ace->flag);
                        WRITE32(ace->access_mask & NFS4_ACE_MASK_ALL);
-                       status = nfsd4_encode_aclname(rqstp, ace->whotype,
-                               ace->who, ace->flag & NFS4_ACE_IDENTIFIER_GROUP,
-                               &p, &buflen);
+                       status = nfsd4_encode_aclname(rqstp, ace, &p, &buflen);
                        if (status == nfserr_resource)
                                goto out_resource;
                        if (status)