Remove pre-Linux 2.6 support
[openafs.git] / src / afs / LINUX / osi_cred.c
index 65e1259..266929c 100644 (file)
-/* Copyright (C) 1995, 1989, 1998 Transarc Corporation - All rights reserved */
+/*
+ * Copyright 2000, International Business Machines Corporation and others.
+ * All Rights Reserved.
+ * 
+ * This software has been released under the terms of the IBM Public
+ * License.  For details, see the LICENSE file in the top-level source
+ * directory or online at http://www.openafs.org/dl/license10.html
+ */
 
 /*
  * osi_cred.c - Linux cred handling routines.
  *
  */
-#include "../afs/param.h"
-#include "../afs/sysincludes.h"
-#include "../afs/afsincludes.h"
-
-/* Setup a pool for creds. Allocate several at a time. */
-#define CRED_ALLOC_STEP 29 /* at 140 bytes/cred = 4060 bytes. */
+#include <afsconfig.h>
+#include "afs/param.h"
 
 
-static cred_t *cred_pool = NULL;
-int cred_allocs = 0;
-int ncreds_inuse = 0;
-
-/* Cred locking assumes current single threaded non-preemptive kernel.
- * Also assuming a fast path through both down and up if no waiters. Otherwise,
- * test if no creds in pool before grabbing lock in crfree().
- */
-static struct semaphore linux_cred_pool_lock = MUTEX;
-#define CRED_LOCK() down(&linux_cred_pool_lock)
-#define CRED_UNLOCK() up(&linux_cred_pool_lock)
+#include "afs/sysincludes.h"
+#include "afsincludes.h"
 
-cred_t *crget(void)
+cred_t *
+crget(void)
 {
     cred_t *tmp;
-    int i;
-
-    CRED_LOCK();
-    if (!cred_pool) {
-       cred_allocs++;
-       cred_pool = (cred_t*)osi_Alloc(CRED_ALLOC_STEP * sizeof(cred_t));
-       if (!cred_pool)
-           osi_Panic("crget: No more memory for creds!\n");
-       
-       for (i=0; i < CRED_ALLOC_STEP-1; i++)
-           cred_pool[i].cr_ref = (int)&cred_pool[i+1];
-       cred_pool[i].cr_ref = 0;
-    }
-    tmp = cred_pool;
-    cred_pool = (cred_t*)tmp->cr_ref;
-    ncreds_inuse++;
-    CRED_UNLOCK();
-
-    memset(tmp, 0, sizeof(cred_t));
+    
+#if !defined(GFP_NOFS)
+#define GFP_NOFS GFP_KERNEL
+#endif
+    tmp = kmalloc(sizeof(cred_t), GFP_NOFS);
+    if (!tmp)
+       osi_Panic("crget: No more memory for creds!\n");
+    
     tmp->cr_ref = 1;
     return tmp;
 }
 
-void crfree(cred_t *cr)
+void
+crfree(cred_t * cr)
 {
     if (cr->cr_ref > 1) {
        cr->cr_ref--;
        return;
     }
 
-    CRED_LOCK();
-    cr->cr_ref = (int)cred_pool;
-    cred_pool = cr;
-    CRED_UNLOCK();
-    ncreds_inuse --;
+    put_group_info(cr->cr_group_info);
+
+    kfree(cr);
 }
 
 
 /* Return a duplicate of the cred. */
-cred_t *crdup(cred_t *cr)
+cred_t *
+crdup(cred_t * cr)
 {
     cred_t *tmp = crget();
-    *tmp = *cr;
-    tmp->cr_ref = 1;
+
+    tmp->cr_uid = cr->cr_uid;
+    tmp->cr_ruid = cr->cr_ruid;
+    tmp->cr_gid = cr->cr_gid;
+    tmp->cr_rgid = cr->cr_rgid;
+
+    get_group_info(cr->cr_group_info);
+    tmp->cr_group_info = cr->cr_group_info;
+
     return tmp;
 }
 
-cred_t *crref(void)
+cred_t *
+crref(void)
 {
     cred_t *cr = crget();
-    cr->cr_uid = current->fsuid;
-    cr->cr_ruid = current->uid;
-    cr->cr_gid = current->fsgid;
-    cr->cr_rgid = current->gid;
-    memcpy(cr->cr_groups, current->groups, NGROUPS * sizeof(gid_t));
-    cr->cr_ngroups = current->ngroups;
+
+    cr->cr_uid = current_fsuid();
+    cr->cr_ruid = current_uid();
+    cr->cr_gid = current_fsgid();
+    cr->cr_rgid = current_gid();
+
+    task_lock(current);
+    get_group_info(current_group_info());
+    cr->cr_group_info = current_group_info();
+    task_unlock(current);
+
     return cr;
 }
 
-
 /* Set the cred info into the current task */
-void crset(cred_t *cr)
+void
+crset(cred_t * cr)
 {
+    struct group_info *old_info;
+#if defined(STRUCT_TASK_HAS_CRED)
+    struct cred *new_creds;
+
+    /* If our current task doesn't have identical real and effective
+     * credentials, commit_cred won't let us change them, so we just
+     * bail here.
+     */
+    if (current->cred != current->real_cred)
+        return;
+    new_creds = prepare_creds();
+    new_creds->fsuid = cr->cr_uid;
+    new_creds->uid = cr->cr_ruid;
+    new_creds->fsgid = cr->cr_gid;
+    new_creds->gid = cr->cr_rgid;
+#else
     current->fsuid = cr->cr_uid;
     current->uid = cr->cr_ruid;
     current->fsgid = cr->cr_gid;
     current->gid = cr->cr_rgid;
-    memcpy(current->groups, cr->cr_groups, NGROUPS * sizeof(gid_t));
-    current->ngroups = cr->cr_ngroups;
+#endif
+
+    /* using set_current_groups() will sort the groups */
+    get_group_info(cr->cr_group_info);
+
+    task_lock(current);
+#if defined(STRUCT_TASK_HAS_CRED)
+    old_info = current->cred->group_info;
+    new_creds->group_info = cr->cr_group_info;
+    commit_creds(new_creds);
+#else
+    old_info = current->group_info;
+    current->group_info = cr->cr_group_info;
+#endif
+    task_unlock(current);
+
+    put_group_info(old_info);
 }