- struct ptlrpc_request *req)
-{
- struct sptlrpc_flavor flavor;
-
- if (exp == NULL)
- return 0;
-
- /* client side export has no imp_reverse, skip
- * FIXME maybe we should check flavor this as well??? */
- if (exp->exp_imp_reverse == NULL)
- return 0;
-
- /* don't care about ctx fini rpc */
- if (req->rq_ctx_fini)
- return 0;
-
- spin_lock(&exp->exp_lock);
-
- /* if flavor just changed (exp->exp_flvr_changed != 0), we wait for
- * the first req with the new flavor, then treat it as current flavor,
- * adapt reverse sec according to it.
- * note the first rpc with new flavor might not be with root ctx, in
- * which case delay the sec_adapt by leaving exp_flvr_adapt == 1. */
- if (unlikely(exp->exp_flvr_changed) &&
- flavor_allowed(&exp->exp_flvr_old[1], req)) {
- /* make the new flavor as "current", and old ones as
- * about-to-expire */
- CDEBUG(D_SEC, "exp %p: just changed: %x->%x\n", exp,
- exp->exp_flvr.sf_rpc, exp->exp_flvr_old[1].sf_rpc);
- flavor = exp->exp_flvr_old[1];
- exp->exp_flvr_old[1] = exp->exp_flvr_old[0];
- exp->exp_flvr_expire[1] = exp->exp_flvr_expire[0];
- exp->exp_flvr_old[0] = exp->exp_flvr;
- exp->exp_flvr_expire[0] = cfs_time_current_sec() +
- EXP_FLVR_UPDATE_EXPIRE;
- exp->exp_flvr = flavor;
-
- /* flavor change finished */
- exp->exp_flvr_changed = 0;
- LASSERT(exp->exp_flvr_adapt == 1);
-
- /* if it's gss, we only interested in root ctx init */
- if (req->rq_auth_gss &&
- !(req->rq_ctx_init && (req->rq_auth_usr_root ||
- req->rq_auth_usr_mdt))) {
- spin_unlock(&exp->exp_lock);
- CDEBUG(D_SEC, "is good but not root(%d:%d:%d:%d)\n",
- req->rq_auth_gss, req->rq_ctx_init,
- req->rq_auth_usr_root, req->rq_auth_usr_mdt);
- return 0;
- }
-
- exp->exp_flvr_adapt = 0;
- spin_unlock(&exp->exp_lock);
-
- return sptlrpc_import_sec_adapt(exp->exp_imp_reverse,
- req->rq_svc_ctx, flavor.sf_rpc);
- }
-
- /* if it equals to the current flavor, we accept it, but need to
- * dealing with reverse sec/ctx */
- if (likely(flavor_allowed(&exp->exp_flvr, req))) {
- /* most cases should return here, we only interested in
- * gss root ctx init */
- if (!req->rq_auth_gss || !req->rq_ctx_init ||
- (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt)) {
- spin_unlock(&exp->exp_lock);
- return 0;
- }
-
- /* if flavor just changed, we should not proceed, just leave
- * it and current flavor will be discovered and replaced
- * shortly, and let _this_ rpc pass through */
- if (exp->exp_flvr_changed) {
- LASSERT(exp->exp_flvr_adapt);
- spin_unlock(&exp->exp_lock);
- return 0;
- }
-
- if (exp->exp_flvr_adapt) {
- exp->exp_flvr_adapt = 0;
- CDEBUG(D_SEC, "exp %p (%x|%x|%x): do delayed adapt\n",
- exp, exp->exp_flvr.sf_rpc,
- exp->exp_flvr_old[0].sf_rpc,
- exp->exp_flvr_old[1].sf_rpc);
- flavor = exp->exp_flvr;
- spin_unlock(&exp->exp_lock);
-
- return sptlrpc_import_sec_adapt(exp->exp_imp_reverse,
- req->rq_svc_ctx,
- flavor.sf_rpc);
- } else {
- CDEBUG(D_SEC, "exp %p (%x|%x|%x): is current flavor, "
- "install rvs ctx\n", exp, exp->exp_flvr.sf_rpc,
- exp->exp_flvr_old[0].sf_rpc,
- exp->exp_flvr_old[1].sf_rpc);
- spin_unlock(&exp->exp_lock);
-
- return sptlrpc_svc_install_rvs_ctx(exp->exp_imp_reverse,
- req->rq_svc_ctx);
- }
- }
-
- if (exp->exp_flvr_expire[0]) {
- if (exp->exp_flvr_expire[0] >= cfs_time_current_sec()) {
- if (flavor_allowed(&exp->exp_flvr_old[0], req)) {
- CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the "
- "middle one ("CFS_DURATION_T")\n", exp,
- exp->exp_flvr.sf_rpc,
- exp->exp_flvr_old[0].sf_rpc,
- exp->exp_flvr_old[1].sf_rpc,
- exp->exp_flvr_expire[0] -
- cfs_time_current_sec());
- spin_unlock(&exp->exp_lock);
- return 0;
- }
- } else {
- CDEBUG(D_SEC, "mark middle expired\n");
- exp->exp_flvr_expire[0] = 0;
- }
- CDEBUG(D_SEC, "exp %p (%x|%x|%x): %x not match middle\n", exp,
- exp->exp_flvr.sf_rpc,
- exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc,
- req->rq_flvr.sf_rpc);
- }
-
- /* now it doesn't match the current flavor, the only chance we can
- * accept it is match the old flavors which is not expired. */
- if (exp->exp_flvr_changed == 0 && exp->exp_flvr_expire[1]) {
- if (exp->exp_flvr_expire[1] >= cfs_time_current_sec()) {
- if (flavor_allowed(&exp->exp_flvr_old[1], req)) {
- CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the "
- "oldest one ("CFS_DURATION_T")\n", exp,
- exp->exp_flvr.sf_rpc,
- exp->exp_flvr_old[0].sf_rpc,
- exp->exp_flvr_old[1].sf_rpc,
- exp->exp_flvr_expire[1] -
- cfs_time_current_sec());
- spin_unlock(&exp->exp_lock);
- return 0;
- }
- } else {
- CDEBUG(D_SEC, "mark oldest expired\n");
- exp->exp_flvr_expire[1] = 0;
- }
- CDEBUG(D_SEC, "exp %p (%x|%x|%x): %x not match found\n",
- exp, exp->exp_flvr.sf_rpc,
- exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc,
- req->rq_flvr.sf_rpc);
- } else {
- CDEBUG(D_SEC, "exp %p (%x|%x|%x): skip the last one\n",
- exp, exp->exp_flvr.sf_rpc, exp->exp_flvr_old[0].sf_rpc,
- exp->exp_flvr_old[1].sf_rpc);
- }
-
- spin_unlock(&exp->exp_lock);
-
- CWARN("req %p: (%u|%u|%u|%u|%u) with unauthorized flavor %x\n",
- 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);
- return -EACCES;
-}
+ struct ptlrpc_request *req)
+{
+ struct sptlrpc_flavor flavor;
+
+ if (exp == NULL)
+ return 0;
+
+ /*
+ * client side export has no imp_reverse, skip
+ * FIXME maybe we should check flavor this as well???
+ */
+ if (exp->exp_imp_reverse == NULL)
+ return 0;
+
+ /* don't care about ctx fini rpc */
+ if (req->rq_ctx_fini)
+ return 0;
+
+ spin_lock(&exp->exp_lock);
+
+ /*
+ * if flavor just changed (exp->exp_flvr_changed != 0), we wait for
+ * the first req with the new flavor, then treat it as current flavor,
+ * adapt reverse sec according to it.
+ * note the first rpc with new flavor might not be with root ctx, in
+ * which case delay the sec_adapt by leaving exp_flvr_adapt == 1.
+ */
+ if (unlikely(exp->exp_flvr_changed) &&
+ flavor_allowed(&exp->exp_flvr_old[1], req)) {
+ /*
+ * make the new flavor as "current", and old ones as
+ * about-to-expire
+ */
+ CDEBUG(D_SEC, "exp %p: just changed: %x->%x\n", exp,
+ exp->exp_flvr.sf_rpc, exp->exp_flvr_old[1].sf_rpc);
+ flavor = exp->exp_flvr_old[1];
+ exp->exp_flvr_old[1] = exp->exp_flvr_old[0];
+ exp->exp_flvr_expire[1] = exp->exp_flvr_expire[0];
+ exp->exp_flvr_old[0] = exp->exp_flvr;
+ exp->exp_flvr_expire[0] = ktime_get_real_seconds() +
+ EXP_FLVR_UPDATE_EXPIRE;
+ exp->exp_flvr = flavor;
+
+ /* flavor change finished */
+ exp->exp_flvr_changed = 0;
+ LASSERT(exp->exp_flvr_adapt == 1);
+
+ /* if it's gss, we only interested in root ctx init */
+ if (req->rq_auth_gss &&
+ !(req->rq_ctx_init &&
+ (req->rq_auth_usr_root || req->rq_auth_usr_mdt ||
+ req->rq_auth_usr_ost))) {
+ spin_unlock(&exp->exp_lock);
+ CDEBUG(D_SEC, "is good but not root(%d:%d:%d:%d:%d)\n",
+ req->rq_auth_gss, req->rq_ctx_init,
+ req->rq_auth_usr_root, req->rq_auth_usr_mdt,
+ req->rq_auth_usr_ost);
+ return 0;
+ }
+
+ exp->exp_flvr_adapt = 0;
+ spin_unlock(&exp->exp_lock);
+
+ return sptlrpc_import_sec_adapt(exp->exp_imp_reverse,
+ req->rq_svc_ctx, &flavor);
+ }
+
+ /*
+ * if it equals to the current flavor, we accept it, but need to
+ * dealing with reverse sec/ctx
+ */
+ if (likely(flavor_allowed(&exp->exp_flvr, req))) {
+ /*
+ * most cases should return here, we only interested in
+ * gss root ctx init
+ */
+ if (!req->rq_auth_gss || !req->rq_ctx_init ||
+ (!req->rq_auth_usr_root && !req->rq_auth_usr_mdt &&
+ !req->rq_auth_usr_ost)) {
+ spin_unlock(&exp->exp_lock);
+ return 0;
+ }
+
+ /*
+ * if flavor just changed, we should not proceed, just leave
+ * it and current flavor will be discovered and replaced
+ * shortly, and let _this_ rpc pass through
+ */
+ if (exp->exp_flvr_changed) {
+ LASSERT(exp->exp_flvr_adapt);
+ spin_unlock(&exp->exp_lock);
+ return 0;
+ }
+
+ if (exp->exp_flvr_adapt) {
+ exp->exp_flvr_adapt = 0;
+ CDEBUG(D_SEC, "exp %p (%x|%x|%x): do delayed adapt\n",
+ exp, exp->exp_flvr.sf_rpc,
+ exp->exp_flvr_old[0].sf_rpc,
+ exp->exp_flvr_old[1].sf_rpc);
+ flavor = exp->exp_flvr;
+ spin_unlock(&exp->exp_lock);
+
+ return sptlrpc_import_sec_adapt(exp->exp_imp_reverse,
+ req->rq_svc_ctx,
+ &flavor);
+ } else {
+ CDEBUG(D_SEC,
+ "exp %p (%x|%x|%x): is current flavor, install rvs ctx\n",
+ exp, exp->exp_flvr.sf_rpc,
+ exp->exp_flvr_old[0].sf_rpc,
+ exp->exp_flvr_old[1].sf_rpc);
+ spin_unlock(&exp->exp_lock);
+
+ return sptlrpc_svc_install_rvs_ctx(exp->exp_imp_reverse,
+ req->rq_svc_ctx);
+ }
+ }
+
+ if (exp->exp_flvr_expire[0]) {
+ if (exp->exp_flvr_expire[0] >= ktime_get_real_seconds()) {
+ if (flavor_allowed(&exp->exp_flvr_old[0], req)) {
+ CDEBUG(D_SEC,
+ "exp %p (%x|%x|%x): match the middle one (%lld)\n",
+ exp, exp->exp_flvr.sf_rpc,
+ exp->exp_flvr_old[0].sf_rpc,
+ exp->exp_flvr_old[1].sf_rpc,
+ (s64)(exp->exp_flvr_expire[0] -
+ ktime_get_real_seconds()));
+ spin_unlock(&exp->exp_lock);
+ return 0;
+ }
+ } else {
+ CDEBUG(D_SEC, "mark middle expired\n");
+ exp->exp_flvr_expire[0] = 0;
+ }
+ CDEBUG(D_SEC, "exp %p (%x|%x|%x): %x not match middle\n", exp,
+ exp->exp_flvr.sf_rpc,
+ exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc,
+ req->rq_flvr.sf_rpc);
+ }
+
+ /*
+ * now it doesn't match the current flavor, the only chance we can
+ * accept it is match the old flavors which is not expired.
+ */
+ if (exp->exp_flvr_changed == 0 && exp->exp_flvr_expire[1]) {
+ if (exp->exp_flvr_expire[1] >= ktime_get_real_seconds()) {
+ if (flavor_allowed(&exp->exp_flvr_old[1], req)) {
+ CDEBUG(D_SEC, "exp %p (%x|%x|%x): match the oldest one (%lld)\n",
+ exp,
+ exp->exp_flvr.sf_rpc,
+ exp->exp_flvr_old[0].sf_rpc,
+ exp->exp_flvr_old[1].sf_rpc,
+ (s64)(exp->exp_flvr_expire[1] -
+ ktime_get_real_seconds()));
+ spin_unlock(&exp->exp_lock);
+ return 0;
+ }
+ } else {
+ CDEBUG(D_SEC, "mark oldest expired\n");
+ exp->exp_flvr_expire[1] = 0;
+ }
+ CDEBUG(D_SEC, "exp %p (%x|%x|%x): %x not match found\n",
+ exp, exp->exp_flvr.sf_rpc,
+ exp->exp_flvr_old[0].sf_rpc, exp->exp_flvr_old[1].sf_rpc,
+ req->rq_flvr.sf_rpc);
+ } else {
+ CDEBUG(D_SEC, "exp %p (%x|%x|%x): skip the last one\n",
+ exp, exp->exp_flvr.sf_rpc, exp->exp_flvr_old[0].sf_rpc,
+ exp->exp_flvr_old[1].sf_rpc);
+ }
+
+ spin_unlock(&exp->exp_lock);
+
+ CWARN("exp %p(%s): req %p (%u|%u|%u|%u|%u|%u) with unauthorized flavor %x, expect %x|%x(%+lld)|%x(%+lld)\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_auth_usr_ost,
+ req->rq_flvr.sf_rpc,
+ exp->exp_flvr.sf_rpc,
+ exp->exp_flvr_old[0].sf_rpc,
+ exp->exp_flvr_expire[0] ?
+ (s64)(exp->exp_flvr_expire[0] - ktime_get_real_seconds()) : 0,
+ exp->exp_flvr_old[1].sf_rpc,
+ exp->exp_flvr_expire[1] ?
+ (s64)(exp->exp_flvr_expire[1] - ktime_get_real_seconds()) : 0);
+ return -EACCES;
+}
+EXPORT_SYMBOL(sptlrpc_target_export_check);