diff options
author | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-13 12:55:38 -0400 |
---|---|---|
committer | Trond Myklebust <Trond.Myklebust@netapp.com> | 2010-05-14 15:09:37 -0400 |
commit | 126e216a8730532dfb685205309275f87e3d133e (patch) | |
tree | 6a73e5d6a5af2866e260ccb7909582e2ccd5741f /net/sunrpc | |
parent | 9bb0b8136a7d5b50c5807af3bf12b758fb257814 (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>
Diffstat (limited to 'net/sunrpc')
-rw-r--r-- | net/sunrpc/auth_gss/auth_gss.c | 65 |
1 files changed, 53 insertions, 12 deletions
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; | |||
57 | static const struct rpc_credops gss_credops; | 57 | static const struct rpc_credops gss_credops; |
58 | static const struct rpc_credops gss_nullops; | 58 | static const struct rpc_credops gss_nullops; |
59 | 59 | ||
60 | #define GSS_RETRY_EXPIRED 5 | ||
61 | static 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 | ||
352 | static void | 355 | static void |
356 | gss_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 | |||
373 | static void | ||
353 | gss_upcall_callback(struct rpc_task *task) | 374 | gss_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); |
530 | out: | 545 | out: |
@@ -1123,6 +1138,23 @@ static int gss_renew_cred(struct rpc_task *task) | |||
1123 | return 0; | 1138 | return 0; |
1124 | } | 1139 | } |
1125 | 1140 | ||
1141 | static 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 | ||
1587 | MODULE_LICENSE("GPL"); | 1622 | MODULE_LICENSE("GPL"); |
1623 | module_param_named(expired_cred_retry_delay, | ||
1624 | gss_expired_cred_retry_delay, | ||
1625 | uint, 0644); | ||
1626 | MODULE_PARM_DESC(expired_cred_retry_delay, "Timeout (in seconds) until " | ||
1627 | "the RPC engine retries an expired credential"); | ||
1628 | |||
1588 | module_init(init_rpcsec_gss) | 1629 | module_init(init_rpcsec_gss) |
1589 | module_exit(exit_rpcsec_gss) | 1630 | module_exit(exit_rpcsec_gss) |