patch-2.4.9 linux/net/sunrpc/auth.c
Next file: linux/net/sunrpc/auth_null.c
Previous file: linux/net/sched/sch_tbf.c
Back to the patch index
Back to the overall index
- Lines: 245
- Date:
Thu Aug 16 09:39:37 2001
- Orig file:
v2.4.8/linux/net/sunrpc/auth.c
- Orig date:
Fri Feb 9 11:29:44 2001
diff -u --recursive --new-file v2.4.8/linux/net/sunrpc/auth.c linux/net/sunrpc/auth.c
@@ -81,42 +81,61 @@
auth->au_nextgc = jiffies + (auth->au_expire >> 1);
}
+/*
+ * Destroy an unreferenced credential
+ */
static inline void
-rpcauth_crdestroy(struct rpc_auth *auth, struct rpc_cred *cred)
+rpcauth_crdestroy(struct rpc_cred *cred)
{
#ifdef RPC_DEBUG
if (cred->cr_magic != RPCAUTH_CRED_MAGIC)
BUG();
cred->cr_magic = 0;
+ if (atomic_read(&cred->cr_count) || cred->cr_auth)
+ BUG();
#endif
- if (auth->au_ops->crdestroy)
- auth->au_ops->crdestroy(cred);
- else
- rpc_free(cred);
+ cred->cr_ops->crdestroy(cred);
}
/*
- * Clear the RPC credential cache
+ * Destroy a list of credentials
+ */
+static inline
+void rpcauth_destroy_credlist(struct rpc_cred *head)
+{
+ struct rpc_cred *cred;
+
+ while ((cred = head) != NULL) {
+ head = cred->cr_next;
+ rpcauth_crdestroy(cred);
+ }
+}
+
+/*
+ * Clear the RPC credential cache, and delete those credentials
+ * that are not referenced.
*/
void
rpcauth_free_credcache(struct rpc_auth *auth)
{
- struct rpc_cred **q, *cred;
- void (*destroy)(struct rpc_cred *);
+ struct rpc_cred **q, *cred, *free = NULL;
int i;
- if (!(destroy = auth->au_ops->crdestroy))
- destroy = (void (*)(struct rpc_cred *)) rpc_free;
-
spin_lock(&rpc_credcache_lock);
for (i = 0; i < RPC_CREDCACHE_NR; i++) {
q = &auth->au_credcache[i];
while ((cred = *q) != NULL) {
*q = cred->cr_next;
- destroy(cred);
+ cred->cr_auth = NULL;
+ if (atomic_read(&cred->cr_count) == 0) {
+ cred->cr_next = free;
+ free = cred;
+ } else
+ cred->cr_next = NULL;
}
}
spin_unlock(&rpc_credcache_lock);
+ rpcauth_destroy_credlist(free);
}
/*
@@ -133,9 +152,10 @@
for (i = 0; i < RPC_CREDCACHE_NR; i++) {
q = &auth->au_credcache[i];
while ((cred = *q) != NULL) {
- if (!cred->cr_count &&
+ if (!atomic_read(&cred->cr_count) &&
time_before(cred->cr_expire, jiffies)) {
*q = cred->cr_next;
+ cred->cr_auth = NULL;
cred->cr_next = free;
free = cred;
continue;
@@ -144,10 +164,7 @@
}
}
spin_unlock(&rpc_credcache_lock);
- while ((cred = free) != NULL) {
- free = cred->cr_next;
- rpcauth_crdestroy(auth, cred);
- }
+ rpcauth_destroy_credlist(free);
auth->au_nextgc = jiffies + auth->au_expire;
}
@@ -163,8 +180,8 @@
spin_lock(&rpc_credcache_lock);
cred->cr_next = auth->au_credcache[nr];
auth->au_credcache[nr] = cred;
- cred->cr_count++;
- cred->cr_expire = jiffies + auth->au_expire;
+ cred->cr_auth = auth;
+ get_rpccred(cred);
spin_unlock(&rpc_credcache_lock);
}
@@ -187,7 +204,7 @@
q = &auth->au_credcache[nr];
while ((cred = *q) != NULL) {
if (!(cred->cr_flags & RPCAUTH_CRED_DEAD) &&
- auth->au_ops->crmatch(cred, taskflags)) {
+ cred->cr_ops->crmatch(cred, taskflags)) {
*q = cred->cr_next;
break;
}
@@ -213,23 +230,23 @@
* Remove cred handle from cache
*/
static void
-rpcauth_remove_credcache(struct rpc_auth *auth, struct rpc_cred *cred)
+rpcauth_remove_credcache(struct rpc_cred *cred)
{
+ struct rpc_auth *auth = cred->cr_auth;
struct rpc_cred **q, *cr;
int nr;
nr = (cred->cr_uid & RPC_CREDCACHE_MASK);
- spin_lock(&rpc_credcache_lock);
q = &auth->au_credcache[nr];
while ((cr = *q) != NULL) {
if (cred == cr) {
*q = cred->cr_next;
cred->cr_next = NULL;
+ cred->cr_auth = NULL;
break;
}
q = &cred->cr_next;
}
- spin_unlock(&rpc_credcache_lock);
}
struct rpc_cred *
@@ -258,7 +275,7 @@
{
dprintk("RPC: matching %s cred %d\n",
auth->au_ops->au_name, taskflags);
- return auth->au_ops->crmatch(cred, taskflags);
+ return cred->cr_ops->crmatch(cred, taskflags);
}
void
@@ -266,26 +283,25 @@
{
dprintk("RPC: %4d holding %s cred %p\n",
task->tk_pid, task->tk_auth->au_ops->au_name, task->tk_msg.rpc_cred);
- if (task->tk_msg.rpc_cred) {
- spin_lock(&rpc_credcache_lock);
- task->tk_msg.rpc_cred->cr_count++;
- task->tk_msg.rpc_cred->cr_expire = jiffies + task->tk_auth->au_expire;
- spin_unlock(&rpc_credcache_lock);
- }
+ if (task->tk_msg.rpc_cred)
+ get_rpccred(task->tk_msg.rpc_cred);
}
void
-rpcauth_releasecred(struct rpc_auth *auth, struct rpc_cred *cred)
+put_rpccred(struct rpc_cred *cred)
{
- spin_lock(&rpc_credcache_lock);
- if (cred != NULL && cred->cr_count > 0) {
- if (!--cred->cr_count && (cred->cr_flags & RPCAUTH_CRED_DEAD)) {
- spin_unlock(&rpc_credcache_lock);
- rpcauth_remove_credcache(auth, cred);
- rpcauth_crdestroy(auth, cred);
- return;
- }
+ if (!atomic_dec_and_lock(&cred->cr_count, &rpc_credcache_lock))
+ return;
+
+ if (cred->cr_auth && cred->cr_flags & RPCAUTH_CRED_DEAD)
+ rpcauth_remove_credcache(cred);
+
+ if (!cred->cr_auth) {
+ spin_unlock(&rpc_credcache_lock);
+ rpcauth_crdestroy(cred);
+ return;
}
+ cred->cr_expire = jiffies + cred->cr_auth->au_expire;
spin_unlock(&rpc_credcache_lock);
}
@@ -298,7 +314,7 @@
dprintk("RPC: %4d releasing %s cred %p\n",
task->tk_pid, auth->au_ops->au_name, cred);
- rpcauth_releasecred(auth, cred);
+ put_rpccred(cred);
task->tk_msg.rpc_cred = NULL;
}
@@ -306,10 +322,11 @@
rpcauth_marshcred(struct rpc_task *task, u32 *p)
{
struct rpc_auth *auth = task->tk_auth;
+ struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %4d marshaling %s cred %p\n",
- task->tk_pid, auth->au_ops->au_name, task->tk_msg.rpc_cred);
- return auth->au_ops->crmarshal(task, p,
+ task->tk_pid, auth->au_ops->au_name, cred);
+ return cred->cr_ops->crmarshal(task, p,
task->tk_flags & RPC_CALL_REALUID);
}
@@ -317,20 +334,22 @@
rpcauth_checkverf(struct rpc_task *task, u32 *p)
{
struct rpc_auth *auth = task->tk_auth;
+ struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %4d validating %s cred %p\n",
- task->tk_pid, auth->au_ops->au_name, task->tk_msg.rpc_cred);
- return auth->au_ops->crvalidate(task, p);
+ task->tk_pid, auth->au_ops->au_name, cred);
+ return cred->cr_ops->crvalidate(task, p);
}
int
rpcauth_refreshcred(struct rpc_task *task)
{
struct rpc_auth *auth = task->tk_auth;
+ struct rpc_cred *cred = task->tk_msg.rpc_cred;
dprintk("RPC: %4d refreshing %s cred %p\n",
- task->tk_pid, auth->au_ops->au_name, task->tk_msg.rpc_cred);
- task->tk_status = auth->au_ops->crrefresh(task);
+ task->tk_pid, auth->au_ops->au_name, cred);
+ task->tk_status = cred->cr_ops->crrefresh(task);
return task->tk_status;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)