X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fptlrpc%2Fgss%2Fgss_svc_upcall.c;h=4b2d927816d339dcdd86cd53633369d916ee1cf3;hb=e2bd32ca75d60870a70cd3a00e8aac8efb751762;hp=b7f9b232c11612b70ff6744efb6aefb57ad04d01;hpb=0b868add80281c085ce1b297d1cb078deaab802a;p=fs%2Flustre-release.git diff --git a/lustre/ptlrpc/gss/gss_svc_upcall.c b/lustre/ptlrpc/gss/gss_svc_upcall.c index b7f9b23..4b2d927 100644 --- a/lustre/ptlrpc/gss/gss_svc_upcall.c +++ b/lustre/ptlrpc/gss/gss_svc_upcall.c @@ -60,9 +60,9 @@ #include #include #include -#include -#include #include +#include +#include #include #include "gss_err.h" @@ -132,7 +132,7 @@ static inline void _cache_unregister_net(struct cache_detail *cd, #endif } /**************************************** - * rsi cache * + * rpc sec init (rsi) cache * ****************************************/ #define RSI_HASHBITS (6) @@ -143,13 +143,18 @@ struct rsi { struct cache_head h; __u32 lustre_svc; __u64 nid; + char nm_name[LUSTRE_NODEMAP_NAME_LENGTH + 1]; wait_queue_head_t waitq; rawobj_t in_handle, in_token; rawobj_t out_handle, out_token; int major_status, minor_status; }; +#ifdef HAVE_CACHE_HEAD_HLIST +static struct hlist_head rsi_table[RSI_HASHMAX]; +#else static struct cache_head *rsi_table[RSI_HASHMAX]; +#endif static struct cache_detail rsi_cache; static struct rsi *rsi_update(struct rsi *new, struct rsi *old); static struct rsi *rsi_lookup(struct rsi *item); @@ -176,6 +181,7 @@ static void rsi_free(struct rsi *rsi) rawobj_free(&rsi->out_token); } +/* See handle_channel_req() userspace for where the upcall data is read */ static void rsi_request(struct cache_detail *cd, struct cache_head *h, char **bpp, int *blen) @@ -191,6 +197,8 @@ static void rsi_request(struct cache_detail *cd, sizeof(rsi->lustre_svc)); qword_addhex(bpp, blen, (char *) &rsi->nid, sizeof(rsi->nid)); qword_addhex(bpp, blen, (char *) &index, sizeof(index)); + qword_addhex(bpp, blen, (char *) rsi->nm_name, + strlen(rsi->nm_name) + 1); qword_addhex(bpp, blen, rsi->in_handle.data, rsi->in_handle.len); qword_addhex(bpp, blen, rsi->in_token.data, rsi->in_token.len); (*bpp)[-1] = '\n'; @@ -221,6 +229,7 @@ static inline void __rsi_init(struct rsi *new, struct rsi *item) new->lustre_svc = item->lustre_svc; new->nid = item->nid; + memcpy(new->nm_name, item->nm_name, sizeof(item->nm_name)); init_waitqueue_head(&new->waitq); } @@ -242,7 +251,11 @@ static void rsi_put(struct kref *ref) { struct rsi *rsi = container_of(ref, struct rsi, h.ref); - LASSERT(rsi->h.next == NULL); +#ifdef HAVE_CACHE_HEAD_HLIST + LASSERT(rsi->h.cache_list.next == NULL); +#else + LASSERT(rsi->h.next == NULL); +#endif rsi_free(rsi); OBD_FREE_PTR(rsi); } @@ -285,7 +298,6 @@ static struct cache_head *rsi_alloc(void) static int rsi_parse(struct cache_detail *cd, char *mesg, int mlen) { char *buf = mesg; - char *ep; int len; struct rsi rsii, *rsip = NULL; time_t expiry; @@ -327,18 +339,21 @@ static int rsi_parse(struct cache_detail *cd, char *mesg, int mlen) if (len <= 0) goto out; - /* major */ - rsii.major_status = simple_strtol(buf, &ep, 10); - if (*ep) - goto out; + /* major */ + status = kstrtoint(buf, 10, &rsii.major_status); + if (status) + goto out; - /* minor */ - len = qword_get(&mesg, buf, mlen); - if (len <= 0) - goto out; - rsii.minor_status = simple_strtol(buf, &ep, 10); - if (*ep) - goto out; + /* minor */ + len = qword_get(&mesg, buf, mlen); + if (len <= 0) { + status = -EINVAL; + goto out; + } + + status = kstrtoint(buf, 10, &rsii.minor_status); + if (status) + goto out; /* out_handle */ len = qword_get(&mesg, buf, mlen); @@ -416,7 +431,7 @@ static struct rsi *rsi_update(struct rsi *new, struct rsi *old) } /**************************************** - * rsc cache * + * rpc sec context (rsc) cache * ****************************************/ #define RSC_HASHBITS (10) @@ -430,7 +445,11 @@ struct rsc { struct gss_svc_ctx ctx; }; +#ifdef HAVE_CACHE_HEAD_HLIST +static struct hlist_head rsc_table[RSC_HASHMAX]; +#else static struct cache_head *rsc_table[RSC_HASHMAX]; +#endif static struct cache_detail rsc_cache; static struct rsc *rsc_update(struct rsc *new, struct rsc *old); static struct rsc *rsc_lookup(struct rsc *item); @@ -477,7 +496,11 @@ static void rsc_put(struct kref *ref) { struct rsc *rsci = container_of(ref, struct rsc, h.ref); +#ifdef HAVE_CACHE_HEAD_HLIST + LASSERT(rsci->h.cache_list.next == NULL); +#else LASSERT(rsci->h.next == NULL); +#endif rsc_free(rsci); OBD_FREE_PTR(rsci); } @@ -550,13 +573,13 @@ static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen) } rsci.ctx.gsc_remote = (tmp_int != 0); - /* root user flag */ - rv = get_int(&mesg, &tmp_int); - if (rv) { - CERROR("fail to get oss user flag\n"); - goto out; - } - rsci.ctx.gsc_usr_root = (tmp_int != 0); + /* root user flag */ + rv = get_int(&mesg, &tmp_int); + if (rv) { + CERROR("fail to get root user flag\n"); + goto out; + } + rsci.ctx.gsc_usr_root = (tmp_int != 0); /* mds user flag */ rv = get_int(&mesg, &tmp_int); @@ -593,41 +616,49 @@ static int rsc_parse(struct cache_detail *cd, char *mesg, int mlen) CERROR("NOENT? set rsc entry negative\n"); set_bit(CACHE_NEGATIVE, &rsci.h.flags); } else { - rawobj_t tmp_buf; - unsigned long ctx_expiry; - - /* gid */ - if (get_int(&mesg, (int *) &rsci.ctx.gsc_gid)) - goto out; - - /* mech name */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) - goto out; - gm = lgss_name_to_mech(buf); - status = -EOPNOTSUPP; - if (!gm) - goto out; - - status = -EINVAL; - /* mech-specific data: */ - len = qword_get(&mesg, buf, mlen); - if (len < 0) - goto out; - - tmp_buf.len = len; - tmp_buf.data = (unsigned char *)buf; - if (lgss_import_sec_context(&tmp_buf, gm, - &rsci.ctx.gsc_mechctx)) - goto out; - - /* currently the expiry time passed down from user-space - * is invalid, here we retrive it from mech. */ - if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) { - CERROR("unable to get expire time, drop it\n"); - goto out; - } - expiry = (time_t) ctx_expiry; + rawobj_t tmp_buf; + time64_t ctx_expiry; + + /* gid */ + if (get_int(&mesg, (int *) &rsci.ctx.gsc_gid)) + goto out; + + /* mech name */ + len = qword_get(&mesg, buf, mlen); + if (len < 0) + goto out; + gm = lgss_name_to_mech(buf); + status = -EOPNOTSUPP; + if (!gm) + goto out; + + status = -EINVAL; + /* mech-specific data: */ + len = qword_get(&mesg, buf, mlen); + if (len < 0) + goto out; + + tmp_buf.len = len; + tmp_buf.data = (unsigned char *)buf; + if (lgss_import_sec_context(&tmp_buf, gm, + &rsci.ctx.gsc_mechctx)) + goto out; + + /* set to seconds since machine booted */ + expiry = ktime_get_seconds(); + + /* currently the expiry time passed down from user-space + * is invalid, here we retrive it from mech. + */ + if (lgss_inquire_context(rsci.ctx.gsc_mechctx, &ctx_expiry)) { + CERROR("unable to get expire time, drop it\n"); + goto out; + } + + /* ctx_expiry is the number of seconds since Jan 1 1970. + * We want just the number of seconds into the future. + */ + expiry += ctx_expiry - ktime_get_real_seconds(); } rsci.h.expiry_time = expiry; @@ -693,24 +724,41 @@ typedef int rsc_entry_match(struct rsc *rscp, long data); static void rsc_flush(rsc_entry_match *match, long data) { - struct cache_head **ch; +#ifdef HAVE_CACHE_HEAD_HLIST + struct cache_head *ch = NULL; + struct hlist_head *head; +#else + struct cache_head **ch; +#endif struct rsc *rscp; int n; ENTRY; write_lock(&rsc_cache.hash_lock); for (n = 0; n < RSC_HASHMAX; n++) { - for (ch = &rsc_cache.hash_table[n]; *ch;) { - rscp = container_of(*ch, struct rsc, h); +#ifdef HAVE_CACHE_HEAD_HLIST + head = &rsc_cache.hash_table[n]; + hlist_for_each_entry(ch, head, cache_list) { + rscp = container_of(ch, struct rsc, h); +#else + for (ch = &rsc_cache.hash_table[n]; *ch;) { + rscp = container_of(*ch, struct rsc, h); +#endif if (!match(rscp, data)) { - ch = &((*ch)->next); +#ifndef HAVE_CACHE_HEAD_HLIST + ch = &((*ch)->next); +#endif continue; } /* it seems simply set NEGATIVE doesn't work */ - *ch = (*ch)->next; - rscp->h.next = NULL; +#ifdef HAVE_CACHE_HEAD_HLIST + hlist_del_init(&ch->cache_list); +#else + *ch = (*ch)->next; + rscp->h.next = NULL; +#endif cache_get(&rscp->h); set_bit(CACHE_NEGATIVE, &rscp->h.flags); COMPAT_RSC_PUT(&rscp->h, &rsc_cache); @@ -774,7 +822,7 @@ int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, struct gss_cli_ctx *gctx) { struct rsc rsci, *rscp = NULL; - unsigned long ctx_expiry; + time64_t ctx_expiry; __u32 major; int rc; ENTRY; @@ -800,12 +848,18 @@ int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, } rsci.h.expiry_time = (time_t) ctx_expiry; - if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_MDC_NAME) == 0) - rsci.ctx.gsc_usr_mds = 1; - else if (strcmp(imp->imp_obd->obd_type->typ_name, LUSTRE_OSC_NAME) == 0) - rsci.ctx.gsc_usr_oss = 1; - else - rsci.ctx.gsc_usr_root = 1; + switch (imp->imp_obd->u.cli.cl_sp_to) { + case LUSTRE_SP_MDT: + rsci.ctx.gsc_usr_mds = 1; + break; + case LUSTRE_SP_OST: + rsci.ctx.gsc_usr_oss = 1; + break; + case LUSTRE_SP_CLI: + rsci.ctx.gsc_usr_root = 1; + default: + break; + } rscp = rsc_update(&rsci, rscp); if (rscp == NULL) @@ -814,7 +868,7 @@ int gss_svc_upcall_install_rvs_ctx(struct obd_import *imp, rscp->target = imp->imp_obd; rawobj_dup(&gctx->gc_svc_handle, &rscp->handle); - CWARN("create reverse svc ctx %p to %s: idx "LPX64"\n", + CWARN("create reverse svc ctx %p to %s: idx %#llx\n", &rscp->ctx, obd2cli_tgt(imp->imp_obd), gsec->gs_rvs_hdl); rc = 0; out: @@ -823,22 +877,22 @@ out: rsc_free(&rsci); if (rc) - CERROR("create reverse svc ctx: idx "LPX64", rc %d\n", + CERROR("create reverse svc ctx: idx %#llx, rc %d\n", gsec->gs_rvs_hdl, rc); RETURN(rc); } int gss_svc_upcall_expire_rvs_ctx(rawobj_t *handle) { - const cfs_time_t expire = 20; - struct rsc *rscp; + const time64_t expire = 20; + struct rsc *rscp; rscp = gss_svc_searchbyctx(handle); if (rscp) { CDEBUG(D_SEC, "reverse svcctx %p (rsc %p) expire soon\n", &rscp->ctx, rscp); - rscp->h.expiry_time = cfs_time_current_sec() + expire; + rscp->h.expiry_time = ktime_get_real_seconds() + expire; COMPAT_RSC_PUT(&rscp->h, &rsc_cache); } return 0; @@ -883,16 +937,22 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req, struct ptlrpc_reply_state *rs; struct rsc *rsci = NULL; struct rsi *rsip = NULL, rsikey; - wait_queue_t wait; + wait_queue_entry_t wait; int replen = sizeof(struct ptlrpc_body); struct gss_rep_header *rephdr; int first_check = 1; int rc = SECSVC_DROP; ENTRY; - memset(&rsikey, 0, sizeof(rsikey)); - rsikey.lustre_svc = lustre_svc; - rsikey.nid = (__u64) req->rq_peer.nid; + memset(&rsikey, 0, sizeof(rsikey)); + rsikey.lustre_svc = lustre_svc; + /* In case of MR, rq_peer is not the NID from which request is received, + * but primary NID of peer. + * So we need rq_source, which contains the NID actually in use. + */ + rsikey.nid = (__u64) req->rq_source.nid; + nodemap_test_nid(req->rq_peer.nid, rsikey.nm_name, + sizeof(rsikey.nm_name)); /* duplicate context handle. for INIT it always 0 */ if (rawobj_dup(&rsikey.in_handle, &gw->gw_handle)) { @@ -919,7 +979,7 @@ int gss_svc_upcall_handle_init(struct ptlrpc_request *req, cache_get(&rsip->h); /* take an extra ref */ init_waitqueue_head(&rsip->waitq); - init_waitqueue_entry_current(&wait); + init_waitqueue_entry(&wait, current); add_wait_queue(&rsip->waitq, &wait); cache_check: @@ -930,16 +990,16 @@ cache_check: switch (rc) { case -ETIMEDOUT: case -EAGAIN: { - int valid; + int valid; - if (first_check) { - first_check = 0; + if (first_check) { + first_check = 0; - read_lock(&rsi_cache.hash_lock); + read_lock(&rsi_cache.hash_lock); valid = test_bit(CACHE_VALID, &rsip->h.flags); - if (valid == 0) + if (valid == 0) set_current_state(TASK_INTERRUPTIBLE); - read_unlock(&rsi_cache.hash_lock); + read_unlock(&rsi_cache.hash_lock); if (valid == 0) { unsigned long jiffies; @@ -949,16 +1009,16 @@ cache_check: } cache_get(&rsip->h); goto cache_check; - } - CWARN("waited %ds timeout, drop\n", GSS_SVC_UPCALL_TIMEOUT); - break; - } - case -ENOENT: - CWARN("cache_check return ENOENT, drop\n"); - break; - case 0: - /* if not the first check, we have to release the extra - * reference we just added on it. */ + } + CWARN("waited %ds timeout, drop\n", GSS_SVC_UPCALL_TIMEOUT); + break; + } + case -ENOENT: + CDEBUG(D_SEC, "cache_check return ENOENT, drop\n"); + break; + case 0: + /* if not the first check, we have to release the extra + * reference we just added on it. */ if (!first_check) cache_put(&rsip->h, &rsi_cache); CDEBUG(D_SEC, "cache_check is good\n"); @@ -976,8 +1036,11 @@ cache_check: if (!rsci) { CERROR("authentication failed\n"); - if (!gss_pack_err_notify(req, GSS_S_FAILURE, 0)) - rc = SECSVC_COMPLETE; + /* gss mechanism returned major and minor code so we return + * those in error message */ + if (!gss_pack_err_notify(req, rsip->major_status, + rsip->minor_status)) + rc = SECSVC_COMPLETE; GOTO(out, rc); } else { @@ -1035,24 +1098,23 @@ cache_check: rc = SECSVC_OK; out: - /* it looks like here we should put rsip also, but this mess up - * with NFS cache mgmt code... FIXME */ -#if 0 - if (rsip) - rsi_put(&rsip->h, &rsi_cache); -#endif - - if (rsci) { - /* if anything went wrong, we don't keep the context too */ - if (rc != SECSVC_OK) + /* it looks like here we should put rsip also, but this mess up + * with NFS cache mgmt code... FIXME + * something like: + * if (rsip) + * rsi_put(&rsip->h, &rsi_cache); */ + + if (rsci) { + /* if anything went wrong, we don't keep the context too */ + if (rc != SECSVC_OK) set_bit(CACHE_NEGATIVE, &rsci->h.flags); - else - CDEBUG(D_SEC, "create rsc with idx "LPX64"\n", - gss_handle_to_u64(&rsci->handle)); + else + CDEBUG(D_SEC, "create rsc with idx %#llx\n", + gss_handle_to_u64(&rsci->handle)); - COMPAT_RSC_PUT(&rsci->h, &rsc_cache); - } - RETURN(rc); + COMPAT_RSC_PUT(&rsci->h, &rsc_cache); + } + RETURN(rc); } struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req, @@ -1062,7 +1124,7 @@ struct gss_svc_ctx *gss_svc_upcall_get_ctx(struct ptlrpc_request *req, rsc = gss_svc_searchbyctx(&gw->gw_handle); if (!rsc) { - CWARN("Invalid gss ctx idx "LPX64" from %s\n", + CWARN("Invalid gss ctx idx %#llx from %s\n", gss_handle_to_u64(&gw->gw_handle), libcfs_nid2str(req->rq_peer.nid)); return NULL; @@ -1114,13 +1176,14 @@ int __init gss_init_svc_upcall(void) /* FIXME this looks stupid. we intend to give lsvcgssd a chance to open * the init upcall channel, otherwise there's big chance that the first * upcall issued before the channel be opened thus nfsv4 cache code will - * drop the request direclty, thus lead to unnecessary recovery time. - * here we wait at miximum 1.5 seconds. */ + * drop the request directly, thus lead to unnecessary recovery time. + * Here we wait at minimum 1.5 seconds. + */ for (i = 0; i < 6; i++) { if (atomic_read(&rsi_cache.readers) > 0) break; set_current_state(TASK_UNINTERRUPTIBLE); - LASSERT(msecs_to_jiffies(MSEC_PER_SEC) >= 4); + LASSERT(msecs_to_jiffies(MSEC_PER_SEC / 4) > 0); schedule_timeout(msecs_to_jiffies(MSEC_PER_SEC / 4)); }