From: Simon Wilkinson Date: Sat, 24 Oct 2009 14:08:52 +0000 (+0100) Subject: Linux: Use atomics for credential reference counts X-Git-Tag: openafs-devel-1_5_67~30 X-Git-Url: http://git.openafs.org/?p=openafs.git;a=commitdiff_plain;h=4f91de7cf429db63bcf67466cf3fb36feb990643 Linux: Use atomics for credential reference counts 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 Tested-by: Derrick Brashear --- diff --git a/src/afs/LINUX/osi_cred.c b/src/afs/LINUX/osi_cred.c index 69b2614..f402a57 100644 --- a/src/afs/LINUX/osi_cred.c +++ b/src/afs/LINUX/osi_cred.c @@ -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 } diff --git a/src/afs/LINUX/osi_machdep.h b/src/afs/LINUX/osi_machdep.h index 52d4ea2..bfd11c1 100644 --- a/src/afs/LINUX/osi_machdep.h +++ b/src/afs/LINUX/osi_machdep.h @@ -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) */ diff --git a/src/afs/afs_osi_gcpags.c b/src/afs/afs_osi_gcpags.c index 6d8f3ba..0c34297 100644 --- a/src/afs/afs_osi_gcpags.c +++ b/src/afs/afs_osi_gcpags.c @@ -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)