X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;ds=sidebyside;f=lustre%2Fptlrpc%2Fsec.c;h=a4289d3b57d8537d9c793803de01686bfba800e3;hb=7dd6c394161a62b229ba65f50044a1d8f2da2d03;hp=402167b4ccd056ee2d416c500c18aba6a828b244;hpb=1f1d3a376d488d715dd1b0c94d5b66ea05c1e6ca;p=fs%2Flustre-release.git diff --git a/lustre/ptlrpc/sec.c b/lustre/ptlrpc/sec.c index 402167b..a4289d3 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/ @@ -40,10 +40,14 @@ #define DEBUG_SUBSYSTEM S_SEC -#include +#include +#ifdef HAVE_UIDGID_HEADER +# include +#endif #include #include +#include #include #include #include @@ -167,6 +171,10 @@ __u32 sptlrpc_name2flavor_base(const char *name) return SPTLRPC_FLVR_KRB5I; if (!strcmp(name, "krb5p")) return SPTLRPC_FLVR_KRB5P; + if (!strcmp(name, "skn")) + return SPTLRPC_FLVR_SKN; + if (!strcmp(name, "ska")) + return SPTLRPC_FLVR_SKA; if (!strcmp(name, "ski")) return SPTLRPC_FLVR_SKI; if (!strcmp(name, "skpi")) @@ -194,6 +202,10 @@ const char *sptlrpc_flavor2name_base(__u32 flvr) return "krb5i"; else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_KRB5P)) return "krb5p"; + else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_SKN)) + return "skn"; + else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_SKA)) + return "ska"; else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_SKI)) return "ski"; else if (base == SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_SKPI)) @@ -366,38 +378,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 +448,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); } @@ -551,7 +578,7 @@ int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req) newctx = req->rq_cli_ctx; LASSERT(newctx); - if (unlikely(newctx == oldctx && + if (unlikely(newctx == oldctx && test_bit(PTLRPC_CTX_DEAD_BIT, &oldctx->cc_flags))) { /* * still get the old dead ctx, usually means system too busy @@ -560,8 +587,16 @@ int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req) "ctx (%p, fl %lx) doesn't switch, relax a little bit\n", newctx, newctx->cc_flags); - schedule_timeout_and_set_state(TASK_INTERRUPTIBLE, - HZ); + set_current_state(TASK_INTERRUPTIBLE); + schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC)); + } else if (unlikely(test_bit(PTLRPC_CTX_UPTODATE_BIT, &newctx->cc_flags) + == 0)) { + /* + * new ctx not up to date yet + */ + CDEBUG(D_SEC, + "ctx (%p, fl %lx) doesn't switch, not up to date yet\n", + newctx, newctx->cc_flags); } else { /* * it's possible newctx == oldctx if we're switching @@ -717,10 +752,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 +817,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); @@ -823,7 +859,7 @@ void sptlrpc_req_set_flavor(struct ptlrpc_request *req, int opcode) LASSERT(req->rq_cli_ctx->cc_sec); LASSERT(req->rq_bulk_read == 0 || req->rq_bulk_write == 0); - /* special security flags accoding to opcode */ + /* special security flags according to opcode */ switch (opcode) { case OST_READ: case MDS_READPAGE: @@ -927,11 +963,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 +1139,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 +1192,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; @@ -1383,24 +1418,6 @@ void flavor_copy(struct sptlrpc_flavor *dst, struct sptlrpc_flavor *src) *dst = *src; } -static void sptlrpc_import_sec_adapt_inplace(struct obd_import *imp, - struct ptlrpc_sec *sec, - struct sptlrpc_flavor *sf) -{ - char str1[32], str2[32]; - - if (sec->ps_flvr.sf_flags != sf->sf_flags) - CDEBUG(D_SEC, "changing sec flags: %s -> %s\n", - sptlrpc_secflags2str(sec->ps_flvr.sf_flags, - str1, sizeof(str1)), - sptlrpc_secflags2str(sf->sf_flags, - str2, sizeof(str2))); - - spin_lock(&sec->ps_lock); - flavor_copy(&sec->ps_flvr, sf); - spin_unlock(&sec->ps_lock); -} - /** * To get an appropriate ptlrpc_sec for the \a imp, according to the current * configuration. Upon called, imp->imp_sec may or may not be NULL. @@ -1465,14 +1482,6 @@ int sptlrpc_import_sec_adapt(struct obd_import *imp, obd_uuid2str(&conn->c_remote_uuid), sptlrpc_flavor2name(&sec->ps_flvr, str, sizeof(str)), sptlrpc_flavor2name(&sf, str2, sizeof(str2))); - - if (SPTLRPC_FLVR_POLICY(sf.sf_rpc) == - SPTLRPC_FLVR_POLICY(sec->ps_flvr.sf_rpc) && - SPTLRPC_FLVR_MECH(sf.sf_rpc) == - SPTLRPC_FLVR_MECH(sec->ps_flvr.sf_rpc)) { - sptlrpc_import_sec_adapt_inplace(imp, sec, &sf); - GOTO(out, rc); - } } else if (SPTLRPC_FLVR_BASE(sf.sf_rpc) != SPTLRPC_FLVR_BASE(SPTLRPC_FLVR_NULL)) { CDEBUG(D_SEC, "import %s->%s netid %x: select flavor %s\n", @@ -2031,7 +2040,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