X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=inline;f=lustre%2Fptlrpc%2Fsec.c;h=443daffb5f17aa864f8dbbdbd8e94a5d7b782224;hb=f625f670afbe954030ff81f0f8522137d6cdd335;hp=402167b4ccd056ee2d416c500c18aba6a828b244;hpb=1f1d3a376d488d715dd1b0c94d5b66ea05c1e6ca;p=fs%2Flustre-release.git diff --git a/lustre/ptlrpc/sec.c b/lustre/ptlrpc/sec.c index 402167b..443daff 100644 --- a/lustre/ptlrpc/sec.c +++ b/lustre/ptlrpc/sec.c @@ -27,7 +27,7 @@ * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved. * Use is subject to license terms. * - * Copyright (c) 2011, 2012, Intel Corporation. + * Copyright (c) 2011, 2014, Intel Corporation. */ /* * This file is part of Lustre, http://www.lustre.org/ @@ -366,38 +366,53 @@ static int import_sec_check_expire(struct obd_import *imp) return 0; CDEBUG(D_SEC, "found delayed sec adapt expired, do it now\n"); - return sptlrpc_import_sec_adapt(imp, NULL, 0); + return sptlrpc_import_sec_adapt(imp, NULL, NULL); } +/** + * Get and validate the client side ptlrpc security facilities from + * \a imp. There is a race condition on client reconnect when the import is + * being destroyed while there are outstanding client bound requests. In + * this case do not output any error messages if import secuity is not + * found. + * + * \param[in] imp obd import associated with client + * \param[out] sec client side ptlrpc security + * + * \retval 0 if security retrieved successfully + * \retval -ve errno if there was a problem + */ static int import_sec_validate_get(struct obd_import *imp, - struct ptlrpc_sec **sec) + struct ptlrpc_sec **sec) { - int rc; + int rc; - if (unlikely(imp->imp_sec_expire)) { - rc = import_sec_check_expire(imp); - if (rc) - return rc; - } + if (unlikely(imp->imp_sec_expire)) { + rc = import_sec_check_expire(imp); + if (rc) + return rc; + } - *sec = sptlrpc_import_sec_ref(imp); - if (*sec == NULL) { - CERROR("import %p (%s) with no sec\n", - imp, ptlrpc_import_state_name(imp->imp_state)); - return -EACCES; - } + *sec = sptlrpc_import_sec_ref(imp); + /* Only output an error when the import is still active */ + if (*sec == NULL) { + if (list_empty(&imp->imp_zombie_chain)) + CERROR("import %p (%s) with no sec\n", + imp, ptlrpc_import_state_name(imp->imp_state)); + return -EACCES; + } - if (unlikely((*sec)->ps_dying)) { - CERROR("attempt to use dying sec %p\n", sec); - sptlrpc_sec_put(*sec); - return -EACCES; - } + if (unlikely((*sec)->ps_dying)) { + CERROR("attempt to use dying sec %p\n", sec); + sptlrpc_sec_put(*sec); + return -EACCES; + } - return 0; + return 0; } /** - * Given a \a req, find or allocate a appropriate context for it. + * Given a \a req, find or allocate an appropriate context for it. * \pre req->rq_cli_ctx == NULL. * * \retval 0 succeed, and req->rq_cli_ctx is set. @@ -421,10 +436,10 @@ int sptlrpc_req_get_ctx(struct ptlrpc_request *req) sptlrpc_sec_put(sec); - if (!req->rq_cli_ctx) { - CERROR("req %p: fail to get context\n", req); - RETURN(-ENOMEM); - } + if (!req->rq_cli_ctx) { + CERROR("req %p: fail to get context\n", req); + RETURN(-ECONNREFUSED); + } RETURN(0); } @@ -561,7 +576,7 @@ int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req) newctx, newctx->cc_flags); schedule_timeout_and_set_state(TASK_INTERRUPTIBLE, - HZ); + msecs_to_jiffies(MSEC_PER_SEC)); } else { /* * it's possible newctx == oldctx if we're switching @@ -717,10 +732,10 @@ again: * it for reply reconstruction. * * Commonly the original context should be uptodate because we - * have a expiry nice time; server will keep its context because + * have an expiry nice time; server will keep its context because * we at least hold a ref of old context which prevent context - * destroying RPC being sent. So server still can accept the request - * and finish the RPC. But if that's not the case: + * from destroying RPC being sent. So server still can accept the + * request and finish the RPC. But if that's not the case: * 1. If server side context has been trimmed, a NO_CONTEXT will * be returned, gss_cli_ctx_verify/unseal will switch to new * context by force. @@ -782,7 +797,8 @@ again: req->rq_restart = 0; spin_unlock(&req->rq_lock); - lwi = LWI_TIMEOUT_INTR(timeout * HZ, ctx_refresh_timeout, + lwi = LWI_TIMEOUT_INTR(msecs_to_jiffies(timeout * MSEC_PER_SEC), + ctx_refresh_timeout, ctx_refresh_interrupt, req); rc = l_wait_event(req->rq_reply_waitq, ctx_check_refresh(ctx), &lwi); @@ -927,11 +943,9 @@ int sptlrpc_import_check_ctx(struct obd_import *imp) if (!req) RETURN(-ENOMEM); - spin_lock_init(&req->rq_lock); + ptlrpc_cli_req_init(req); atomic_set(&req->rq_refcount, 10000); - INIT_LIST_HEAD(&req->rq_ctx_chain); - init_waitqueue_head(&req->rq_reply_waitq); - init_waitqueue_head(&req->rq_set_waitq); + req->rq_import = imp; req->rq_flvr = sec->ps_flvr; req->rq_cli_ctx = ctx; @@ -1105,15 +1119,17 @@ int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req, struct ptlrpc_request **req_ret) { struct ptlrpc_request *early_req; - char *early_buf; - int early_bufsz, early_size; - int rc; + char *early_buf; + int early_bufsz, early_size; + int rc; ENTRY; early_req = ptlrpc_request_cache_alloc(GFP_NOFS); if (early_req == NULL) RETURN(-ENOMEM); + ptlrpc_cli_req_init(early_req); + early_size = req->rq_nob_received; early_bufsz = size_roundup_power2(early_size); OBD_ALLOC_LARGE(early_buf, early_bufsz); @@ -1156,7 +1172,6 @@ int sptlrpc_cli_unwrap_early_reply(struct ptlrpc_request *req, memcpy(early_buf, req->rq_repbuf, early_size); spin_unlock(&req->rq_lock); - spin_lock_init(&early_req->rq_lock); early_req->rq_cli_ctx = sptlrpc_cli_ctx_get(req->rq_cli_ctx); early_req->rq_flvr = req->rq_flvr; early_req->rq_repbuf = early_buf; @@ -2031,7 +2046,7 @@ static int sptlrpc_svc_check_from(struct ptlrpc_request *req, int svc_rc) /** * Used by ptlrpc server, to perform transformation upon request message of - * incoming \a req. This must be the first thing to do with a incoming + * incoming \a req. This must be the first thing to do with an incoming * request in ptlrpc layer. * * \retval SECSVC_OK success, and req->rq_reqmsg point to request message in