__s64 ses_stamp; /* time stamp in milliseconds */
}; /*** session id */
-extern struct lst_sid LST_INVALID_SID;
-
struct lst_bid {
__u64 bat_id; /* unique id in session */
};
__u32 ping_errors;
} __attribute__((packed));
+#define LNET_SELFTEST_GENL_NAME "lnet_selftest"
+#define LNET_SELFTEST_GENL_VERSION 0x1
+
+/* enum lnet_selftest_commands - Supported core LNet Selftest Netlink
+ * commands
+ *
+ * @LNET_SELFTEST_CMD_UNSPEC: unspecified command to catch errors
+ * @LNET_SELFTEST_CMD_SESSIONS: command to manage sessions
+ */
+enum lnet_selftest_commands {
+ LNET_SELFTEST_CMD_UNSPEC = 0,
+
+ LNET_SELFTEST_CMD_SESSIONS = 1,
+
+ __LNET_SELFTEST_CMD_MAX_PLUS_ONE,
+};
+
+#define LNET_SELFTEST_CMD_MAX (__LNET_SELFTEST_CMD_MAX_PLUS_ONE - 1)
+
#endif
* Author: Liang Zhen <liangzhen@clusterfs.com>
*/
+#include <libcfs/linux/linux-net.h>
#include <libcfs/libcfs.h>
#include <lnet/lib-lnet.h>
#include "console.h"
static int
-lst_session_new_ioctl(struct lstio_session_new_args *args)
-{
- char *name;
- int rc;
-
- if (args->lstio_ses_idp == NULL || /* address for output sid */
- args->lstio_ses_key == 0 || /* no key is specified */
- args->lstio_ses_namep == NULL || /* session name */
- args->lstio_ses_nmlen <= 0 ||
- args->lstio_ses_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- LIBCFS_ALLOC(name, args->lstio_ses_nmlen + 1);
- if (name == NULL)
- return -ENOMEM;
-
- if (copy_from_user(name, args->lstio_ses_namep,
- args->lstio_ses_nmlen)) {
- LIBCFS_FREE(name, args->lstio_ses_nmlen + 1);
- return -EFAULT;
- }
-
- name[args->lstio_ses_nmlen] = 0;
-
- rc = lstcon_session_new(name,
- args->lstio_ses_key,
- args->lstio_ses_feats,
- args->lstio_ses_timeout,
- args->lstio_ses_force,
- args->lstio_ses_idp);
-
- LIBCFS_FREE(name, args->lstio_ses_nmlen + 1);
- return rc;
-}
-
-static int
-lst_session_end_ioctl(struct lstio_session_end_args *args)
-{
- if (args->lstio_ses_key != console_session.ses_key)
- return -EACCES;
-
- return lstcon_session_end();
-}
-
-static int
-lst_session_info_ioctl(struct lstio_session_info_args *args)
-{
- /* no checking of key */
-
- if (args->lstio_ses_idp == NULL || /* address for ouput sid */
- args->lstio_ses_keyp == NULL || /* address for ouput key */
- args->lstio_ses_featp == NULL || /* address for ouput features */
- args->lstio_ses_ndinfo == NULL || /* address for output ndinfo */
- args->lstio_ses_namep == NULL || /* address for ouput name */
- args->lstio_ses_nmlen <= 0 ||
- args->lstio_ses_nmlen > LST_NAME_SIZE)
- return -EINVAL;
-
- return lstcon_session_info(args->lstio_ses_idp,
- args->lstio_ses_keyp,
- args->lstio_ses_featp,
- args->lstio_ses_ndinfo,
- args->lstio_ses_namep,
- args->lstio_ses_nmlen);
-}
-
-static int
lst_debug_ioctl(struct lstio_debug_args *args)
{
char *name = NULL;
switch (opc) {
case LSTIO_SESSION_NEW:
- rc = lst_session_new_ioctl((struct lstio_session_new_args *)buf);
- break;
+ fallthrough;
case LSTIO_SESSION_END:
- rc = lst_session_end_ioctl((struct lstio_session_end_args *)buf);
- break;
+ fallthrough;
case LSTIO_SESSION_INFO:
- rc = lst_session_info_ioctl((struct lstio_session_info_args *)buf);
+ rc = -EOPNOTSUPP;
break;
case LSTIO_DEBUG:
rc = lst_debug_ioctl((struct lstio_debug_args *)buf);
err:
return notifier_from_ioctl_errno(rc);
}
+
+static struct genl_family lst_family;
+
+static const struct ln_key_list lst_session_keys = {
+ .lkl_maxattr = LNET_SELFTEST_SESSION_MAX,
+ .lkl_list = {
+ [LNET_SELFTEST_SESSION_HDR] = {
+ .lkp_value = "session",
+ .lkp_key_format = LNKF_MAPPING,
+ .lkp_data_type = NLA_NUL_STRING,
+ },
+ [LNET_SELFTEST_SESSION_NAME] = {
+ .lkp_value = "name",
+ .lkp_data_type = NLA_STRING,
+ },
+ [LNET_SELFTEST_SESSION_KEY] = {
+ .lkp_value = "key",
+ .lkp_data_type = NLA_U32,
+ },
+ [LNET_SELFTEST_SESSION_TIMESTAMP] = {
+ .lkp_value = "timestamp",
+ .lkp_data_type = NLA_S64,
+ },
+ [LNET_SELFTEST_SESSION_NID] = {
+ .lkp_value = "nid",
+ .lkp_data_type = NLA_STRING,
+ },
+ [LNET_SELFTEST_SESSION_NODE_COUNT] = {
+ .lkp_value = "nodes",
+ .lkp_data_type = NLA_U16,
+ },
+ },
+};
+
+static int lst_sessions_show_dump(struct sk_buff *msg,
+ struct netlink_callback *cb)
+{
+ const struct ln_key_list *all[] = {
+ &lst_session_keys, NULL
+ };
+#ifdef HAVE_NL_PARSE_WITH_EXT_ACK
+ struct netlink_ext_ack *extack = NULL;
+#endif
+ int portid = NETLINK_CB(cb->skb).portid;
+ int seq = cb->nlh->nlmsg_seq;
+ unsigned int node_count = 0;
+ struct lstcon_ndlink *ndl;
+ int flag = NLM_F_MULTI;
+ int rc = 0;
+ void *hdr;
+
+#ifdef HAVE_NL_DUMP_WITH_EXT_ACK
+ extack = cb->extack;
+#endif
+ if (console_session.ses_state != LST_SESSION_ACTIVE) {
+ NL_SET_ERR_MSG(extack, "session is not active");
+ GOTO(out_unlock, rc = -ESRCH);
+ }
+
+ list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
+ node_count++;
+
+ rc = lnet_genl_send_scalar_list(msg, portid, seq, &lst_family,
+ NLM_F_CREATE | NLM_F_MULTI,
+ LNET_SELFTEST_CMD_SESSIONS, all);
+ if (rc < 0) {
+ NL_SET_ERR_MSG(extack, "failed to send key table");
+ GOTO(out_unlock, rc);
+ }
+
+ if (console_session.ses_force)
+ flag |= NLM_F_REPLACE;
+
+ hdr = genlmsg_put(msg, portid, seq, &lst_family, flag,
+ LNET_SELFTEST_CMD_SESSIONS);
+ if (!hdr) {
+ NL_SET_ERR_MSG(extack, "failed to send values");
+ genlmsg_cancel(msg, hdr);
+ GOTO(out_unlock, rc = -EMSGSIZE);
+ }
+
+ nla_put_string(msg, LNET_SELFTEST_SESSION_NAME,
+ console_session.ses_name);
+ nla_put_u32(msg, LNET_SELFTEST_SESSION_KEY,
+ console_session.ses_key);
+ nla_put_u64_64bit(msg, LNET_SELFTEST_SESSION_TIMESTAMP,
+ console_session.ses_id.ses_stamp,
+ LNET_SELFTEST_SESSION_PAD);
+ nla_put_string(msg, LNET_SELFTEST_SESSION_NID,
+ libcfs_nidstr(&console_session.ses_id.ses_nid));
+ nla_put_u16(msg, LNET_SELFTEST_SESSION_NODE_COUNT,
+ node_count);
+ genlmsg_end(msg, hdr);
+out_unlock:
+ return lnet_nl_send_error(cb->skb, portid, seq, rc);
+}
+
+static int lst_sessions_cmd(struct sk_buff *skb, struct genl_info *info)
+{
+ struct sk_buff *msg = NULL;
+ int rc = 0;
+
+ mutex_lock(&console_session.ses_mutex);
+
+ console_session.ses_laststamp = ktime_get_real_seconds();
+
+ if (console_session.ses_shutdown) {
+ GENL_SET_ERR_MSG(info, "session is shutdown");
+ GOTO(out_unlock, rc = -ESHUTDOWN);
+ }
+
+ if (console_session.ses_expired)
+ lstcon_session_end();
+
+ if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE) &&
+ console_session.ses_state == LST_SESSION_NONE) {
+ GENL_SET_ERR_MSG(info, "session is not active");
+ GOTO(out_unlock, rc = -ESRCH);
+ }
+
+ memset(&console_session.ses_trans_stat, 0,
+ sizeof(struct lstcon_trans_stat));
+
+ if (!(info->nlhdr->nlmsg_flags & NLM_F_CREATE)) {
+ lstcon_session_end();
+ GOTO(out_unlock, rc);
+ }
+
+ if (info->attrs[LN_SCALAR_ATTR_LIST]) {
+ struct genlmsghdr *gnlh = nlmsg_data(info->nlhdr);
+ const struct ln_key_list *all[] = {
+ &lst_session_keys, NULL
+ };
+ char name[LST_NAME_SIZE];
+ struct nlmsghdr *nlh;
+ struct nlattr *item;
+ bool force = false;
+ s64 timeout = 300;
+ void *hdr;
+ int rem;
+
+ if (info->nlhdr->nlmsg_flags & NLM_F_REPLACE)
+ force = true;
+
+ nla_for_each_nested(item, info->attrs[LN_SCALAR_ATTR_LIST],
+ rem) {
+ if (nla_type(item) != LN_SCALAR_ATTR_VALUE)
+ continue;
+
+ if (nla_strcmp(item, "name") == 0) {
+ ssize_t len;
+
+ item = nla_next(item, &rem);
+ if (nla_type(item) != LN_SCALAR_ATTR_VALUE)
+ GOTO(err_conf, rc = -EINVAL);
+
+ len = nla_strscpy(name, item, sizeof(name));
+ if (len < 0)
+ rc = len;
+ } else if (nla_strcmp(item, "timeout") == 0) {
+ item = nla_next(item, &rem);
+ if (nla_type(item) !=
+ LN_SCALAR_ATTR_INT_VALUE)
+ GOTO(err_conf, rc = -EINVAL);
+
+ timeout = nla_get_s64(item);
+ if (timeout < 0)
+ rc = -ERANGE;
+ }
+ if (rc < 0) {
+err_conf:
+ GENL_SET_ERR_MSG(info,
+ "failed to get config");
+ GOTO(out_unlock, rc);
+ }
+ }
+
+ rc = lstcon_session_new(name, info->nlhdr->nlmsg_pid,
+ gnlh->version, timeout,
+ force);
+ if (rc < 0) {
+ GENL_SET_ERR_MSG(info, "new session creation failed");
+ lstcon_session_end();
+ GOTO(out_unlock, rc);
+ }
+
+ msg = genlmsg_new(GENLMSG_DEFAULT_SIZE, GFP_KERNEL);
+ if (!msg) {
+ GENL_SET_ERR_MSG(info, "msg allocation failed");
+ GOTO(out_unlock, rc = -ENOMEM);
+ }
+
+ rc = lnet_genl_send_scalar_list(msg, info->snd_portid,
+ info->snd_seq, &lst_family,
+ NLM_F_CREATE | NLM_F_MULTI,
+ LNET_SELFTEST_CMD_SESSIONS,
+ all);
+ if (rc < 0) {
+ GENL_SET_ERR_MSG(info, "failed to send key table");
+ GOTO(out_unlock, rc);
+ }
+
+ hdr = genlmsg_put(msg, info->snd_portid, info->snd_seq,
+ &lst_family, NLM_F_MULTI,
+ LNET_SELFTEST_CMD_SESSIONS);
+ if (!hdr) {
+ GENL_SET_ERR_MSG(info, "failed to send values");
+ genlmsg_cancel(msg, hdr);
+ GOTO(out_unlock, rc = -EMSGSIZE);
+ }
+
+ nla_put_string(msg, LNET_SELFTEST_SESSION_NAME,
+ console_session.ses_name);
+ nla_put_u32(msg, LNET_SELFTEST_SESSION_KEY,
+ console_session.ses_key);
+ nla_put_u64_64bit(msg, LNET_SELFTEST_SESSION_TIMESTAMP,
+ console_session.ses_id.ses_stamp,
+ LNET_SELFTEST_SESSION_PAD);
+ nla_put_string(msg, LNET_SELFTEST_SESSION_NID,
+ libcfs_nidstr(&console_session.ses_id.ses_nid));
+ nla_put_u16(msg, LNET_SELFTEST_SESSION_NODE_COUNT, 0);
+
+ genlmsg_end(msg, hdr);
+
+ nlh = nlmsg_put(msg, info->snd_portid, info->snd_seq,
+ NLMSG_DONE, 0, NLM_F_MULTI);
+ if (!nlh) {
+ GENL_SET_ERR_MSG(info, "failed to complete message");
+ genlmsg_cancel(msg, hdr);
+ GOTO(out_unlock, rc = -ENOMEM);
+ }
+ rc = genlmsg_reply(msg, info);
+ if (rc)
+ GENL_SET_ERR_MSG(info, "failed to send reply");
+ }
+out_unlock:
+ if (rc < 0 && msg)
+ nlmsg_free(msg);
+ mutex_unlock(&console_session.ses_mutex);
+ return rc;
+}
+
+static const struct genl_multicast_group lst_mcast_grps[] = {
+ { .name = "sessions", },
+};
+
+static const struct genl_ops lst_genl_ops[] = {
+ {
+ .cmd = LNET_SELFTEST_CMD_SESSIONS,
+ .dumpit = lst_sessions_show_dump,
+ .doit = lst_sessions_cmd,
+ },
+};
+
+static struct genl_family lst_family = {
+ .name = LNET_SELFTEST_GENL_NAME,
+ .version = LNET_SELFTEST_GENL_VERSION,
+ .maxattr = LN_SCALAR_MAX,
+ .module = THIS_MODULE,
+ .ops = lst_genl_ops,
+ .n_ops = ARRAY_SIZE(lst_genl_ops),
+ .mcgrps = lst_mcast_grps,
+ .n_mcgrps = ARRAY_SIZE(lst_mcast_grps),
+};
+
+int lstcon_init_netlink(void)
+{
+ return genl_register_family(&lst_family);
+}
+
+void lstcon_fini_netlink(void)
+{
+ genl_unregister_family(&lst_family);
+}
return rc;
msrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.mksn_reqst;
- msrq->mksn_sid = console_session.ses_id;
- msrq->mksn_force = console_session.ses_force;
+ msrq->mksn_sid.ses_stamp = console_session.ses_id.ses_stamp;
+ msrq->mksn_sid.ses_nid =
+ lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
+ msrq->mksn_force = console_session.ses_force;
strlcpy(msrq->mksn_name, console_session.ses_name,
sizeof(msrq->mksn_name));
break;
if (rc != 0)
return rc;
- rsrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.rmsn_reqst;
- rsrq->rmsn_sid = console_session.ses_id;
- break;
+ rsrq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.rmsn_reqst;
+ rsrq->rmsn_sid.ses_stamp = console_session.ses_id.ses_stamp;
+ rsrq->rmsn_sid.ses_nid =
+ lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
+ break;
default:
LBUG();
drq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.dbg_reqst;
- drq->dbg_sid = console_session.ses_id;
+ drq->dbg_sid.ses_stamp = console_session.ses_id.ses_stamp;
+ drq->dbg_sid.ses_nid =
+ lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
drq->dbg_flags = 0;
return rc;
brq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.bat_reqst;
- brq->bar_sid = console_session.ses_id;
+ brq->bar_sid.ses_stamp = console_session.ses_id.ses_stamp;
+ brq->bar_sid.ses_nid =
+ lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
brq->bar_bid = tsb->tsb_id;
brq->bar_testidx = tsb->tsb_index;
brq->bar_opc = transop == LST_TRANS_TSBRUN ? SRPC_BATCH_OPC_RUN :
srq = &(*crpc)->crp_rpc->crpc_reqstmsg.msg_body.stat_reqst;
- srq->str_sid = console_session.ses_id;
+
+ srq->str_sid.ses_stamp = console_session.ses_id.ses_stamp;
+ srq->str_sid.ses_nid =
+ lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
srq->str_type = 0; /* XXX remove it */
return 0;
trq->tsr_loop = test->tes_loop;
}
- trq->tsr_sid = console_session.ses_id;
+ trq->tsr_sid.ses_stamp = console_session.ses_id.ses_stamp;
+ trq->tsr_sid.ses_nid =
+ lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
trq->tsr_bid = test->tes_hdr.tsb_id;
trq->tsr_concur = test->tes_concur;
trq->tsr_is_client = (transop == LST_TRANS_TSBCLIADD) ? 1 : 0;
drq = &crpc->crp_rpc->crpc_reqstmsg.msg_body.dbg_reqst;
- drq->dbg_sid = console_session.ses_id;
+ drq->dbg_sid.ses_stamp = console_session.ses_id.ses_stamp;
+ drq->dbg_sid.ses_nid =
+ lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
drq->dbg_flags = 0;
lstcon_rpc_trans_addreq(trans, crpc);
}
int
-lstcon_session_match(struct lst_sid sid)
+lstcon_session_match(struct lst_sid id)
{
- return (console_session.ses_id.ses_nid == sid.ses_nid &&
- console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1: 0;
+ struct lst_session_id sid;
+
+ sid.ses_stamp = id.ses_stamp;
+ lnet_nid4_to_nid(id.ses_nid, &sid.ses_nid);
+
+ return (nid_same(&console_session.ses_id.ses_nid, &sid.ses_nid) &&
+ console_session.ses_id.ses_stamp == sid.ses_stamp) ? 1 : 0;
}
static void
-lstcon_new_session_id(struct lst_sid *sid)
+lstcon_new_session_id(struct lst_session_id *sid)
{
struct lnet_processid id;
LASSERT(console_session.ses_state == LST_SESSION_NONE);
LNetGetId(1, &id);
- sid->ses_nid = lnet_nid_to_nid4(&id.nid);
+ sid->ses_nid = id.nid;
sid->ses_stamp = div_u64(ktime_get_ns(), NSEC_PER_MSEC);
}
int
lstcon_session_new(char *name, int key, unsigned feats,
- int timeout, int force, struct lst_sid __user *sid_up)
+ int timeout, int force)
{
int rc = 0;
int i;
lstcon_new_session_id(&console_session.ses_id);
console_session.ses_key = key;
- console_session.ses_state = LST_SESSION_ACTIVE;
console_session.ses_force = !!force;
console_session.ses_features = feats;
console_session.ses_feats_updated = 0;
return rc;
}
- if (copy_to_user(sid_up, &console_session.ses_id,
- sizeof(struct lst_sid)) == 0)
- return rc;
-
- lstcon_session_end();
-
- return -EFAULT;
-}
-
-int
-lstcon_session_info(struct lst_sid __user *sid_up, int __user *key_up,
- unsigned __user *featp,
- struct lstcon_ndlist_ent __user *ndinfo_up,
- char __user *name_up, int len)
-{
- struct lstcon_ndlist_ent *entp;
- struct lstcon_ndlink *ndl;
- int rc = 0;
+ console_session.ses_state = LST_SESSION_ACTIVE;
- if (console_session.ses_state != LST_SESSION_ACTIVE)
- return -ESRCH;
-
- LIBCFS_ALLOC(entp, sizeof(*entp));
- if (entp == NULL)
- return -ENOMEM;
-
- list_for_each_entry(ndl, &console_session.ses_ndl_list, ndl_link)
- LST_NODE_STATE_COUNTER(ndl->ndl_node, entp);
-
- if (copy_to_user(sid_up, &console_session.ses_id,
- sizeof(struct lst_sid)) ||
- copy_to_user(key_up, &console_session.ses_key,
- sizeof(*key_up)) ||
- copy_to_user(featp, &console_session.ses_features,
- sizeof(*featp)) ||
- copy_to_user(ndinfo_up, entp, sizeof(*entp)) ||
- copy_to_user(name_up, console_session.ses_name, len))
- rc = -EFAULT;
-
- LIBCFS_FREE(entp, sizeof(*entp));
-
- return rc;
+ return rc;
}
-int
-lstcon_session_end(void)
+int lstcon_session_end(void)
{
struct lstcon_rpc_trans *trans;
struct lstcon_group *grp;
mutex_lock(&console_session.ses_mutex);
- jrep->join_sid = console_session.ses_id;
+ jrep->join_sid.ses_stamp = console_session.ses_id.ses_stamp;
+ jrep->join_sid.ses_nid = lnet_nid_to_nid4(&console_session.ses_id.ses_nid);
- if (console_session.ses_id.ses_nid == LNET_NID_ANY) {
+ if (LNET_NID_IS_ANY(&console_session.ses_id.ses_nid)) {
jrep->join_status = ESRCH;
goto out;
}
goto out;
}
+ rc = lstcon_init_netlink();
+ if (rc < 0)
+ goto out;
+
rc = blocking_notifier_chain_register(&libcfs_ioctl_list,
&lstcon_ioctl_handler);
- if (rc == 0) {
- lstcon_rpc_module_init();
- return 0;
+ if (rc < 0) {
+ lstcon_fini_netlink();
+ goto out;
}
+ lstcon_rpc_module_init();
+ return 0;
+
out:
srpc_shutdown_service(&lstcon_acceptor_service);
srpc_remove_service(&lstcon_acceptor_service);
blocking_notifier_chain_unregister(&libcfs_ioctl_list,
&lstcon_ioctl_handler);
+ lstcon_fini_netlink();
mutex_lock(&console_session.ses_mutex);
struct lstcon_session {
struct mutex ses_mutex; /* only 1 thread in session */
- struct lst_sid ses_id; /* global session id */
- int ses_key; /* local session key */
+ struct lst_session_id ses_id; /* global session id */
+ u32 ses_key; /* local session key */
int ses_state; /* state of session */
int ses_timeout; /* timeout in seconds */
time64_t ses_laststamp; /* last operation stamp (seconds) */
extern int lstcon_session_match(struct lst_sid sid);
extern int lstcon_session_new(char *name, int key, unsigned version,
- int timeout, int flags, struct lst_sid __user *sid_up);
-extern int lstcon_session_info(struct lst_sid __user *sid_up, int __user *key,
- unsigned __user *verp,
- struct lstcon_ndlist_ent __user *entp,
- char __user *name_up, int len);
+ int timeout, int flags);
extern int lstcon_session_end(void);
extern int lstcon_session_debug(int timeout,
struct list_head __user *result_up);
int lstcon_ioctl_entry(struct notifier_block *nb,
unsigned long cmd, void *vdata);
+
int lstcon_console_init(void);
int lstcon_console_fini(void);
+int lstcon_init_netlink(void);
+void lstcon_fini_netlink(void);
+
#endif
#include "selftest.h"
-struct lst_sid LST_INVALID_SID = { .ses_nid = LNET_NID_ANY, .ses_stamp = -1};
+struct lst_session_id LST_INVALID_SID = { .ses_nid = LNET_ANY_NID, .ses_stamp = -1};
static int session_timeout = 100;
module_param(session_timeout, int, 0444);
LASSERT (sn == sfw_data.fw_session);
CWARN ("Session expired! sid: %s-%llu, name: %s\n",
- libcfs_nid2str(sn->sn_id.ses_nid),
+ libcfs_nidstr(&sn->sn_id.ses_nid),
sn->sn_id.ses_stamp, &sn->sn_name[0]);
sn->sn_timer_active = 0;
strlcpy(&sn->sn_name[0], name, sizeof(sn->sn_name));
sn->sn_timer_active = 0;
- sn->sn_id = sid;
+ sn->sn_id.ses_stamp = sid.ses_stamp;
+ lnet_nid4_to_nid(sid.ses_nid, &sn->sn_id.ses_nid);
sn->sn_features = features;
sn->sn_timeout = session_timeout;
sn->sn_started = ktime_get();
return bat;
}
+static struct lst_sid get_old_sid(struct sfw_session *sn)
+{
+ struct lst_sid sid = { .ses_nid = LNET_NID_ANY, .ses_stamp = -1 };
+
+ if (sn) {
+ sid.ses_stamp = sn->sn_id.ses_stamp;
+ sid.ses_nid = lnet_nid_to_nid4(&sn->sn_id.ses_nid);
+ }
+
+ return sid;
+}
+
static int
sfw_get_stats(struct srpc_stat_reqst *request, struct srpc_stat_reply *reply)
{
struct sfw_counters *cnt = &reply->str_fw;
struct sfw_batch *bat;
- reply->str_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id;
+ reply->str_sid = get_old_sid(sn);
if (request->str_sid.ses_nid == LNET_NID_ANY) {
reply->str_status = EINVAL;
int cplen = 0;
if (request->mksn_sid.ses_nid == LNET_NID_ANY) {
- reply->mksn_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id;
+ reply->mksn_sid = get_old_sid(sn);
reply->mksn_status = EINVAL;
return 0;
}
if (sn != NULL) {
reply->mksn_status = 0;
- reply->mksn_sid = sn->sn_id;
+ reply->mksn_sid = get_old_sid(sn);
reply->mksn_timeout = sn->sn_timeout;
if (sfw_sid_equal(request->mksn_sid, sn->sn_id)) {
spin_unlock(&sfw_data.fw_lock);
reply->mksn_status = 0;
- reply->mksn_sid = sn->sn_id;
+ reply->mksn_sid = get_old_sid(sn);
reply->mksn_timeout = sn->sn_timeout;
return 0;
}
{
struct sfw_session *sn = sfw_data.fw_session;
- reply->rmsn_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id;
+ reply->rmsn_sid = get_old_sid(sn);
if (request->rmsn_sid.ses_nid == LNET_NID_ANY) {
reply->rmsn_status = EINVAL;
spin_unlock(&sfw_data.fw_lock);
reply->rmsn_status = 0;
- reply->rmsn_sid = LST_INVALID_SID;
+ reply->rmsn_sid = get_old_sid(NULL);
LASSERT(sfw_data.fw_session == NULL);
return 0;
}
if (sn == NULL) {
reply->dbg_status = ESRCH;
- reply->dbg_sid = LST_INVALID_SID;
+ reply->dbg_sid = get_old_sid(NULL);
return 0;
}
reply->dbg_status = 0;
- reply->dbg_sid = sn->sn_id;
+ reply->dbg_sid = get_old_sid(sn);
reply->dbg_timeout = sn->sn_timeout;
if (strlcpy(reply->dbg_name, &sn->sn_name[0], sizeof(reply->dbg_name))
>= sizeof(reply->dbg_name))
struct sfw_batch *bat;
request = &rpc->srpc_reqstbuf->buf_msg.msg_body.tes_reqst;
- reply->tsr_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id;
+ reply->tsr_sid = get_old_sid(sn);
if (request->tsr_loop == 0 ||
request->tsr_concur == 0 ||
int rc = 0;
struct sfw_batch *bat;
- reply->bar_sid = (sn == NULL) ? LST_INVALID_SID : sn->sn_id;
+ reply->bar_sid = get_old_sid(sn);
if (sn == NULL || !sfw_sid_equal(request->bar_sid, sn->sn_id)) {
reply->bar_status = ESRCH;
"features of current session: %x/%x\n",
request->msg_ses_feats, sn->sn_features);
reply->msg_body.reply.status = EPROTO;
- reply->msg_body.reply.sid = sn->sn_id;
+ reply->msg_body.reply.sid.ses_stamp = sn->sn_id.ses_stamp;
+ reply->msg_body.reply.sid.ses_nid =
+ lnet_nid_to_nid4(&sn->sn_id.ses_nid);
goto out;
}
#define MADE_WITHOUT_COMPROMISE
#endif
+/* enum lnet_selftest_session_attrs - LNet selftest session Netlink
+ * attributes
+ *
+ * @LNET_SELFTEST_SESSION_UNSPEC: unspecified attribute to catch errors
+ * @LNET_SELFTEST_SESSION_PAD: padding for 64-bit attributes, ignore
+ *
+ * @LENT_SELFTEST_SESSION_HDR: Netlink group this data is for
+ * (NLA_NUL_STRING)
+ * @LNET_SELFTEST_SESSION_NAME: name of this session (NLA_STRING)
+ * @LNET_SELFTEST_SESSION_KEY: key used to represent the session
+ * (NLA_U32)
+ * @LNET_SELFTEST_SESSION_TIMESTAMP: timestamp when the session was created
+ * (NLA_S64)
+ * @LNET_SELFTEST_SESSION_NID: NID of the node selftest ran on
+ * (NLA_STRING)
+ * @LNET_SELFTEST_SESSION_NODE_COUNT: Number of nodes in use (NLA_U16)
+ */
+enum lnet_selftest_session_attrs {
+ LNET_SELFTEST_SESSION_UNSPEC = 0,
+ LNET_SELFTEST_SESSION_PAD = LNET_SELFTEST_SESSION_UNSPEC,
+
+ LNET_SELFTEST_SESSION_HDR,
+ LNET_SELFTEST_SESSION_NAME,
+ LNET_SELFTEST_SESSION_KEY,
+ LNET_SELFTEST_SESSION_TIMESTAMP,
+ LNET_SELFTEST_SESSION_NID,
+ LNET_SELFTEST_SESSION_NODE_COUNT,
+
+ __LNET_SELFTEST_SESSION_MAX_PLUS_ONE,
+};
+
+#define LNET_SELFTEST_SESSION_MAX (__LNET_SELFTEST_SESSION_MAX_PLUS_ONE - 1)
#define SWI_STATE_NEWBORN 0
#define SWI_STATE_REPLY_SUBMITTED 1
int (*sv_bulk_ready)(struct srpc_server_rpc *, int);
};
+struct lst_session_id {
+ s64 ses_stamp; /* time stamp in milliseconds */
+ struct lnet_nid ses_nid; /* nid of console node */
+}; /*** session id (large addr) */
+
+extern struct lst_session_id LST_INVALID_SID;
+
struct sfw_session {
/* chain on fw_zombie_sessions */
struct list_head sn_list;
- struct lst_sid sn_id; /* unique identifier */
+ struct lst_session_id sn_id; /* unique identifier */
/* # seconds' inactivity to expire */
unsigned int sn_timeout;
int sn_timer_active;
ktime_t sn_started;
};
-#define sfw_sid_equal(sid0, sid1) ((sid0).ses_nid == (sid1).ses_nid && \
- (sid0).ses_stamp == (sid1).ses_stamp)
+static inline int sfw_sid_equal(struct lst_sid sid0,
+ struct lst_session_id sid1)
+{
+ struct lnet_nid ses_nid;
+
+ lnet_nid4_to_nid(sid0.ses_nid, &ses_nid);
+
+ return ((sid0.ses_stamp == sid1.ses_stamp) &&
+ nid_same(&ses_nid, &sid1.ses_nid));
+}
struct sfw_batch {
struct list_head bat_list; /* chain on sn_batches */
lst_SOURCES = lst.c
lst_CFLAGS = -fPIC -D_LINUX_TIME_H -D_GNU_SOURCE $(LIBNL3_CFLAGS)
lst_LDADD = $(top_builddir)/lnet/utils/lnetconfig/liblnetconfig.la \
- $(LIBEFENCE)
+ $(LIBEFENCE) $(LIBNL3_LIBS) -lyaml
if TESTS
sbin_PROGRAMS += wirecheck
#include "lnetconfig/liblnetconfig.h"
struct lst_sid LST_INVALID_SID = { .ses_nid = LNET_NID_ANY, .ses_stamp = -1 };
-static struct lst_sid session_id;
-static int session_key;
+static unsigned int session_key;
static int lst_list_commands(int argc, char **argv);
/* All nodes running 2.6.50 or later understand feature LST_FEAT_BULK_LEN */
-static unsigned session_features = LST_FEATS_MASK;
+static unsigned int session_features = LST_FEATS_MASK;
static struct lstcon_trans_stat trans_stat;
typedef struct list_string {
return 0;
}
+int lst_yaml_session(const char *label, const char *timeout, int nlflags,
+ const char *errmsg)
+{
+ struct lstcon_ndlist_ent ndinfo = { };
+ struct lst_sid sid = LST_INVALID_SID;
+ /* nlflags being zero means we are destroying the session.
+ * No parsing of reply needed.
+ */
+ bool done = nlflags ? false : true;
+ char nid[LNET_NIDSTR_SIZE];
+ char name[LST_NAME_SIZE];
+ unsigned int key = 0;
+ yaml_emitter_t request;
+ yaml_parser_t reply;
+ yaml_event_t event;
+ struct nl_sock *sk;
+ int rc;
+
+ sk = nl_socket_alloc();
+ if (!sk)
+ return -1;
+
+ /* Note: NL_AUTO_PID == zero which we use by default for the
+ * session_key when creating a new session. This is considered
+ * an invalid key so we need to get the real session key from
+ * the yaml parser yet to be created. If the user did request
+ * a specific session key then set the socket's port id to this
+ * value.
+ */
+ if (session_key)
+ nl_socket_set_local_port(sk, session_key);
+
+ /* Setup reply parser to recieve Netlink packets */
+ rc = yaml_parser_initialize(&reply);
+ if (rc == 0) {
+ nl_socket_free(sk);
+ return -1;
+ }
+
+ rc = yaml_parser_set_input_netlink(&reply, sk, false);
+ if (rc == 0)
+ goto parser_error;
+
+ /* Create Netlink emitter to send request to kernel */
+ yaml_emitter_initialize(&request);
+ rc = yaml_emitter_set_output_netlink(&request, sk,
+ LNET_SELFTEST_GENL_NAME,
+ LNET_SELFTEST_GENL_VERSION,
+ LNET_SELFTEST_CMD_SESSIONS,
+ nlflags);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_emitter_open(&request);
+ yaml_document_start_event_initialize(&event, NULL, NULL, NULL, 0);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1, YAML_BLOCK_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"sessions",
+ strlen("sessions"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ if (!label) {
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"",
+ strlen(""), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+ goto skip_params;
+ }
+
+ /* sessions: { name: 'name', timeout: 300 }
+ * or
+ * sessions:
+ * name: 'name'
+ * timeout: 300
+ */
+ yaml_mapping_start_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_MAP_TAG,
+ 1, YAML_FLOW_MAPPING_STYLE);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"name",
+ strlen("name"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)label,
+ strlen(label), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ if (timeout) {
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)"timeout",
+ strlen("timeout"), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_scalar_event_initialize(&event, NULL,
+ (yaml_char_t *)YAML_STR_TAG,
+ (yaml_char_t *)timeout,
+ strlen(timeout), 1, 0,
+ YAML_PLAIN_SCALAR_STYLE);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+ }
+
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+skip_params:
+ yaml_mapping_end_event_initialize(&event);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ yaml_document_end_event_initialize(&event, 0);
+ rc = yaml_emitter_emit(&request, &event);
+ if (rc == 0)
+ goto emitter_error;
+
+ rc = yaml_emitter_close(&request);
+ if (rc == 0) {
+emitter_error:
+ yaml_emitter_log_error(&request, stderr);
+ yaml_emitter_delete(&request);
+ errmsg = NULL;
+ goto parser_error;
+ }
+ yaml_emitter_delete(&request);
+
+ while (!done) {
+ rc = yaml_parser_parse(&reply, &event);
+ if (rc == 0)
+ goto parser_error;
+
+ if (event.type == YAML_SCALAR_EVENT) {
+ char *tmp, *endp = NULL;
+
+ if (strcmp((char *)event.data.scalar.value,
+ "name") == 0) {
+ yaml_event_delete(&event);
+ rc = yaml_parser_parse(&reply, &event);
+ if (rc == 0)
+ goto parser_error;
+
+ strncpy(name, (char *)event.data.scalar.value,
+ sizeof(name) - 1);
+ }
+
+ if (strcmp((char *)event.data.scalar.value,
+ "key") == 0) {
+ yaml_event_delete(&event);
+ rc = yaml_parser_parse(&reply, &event);
+ if (rc == 0)
+ goto parser_error;
+
+ tmp = (char *)event.data.scalar.value;
+ key = strtoul(tmp, &endp, 10);
+ if (endp == tmp)
+ goto parser_error;
+ }
+
+ if (strcmp((char *)event.data.scalar.value,
+ "timestamp") == 0) {
+ yaml_event_delete(&event);
+ rc = yaml_parser_parse(&reply, &event);
+ if (rc == 0)
+ goto parser_error;
+
+ tmp = (char *)event.data.scalar.value;
+ sid.ses_stamp = strtoll(tmp, &endp, 10);
+ if (endp == tmp)
+ goto parser_error;
+ }
+
+ if (strcmp((char *)event.data.scalar.value,
+ "nid") == 0) {
+ yaml_event_delete(&event);
+ rc = yaml_parser_parse(&reply, &event);
+ if (rc == 0)
+ goto parser_error;
+
+ strncpy(nid, (char *)event.data.scalar.value,
+ sizeof(nid) - 1);
+ }
+
+ if (strcmp((char *)event.data.scalar.value,
+ "nodes") == 0) {
+ yaml_event_delete(&event);
+ rc = yaml_parser_parse(&reply, &event);
+ if (rc == 0)
+ goto parser_error;
+
+ tmp = (char *)event.data.scalar.value;
+ ndinfo.nle_nnode = strtoul(tmp, &endp, 10);
+ if (endp == tmp)
+ goto parser_error;
+ }
+ }
+
+ done = (event.type == YAML_STREAM_END_EVENT);
+
+ yaml_event_delete(&event);
+ }
+
+ if (nlflags & NLM_F_CREATE) {
+ session_features = yaml_parser_get_reader_proto_version(&reply);
+ session_key = key;
+ }
+parser_error:
+ if (rc == 0 && errmsg)
+ yaml_parser_log_error(&reply, stderr, errmsg);
+ yaml_parser_delete(&reply);
+ nl_socket_free(sk);
+
+ if (((nlflags & NLM_F_DUMP) == NLM_F_DUMP) && rc != 0) {
+ fprintf(stdout,
+ "%s ID: %ju@%s, KEY: %u FEATURES: %x NODES: %d\n",
+ name, (uintmax_t)sid.ses_stamp, nid,
+ key, session_features, ndinfo.nle_nnode);
+ }
+
+ return rc == 0 ? -1 : 0;
+}
+
int
lst_new_session_ioctl(char *name, int timeout, int force, struct lst_sid *sid)
{
jt_lst_new_session(int argc, char **argv)
{
char buf[LST_NAME_SIZE * 2 + 1];
- char *name;
+ char *name, *timeout_s = NULL;
+ int nlflags = NLM_F_CREATE;
+ struct lst_sid session_id;
int optidx = 0;
int timeout = 300;
int force = 0;
{ .name = "force", .has_arg = no_argument, .val = 'f' },
{ .name = NULL } };
- if (session_key == 0) {
- fprintf(stderr,
- "Can't find env LST_SESSION or value is not valid\n");
- return -1;
- }
-
while (1) {
-
c = getopt_long(argc, argv, "ft:",
session_opts, &optidx);
-
if (c == -1)
break;
switch (c) {
case 'f':
+ nlflags |= NLM_F_REPLACE;
force = 1;
break;
case 't':
- timeout = atoi(optarg);
+ timeout_s = optarg;
break;
default:
lst_print_usage(argv[0]);
}
}
- if (timeout <= 0) {
- fprintf(stderr, "Invalid timeout value\n");
- return -1;
- }
+ if (timeout_s) {
+ timeout = atoi(timeout_s);
+ if (timeout <= 0) {
+ fprintf(stderr, "Invalid timeout value\n");
+ return -1;
+ }
+ }
if (optind == argc - 1) {
name = argv[optind ++];
LST_NAME_SIZE - 1);
return -1;
}
-
} else if (optind == argc) {
char user[LST_NAME_SIZE];
char host[LST_NAME_SIZE];
snprintf(buf, sizeof(buf), "%s@%s", user, host);
name = buf;
-
} else {
lst_print_usage(argv[0]);
return -1;
}
+ rc = lst_yaml_session(name, timeout_s, nlflags, "new session");
+ if (rc == 0)
+ goto success;
+
+ if (session_key == 0) {
+ fprintf(stderr,
+ "Can't find env LST_SESSION or value is not valid\n");
+ return -1;
+ }
+
rc = lst_new_session_ioctl(name, timeout, force, &session_id);
if (rc != 0) {
lst_print_error("session", "Failed to create session: %s\n",
strerror(errno));
return rc;
}
-
+success:
fprintf(stdout, "SESSION: %s FEATURES: %x TIMEOUT: %d FORCE: %s\n",
name, session_features, timeout, force ? "Yes" : "No");
return 0;
{
struct lstcon_ndlist_ent ndinfo;
struct lst_sid sid;
- char name[LST_NAME_SIZE];
- unsigned feats;
- int key;
- int rc;
+ char name[LST_NAME_SIZE];
+ unsigned int feats;
+ int key;
+ int rc;
+
+ rc = lst_yaml_session(NULL, NULL, NLM_F_DUMP, "show session");
+ if (rc == 0)
+ return 0;
rc = lst_session_info_ioctl(name, sizeof(name), &key,
&feats, &sid, &ndinfo);
return -1;
}
+ rc = lst_yaml_session(NULL, NULL, 0, "end session");
+ if (rc == 0)
+ goto finish;
+
rc = lst_end_session_ioctl();
if (rc == 0) {
strerror(errno));
return rc;
}
-
+finish:
if (trans_stat.trs_rpc_errno != 0) {
fprintf(stderr,
"[RPC] Failed to send %d session RPCs: %s\n",