diff options
Diffstat (limited to 'net/sunrpc/svcauth_unix.c')
-rw-r--r-- | net/sunrpc/svcauth_unix.c | 47 |
1 files changed, 44 insertions, 3 deletions
diff --git a/net/sunrpc/svcauth_unix.c b/net/sunrpc/svcauth_unix.c index 40d41a2831d7..e1bd933629fe 100644 --- a/net/sunrpc/svcauth_unix.c +++ b/net/sunrpc/svcauth_unix.c | |||
@@ -9,6 +9,7 @@ | |||
9 | #include <linux/seq_file.h> | 9 | #include <linux/seq_file.h> |
10 | #include <linux/hash.h> | 10 | #include <linux/hash.h> |
11 | #include <linux/string.h> | 11 | #include <linux/string.h> |
12 | #include <net/sock.h> | ||
12 | 13 | ||
13 | #define RPCDBG_FACILITY RPCDBG_AUTH | 14 | #define RPCDBG_FACILITY RPCDBG_AUTH |
14 | 15 | ||
@@ -375,6 +376,44 @@ void svcauth_unix_purge(void) | |||
375 | cache_purge(&ip_map_cache); | 376 | cache_purge(&ip_map_cache); |
376 | } | 377 | } |
377 | 378 | ||
379 | static inline struct ip_map * | ||
380 | ip_map_cached_get(struct svc_rqst *rqstp) | ||
381 | { | ||
382 | struct ip_map *ipm = rqstp->rq_sock->sk_info_authunix; | ||
383 | if (ipm != NULL) { | ||
384 | if (!cache_valid(&ipm->h)) { | ||
385 | /* | ||
386 | * The entry has been invalidated since it was | ||
387 | * remembered, e.g. by a second mount from the | ||
388 | * same IP address. | ||
389 | */ | ||
390 | rqstp->rq_sock->sk_info_authunix = NULL; | ||
391 | cache_put(&ipm->h, &ip_map_cache); | ||
392 | return NULL; | ||
393 | } | ||
394 | cache_get(&ipm->h); | ||
395 | } | ||
396 | return ipm; | ||
397 | } | ||
398 | |||
399 | static inline void | ||
400 | ip_map_cached_put(struct svc_rqst *rqstp, struct ip_map *ipm) | ||
401 | { | ||
402 | struct svc_sock *svsk = rqstp->rq_sock; | ||
403 | |||
404 | if (svsk->sk_sock->type == SOCK_STREAM && svsk->sk_info_authunix == NULL) | ||
405 | svsk->sk_info_authunix = ipm; /* newly cached, keep the reference */ | ||
406 | else | ||
407 | cache_put(&ipm->h, &ip_map_cache); | ||
408 | } | ||
409 | |||
410 | void | ||
411 | svcauth_unix_info_release(void *info) | ||
412 | { | ||
413 | struct ip_map *ipm = info; | ||
414 | cache_put(&ipm->h, &ip_map_cache); | ||
415 | } | ||
416 | |||
378 | static int | 417 | static int |
379 | svcauth_unix_set_client(struct svc_rqst *rqstp) | 418 | svcauth_unix_set_client(struct svc_rqst *rqstp) |
380 | { | 419 | { |
@@ -384,8 +423,10 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
384 | if (rqstp->rq_proc == 0) | 423 | if (rqstp->rq_proc == 0) |
385 | return SVC_OK; | 424 | return SVC_OK; |
386 | 425 | ||
387 | ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class, | 426 | ipm = ip_map_cached_get(rqstp); |
388 | rqstp->rq_addr.sin_addr); | 427 | if (ipm == NULL) |
428 | ipm = ip_map_lookup(rqstp->rq_server->sv_program->pg_class, | ||
429 | rqstp->rq_addr.sin_addr); | ||
389 | 430 | ||
390 | if (ipm == NULL) | 431 | if (ipm == NULL) |
391 | return SVC_DENIED; | 432 | return SVC_DENIED; |
@@ -400,7 +441,7 @@ svcauth_unix_set_client(struct svc_rqst *rqstp) | |||
400 | case 0: | 441 | case 0: |
401 | rqstp->rq_client = &ipm->m_client->h; | 442 | rqstp->rq_client = &ipm->m_client->h; |
402 | kref_get(&rqstp->rq_client->ref); | 443 | kref_get(&rqstp->rq_client->ref); |
403 | cache_put(&ipm->h, &ip_map_cache); | 444 | ip_map_cached_put(rqstp, ipm); |
404 | break; | 445 | break; |
405 | } | 446 | } |
406 | return SVC_OK; | 447 | return SVC_OK; |