support gss on mgc-mgs connection.
b=16054
r=umka
r=vitaly
int lmd_exclude_count;
char *lmd_dev; /* device name */
char *lmd_profile; /* client only */
+ char *lmd_mgssec; /* sptlrpc flavor to mgs */
char *lmd_opts; /* lustre mount options (as opposed to
_device_ mount options) */
__u32 *lmd_exclude; /* array of OSTs to ignore */
SPTLRPC_MECH_GSS_KRB5, \
SPTLRPC_SVC_PRIV)
-#define SPTLRPC_FLVR_INVALID ((__u16) -1)
+#define SPTLRPC_FLVR_ANY ((__u16) 0xf000)
+#define SPTLRPC_FLVR_INVALID ((__u16) 0xffff)
#define SPTLRPC_FLVR_DEFAULT SPTLRPC_FLVR_NULL
struct sptlrpc_rule *srs_rules;
};
+int sptlrpc_parse_flavor(const char *str, struct sptlrpc_flavor *flvr);
+
static inline void sptlrpc_rule_set_init(struct sptlrpc_rule_set *set)
{
memset(set, 0, sizeof(*set));
int sptlrpc_rule_set_merge(struct sptlrpc_rule_set *set,
struct sptlrpc_rule *rule,
int expand);
+int sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
+ enum lustre_sec_part from,
+ enum lustre_sec_part to,
+ lnet_nid_t nid,
+ struct sptlrpc_flavor *sf);
void sptlrpc_rule_set_dump(struct sptlrpc_rule_set *set);
int sptlrpc_process_config(struct lustre_cfg *lcfg);
enum lustre_sec_part cl_sp_me;
enum lustre_sec_part cl_sp_to;
+ struct sptlrpc_flavor cl_flvr_mgc; /* fixed flavor of mgc->mgs */
//struct llog_canceld_ctxt *cl_llcd; /* it's included by obd_llog_ctxt */
void *cl_llcd_offset;
#define KEY_BLOCKSIZE_BITS "blocksize_bits"
#define KEY_FIEMAP "FIEMAP"
#define KEY_SPTLRPC_CONF "sptlrpc_conf"
+#define KEY_MGSSEC "mgssec"
/* XXX unused ?*/
#define KEY_INTERMDS "inter_mds"
#define KEY_ASYNC "async"
connect_op = MGS_CONNECT;
cli->cl_sp_me = LUSTRE_SP_MGC;
cli->cl_sp_to = LUSTRE_SP_MGS;
+ cli->cl_flvr_mgc.sf_rpc = SPTLRPC_FLVR_INVALID;
} else {
CERROR("unknown client OBD type \"%s\", can't setup\n",
name);
exp->exp_sp_peer = req->rq_sp_from;
exp->exp_flvr = flvr;
- if (exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+ if (exp->exp_flvr.sf_rpc != SPTLRPC_FLVR_ANY &&
+ exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
CERROR("unauthorized rpc flavor %x from %s, "
"expect %x\n", req->rq_flvr.sf_rpc,
libcfs_nid2str(req->rq_peer.nid),
/* Stop watching for updates on this log. */
static int config_log_end(char *logname, struct config_llog_instance *cfg)
{
- struct config_llog_data *cld, *cld_sptlrpc;
+ struct config_llog_data *cld, *cld_sptlrpc = NULL;
int rc = 0;
ENTRY;
cld = config_log_find(logname, cfg);
if (IS_ERR(cld))
RETURN(PTR_ERR(cld));
- /* drop the ref from the find */
- config_log_put(cld);
down(&llog_process_lock);
+ /*
+ * if cld_stopping is set, it means we didn't start the log thus
+ * not owning the start ref. this can happen after previous umount:
+ * the cld still hanging there waiting for lock cancel, and we
+ * remount again but failed in the middle and call log_end without
+ * calling start_log.
+ */
+ if (unlikely(cld->cld_stopping)) {
+ up(&llog_process_lock);
+ /* drop the ref from the find */
+ config_log_put(cld);
+ RETURN(rc);
+ }
+
cld->cld_stopping = 1;
up(&llog_process_lock);
if (cld_sptlrpc)
config_log_put(cld_sptlrpc);
+ /* drop the ref from the find */
+ config_log_put(cld);
/* drop the start ref */
config_log_put(cld);
+
CDEBUG(D_MGC, "end config log %s (%d)\n", logname ? logname : "client",
rc);
RETURN(rc);
lprocfs_mgc_init_vars(&lvars);
lprocfs_obd_setup(obd, lvars.obd_vars);
+ sptlrpc_lprocfs_cliobd_attach(obd);
spin_lock(&config_list_lock);
atomic_inc(&mgc_count);
rc = mgc_set_mgs_param(exp, msp);
RETURN(rc);
}
+ if (KEY_IS(KEY_MGSSEC)) {
+ struct client_obd *cli = &exp->exp_obd->u.cli;
+ struct sptlrpc_flavor flvr;
+
+ /*
+ * empty string means using current flavor, if which haven't
+ * been set yet, set it as null.
+ *
+ * if flavor has been set previously, check the asking flavor
+ * must match the existing one.
+ */
+ if (vallen == 0) {
+ if (cli->cl_flvr_mgc.sf_rpc != SPTLRPC_FLVR_INVALID)
+ RETURN(0);
+ val = "null";
+ vallen = 4;
+ }
+
+ rc = sptlrpc_parse_flavor(val, &flvr);
+ if (rc) {
+ CERROR("invalid sptlrpc flavor %s to MGS\n",
+ (char *) val);
+ RETURN(rc);
+ }
+
+ /*
+ * caller already hold a mutex
+ */
+ if (cli->cl_flvr_mgc.sf_rpc == SPTLRPC_FLVR_INVALID) {
+ cli->cl_flvr_mgc = flvr;
+ } else if (memcmp(&cli->cl_flvr_mgc, &flvr,
+ sizeof(flvr)) != 0) {
+ char str[20];
+
+ sptlrpc_flavor2name(&cli->cl_flvr_mgc,
+ str, sizeof(str));
+ LCONSOLE_ERROR("asking sptlrpc flavor %s to MGS but "
+ "currently %s is in use\n",
+ (char *) val, str);
+ rc = -EPERM;
+ }
+ RETURN(rc);
+ }
RETURN(rc);
}
LPROC_SEQ_FOPS_RO(mgs_fs);
+static void seq_show_srpc_rules(struct seq_file *seq, const char *tgtname,
+ struct sptlrpc_rule_set *rset)
+{
+ struct sptlrpc_rule *r;
+ char dirbuf[10];
+ char flvrbuf[40];
+ char *net;
+ int i;
+
+ for (i = 0; i < rset->srs_nrule; i++) {
+ r = &rset->srs_rules[i];
+
+ if (r->sr_netid == LNET_NIDNET(LNET_NID_ANY))
+ net = "default";
+ else
+ net = libcfs_net2str(r->sr_netid);
+
+ if (r->sr_from == LUSTRE_SP_ANY && r->sr_to == LUSTRE_SP_ANY)
+ dirbuf[0] = '\0';
+ else
+ snprintf(dirbuf, sizeof(dirbuf), ".%s2%s",
+ sptlrpc_part2name(r->sr_from),
+ sptlrpc_part2name(r->sr_to));
+
+ sptlrpc_flavor2name(&r->sr_flvr, flvrbuf, sizeof(flvrbuf));
+ seq_printf(seq, "%s.srpc.flavor.%s%s=%s\n", tgtname,
+ net, dirbuf, flvrbuf);
+ }
+}
+
+static int mgsself_srpc_seq_show(struct seq_file *seq, void *v)
+{
+ struct obd_device *obd = seq->private;
+ struct fs_db *fsdb;
+ int rc;
+
+ rc = mgs_find_or_make_fsdb(obd, MGSSELF_NAME, &fsdb);
+ if (rc)
+ return rc;
+
+ down(&fsdb->fsdb_sem);
+ seq_show_srpc_rules(seq, fsdb->fsdb_name, &fsdb->fsdb_srpc_gen);
+ up(&fsdb->fsdb_sem);
+ return 0;
+}
+
+LPROC_SEQ_FOPS_RO(mgsself_srpc);
+
int lproc_mgs_setup(struct obd_device *obd)
{
struct mgs_obd *mgs = &obd->u.mgs;
rc = lprocfs_obd_seq_create(obd, "filesystems", 0444,
&mgs_fs_fops, obd);
+ rc = lprocfs_obd_seq_create(obd, "srpc_rules", 0600,
+ &mgsself_srpc_fops, obd);
mgs->mgs_proc_live = lprocfs_register("live", obd->obd_proc_entry,
NULL, NULL);
return lprocfs_obd_cleanup(obd);
}
-static void seq_show_srpc_rule(struct seq_file *seq, const char *tgtname,
- struct sptlrpc_rule_set *rset)
-{
- struct sptlrpc_rule *r;
- char dirbuf[10];
- char flvrbuf[40];
- char *net;
- int i;
-
- for (i = 0; i < rset->srs_nrule; i++) {
- r = &rset->srs_rules[i];
-
- if (r->sr_netid == LNET_NIDNET(LNET_NID_ANY))
- net = "default";
- else
- net = libcfs_net2str(r->sr_netid);
-
- if (r->sr_from == LUSTRE_SP_ANY && r->sr_to == LUSTRE_SP_ANY)
- dirbuf[0] = '\0';
- else
- snprintf(dirbuf, sizeof(dirbuf), ".%s2%s",
- sptlrpc_part2name(r->sr_from),
- sptlrpc_part2name(r->sr_to));
-
- sptlrpc_flavor2name(&r->sr_flvr, flvrbuf, sizeof(flvrbuf));
- seq_printf(seq, "%s.srpc.flavor.%s%s=%s\n", tgtname,
- net, dirbuf, flvrbuf);
- }
-}
-
static int mgs_live_seq_show(struct seq_file *seq, void *v)
{
struct fs_db *fsdb = seq->private;
#endif
for (srpc_tgt = fsdb->fsdb_srpc_tgt; srpc_tgt;
srpc_tgt = srpc_tgt->mtsc_next) {
- seq_show_srpc_rule(seq, srpc_tgt->mtsc_tgt,
- &srpc_tgt->mtsc_rset);
+ seq_show_srpc_rules(seq, srpc_tgt->mtsc_tgt,
+ &srpc_tgt->mtsc_rset);
}
- seq_show_srpc_rule(seq, fsdb->fsdb_name, &fsdb->fsdb_srpc_gen);
+ seq_show_srpc_rules(seq, fsdb->fsdb_name, &fsdb->fsdb_srpc_gen);
up(&fsdb->fsdb_sem);
return 0;
exp = class_conn2export(conn);
LASSERT(exp);
- exp->exp_flvr.sf_rpc = SPTLRPC_FLVR_NULL;
-
mgs_counter_incr(exp, LPROC_MGS_CONNECT);
if (data != NULL) {
RETURN(rc);
}
+/*
+ * similar as in ost_connect_check_sptlrpc()
+ */
+static int mgs_connect_check_sptlrpc(struct ptlrpc_request *req)
+{
+ struct obd_export *exp = req->rq_export;
+ struct obd_device *obd = exp->exp_obd;
+ struct fs_db *fsdb;
+ struct sptlrpc_flavor flvr;
+ int rc = 0;
+
+ if (exp->exp_flvr.sf_rpc == SPTLRPC_FLVR_INVALID) {
+ rc = mgs_find_or_make_fsdb(obd, MGSSELF_NAME, &fsdb);
+ if (rc)
+ return rc;
+
+ down(&fsdb->fsdb_sem);
+ if (sptlrpc_rule_set_choose(&fsdb->fsdb_srpc_gen,
+ LUSTRE_SP_MGC, LUSTRE_SP_MGS,
+ req->rq_peer.nid,
+ &flvr) == 0) {
+ /* by defualt allow any flavors */
+ flvr.sf_rpc = SPTLRPC_FLVR_ANY;
+ }
+ up(&fsdb->fsdb_sem);
+
+ spin_lock(&exp->exp_lock);
+
+ exp->exp_sp_peer = req->rq_sp_from;
+ exp->exp_flvr = flvr;
+
+ if (exp->exp_flvr.sf_rpc != SPTLRPC_FLVR_ANY &&
+ exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+ CERROR("invalid rpc flavor %x, expect %x, from %s\n",
+ req->rq_flvr.sf_rpc, exp->exp_flvr.sf_rpc,
+ libcfs_nid2str(req->rq_peer.nid));
+ rc = -EACCES;
+ }
+
+ spin_unlock(&exp->exp_lock);
+ } else {
+ if (exp->exp_sp_peer != req->rq_sp_from) {
+ CERROR("RPC source %s doesn't match %s\n",
+ sptlrpc_part2name(req->rq_sp_from),
+ sptlrpc_part2name(exp->exp_sp_peer));
+ rc = -EACCES;
+ } else {
+ rc = sptlrpc_target_export_check(exp, req);
+ }
+ }
+
+ return rc;
+}
+
/* Called whenever a target cleans up. */
/* XXX - Currently unused */
static int mgs_handle_target_del(struct ptlrpc_request *req)
LASSERT(current->journal_info == NULL);
opc = lustre_msg_get_opc(req->rq_reqmsg);
+
+ if (opc == SEC_CTX_INIT ||
+ opc == SEC_CTX_INIT_CONT ||
+ opc == SEC_CTX_FINI)
+ GOTO(out, rc = 0);
+
if (opc != MGS_CONNECT) {
if (req->rq_export == NULL) {
CERROR("lustre_mgs: operation %d on unconnected MGS\n",
/* MGS and MDS have same request format for connect */
req_capsule_set(&req->rq_pill, &RQF_MDS_CONNECT);
rc = target_handle_connect(req);
+ if (rc == 0)
+ rc = mgs_connect_check_sptlrpc(req);
+
if (!rc && (lustre_msg_get_conn_cnt(req->rq_reqmsg) > 1))
/* Make clients trying to reconnect after a MGS restart
happy; also requires obd_replayable */
struct vfsmount *inmnt,
struct list_head *dentry_list);
+#define MGSSELF_NAME "_mgs"
+
struct mgs_tgt_srpc_conf {
struct mgs_tgt_srpc_conf *mtsc_next;
char *mtsc_tgt;
/* in-memory copy of the srpc rules, guarded by fsdb_sem */
struct sptlrpc_rule_set fsdb_srpc_gen;
struct mgs_tgt_srpc_conf *fsdb_srpc_tgt;
- unsigned int fsdb_srpc_fl_udesc:1;
+ unsigned int fsdb_fl_udesc:1,
+ fsdb_fl_mgsself:1;
};
int mgs_init_fsdb_list(struct obd_device *obd);
int mgs_cleanup_fsdb_list(struct obd_device *obd);
+int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
+ struct fs_db **dbh);
int mgs_get_fsdb_srpc_from_llog(struct obd_device *obd, struct fs_db *fsdb);
int mgs_check_index(struct obd_device *obd, struct mgs_target_info *mti);
int mgs_check_failnid(struct obd_device *obd, struct mgs_target_info *mti);
int rc;
ENTRY;
+ if (strlen(fsname) >= sizeof(fsdb->fsdb_name)) {
+ CERROR("fsname %s is too long\n", fsname);
+ RETURN(NULL);
+ }
+
OBD_ALLOC_PTR(fsdb);
if (!fsdb)
RETURN(NULL);
- OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
- OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
- if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
- CERROR("No memory for index maps\n");
- GOTO(err, 0);
- }
+ strcpy(fsdb->fsdb_name, fsname);
+ sema_init(&fsdb->fsdb_sem, 1);
+ fsdb->fsdb_fl_udesc = 1;
- strncpy(fsdb->fsdb_name, fsname, sizeof(fsdb->fsdb_name));
- fsdb->fsdb_name[sizeof(fsdb->fsdb_name) - 1] = 0;
- rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
- if (rc)
- GOTO(err, rc);
- rc = name_create(&fsdb->fsdb_mdtlmv, fsname, "-mdtlmv");
- if (rc)
- GOTO(err, rc);
- rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
- if (rc)
- GOTO(err, rc);
+ if (strcmp(fsname, MGSSELF_NAME) == 0) {
+ fsdb->fsdb_fl_mgsself = 1;
+ } else {
+ OBD_ALLOC(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
+ OBD_ALLOC(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
+ if (!fsdb->fsdb_ost_index_map || !fsdb->fsdb_mdt_index_map) {
+ CERROR("No memory for index maps\n");
+ GOTO(err, 0);
+ }
- rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
- if (rc)
- GOTO(err, rc);
+ rc = name_create(&fsdb->fsdb_mdtlov, fsname, "-mdtlov");
+ if (rc)
+ GOTO(err, rc);
+ rc = name_create(&fsdb->fsdb_mdtlmv, fsname, "-mdtlmv");
+ if (rc)
+ GOTO(err, rc);
+ rc = name_create(&fsdb->fsdb_clilov, fsname, "-clilov");
+ if (rc)
+ GOTO(err, rc);
+ rc = name_create(&fsdb->fsdb_clilmv, fsname, "-clilmv");
+ if (rc)
+ GOTO(err, rc);
+
+ lproc_mgs_add_live(obd, fsdb);
+ }
- fsdb->fsdb_srpc_fl_udesc = 1;
- sema_init(&fsdb->fsdb_sem, 1);
list_add(&fsdb->fsdb_list, &mgs->mgs_fs_db_list);
- lproc_mgs_add_live(obd, fsdb);
RETURN(fsdb);
err:
down(&fsdb->fsdb_sem);
lproc_mgs_del_live(obd, fsdb);
list_del(&fsdb->fsdb_list);
- OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
- OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
+ if (fsdb->fsdb_ost_index_map)
+ OBD_FREE(fsdb->fsdb_ost_index_map, INDEX_MAP_SIZE);
+ if (fsdb->fsdb_mdt_index_map)
+ OBD_FREE(fsdb->fsdb_mdt_index_map, INDEX_MAP_SIZE);
name_destroy(&fsdb->fsdb_clilov);
name_destroy(&fsdb->fsdb_clilmv);
name_destroy(&fsdb->fsdb_mdtlov);
return 0;
}
-static int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
- struct fs_db **dbh)
+int mgs_find_or_make_fsdb(struct obd_device *obd, char *name,
+ struct fs_db **dbh)
{
struct mgs_obd *mgs = &obd->u.mgs;
struct fs_db *fsdb;
if (!fsdb)
return -ENOMEM;
- /* populate the db from the client llog */
- rc = mgs_get_fsdb_from_llog(obd, fsdb);
- if (rc) {
- CERROR("Can't get db from client log %d\n", rc);
- mgs_free_fsdb(obd, fsdb);
- return rc;
+ if (!fsdb->fsdb_fl_mgsself) {
+ /* populate the db from the client llog */
+ rc = mgs_get_fsdb_from_llog(obd, fsdb);
+ if (rc) {
+ CERROR("Can't get db from client log %d\n", rc);
+ mgs_free_fsdb(obd, fsdb);
+ return rc;
+ }
}
/* populate srpc rules from params llog */
goto error_out;
if (strcmp(ptr, "yes") == 0) {
- fsdb->fsdb_srpc_fl_udesc = 1;
+ fsdb->fsdb_fl_udesc = 1;
CWARN("Enable user descriptor shipping from client to MDT\n");
} else if (strcmp(ptr, "no") == 0) {
- fsdb->fsdb_srpc_fl_udesc = 0;
+ fsdb->fsdb_fl_udesc = 0;
CWARN("Disable user descriptor shipping from client to MDT\n");
} else {
*(ptr - 1) = '=';
if (rc)
RETURN(rc);
+ /* mgs rules implies must be mgc->mgs */
+ if (fsdb->fsdb_fl_mgsself) {
+ if ((rule.sr_from != LUSTRE_SP_MGC &&
+ rule.sr_from != LUSTRE_SP_ANY) ||
+ (rule.sr_to != LUSTRE_SP_MGS &&
+ rule.sr_to != LUSTRE_SP_ANY))
+ RETURN(-EINVAL);
+ }
+
/* preapre room for this coming rule. svcname format should be:
* - fsname: general rule
* - fsname-tgtname: target-specific rule
/* previous steps guaranteed the syntax is correct */
rc = mgs_srpc_set_param_disk(obd, fsdb, mti, copy);
+ if (rc)
+ goto out_free;
+
+ if (fsdb->fsdb_fl_mgsself) {
+ /*
+ * for mgs rules, make them effective immediately.
+ */
+ LASSERT(fsdb->fsdb_srpc_tgt == NULL);
+ sptlrpc_target_update_exp_flavor(obd, &fsdb->fsdb_srpc_gen);
+ }
+
out_free:
OBD_FREE(copy, copy_size);
RETURN(rc);
rc = mgs_find_or_make_fsdb(obd, fsname, &fsdb);
if (rc)
RETURN(rc);
- if (fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
+ if (!fsdb->fsdb_fl_mgsself && fsdb->fsdb_flags & FSDB_LOG_EMPTY) {
CERROR("No filesystem targets for %s. cfg_device from lctl "
"is '%s'\n", fsname, devname);
mgs_free_fsdb(obd, fsdb);
struct obd_uuid *uuid;
class_uuid_t uuidc;
lnet_nid_t nid;
- char *mgcname, *niduuid;
+ char *mgcname, *niduuid, *mgssec;
char *ptr;
int recov_bk;
int rc = 0, i = 0, j, len;
GOTO(out_free, rc = -ENOMEM);
sprintf(mgcname, "%s%s", LUSTRE_MGC_OBDNAME, libcfs_nid2str(nid));
+ mgssec = lsi->lsi_lmd->lmd_mgssec ? lsi->lsi_lmd->lmd_mgssec : "";
+
mutex_down(&mgc_start_lock);
obd = class_name2obd(mgcname);
if (obd && !obd->obd_stopping) {
+ rc = obd_set_info_async(obd->obd_self_export,
+ strlen(KEY_MGSSEC), KEY_MGSSEC,
+ strlen(mgssec), mgssec, NULL);
+ if (rc)
+ GOTO(out_free, rc);
+
/* Re-using an existing MGC */
atomic_inc(&obd->u.cli.cl_mgc_refcount);
GOTO(out_free, rc = -ENOTCONN);
}
+ rc = obd_set_info_async(obd->obd_self_export,
+ strlen(KEY_MGSSEC), KEY_MGSSEC,
+ strlen(mgssec), mgssec, NULL);
+ if (rc)
+ GOTO(out_free, rc);
+
/* Keep a refcount of servers/clients who started with "mount",
so we know when we can get rid of the mgc. */
atomic_set(&obd->u.cli.cl_mgc_refcount, 1);
if (lsi->lsi_lmd->lmd_profile != NULL)
OBD_FREE(lsi->lsi_lmd->lmd_profile,
strlen(lsi->lsi_lmd->lmd_profile) + 1);
+ if (lsi->lsi_lmd->lmd_mgssec != NULL)
+ OBD_FREE(lsi->lsi_lmd->lmd_mgssec,
+ strlen(lsi->lsi_lmd->lmd_mgssec) + 1);
if (lsi->lsi_lmd->lmd_opts != NULL)
OBD_FREE(lsi->lsi_lmd->lmd_opts,
strlen(lsi->lsi_lmd->lmd_opts) + 1);
}
/* Start MGS before MGC */
- if (IS_MGS(lsi->lsi_ldd) && !(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOMGS)) {
+ if (IS_MGS(lsi->lsi_ldd) && !(lsi->lsi_lmd->lmd_flags & LMD_FLG_NOMGS)){
rc = server_start_mgs(sb);
if (rc)
GOTO(out_mnt, rc);
RETURN(rc);
}
+static int lmd_parse_mgssec(struct lustre_mount_data *lmd, char *ptr)
+{
+ char *tail;
+ int length;
+
+ if (lmd->lmd_mgssec != NULL) {
+ OBD_FREE(lmd->lmd_mgssec, strlen(lmd->lmd_mgssec) + 1);
+ lmd->lmd_mgssec = NULL;
+ }
+
+ tail = strchr(ptr, ',');
+ if (tail == NULL)
+ length = strlen(ptr);
+ else
+ length = tail - ptr;
+
+ OBD_ALLOC(lmd->lmd_mgssec, length + 1);
+ if (lmd->lmd_mgssec == NULL)
+ return -ENOMEM;
+
+ memcpy(lmd->lmd_mgssec, ptr, length);
+ lmd->lmd_mgssec[length] = '\0';
+ return 0;
+}
+
/* mount -v -t lustre uml1:uml2:/lustre-client /mnt/lustre */
static int lmd_parse(char *options, struct lustre_mount_data *lmd)
{
} else if (strncmp(s1, "nomgs", 5) == 0) {
lmd->lmd_flags |= LMD_FLG_NOMGS;
clear++;
+ } else if (strncmp(s1, "mgssec=", 7) == 0) {
+ rc = lmd_parse_mgssec(lmd, s1 + 7);
+ if (rc)
+ goto invalid;
+ clear++;
/* ost exclusion list */
} else if (strncmp(s1, "exclude=", 8) == 0) {
rc = lmd_make_exclusion(lmd, s1 + 7);
exp->exp_sp_peer = req->rq_sp_from;
exp->exp_flvr = flvr;
- if (exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
+ if (exp->exp_flvr.sf_rpc != SPTLRPC_FLVR_ANY &&
+ exp->exp_flvr.sf_rpc != req->rq_flvr.sf_rpc) {
CERROR("unauthorized rpc flavor %x from %s, "
"expect %x\n", req->rq_flvr.sf_rpc,
libcfs_nid2str(req->rq_peer.nid),
};
enum ptlrpc_gss_tgt {
- LUSTRE_GSS_TGT_MDS = 0,
- LUSTRE_GSS_TGT_OSS = 1,
- LUSTRE_GSS_TGT_MGS = 2,
+ LUSTRE_GSS_TGT_MGS = 0,
+ LUSTRE_GSS_TGT_MDS = 1,
+ LUSTRE_GSS_TGT_OSS = 2,
};
enum ptlrpc_gss_header_flags {
{
const char *name = imp->imp_obd->obd_type->typ_name;
+ if (!strcmp(name, LUSTRE_MGC_NAME))
+ return LUSTRE_GSS_TGT_MGS;
if (!strcmp(name, LUSTRE_MDC_NAME))
return LUSTRE_GSS_TGT_MDS;
if (!strcmp(name, LUSTRE_OSC_NAME))
if (svc_ctx == NULL) {
struct client_obd *cliobd = &imp->imp_obd->u.cli;
- /* normal import, determine flavor from rule set */
- sptlrpc_conf_choose_flavor(cliobd->cl_sp_me, cliobd->cl_sp_to,
- &cliobd->cl_target_uuid,
- conn->c_self, &sf);
+ /*
+ * normal import, determine flavor from rule set, except
+ * for mgc the flavor is predetermined.
+ */
+ if (cliobd->cl_sp_me == LUSTRE_SP_MGC)
+ sf = cliobd->cl_flvr_mgc;
+ else
+ 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_sp_me;
} else {
{
struct sptlrpc_flavor *flvr = &req->rq_flvr;
- if (exp->sf_rpc == flvr->sf_rpc)
+ if (exp->sf_rpc == SPTLRPC_FLVR_ANY || exp->sf_rpc == flvr->sf_rpc)
return 1;
if ((req->rq_ctx_init || req->rq_ctx_fini) &&
* krb5i-bulkp
* krb5i-bulkp:sha512/arc4
*/
-static int parse_flavor(const char *str, struct sptlrpc_flavor *flvr)
+int sptlrpc_parse_flavor(const char *str, struct sptlrpc_flavor *flvr)
{
const char *f;
char *bulk, *alg, *enc;
CERROR("invalid flavor string: %s\n", str);
return -EINVAL;
}
+EXPORT_SYMBOL(sptlrpc_parse_flavor);
/****************************************
* configure rules *
}
/* 2.1 flavor */
- rc = parse_flavor(flavor, &rule->sr_flvr);
+ rc = sptlrpc_parse_flavor(flavor, &rule->sr_flvr);
if (rc)
RETURN(-EINVAL);
* given from/to/nid, determine a matching flavor in ruleset.
* return 1 if a match found, otherwise return 0.
*/
-static int sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
- enum lustre_sec_part from,
- enum lustre_sec_part to,
- lnet_nid_t nid,
- struct sptlrpc_flavor *sf)
+int sptlrpc_rule_set_choose(struct sptlrpc_rule_set *rset,
+ enum lustre_sec_part from,
+ enum lustre_sec_part to,
+ lnet_nid_t nid,
+ struct sptlrpc_flavor *sf)
{
struct sptlrpc_rule *r;
int n;
return 0;
}
+EXPORT_SYMBOL(sptlrpc_rule_set_choose);
void sptlrpc_rule_set_dump(struct sptlrpc_rule_set *rset)
{
RETURN(-EINVAL);
}
+ CDEBUG(D_SEC, "got one rule: %s.%s\n", target, param);
+
/* parse rule to make sure the format is correct */
if (strncmp(param, PARAM_SRPC_FLVR, sizeof(PARAM_SRPC_FLVR) - 1) != 0) {
CERROR("Invalid sptlrpc parameter: %s\n", param);
cnt_all2mdt=0
cnt_all2all=0
DBENCH_PID=0
-PROC_CLI="srpc.info"
-# Escape "." to use lctl
-PROC_CLI=${PROC_CLI//\./\*}
+PROC_CLI="srpc_info"
# set manually
GSS=true
echo $cnt;
}
+flvr_cnt_mgc2mgs()
+{
+ local flavor=$1
+
+ output=`do_facet client lctl get_param -n mgc.*.$PROC_CLI 2>/dev/null`
+ count_flvr "$output" $flavor
+}
+
do_check_flavor()
{
local dir=$1 # from to
chmod 0777 $DIR || error "chmod $DIR failed"
# access w/o cred
$RUNAS kdestroy
+ $RUNAS $LFS flushctx || error "can't flush ctx"
$RUNAS touch $file && error "unexpected success"
# access w/ cred
}
run_test 102 "survive from insanely fast flavor switch"
+test_150() {
+ local save_opts
+
+ # started from default flavors
+ restore_to_default_flavor
+
+ # at this time no rules has been set on mgs; mgc use null
+ # flavor connect to mgs.
+ count=`flvr_cnt_mgc2mgs null`
+ [ $count -eq 1 ] || error "$count mgc connection use null flavor"
+
+ # umount both clients
+ zconf_umount $HOSTNAME $MOUNT || return 1
+ zconf_umount $HOSTNAME $MOUNT2 || return 2
+
+ # mount client with default flavor - should succeed
+ zconf_mount $HOSTNAME $MOUNT || error "mount with default flavor should have succeeded"
+ zconf_umount $HOSTNAME $MOUNT || return 5
+
+ # mount client with conflict flavor - should fail
+ save_opts=$MOUNTOPT
+ MOUNTOPT="$MOUNTOPT,mgssec=krb5p"
+ zconf_mount $HOSTNAME $MOUNT && error "mount with conflict flavor should have failed"
+ MOUNTOPT=$save_opts
+
+ # mount client with same flavor - should succeed
+ save_opts=$MOUNTOPT
+ MOUNTOPT="$MOUNTOPT,mgssec=null"
+ zconf_mount $HOSTNAME $MOUNT || error "mount with same flavor should have succeeded"
+ zconf_umount $HOSTNAME $MOUNT || return 6
+ MOUNTOPT=$save_opts
+}
+run_test 150 "secure mgs connection: client flavor setting"
+
+test_151() {
+ local save_opts
+
+ # set mgs only accept krb5p
+ set_rule _mgs any any krb5p
+
+ # umount everything, modules still loaded
+ stopall
+
+ # mount mgs with default flavor, in current framework it means mgs+mdt1.
+ # the connection of mgc of mdt1 to mgs is expected fail.
+ DEVNAME=$(mdsdevname 1)
+ start mds1 $DEVNAME $MDS_MOUNT_OPTS && error "mount with default flavor should have failed"
+
+ # mount with unauthorized flavor should fail
+ save_opts=$MDS_MOUNT_OPTS
+ MDS_MOUNT_OPTS="$MDS_MOUNT_OPTS,mgssec=null"
+ start mds1 $DEVNAME $MDS_MOUNT_OPTS && error "mount with unauthorized flavor should have failed"
+ MDS_MOUNT_OPTS=$save_opts
+
+ # mount with designated flavor should succeed
+ save_opts=$MDS_MOUNT_OPTS
+ MDS_MOUNT_OPTS="$MDS_MOUNT_OPTS,mgssec=krb5p"
+ start mds1 $DEVNAME $MDS_MOUNT_OPTS || error "mount with designated flavor should have succeeded"
+ MDS_MOUNT_OPTS=$save_opts
+
+ stop mds1 -f
+}
+run_test 151 "secure mgs connection: server flavor control"
+
equals_msg `basename $0`: test complete, cleaning up
check_and_cleanup_lustre
[ -f "$TESTSUITELOG" ] && cat $TESTSUITELOG && grep -q FAIL $TESTSUITELOG && exit 1 || true
#include "lsupport.h"
/* Global gssd_credentials handle */
+gss_cred_id_t gssd_cred_mgs;
gss_cred_id_t gssd_cred_mds;
gss_cred_id_t gssd_cred_oss;
+int gssd_cred_mgs_valid = 0;
int gssd_cred_mds_valid = 0;
int gssd_cred_oss_valid = 0;
+char *mgs_local_realm = NULL;
char *mds_local_realm = NULL;
char *oss_local_realm = NULL;
return 0;
}
-int gssd_prepare_creds(int must_srv_mds, int must_srv_oss)
+int gssd_prepare_creds(int must_srv_mgs, int must_srv_mds, int must_srv_oss)
{
+ if (gssd_acquire_cred(GSSD_SERVICE_MGS, &gssd_cred_mgs,
+ &mgs_local_realm, &gssd_cred_mgs_valid)) {
+ if (must_srv_mgs)
+ return -1;
+ }
+
if (gssd_acquire_cred(GSSD_SERVICE_MDS, &gssd_cred_mds,
&mds_local_realm, &gssd_cred_mds_valid)) {
if (must_srv_mds)
return -1;
}
- if (!gssd_cred_mds_valid && !gssd_cred_oss_valid) {
- printerr(0, "can't obtain both mds & oss creds, exit\n");
+ if (!gssd_cred_mgs_valid &&
+ !gssd_cred_mds_valid &&
+ !gssd_cred_oss_valid) {
+ printerr(0, "can't obtain any service creds, exit\n");
return -1;
}
+ if (gssd_cred_mgs_valid)
+ printerr(0, "Ready to serve Lustre MGS in realm %s\n",
+ mgs_local_realm ? mgs_local_realm : "N/A");
if (gssd_cred_mds_valid)
printerr(0, "Ready to serve Lustre MDS in realm %s\n",
mds_local_realm ? mds_local_realm : "N/A");
gss_cred_id_t gssd_select_svc_cred(int lustre_svc)
{
switch (lustre_svc) {
+ case LUSTRE_GSS_SVC_MGS:
+ if (!gssd_cred_mgs_valid) {
+ printerr(0, "ERROR: service cred for mgs not ready\n");
+ return NULL;
+ }
+ return gssd_cred_mgs;
case LUSTRE_GSS_SVC_MDS:
if (!gssd_cred_mds_valid) {
printerr(0, "ERROR: service cred for mds not ready\n");
#define GSSD_DEFAULT_CRED_PREFIX "krb5cc_"
#define GSSD_DEFAULT_MACHINE_CRED_SUFFIX "machine"
#define GSSD_DEFAULT_KEYTAB_FILE "/etc/krb5.keytab"
+#define GSSD_SERVICE_MGS "lustre_mgs"
#define GSSD_SERVICE_MDS "lustre_mds"
#define GSSD_SERVICE_OSS "lustre_oss"
#define GSSD_SERVICE_MDS_NAMELEN 10
#include "lgss_krb5_utils.h"
const char *lgss_svc_str[LGSS_SVC_MAX] = {
+ [LGSS_SVC_MGS] = LGSS_SVC_MGS_STR,
[LGSS_SVC_MDS] = LGSS_SVC_MDS_STR,
[LGSS_SVC_OSS] = LGSS_SVC_OST_STR,
- [LGSS_SVC_MGS] = LGSS_SVC_MGS_STR,
};
/****************************************
#include <libcfs/libcfs.h>
+#define LGSS_SVC_MGS_STR "lustre_mgs"
#define LGSS_SVC_MDS_STR "lustre_mds"
#define LGSS_SVC_OST_STR "lustre_oss"
-#define LGSS_SVC_MGS_STR "lustre_mgs"
#define LGSS_USR_ROOT_STR "lustre_root"
typedef enum {
- LGSS_SVC_MDS = 0,
- LGSS_SVC_OSS = 1,
- LGSS_SVC_MGS = 2,
+ LGSS_SVC_MGS = 0,
+ LGSS_SVC_MDS = 1,
+ LGSS_SVC_OSS = 2,
LGSS_SVC_MAX
} lgss_svc_t;
const char * lustre_svc_name[] =
{
+ [LUSTRE_GSS_SVC_MGS] = "MGS",
[LUSTRE_GSS_SVC_MDS] = "MDS",
[LUSTRE_GSS_SVC_OSS] = "OSS",
};
* copied from lustre source
*/
-#define LUSTRE_GSS_SVC_MDS 0
-#define LUSTRE_GSS_SVC_OSS 1
+#define LUSTRE_GSS_SVC_MGS 0
+#define LUSTRE_GSS_SVC_MDS 1
+#define LUSTRE_GSS_SVC_OSS 2
extern const char * lustre_svc_name[];
static void
usage(char *progname)
{
- fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-m] [-o]\n",
+ fprintf(stderr, "usage: %s [-n] [-f] [-v] [-r] [-m] [-o] [-g]\n",
progname);
exit(1);
}
int fg = 0;
int verbosity = 0;
int opt;
- int must_srv_mds = 0, must_srv_oss = 0;
+ int must_srv_mds = 0, must_srv_oss = 0, must_srv_mgs = 0;
extern char *optarg;
char *progname;
- while ((opt = getopt(argc, argv, "fivrnp:")) != -1) {
+ while ((opt = getopt(argc, argv, "fvrnmog:")) != -1) {
switch (opt) {
case 'f':
fg = 1;
get_creds = 1;
must_srv_oss = 1;
break;
+ case 'g':
+ get_creds = 1;
+ must_srv_mgs = 1;
+ break;
default:
usage(argv[0]);
break;
exit(1);
}
- if (get_creds && gssd_prepare_creds(must_srv_mds, must_srv_oss)) {
+ if (get_creds &&
+ gssd_prepare_creds(must_srv_mgs, must_srv_mds, must_srv_oss)) {
printerr(0, "unable to obtain root (machine) credentials\n");
printerr(0, "do you have a keytab entry for "
- "nfs/<your.host>@<YOUR.REALM> in "
+ "<lustre_xxs>/<your.host>@<YOUR.REALM> in "
"/etc/krb5.keytab?\n");
exit(1);
}
int handle_nullreq(FILE *f);
void svcgssd_run(void);
-int gssd_prepare_creds(int must_srv_mds, int must_srv_oss);
+int gssd_prepare_creds(int must_srv_mgs, int must_srv_mds, int must_srv_oss);
gss_cred_id_t gssd_select_svc_cred(int lustre_svc);
extern char *mds_local_realm;
#define GSSD_SERVICE_NAME "lustre"
/* XXX */
+#define GSSD_SERVICE_MGS "lustre_mgs"
#define GSSD_SERVICE_MDS "lustre_mds"
#define GSSD_SERVICE_OSS "lustre_oss"
#define LUSTRE_ROOT_NAME "lustre_root"
if (host)
*host++ = '\0';
- if (strcmp(sname, GSSD_SERVICE_OSS) == 0) {
- printerr(0, "forbid "GSSD_SERVICE_OSS" as user name\n");
+ if (strcmp(sname, GSSD_SERVICE_OSS) == 0 ||
+ strcmp(sname, GSSD_SERVICE_MGS) == 0) {
+ printerr(0, "forbid %s as user name\n", sname);
goto out_free;
}
if (rc) {
if (errno == ENOSYS)
fprintf(stderr, "Make sure cfg_device is set first.\n");
- if (errno == EINVAL)
- fprintf(stderr, "cfg_device should be of the form "
- "'lustre-MDT0000'\n");
}
return rc;
}