return ctx->cc_ops->display(ctx, buf, bufsize);
}
-static int sptlrpc_import_sec_check_expire(struct obd_import *imp)
+static int import_sec_check_expire(struct obd_import *imp)
{
int adapt = 0;
return sptlrpc_import_sec_adapt(imp, NULL, 0);
}
-int sptlrpc_req_get_ctx(struct ptlrpc_request *req)
+static int import_sec_validate_get(struct obd_import *imp,
+ struct ptlrpc_sec **sec)
{
- struct obd_import *imp = req->rq_import;
- struct ptlrpc_sec *sec;
- int rc;
- ENTRY;
-
- LASSERT(!req->rq_cli_ctx);
- LASSERT(imp);
+ int rc;
if (unlikely(imp->imp_sec_expire)) {
- rc = sptlrpc_import_sec_check_expire(imp);
+ rc = import_sec_check_expire(imp);
if (rc)
- RETURN(rc);
+ return rc;
}
- sec = sptlrpc_import_sec_ref(imp);
- if (sec == NULL) {
- CERROR("import %p (%s) with no ptlrpc_sec\n",
+ *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);
+ return -EACCES;
}
- if (unlikely(sec->ps_dying)) {
+ if (unlikely((*sec)->ps_dying)) {
CERROR("attempt to use dying sec %p\n", sec);
+ sptlrpc_sec_put(*sec);
return -EACCES;
}
+ return 0;
+}
+
+int sptlrpc_req_get_ctx(struct ptlrpc_request *req)
+{
+ struct obd_import *imp = req->rq_import;
+ struct ptlrpc_sec *sec;
+ int rc;
+ ENTRY;
+
+ LASSERT(!req->rq_cli_ctx);
+ LASSERT(imp);
+
+ rc = import_sec_validate_get(imp, &sec);
+ if (rc)
+ RETURN(rc);
+
req->rq_cli_ctx = get_my_ctx(sec);
sptlrpc_sec_put(sec);
return rc;
}
-/*
+/**
+ * if current context has died, or if we resend after flavor switched,
+ * call this func to switch context. if no switch is needed, request
+ * will end up with the same context.
+ *
* request must have a context. in any case of failure, restore the
- * restore the old one. a request must have a ctx.
+ * restore the old one - a request must have a context.
*/
int sptlrpc_req_replace_dead_ctx(struct ptlrpc_request *req)
{
ENTRY;
LASSERT(oldctx);
- LASSERT(test_bit(PTLRPC_CTX_DEAD_BIT, &oldctx->cc_flags));
sptlrpc_cli_ctx_get(oldctx);
sptlrpc_req_put_ctx(req, 0);
LASSERT(newctx);
if (unlikely(newctx == oldctx)) {
- /*
- * still get the old ctx, usually means system busy
- */
- CWARN("ctx (%p, fl %lx) doesn't switch, relax a little bit\n",
- newctx, newctx->cc_flags);
-
- cfs_schedule_timeout(CFS_TASK_INTERRUPTIBLE, HZ);
+ if (test_bit(PTLRPC_CTX_DEAD_BIT, &oldctx->cc_flags)) {
+ /*
+ * still get the old ctx, usually means system busy
+ */
+ CWARN("ctx (%p, fl %lx) doesn't switch, "
+ "relax a little bit\n",
+ newctx, newctx->cc_flags);
+
+ cfs_schedule_timeout(CFS_TASK_INTERRUPTIBLE, HZ);
+ }
} else {
rc = sptlrpc_req_ctx_switch(req, oldctx, newctx);
if (rc) {
int sptlrpc_req_refresh_ctx(struct ptlrpc_request *req, long timeout)
{
struct ptlrpc_cli_ctx *ctx = req->rq_cli_ctx;
+ struct ptlrpc_sec *sec;
struct l_wait_info lwi;
int rc;
ENTRY;
LASSERT(ctx);
+ if (req->rq_ctx_init || req->rq_ctx_fini)
+ RETURN(0);
+
/*
* during the process a request's context might change type even
* (e.g. from gss ctx to plain ctx), so each loop we need to re-check
* everything
*/
again:
- /* skip special ctxs */
- if (cli_ctx_is_eternal(ctx) || req->rq_ctx_init || req->rq_ctx_fini)
+ rc = import_sec_validate_get(req->rq_import, &sec);
+ if (rc)
+ RETURN(rc);
+
+ if (sec->ps_flvr.sf_rpc != req->rq_flvr.sf_rpc)
+ sptlrpc_req_replace_dead_ctx(req);
+
+ sptlrpc_sec_put(sec);
+
+ if (cli_ctx_is_eternal(ctx))
RETURN(0);
- if (test_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags)) {
+ if (unlikely(test_bit(PTLRPC_CTX_NEW_BIT, &ctx->cc_flags))) {
LASSERT(ctx->cc_ops->refresh);
ctx->cc_ops->refresh(ctx);
}
}
if (unlikely(test_bit(PTLRPC_CTX_DEAD_BIT, &ctx->cc_flags))) {
+ /*
+ * don't switch ctx if import was deactivated
+ */
+ if (req->rq_import->imp_deactive) {
+ req_off_ctx_list(req, ctx);
+ req->rq_err = 1;
+ RETURN(-EINTR);
+ }
+
rc = sptlrpc_req_replace_dead_ctx(req);
if (rc) {
LASSERT(ctx == req->rq_cli_ctx);
list_add(&req->rq_ctx_chain, &ctx->cc_req_list);
spin_unlock(&ctx->cc_lock);
- if (timeout < 0) {
+ if (timeout < 0)
RETURN(-EWOULDBLOCK);
- }
/* Clear any flags that may be present from previous sends */
LASSERT(req->rq_receiving_reply == 0);
sptlrpc_sec_put(sec);
if (!ctx)
- RETURN(1);
+ RETURN(-ENOMEM);
if (cli_ctx_is_eternal(ctx) ||
ctx->cc_ops->validate(ctx) == 0) {
RETURN(0);
}
+ if (cli_ctx_is_error(ctx)) {
+ sptlrpc_cli_ctx_put(ctx, 1);
+ RETURN(-EACCES);
+ }
+
OBD_ALLOC_PTR(req);
if (!req)
RETURN(-ENOMEM);
CFS_INIT_LIST_HEAD(&req->rq_ctx_chain);
cfs_waitq_init(&req->rq_reply_waitq);
req->rq_import = imp;
+ req->rq_flvr = sec->ps_flvr;
req->rq_cli_ctx = ctx;
rc = sptlrpc_req_refresh_ctx(req, 0);
enum lustre_sec_part sp;
int rc;
+ might_sleep();
+
if (imp == NULL)
return 0;
conn = imp->imp_connection;
if (svc_ctx == NULL) {
+ struct client_obd *cliobd = &imp->imp_obd->u.cli;
/* normal import, determine flavor from rule set */
- sptlrpc_rule_set_choose(&imp->imp_obd->u.cli.cl_sptlrpc_rset,
- LUSTRE_SP_ANY, conn->c_self, &sf);
+ sptlrpc_conf_choose_flavor(cliobd->cl_sp_me, cliobd->cl_sp_to,
+ &cliobd->cl_target_uuid,
+ conn->c_self, &sf);
- sp = imp->imp_obd->u.cli.cl_sec_part;
+ sp = imp->imp_obd->u.cli.cl_sp_me;
} else {
/* reverse import, determine flavor from incoming reqeust */
sf.sf_rpc = rpc_flavor;
spin_unlock(&exp->exp_lock);
- CWARN("req %p: (%u|%u|%u|%u|%u) with unauthorized flavor %x\n",
+ CWARN("exp %p(%s): req %p (%u|%u|%u|%u|%u) with "
+ "unauthorized flavor %x, expect %x|%x(%+ld)|%x(%+ld)\n",
+ exp, exp->exp_obd->obd_name,
req, req->rq_auth_gss, req->rq_ctx_init, req->rq_ctx_fini,
- req->rq_auth_usr_root, req->rq_auth_usr_mdt, req->rq_flvr.sf_rpc);
+ req->rq_auth_usr_root, req->rq_auth_usr_mdt, req->rq_flvr.sf_rpc,
+ exp->exp_flvr.sf_rpc,
+ exp->exp_flvr_old[0].sf_rpc,
+ exp->exp_flvr_expire[0] ?
+ (unsigned long) (exp->exp_flvr_expire[0] -
+ cfs_time_current_sec()) : 0,
+ exp->exp_flvr_old[1].sf_rpc,
+ exp->exp_flvr_expire[1] ?
+ (unsigned long) (exp->exp_flvr_expire[1] -
+ cfs_time_current_sec()) : 0);
return -EACCES;
}
+EXPORT_SYMBOL(sptlrpc_target_export_check);
void sptlrpc_target_update_exp_flavor(struct obd_device *obd,
struct sptlrpc_rule_set *rset)
* (exp_flvr_changed == 1), this will override the
* previous one. */
spin_lock(&exp->exp_lock);
- sptlrpc_rule_set_choose(rset, exp->exp_sp_peer,
- exp->exp_connection->c_peer.nid,
- &new_flvr);
+ sptlrpc_target_choose_flavor(rset, exp->exp_sp_peer,
+ exp->exp_connection->c_peer.nid,
+ &new_flvr);
if (exp->exp_flvr_changed ||
memcmp(&new_flvr, &exp->exp_flvr, sizeof(new_flvr))) {
exp->exp_flvr_old[1] = new_flvr;
exp->exp_flvr_expire[1] = 0;
exp->exp_flvr_changed = 1;
exp->exp_flvr_adapt = 1;
+
CDEBUG(D_SEC, "exp %p (%s): updated flavor %x->%x\n",
exp, sptlrpc_part2name(exp->exp_sp_peer),
exp->exp_flvr.sf_rpc,
case LUSTRE_SP_CLI:
case LUSTRE_SP_MDT:
case LUSTRE_SP_OST:
+ case LUSTRE_SP_MGC:
case LUSTRE_SP_MGS:
case LUSTRE_SP_ANY:
break;
rwlock_init(&policy_lock);
- rc = sptlrpc_gc_start_thread();
+ rc = sptlrpc_gc_init();
if (rc)
goto out;
- rc = sptlrpc_enc_pool_init();
+ rc = sptlrpc_conf_init();
if (rc)
goto out_gc;
+ rc = sptlrpc_enc_pool_init();
+ if (rc)
+ goto out_conf;
+
rc = sptlrpc_null_init();
if (rc)
goto out_pool;
sptlrpc_null_fini();
out_pool:
sptlrpc_enc_pool_fini();
+out_conf:
+ sptlrpc_conf_fini();
out_gc:
- sptlrpc_gc_stop_thread();
+ sptlrpc_gc_fini();
out:
return rc;
}
sptlrpc_plain_fini();
sptlrpc_null_fini();
sptlrpc_enc_pool_fini();
- sptlrpc_gc_stop_thread();
+ sptlrpc_conf_fini();
+ sptlrpc_gc_fini();
}