Linux: Rework PAG to group conversions
authorSimon Wilkinson <sxw@inf.ed.ac.uk>
Sat, 19 Dec 2009 23:58:54 +0000 (23:58 +0000)
committerDerrick Brashear <shadow|account-1000005@unknown>
Wed, 13 Jan 2010 18:03:27 +0000 (10:03 -0800)
The change to using a single group for PAGs on Linux led to a load
of special cases throughout the code. This patch moves the OS
dependent parts of this into the LINUX/ platform directory, and
rearranges that file so that there is a clear distinction between
the one and two group sections of the code.

Change-Id: Ib6e6f081519b23494dcf731b4be689c006180c68
Reviewed-on: http://gerrit.openafs.org/1007
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>

src/afs/LINUX/osi_groups.c
src/afs/afs_osi_pag.c
src/afs/afs_prototypes.h

index e37e8c9..11bd17a 100644 (file)
 #include <linux/smp_lock.h>
 
 #ifdef AFS_LINUX26_ONEGROUP_ENV
-#define NUMPAGGROUPS 1
+# define NUMPAGGROUPS 1
+
+static afs_uint32
+afs_linux_pag_from_groups(struct group_info *group_info) {
+    afs_uint32 g0 = 0;
+    afs_uint32 i;
+
+    if (group_info->ngroups < NUMPAGGROUPS)
+       return NOPAG;
+
+    for (i = 0; (i < group_info->ngroups &&
+                (g0 = GROUP_AT(group_info, i)) != (gid_t) NOGROUP); i++) {
+       if (((g0 >> 24) & 0xff) == 'A')
+           return g0;
+    }
+    return NOPAG;
+}
+
+static inline void
+afs_linux_pag_to_groups(afs_uint32 newpag,
+                       struct group_info *old, struct group_info **new) {
+    int need_space = 0;
+    int i;
+    int j;
+
+    if (afs_linux_pag_from_groups(old) == NOPAG)
+       need_space = NUMPAGGROUPS;
+
+    *new = groups_alloc(old->ngroups + need_space);
+
+    for (i = 0, j = 0; i < old->ngroups; ++i) {
+       int ths = GROUP_AT(old, i);
+       int last = i > 0 ? GROUP_AT(old, i-1) : 0;
+       if ((ths >> 24) == 'A')
+           continue;
+       if (last <= newpag && ths > newpag) {
+          GROUP_AT(*new, j) = newpag;
+          j++;
+       }
+       GROUP_AT(*new, j) = ths;
+       j++;
+    }
+    if (j != i + need_space)
+        GROUP_AT(*new, j) = newpag;
+}
+
 #else
-#define NUMPAGGROUPS 2
+# define NUMPAGGROUPS 2
+
+static inline afs_uint32
+afs_linux_pag_from_groups(struct group_info *group_info) {
+
+    if (group_info->ngroups < NUMPAGGROUPS)
+       return NOPAG;
+
+    return afs_get_pag_from_groups(GROUP_AT(group_info, 0), GROUP_AT(group_info, 1));
+}
+
+static inline void
+afs_linux_pag_to_groups(afs_uint32 newpag,
+                       struct group_info *old, struct group_info *new) {
+    int need_space = 0;
+    int i;
+    gid_t g0;
+    gid_t g1;
+
+    if (afs_linux_pag_from_groups(old) == NOPAG)
+       need_space = NUMPAGGGROUPS;
+
+    *new = groups_alloc(old->ngroups + need_space);
+
+    for (i = 0; i < old->ngroups; ++i)
+          GROUP_AT(new, i + need_space) = GROUP_AT(old, i);
+
+    afs_get_groups_from_pag(newpag, &g0, g1);
+    GROUP_AT(new, 0) = g0;
+    GROUP_AT(new, 1) = g1;
+}
 #endif
 
