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>
#if defined(STRUCT_TASK_HAS_CRED)
get_cred(tmp);
#else
- tmp->cr_ref = 1;
+ atomic_set(&tmp->cr_ref, 1);
#endif
return tmp;
}
#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
}
#else
typedef struct afs_cred {
- int cr_ref;
+ atomic_t cr_ref;
uid_t cr_uid;
uid_t cr_ruid;
gid_t cr_gid;
#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) */
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)