]> git.michaelhowe.org Git - packages/o/openafs.git/commitdiff
Linux: Use atomics for credential reference counts
authorSimon Wilkinson <sxw@inf.ed.ac.uk>
Sat, 24 Oct 2009 14:08:52 +0000 (15:08 +0100)
committerDerrick Brashear <shadow|account-1000005@unknown>
Fri, 20 Nov 2009 12:39:23 +0000 (04:39 -0800)
The reference count maintained as part of the afs_cred structure
wasn't being maintained atomically, requiring that crfree and
crhold always be called with the GLOCK held.

This patch just switches to using Linux's inbuilt atomic types to
maintain the reference count.

Change-Id: I1787061afbb48e234b4839b38b8801168ea2f25f
Reviewed-on: http://gerrit.openafs.org/726
Reviewed-by: Derrick Brashear <shadow@dementia.org>
Tested-by: Derrick Brashear <shadow@dementia.org>
src/afs/LINUX/osi_cred.c
src/afs/LINUX/osi_machdep.h
src/afs/afs_osi_gcpags.c

index 69b2614965963f4dd660c3496710e8eb8ddec6a5..f402a574634297616ee9dbec052931f247282c4a 100644 (file)
@@ -45,7 +45,7 @@ crget(void)
 #if defined(STRUCT_TASK_HAS_CRED)
     get_cred(tmp);
 #else
-    tmp->cr_ref = 1;
+    atomic_set(&tmp->cr_ref, 1);
 #endif
     return tmp;
 }
@@ -56,12 +56,10 @@ crfree(cred_t * cr)
 #if defined(STRUCT_TASK_HAS_CRED)
     put_cred(cr);
 #else
-    if (cr->cr_ref > 1) {
-       cr->cr_ref--;
-       return;
+    if (atomic_dec_and_test(&cr->cr_ref)) {
+        put_group_info(afs_cr_group_info(cr));
+        kfree(cr);
     }
-    put_group_info(afs_cr_group_info(cr));
-    kfree(cr);
 #endif
 }
 
index 52d4ea20dd970427bda147f51686d33871c99c81..bfd11c1abdbaa810593501b112f2443c6bb8287e 100644 (file)
@@ -197,7 +197,7 @@ afs_set_cr_group_info(cred_t *cred, struct group_info *group_info) {
 #else
 
 typedef struct afs_cred {
-    int cr_ref;
+    atomic_t cr_ref;
     uid_t cr_uid;
     uid_t cr_ruid;
     gid_t cr_gid;
@@ -222,7 +222,7 @@ afs_set_cr_group_info(cred_t *cred, struct group_info *group_info) {
 #define task_user(task) (task->user)
 #define task_session_keyring(task) (task->signal->session_keyring)
 #define current_session_keyring() (current->signal->session_keyring)
-#define crhold(c) (c)->cr_ref++
+#define crhold(c) atomic_inc(&(c)->cr_ref)
 
 #endif /* defined(STRUCT_TASK_HAS_CRED) */
 
index 6d8f3bae5cf51e5d686c9b41ce39f3c09fba196e..0c34297ae32acba0b68d2fd5d5f81d55bc2087d9 100644 (file)
@@ -470,7 +470,10 @@ afs_osi_proc2cred(afs_proc_t * pr)
     if ((pr->state == TASK_RUNNING) || (pr->state == TASK_INTERRUPTIBLE)
        || (pr->state == TASK_UNINTERRUPTIBLE)
        || (pr->state == TASK_STOPPED)) {
-       cr.cr_ref = 1;
+       /* This is dangerous. If anyone ever crfree's the cred that's
+        * returned from here, we'll go boom, because it's statically
+        * allocated. */
+       atomic_set(&cr.cr_ref, 1);
        afs_set_cr_uid(&cr, task_uid(pr));
 #if defined(AFS_LINUX26_ENV)
 #if defined(STRUCT_TASK_HAS_CRED)