+ /* write temporary log */
+ rc = llog_create(ctxt, &llh, NULL, LOG_SPTLRPC_TMP);
+ if (rc)
+ GOTO(out_dput, rc);
+ rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
+ if (rc)
+ GOTO(out_close, rc);
+
+ rc = sptlrpc_record_rules(llh, conf);
+
+out_close:
+ llog_close(llh);
+
+ if (rc == 0) {
+ rc = lustre_rename(dentry, obd->obd_lvfs_ctxt.pwdmnt,
+ LOG_SPTLRPC_TMP, LOG_SPTLRPC);
+ }
+
+out_dput:
+ l_dput(dentry);
+out_ctx:
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ llog_ctxt_put(ctxt);
+ CDEBUG(D_SEC, "target %s: write local sptlrpc conf: rc = %d\n",
+ obd->obd_name, rc);
+ RETURN(rc);
+}
+
+static int local_read_handler(struct llog_handle *llh,
+ struct llog_rec_hdr *rec,
+ void *data)
+{
+ struct sptlrpc_conf *conf = (struct sptlrpc_conf *) data;
+ struct lustre_cfg *lcfg = (struct lustre_cfg *)(rec + 1);
+ int cfg_len, rc;
+ ENTRY;
+
+ if (rec->lrh_type != OBD_CFG_REC) {
+ CERROR("unhandled lrh_type: %#x\n", rec->lrh_type);
+ RETURN(-EINVAL);
+ }
+
+ cfg_len = rec->lrh_len - sizeof(struct llog_rec_hdr) -
+ sizeof(struct llog_rec_tail);
+
+ rc = lustre_cfg_sanity_check(lcfg, cfg_len);
+ if (rc) {
+ CERROR("Insane cfg\n");
+ RETURN(rc);
+ }
+
+ if (lcfg->lcfg_command != LCFG_SPTLRPC_CONF) {
+ CERROR("invalid command (%x)\n", lcfg->lcfg_command);
+ RETURN(-EINVAL);
+ }
+
+ RETURN(__sptlrpc_process_config(lcfg, conf));
+}
+
+static
+int sptlrpc_target_local_read_conf(struct obd_device *obd,
+ struct sptlrpc_conf *conf)
+{
+ struct llog_handle *llh = NULL;
+ struct llog_ctxt *ctxt;
+ struct lvfs_run_ctxt saved;
+ int rc;
+ ENTRY;
+
+ LASSERT(conf->sc_updated == 0 && conf->sc_local == 0);
+
+ ctxt = llog_get_context(obd, LLOG_CONFIG_ORIG_CTXT);
+ if (ctxt == NULL) {
+ CERROR("missing llog context\n");
+ RETURN(-EINVAL);
+ }
+
+ push_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+
+ rc = llog_create(ctxt, &llh, NULL, LOG_SPTLRPC);
+ if (rc)
+ GOTO(out_pop, rc);
+
+ rc = llog_init_handle(llh, LLOG_F_IS_PLAIN, NULL);
+ if (rc)
+ GOTO(out_close, rc);
+
+ if (llog_get_size(llh) <= 1) {
+ CDEBUG(D_SEC, "no local sptlrpc copy found\n");
+ GOTO(out_close, rc = 0);
+ }
+
+ rc = llog_process(llh, local_read_handler, (void *) conf, NULL);
+
+ if (rc == 0) {
+ conf->sc_local = 1;
+ } else {
+ sptlrpc_conf_free_rsets(conf);
+ }
+
+out_close:
+ llog_close(llh);
+out_pop:
+ pop_ctxt(&saved, &obd->obd_lvfs_ctxt, NULL);
+ llog_ctxt_put(ctxt);
+ CDEBUG(D_SEC, "target %s: read local sptlrpc conf: rc = %d\n",
+ obd->obd_name, rc);
+ RETURN(rc);
+}
+
+#endif /* __KRENEL__ */
+
+/**
+ * called by target devices, extract sptlrpc rules which applies to
+ * this target, to be used for future rpc flavor checking.
+ */
+int sptlrpc_conf_target_get_rules(struct obd_device *obd,
+ struct sptlrpc_rule_set *rset,
+ int initial)
+{
+ struct sptlrpc_conf *conf;
+ struct sptlrpc_conf_tgt *conf_tgt;
+ enum lustre_sec_part sp_dst;
+ char fsname[MTI_NAME_MAXLEN];
+ int rc = 0;
+ ENTRY;
+
+ if (strcmp(obd->obd_type->typ_name, LUSTRE_MDT_NAME) == 0) {
+ sp_dst = LUSTRE_SP_MDT;
+ } else if (strcmp(obd->obd_type->typ_name, LUSTRE_OST_NAME) == 0) {
+ sp_dst = LUSTRE_SP_OST;
+ } else {
+ CERROR("unexpected obd type %s\n", obd->obd_type->typ_name);
+ RETURN(-EINVAL);
+ }
+ CDEBUG(D_SEC, "get rules for target %s\n", obd->obd_uuid.uuid);
+
+ target2fsname(obd->obd_uuid.uuid, fsname, sizeof(fsname));
+
+ mutex_lock(&sptlrpc_conf_lock);
+
+ conf = sptlrpc_conf_get(fsname, 0);
+ if (conf == NULL) {
+ CERROR("missing sptlrpc config log\n");
+ GOTO(out, rc);
+ }
+
+#ifdef __KERNEL__
+ if (conf->sc_updated == 0) {
+ /*
+ * always read from local copy. here another option is
+ * if we already have a local copy (read from another
+ * target device hosted on the same node) we simply use that.
+ */
+ if (conf->sc_local)
+ sptlrpc_conf_free_rsets(conf);
+
+ sptlrpc_target_local_read_conf(obd, conf);
+ } else {
+ LASSERT(conf->sc_local == 0);
+
+ /* write a local copy */
+ if (initial || conf->sc_modified)
+ sptlrpc_target_local_copy_conf(obd, conf);
+ else
+ CDEBUG(D_SEC, "unchanged, skip updating local copy\n");
+ }
+#endif
+
+ /* extract rule set for this target */
+ conf_tgt = sptlrpc_conf_get_tgt(conf, obd->obd_name, 0);
+
+ rc = sptlrpc_rule_set_extract(&conf->sc_rset,
+ conf_tgt ? &conf_tgt->sct_rset: NULL,
+ LUSTRE_SP_ANY, sp_dst, rset);
+out:
+ mutex_unlock(&sptlrpc_conf_lock);
+ RETURN(rc);
+}
+EXPORT_SYMBOL(sptlrpc_conf_target_get_rules);