aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTrond Myklebust <Trond.Myklebust@netapp.com>2010-05-13 12:55:38 -0400
committerTrond Myklebust <Trond.Myklebust@netapp.com>2010-05-14 15:09:37 -0400
commit126e216a8730532dfb685205309275f87e3d133e (patch)
tree6a73e5d6a5af2866e260ccb7909582e2ccd5741f
parent9bb0b8136a7d5b50c5807af3bf12b758fb257814 (diff)
SUNRPC: Don't spam gssd with upcall requests when the kerberos key expired
Now that the rpc.gssd daemon can explicitly tell us that the key expired, we should cache that information to avoid spamming gssd. Signed-off-by: Trond Myklebust <Trond.Myklebust@netapp.com>
-rw-r--r--include/linux/sunrpc/auth.h1
-rw-r--r--include/linux/sunrpc/auth_gss.h1
-rw-r--r--net/sunrpc/auth_gss/auth_gss.c65
3 files changed, 55 insertions, 12 deletions
diff --git a/include/linux/sunrpc/auth.h b/include/linux/sunrpc/auth.h
index 996df4dac7d4..87d7ec0bf779 100644
--- a/include/linux/sunrpc/auth.h
+++ b/include/linux/sunrpc/auth.h
@@ -54,6 +54,7 @@ struct rpc_cred {
54#define RPCAUTH_CRED_NEW 0 54#define RPCAUTH_CRED_NEW 0
55#define RPCAUTH_CRED_UPTODATE 1 55#define RPCAUTH_CRED_UPTODATE 1
56#define RPCAUTH_CRED_HASHED 2 56#define RPCAUTH_CRED_HASHED 2
57#define RPCAUTH_CRED_NEGATIVE 3
57 58
58#define RPCAUTH_CRED_MAGIC 0x0f4aa4f0 59#define RPCAUTH_CRED_MAGIC 0x0f4aa4f0
59 60
diff --git a/include/linux/sunrpc/auth_gss.h b/include/linux/sunrpc/auth_gss.h
index d48d4e605f74..671538d25bc1 100644
--- a/include/linux/sunrpc/auth_gss.h
+++ b/include/linux/sunrpc/auth_gss.h
@@ -82,6 +82,7 @@ struct gss_cred {
82 enum rpc_gss_svc gc_service; 82 enum rpc_gss_svc gc_service;
83 struct gss_cl_ctx *gc_ctx; 83 struct gss_cl_ctx *gc_ctx;
84 struct gss_upcall_msg *gc_upcall; 84 struct gss_upcall_msg *gc_upcall;
85 unsigned long gc_upcall_timestamp;
85 unsigned char gc_machine_cred : 1; 86 unsigned char gc_machine_cred : 1;
86}; 87};
87 88
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index 48a7939dc9e2..8da2a0e68574 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -57,6 +57,9 @@ static const struct rpc_authops authgss_ops;
57static const struct rpc_credops gss_credops; 57static const struct rpc_credops gss_credops;
58static const struct rpc_credops gss_nullops; 58static const struct rpc_credops gss_nullops;
59 59
60#define GSS_RETRY_EXPIRED 5
61static unsigned int gss_expired_cred_retry_delay = GSS_RETRY_EXPIRED;
62
60#ifdef RPC_DEBUG 63#ifdef RPC_DEBUG
61# define RPCDBG_FACILITY RPCDBG_AUTH 64# define RPCDBG_FACILITY RPCDBG_AUTH
62#endif 65#endif
@@ -350,6 +353,24 @@ gss_unhash_msg(struct gss_upcall_msg *gss_msg)
350} 353}
351 354
352static void 355static void
356gss_handle_downcall_result(struct gss_cred *gss_cred, struct gss_upcall_msg *gss_msg)
357{
358 switch (gss_msg->msg.errno) {
359 case 0:
360 if (gss_msg->ctx == NULL)
361 break;
362 clear_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags);
363 gss_cred_set_ctx(&gss_cred->gc_base, gss_msg->ctx);
364 break;
365 case -EKEYEXPIRED:
366 set_bit(RPCAUTH_CRED_NEGATIVE, &gss_cred->gc_base.cr_flags);
367 }
368 gss_cred->gc_upcall_timestamp = jiffies;
369 gss_cred->gc_upcall = NULL;
370 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
371}
372
373static void
353gss_upcall_callback(struct rpc_task *task) 374gss_upcall_callback(struct rpc_task *task)
354{ 375{
355 struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred, 376 struct gss_cred *gss_cred = container_of(task->tk_msg.rpc_cred,
@@ -358,13 +379,9 @@ gss_upcall_callback(struct rpc_task *task)
358 struct inode *inode = &gss_msg->inode->vfs_inode; 379 struct inode *inode = &gss_msg->inode->vfs_inode;
359 380
360 spin_lock(&inode->i_lock); 381 spin_lock(&inode->i_lock);
361 if (gss_msg->ctx) 382 gss_handle_downcall_result(gss_cred, gss_msg);
362 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
363 else
364 task->tk_status = gss_msg->msg.errno;
365 gss_cred->gc_upcall = NULL;
366 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
367 spin_unlock(&inode->i_lock); 383 spin_unlock(&inode->i_lock);
384 task->tk_status = gss_msg->msg.errno;
368 gss_release_msg(gss_msg); 385 gss_release_msg(gss_msg);
369} 386}
370 387
@@ -513,18 +530,16 @@ gss_refresh_upcall(struct rpc_task *task)
513 spin_lock(&inode->i_lock); 530 spin_lock(&inode->i_lock);
514 if (gss_cred->gc_upcall != NULL) 531 if (gss_cred->gc_upcall != NULL)
515 rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL); 532 rpc_sleep_on(&gss_cred->gc_upcall->rpc_waitqueue, task, NULL);
516 else if (gss_msg->ctx != NULL) { 533 else if (gss_msg->ctx == NULL && gss_msg->msg.errno >= 0) {
517 gss_cred_set_ctx(task->tk_msg.rpc_cred, gss_msg->ctx);
518 gss_cred->gc_upcall = NULL;
519 rpc_wake_up_status(&gss_msg->rpc_waitqueue, gss_msg->msg.errno);
520 } else if (gss_msg->msg.errno >= 0) {
521 task->tk_timeout = 0; 534 task->tk_timeout = 0;
522 gss_cred->gc_upcall = gss_msg; 535 gss_cred->gc_upcall = gss_msg;
523 /* gss_upcall_callback will release the reference to gss_upcall_msg */ 536 /* gss_upcall_callback will release the reference to gss_upcall_msg */
524 atomic_inc(&gss_msg->count); 537 atomic_inc(&gss_msg->count);
525 rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback); 538 rpc_sleep_on(&gss_msg->rpc_waitqueue, task, gss_upcall_callback);
526 } else 539 } else {
540 gss_handle_downcall_result(gss_cred, gss_msg);
527 err = gss_msg->msg.errno; 541 err = gss_msg->msg.errno;
542 }
528 spin_unlock(&inode->i_lock); 543 spin_unlock(&inode->i_lock);
529 gss_release_msg(gss_msg); 544 gss_release_msg(gss_msg);
530out: 545out:
@@ -1123,6 +1138,23 @@ static int gss_renew_cred(struct rpc_task *task)
1123 return 0; 1138 return 0;
1124} 1139}
1125 1140
1141static int gss_cred_is_negative_entry(struct rpc_cred *cred)
1142{
1143 if (test_bit(RPCAUTH_CRED_NEGATIVE, &cred->cr_flags)) {
1144 unsigned long now = jiffies;
1145 unsigned long begin, expire;
1146 struct gss_cred *gss_cred;
1147
1148 gss_cred = container_of(cred, struct gss_cred, gc_base);
1149 begin = gss_cred->gc_upcall_timestamp;
1150 expire = begin + gss_expired_cred_retry_delay * HZ;
1151
1152 if (time_in_range_open(now, begin, expire))
1153 return 1;
1154 }
1155 return 0;
1156}
1157
1126/* 1158/*
1127* Refresh credentials. XXX - finish 1159* Refresh credentials. XXX - finish
1128*/ 1160*/
@@ -1132,6 +1164,9 @@ gss_refresh(struct rpc_task *task)
1132 struct rpc_cred *cred = task->tk_msg.rpc_cred; 1164 struct rpc_cred *cred = task->tk_msg.rpc_cred;
1133 int ret = 0; 1165 int ret = 0;
1134 1166
1167 if (gss_cred_is_negative_entry(cred))
1168 return -EKEYEXPIRED;
1169
1135 if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) && 1170 if (!test_bit(RPCAUTH_CRED_NEW, &cred->cr_flags) &&
1136 !test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) { 1171 !test_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags)) {
1137 ret = gss_renew_cred(task); 1172 ret = gss_renew_cred(task);
@@ -1585,5 +1620,11 @@ static void __exit exit_rpcsec_gss(void)
1585} 1620}
1586 1621
1587MODULE_LICENSE("GPL"); 1622MODULE_LICENSE("GPL");
1623module_param_named(expired_cred_retry_delay,
1624 gss_expired_cred_retry_delay,
1625 uint, 0644);
1626MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until "
1627 "the RPC engine retries an expired credential");
1628
1588module_init(init_rpcsec_gss) 1629module_init(init_rpcsec_gss)
1589module_exit(exit_rpcsec_gss) 1630module_exit(exit_rpcsec_gss)