+afs_int32
+osi_get_group_pag(afs_ucred_t *cred) {
+    return afs_linux_pag_from_groups(afs_cr_group_info(cred));
+}
+
+
 static int
 afs_setgroups(cred_t **cr, struct group_info *group_info, int change_parent)
 {
@@ -59,76 +140,23 @@ afs_setgroups(cred_t **cr, struct group_info *group_info, int change_parent)
 
     return (0);
 }
-/* Returns number of groups. And we trust groups to be large enough to
- * hold all the groups.
- */
-static struct group_info *
-afs_getgroups(cred_t * cr)
-{
-    AFS_STATCNT(afs_getgroups);
-
-    get_group_info(afs_cr_group_info(cr));
-    return afs_cr_group_info(cr);
-}
 
 int
 __setpag(cred_t **cr, afs_uint32 pagvalue, afs_uint32 *newpag,
          int change_parent)
 {
     struct group_info *group_info;
-#ifndef AFS_LINUX26_ONEGROUP_ENV
-    gid_t g0, g1;
-#endif
     struct group_info *tmp;
-    int i;
-#ifdef AFS_LINUX26_ONEGROUP_ENV
-    int j;
-#endif
-    int need_space = 0;
 
-    group_info = afs_getgroups(*cr);
-    if (group_info->ngroups < NUMPAGGROUPS
-       ||  afs_get_pag_from_groups(
-#ifdef AFS_LINUX26_ONEGROUP_ENV
-           group_info
-#else
-           GROUP_AT(group_info, 0) ,GROUP_AT(group_info, 1)
-#endif
-                                   ) == NOPAG) 
-       /* We will have to make sure group_info is big enough for pag */
-       need_space = NUMPAGGROUPS;
+    get_group_info(afs_cr_group_info(*cr));
+    group_info = afs_cr_group_info(*cr);
 
-    tmp = groups_alloc(group_info->ngroups + need_space);
-    
     *newpag = (pagvalue == -1 ? genpag() : pagvalue);
-#ifdef AFS_LINUX26_ONEGROUP_ENV
-    for (i = 0, j = 0; i < group_info->ngroups; ++i) {
-       int ths = GROUP_AT(group_info, i);
-       int last = i > 0 ? GROUP_AT(group_info, i-1) : 0;
-       if ((ths >> 24) == 'A')
-           continue;
-       if (last <= *newpag && ths > *newpag) {
-          GROUP_AT(tmp, j) = *newpag;
-          j++;
-       }
-       GROUP_AT(tmp, j) = ths;
-       j++;
-    }
-    if (j != i + need_space)
-        GROUP_AT(tmp, j) = *newpag;
-#else
-    for (i = 0; i < group_info->ngroups; ++i)
-      GROUP_AT(tmp, i + need_space) = GROUP_AT(group_info, i);
-#endif
+    afs_linux_pag_to_groups(*newpag, group_info, &tmp);
+
     put_group_info(group_info);
     group_info = tmp;
 
-#ifndef AFS_LINUX26_ONEGROUP_ENV
-    afs_get_groups_from_pag(*newpag, &g0, &g1);
-    GROUP_AT(group_info, 0) = g0;
-    GROUP_AT(group_info, 1) = g1;
-#endif
-
     afs_setgroups(cr, group_info, change_parent);
 
     put_group_info(group_info);
@@ -406,9 +434,6 @@ static int afs_pag_instantiate(struct key *key, const void *data, size_t datalen
 {
     int code;
     afs_uint32 *userpag, pag = NOPAG;
-#ifndef AFS_LINUX26_ONEGROUP_ENV
-    int g0, g1;
-#endif
 
     if (key->uid != 0 || key->gid != 0)
        return -EPERM;
@@ -419,18 +444,9 @@ static int afs_pag_instantiate(struct key *key, const void *data, size_t datalen
     if (datalen != sizeof(afs_uint32) || !data)
        goto error;
 
-    if (current_group_info()->ngroups < NUMPAGGROUPS)
-       goto error;
-
     /* ensure key being set matches current pag */
-#ifdef AFS_LINUX26_ONEGROUP_ENV
-    pag = afs_get_pag_from_groups(current_group_info());
-#else
-    g0 = GROUP_AT(current_group_info(), 0);
-    g1 = GROUP_AT(current_group_info(), 1);
+    pag = afs_linux_pag_from_groups(current_group_info());
 
-    pag = afs_get_pag_from_groups(g0, g1);
-#endif
     if (pag == NOPAG)
        goto error;
 
@@ -552,7 +568,7 @@ osi_get_keyring_pag(afs_ucred_t *cred)
                 * and the creds are from the current process */
                if (afs_linux_cred_is_current(cred) &&
                     ((keyring_pag >> 24) & 0xff) == 'A' &&
-                   keyring_pag != afs_get_pag_from_groups(current_group_info())) {
+                   keyring_pag != afs_linux_pag_from_groups(current_group_info())) {
                        __setpag(&cred, keyring_pag, &newpag, 0);
                }
            }
index 4db10a8..f6356db 100644 (file)
@@ -465,23 +465,7 @@ afs_InitReq(register struct vrequest *av, afs_ucred_t *acred)
     return 0;
 }
 
-
-#ifdef AFS_LINUX26_ONEGROUP_ENV
-afs_uint32
-afs_get_pag_from_groups(struct group_info *group_info)
-{
-    afs_uint32 g0 = 0;
-    afs_uint32 i;
-
-    AFS_STATCNT(afs_get_pag_from_groups);
-    for (i = 0; (i < group_info->ngroups && 
-                (g0 = GROUP_AT(group_info, i)) != (gid_t) NOGROUP); i++) {
-       if (((g0 >> 24) & 0xff) == 'A')
-           return g0;
-    }
-    return NOPAG;
-}
-#else
+#ifndef AFS_LINUX26_ONEGROUP_ENV
 afs_uint32
 afs_get_pag_from_groups(gid_t g0a, gid_t g1a)
 {
@@ -498,51 +482,50 @@ afs_get_pag_from_groups(gid_t g0a, gid_t g1a)
        h = (g0 >> 14);
        h = (g1 >> 14) + h + h + h;
        ret = ((h << 28) | l);
-#if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
+# if defined(UKERNEL) && defined(AFS_WEB_ENHANCEMENTS)
        return ret;
-#else
+# else
        /* Additional testing */
        if (((ret >> 24) & 0xff) == 'A')
            return ret;
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
+# endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
     }
     return NOPAG;
 }
-#endif
 
 void
 afs_get_groups_from_pag(afs_uint32 pag, gid_t * g0p, gid_t * g1p)
 {
-#ifndef AFS_LINUX26_ONEGROUP_ENV
     unsigned short g0, g1;
-#endif
-
 
     AFS_STATCNT(afs_get_groups_from_pag);
-#ifdef AFS_LINUX26_ONEGROUP_ENV
     *g0p = pag;
     *g1p = 0;
-#else
-#if !defined(UKERNEL) || !defined(AFS_WEB_ENHANCEMENTS)
+# if !defined(UKERNEL) || !defined(AFS_WEB_ENHANCEMENTS)
     pag &= 0x7fffffff;
-#endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
+# endif /* UKERNEL && AFS_WEB_ENHANCEMENTS */
     g0 = 0x3fff & (pag >> 14);
     g1 = 0x3fff & pag;
     g0 |= ((pag >> 28) / 3) << 14;
     g1 |= ((pag >> 28) % 3) << 14;
     *g0p = g0 + 0x3f00;
     *g1p = g1 + 0x3f00;
-#endif
 }
+#else
+void afs_get_groups_from_pag(afs_uint32 pag, gid_t *g0p, gid_t *g1p)
+{
+    AFS_STATCNT(afs_get_groups_from_pag);
+    *g0p = pag;
+    *g1p = 0;
+}
+#endif
 
-
-afs_int32
-afs_get_group_pag(afs_ucred_t *cred)
+#ifndef AFS_LINUX26_ENV
+static afs_int32
+osi_get_group_pag(afs_ucred_t *cred)
 {
     afs_int32 pag = NOPAG;
-#if !defined(AFS_LINUX26_ONEGROUP_ENV)
     gid_t g0, g1;
-#endif
 #if defined(AFS_SUN510_ENV)
     const gid_t *gids;
     int ngroups;
@@ -561,28 +544,24 @@ afs_get_group_pag(afs_ucred_t *cred)
     g0 = cred->cr_groups[1];
     g1 = cred->cr_groups[2];
 #else
-#if defined(AFS_AIX_ENV)
+# if defined(AFS_AIX_ENV)
     if (cred->cr_ngrps < 2)
        return NOPAG;
-#elif defined(AFS_LINUX26_ENV)
+# elif defined(AFS_LINUX26_ENV)
     if (afs_cr_group_info(cred)->ngroups < NUMPAGGROUPS)
        return NOPAG;
-#elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_XBSD_ENV)
-#if defined(AFS_SUN510_ENV)
+# elif defined(AFS_SGI_ENV) || defined(AFS_SUN5_ENV) || defined(AFS_LINUX20_ENV) || defined(AFS_XBSD_ENV)
+#  if defined(AFS_SUN510_ENV)
     if (ngroups < 2) {
-#else
+#  else
     if (cred->cr_ngroups < 2) {
-#endif
+#  endif
        return NOPAG;
     }
-#endif
-#if defined(AFS_AIX51_ENV)
+# endif
+# if defined(AFS_AIX51_ENV)
     g0 = cred->cr_groupset.gs_union.un_groups[0];
     g1 = cred->cr_groupset.gs_union.un_groups[1];
-#elif defined(AFS_LINUX26_ONEGROUP_ENV)
-#elif defined(AFS_LINUX26_ENV)
-    g0 = GROUP_AT(afs_cr_group_info(cred), 0);
-    g1 = GROUP_AT(afs_cr_group_info(cred), 1);
 #elif defined(AFS_SUN510_ENV)
     g0 = gids[0];
     g1 = gids[1];
@@ -591,13 +570,10 @@ afs_get_group_pag(afs_ucred_t *cred)
     g1 = cred->cr_groups[1];
 #endif
 #endif
-#if defined(AFS_LINUX26_ONEGROUP_ENV)
-    pag = (afs_int32) afs_get_pag_from_groups(afs_cr_group_info(cred));
-#else
     pag = (afs_int32) afs_get_pag_from_groups(g0, g1);
-#endif
     return pag;
 }
+#endif
 
 
 afs_int32
@@ -619,12 +595,12 @@ PagInCred(afs_ucred_t *cred)
      * to looking at the keyrings.
      */
 # if !defined(STRUCT_TASK_HAS_CRED)
-    pag = afs_get_group_pag(cred);
+    pag = osi_get_group_pag(cred);
 # endif
     if (pag == NOPAG)
        pag = osi_get_keyring_pag(cred);
 #else
-    pag = afs_get_group_pag(cred);
+    pag = osi_get_group_pag(cred);
 #endif
     return pag;
 }
index 6fed266..725ff06 100644 (file)
@@ -581,13 +581,7 @@ extern int AddPag(afs_proc_t *p, afs_int32 aval, afs_ucred_t **credpp);
 extern int AddPag(afs_int32 aval, afs_ucred_t **credpp);
 #endif
 extern int afs_InitReq(register struct vrequest *av, afs_ucred_t *acred);
-#if defined(UKERNEL)
 extern afs_uint32 afs_get_pag_from_groups(gid_t g0a, gid_t g1a);
-#else
-#ifdef AFS_LINUX26_ONEGROUP_ENV
-extern afs_uint32 afs_get_pag_from_groups(struct group_info *gi);
-#endif
-#endif
 extern void afs_get_groups_from_pag(afs_uint32 pag, gid_t * g0p, gid_t * g1p);
 extern afs_int32 PagInCred(afs_ucred_t *cred);