+ /* If sec is provided, we must use the existing context for root that
+ * it references. If not root, or no existing context, or same context,
+ * just fail replacing the dead context.
+ */
+ if (sec) {
+ newctx = get_my_ctx(sec, true);
+ if (!newctx)
+ GOTO(restore, rc = -EINVAL);
+ if (IS_ERR(newctx))
+ GOTO(restore, rc = PTR_ERR(newctx));
+ if (newctx == oldctx) {
+ sptlrpc_cli_ctx_put(newctx, 0);
+ GOTO(restore, rc = -ENODATA);
+ }
+ /* Because we are replacing an erroneous ctx, new sec ctx is
+ * expected to have higher imp generation or same imp generation
+ * but higher imp connection count.
+ */
+ if (newctx->cc_impgen < oldctx->cc_impgen ||
+ (newctx->cc_impgen == oldctx->cc_impgen &&
+ newctx->cc_impconncnt <= oldctx->cc_impconncnt))
+ CERROR("ctx (%p, fl %lx) will switch, but does not look more recent than old ctx: imp gen %d vs %d, imp conn cnt %d vs %d\n",
+ newctx, newctx->cc_flags,
+ newctx->cc_impgen, oldctx->cc_impgen,
+ newctx->cc_impconncnt, oldctx->cc_impconncnt);
+ req->rq_cli_ctx = newctx;
+ } else {
+ rc = sptlrpc_req_get_ctx(req);
+ if (unlikely(rc)) {
+ LASSERT(!req->rq_cli_ctx);