LMV_TYPE = 2,
CLI_TYPE = 3,
};
+int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, int *indices,
+ char **status, int *ost_count, enum tgt_type type);
int llapi_file_get_type_uuid(const char *path, enum tgt_type type,
struct obd_uuid *uuid);
int llapi_file_fget_type_uuid(int fd, enum tgt_type type,
int lustre_stats_dump(struct sk_buff *msg, struct netlink_callback *cb);
int lustre_stats_done(struct netlink_callback *cb);
+/**
+ * enum lustre_target_attrs - Lustre general top-level netlink
+ * attributes that describe lustre
+ * 'target_obd'. These values are used
+ * to piece togther messages for
+ * sending and receiving.
+ *
+ * @LUSTRE_TARGET_ATTR_UNSPEC: unspecified attribute to catch errors
+ *
+ * @LUSTRE_TARGET_ATTR_HDR: Netlink group this data is for
+ * (NLA_NUL_STRING)
+ * @LUSTRE_TARGET_ATTR_SOURCE: obd device targets belong too
+ * (NLA_STRING)
+ * @LUSTRE_TARGET_ATTR_PROP_LIST: list of target properties (NLA_NESTED)
+ */
+enum lustre_target_attrs {
+ LUSTRE_TARGET_ATTR_UNSPEC = 0,
+
+ LUSTRE_TARGET_ATTR_HDR,
+ LUSTRE_TARGET_ATTR_SOURCE,
+ LUSTRE_TARGET_ATTR_PROP_LIST,
+
+ __LUSTRE_TARGET_ATTR_MAX_PLUS_ONE,
+};
+
+#define LUSTRE_TARGET_ATTR_MAX (__LUSTRE_TARGET_ATTR_MAX_PLUS_ONE - 1)
+
+/**
+ * enum lustre_target_props_attrs
+ *
+ * @LUSTRE_TARGET_PROP_ATTR_UNSPEC: unspecified attribute to catch errors
+ * @LUSTRE_TARGET_PROP_ATTR_INDEX: target number used as an index (NLA_U16)
+ * @LUSTRE_DEVICE_PROP_ATTR_UUID: UUID of the target (NLA_STRING)
+ * @LUSTRE_DEVICE_PROP_ATTR_STATUS: status of the target (NLA_STRING)
+ */
+enum lustre_target_prop_attrs {
+ LUSTRE_TARGET_PROP_ATTR_UNSPEC = 0,
+
+ LUSTRE_TARGET_PROP_ATTR_INDEX,
+ LUSTRE_TARGET_PROP_ATTR_UUID,
+ LUSTRE_TARGET_PROP_ATTR_STATUS,
+
+ __LUSTRE_TARGET_PROP_ATTR_MAX_PLUS_ONE,
+};
+
+#define LUSTRE_TARGET_PROP_ATTR_MAX (__LUSTRE_TARGET_PROP_ATTR_MAX_PLUS_ONE - 1)
+
/* prototype for callback function on kuc groups */
typedef int (*libcfs_kkuc_cb_t)(void *data, void *cb_arg);
* @LUSTRE_CMD_UNSPEC: unspecified command to catch errors
*
* @LUSTRE_CMD_DEVICES: command to manage the Lustre devices
+ * @LUSTRE_CMD_TARGETS: command to manage the Lustre targets
* @LUSTRE_CMD_STATS: Lustre stats collection command
*/
enum lustre_commands {
LUSTRE_CMD_UNSPEC = 0,
LUSTRE_CMD_DEVICES = 1,
+ LUSTRE_CMD_TARGETS = 3,
LUSTRE_CMD_STATS = 5,
__LUSTRE_CMD_MAX_PLUS_ONE
}
LUSTRE_RW_ATTR(qos_threshold_rr);
-#ifdef CONFIG_PROC_FS
/* directories with exclude prefixes will be created on the same MDT as its
* parent directory, the prefixes are set with the rule as shell environment
* PATH: ':' is used as separator for prefixes. And for convenience, '+/-' is
OBD_FREE(buf, count + 1);
return count;
}
-LPROC_SEQ_FOPS(qos_exclude_prefixes);
+LDEBUGFS_SEQ_FOPS(qos_exclude_prefixes);
+
+static struct ldebugfs_vars ldebugfs_lmv_obd_vars[] = {
+ { .name = "qos_exclude_prefixes",
+ .fops = &qos_exclude_prefixes_fops },
+ { NULL }
+};
static void *lmv_tgt_seq_start(struct seq_file *p, loff_t *pos)
{
return rc;
seq = file->private_data;
- seq->private = pde_data(inode);
+ seq->private = inode->i_private;
return 0;
}
-static const struct proc_ops lmv_proc_target_fops = {
- PROC_OWNER(THIS_MODULE)
- .proc_open = lmv_target_seq_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = seq_release,
+static const struct file_operations lmv_debugfs_target_fops = {
+ .owner = THIS_MODULE,
+ .open = lmv_target_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
};
-static struct lprocfs_vars lprocfs_lmv_obd_vars[] = {
- { .name = "qos_exclude_prefixes",
- .fops = &qos_exclude_prefixes_fops },
- { .name = "target_obd",
- .fops = &lmv_proc_target_fops },
- { NULL }
-};
-#endif /* CONFIG_PROC_FS */
-
static struct attribute *lmv_attrs[] = {
&lustre_attr_activeobd.attr,
&lustre_attr_desc_uuid.attr,
int rc;
obd->obd_ktype.default_groups = KOBJ_ATTR_GROUPS(lmv);
-#ifdef CONFIG_PROC_FS
- obd->obd_vars = lprocfs_lmv_obd_vars;
-#endif
+ obd->obd_debugfs_vars = ldebugfs_lmv_obd_vars;
rc = lprocfs_obd_setup(obd, false);
if (rc)
goto out_failed;
goto out_failed;
}
#endif /* CONFIG_PROC_FS */
+ debugfs_create_file("target_obd", 0444, obd->obd_debugfs_entry,
+ obd, &lmv_debugfs_target_fops);
out_failed:
return rc;
}
return rc;
seq = file->private_data;
- seq->private = pde_data(inode);
+ seq->private = inode->i_private;
return 0;
}
{ NULL }
};
-static struct proc_ops lod_proc_target_fops = {
- PROC_OWNER(THIS_MODULE)
- .proc_open = lod_osts_seq_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = lprocfs_seq_release,
+static const struct file_operations lod_debugfs_target_fops = {
+ .owner = THIS_MODULE,
+ .open = lod_osts_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
};
static struct attribute *lod_attrs[] = {
GOTO(out, rc);
}
- rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd",
- 0444, &lod_proc_target_fops, obd);
- if (rc) {
- CWARN("%s: Error adding the target_obd file %d\n",
- obd->obd_name, rc);
- GOTO(out, rc);
- }
-
lod->lod_pool_proc_entry = lprocfs_register("pools",
obd->obd_proc_entry,
NULL, NULL);
ldebugfs_add_vars(obd->obd_debugfs_entry, ldebugfs_lod_vars, lod);
+ debugfs_create_file("target_obd", 0444, obd->obd_debugfs_entry,
+ obd, &lod_debugfs_target_fops);
+
lod->lod_debugfs = ldebugfs_add_symlink(obd->obd_name, "lov",
"../lod/%s", obd->obd_name);
if (!lod->lod_debugfs)
}
LUSTRE_RO_ATTR(desc_uuid);
-#ifdef CONFIG_PROC_FS
static void *lov_tgt_seq_start(struct seq_file *p, loff_t *pos)
{
struct obd_device *obd = p->private;
return rc;
seq = file->private_data;
- seq->private = pde_data(inode);
+ seq->private = inode->i_private;
return 0;
}
-static const struct proc_ops lov_proc_target_fops = {
- PROC_OWNER(THIS_MODULE)
- .proc_open = lov_target_seq_open,
- .proc_read = seq_read,
- .proc_lseek = seq_lseek,
- .proc_release = lprocfs_seq_release,
+static const struct file_operations lov_debugfs_target_fops = {
+ .owner = THIS_MODULE,
+ .open = lov_target_seq_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = seq_release,
};
-#endif /* CONFIG_PROC_FS */
static struct attribute *lov_attrs[] = {
&lustre_attr_activeobd.attr,
if (rc)
GOTO(out, rc);
+ debugfs_create_file("target_obd", 0444, obd->obd_debugfs_entry,
+ obd, &lov_debugfs_target_fops);
#ifdef CONFIG_PROC_FS
- rc = lprocfs_seq_create(obd->obd_proc_entry, "target_obd", 0444,
- &lov_proc_target_fops, obd);
- if (rc)
- CWARN("%s: Error adding the target_obd file : rc %d\n",
- obd->obd_name, rc);
-
lov->lov_pool_proc_entry = lprocfs_register("pools",
obd->obd_proc_entry,
NULL, NULL);
#define DEBUG_SUBSYSTEM S_CLASS
+#include <lustre_compat/linux/generic-radix-tree.h>
#include <linux/file.h>
#include <lustre_compat/linux/glob.h>
#include <linux/types.h>
return 0;
}
+/* target_obd handling */
+struct lu_tgt_list {
+ char ltl_src[MAX_OBD_NAME * 4];
+ struct lu_tgt_descs *ltl_desc;
+};
+
+struct genl_tgts_list {
+ unsigned int gol_index;
+ unsigned int gol_count;
+ GENRADIX(struct lu_tgt_list) gol_list;
+};
+
+static inline struct genl_tgts_list *
+target_dump_ctx(struct netlink_callback *cb)
+{
+ return (struct genl_tgts_list *)cb->args[0];
+}
+
+static int lustre_targets_done(struct netlink_callback *cb)
+{
+ struct genl_tgts_list *tlist = target_dump_ctx(cb);
+
+ if (tlist) {
+ genradix_free(&tlist->gol_list);
+ LIBCFS_FREE(tlist, sizeof(*tlist));
+ cb->args[0] = 0;
+ }
+
+ return 0;
+}
+
+/* generic ->start() handler for GET requests */
+static int lustre_targets_start(struct netlink_callback *cb)
+{
+ struct genlmsghdr *gnlh = nlmsg_data(cb->nlh);
+#ifdef HAVE_NL_PARSE_WITH_EXT_ACK
+ struct netlink_ext_ack *extack = NULL;
+#endif
+ int msg_len = genlmsg_len(gnlh);
+ struct genl_tgts_list *tlist;
+ unsigned long idx = 0;
+ int rc = 0;
+
+ LIBCFS_ALLOC(tlist, sizeof(*tlist));
+ if (!tlist) {
+ NL_SET_ERR_MSG(extack, "failed to setup obd list");
+ return -ENOMEM;
+ }
+ genradix_init(&tlist->gol_list);
+ tlist->gol_index = 0;
+ tlist->gol_count = 0;
+ cb->args[0] = (long)tlist;
+
+ if (msg_len > 0) {
+ struct nlattr *params = genlmsg_data(gnlh);
+ struct nlattr *target;
+ int rem;
+
+ if (!(nla_type(params) & LN_SCALAR_ATTR_LIST)) {
+ NL_SET_ERR_MSG(extack, "no configuration");
+ GOTO(report_err, rc = -EINVAL);
+ }
+
+ nla_for_each_nested(target, params, rem) {
+ struct nlattr *prop;
+ int rem2;
+
+ nla_for_each_nested(prop, target, rem2) {
+ char name[MAX_OBD_NAME * 4], *filter;
+ struct obd_device *obd;
+ char type[5];
+ ssize_t len;
+
+ if (nla_type(prop) != LN_SCALAR_ATTR_VALUE ||
+ nla_strcmp(prop, "source") != 0)
+ continue;
+
+ prop = nla_next(prop, &rem2);
+ if (nla_type(prop) != LN_SCALAR_ATTR_VALUE)
+ GOTO(report_err, rc = -EINVAL);
+
+ len = nla_strscpy(name, prop, sizeof(name));
+ if (len < 0)
+ GOTO(report_err, rc = (int)len);
+
+ filter = strim(name); /* remove any whitespaces */
+ len = strcspn(filter, ".") + 1;
+ strscpy(type, name, min_t(size_t, len, sizeof(type)));
+
+ obd_device_lock();
+ obd_device_for_each(idx, obd) {
+ struct lu_tgt_descs *ltd = NULL;
+ struct lu_tgt_list *ltl;
+
+ /* Only look at specific obds */
+ if (strncmp(obd->obd_type->typ_name,
+ LUSTRE_LMV_NAME,
+ strlen(LUSTRE_LMV_NAME)) == 0)
+ ltd = &obd->u.lmv.lmv_mdt_descs;
+ else if (strncmp(obd->obd_type->typ_name,
+ LUSTRE_LOV_NAME,
+ strlen(LUSTRE_LOV_NAME)) == 0)
+ ltd = &obd->u.lov.lov_ost_descs;
+ if (!ltd)
+ continue;
+
+ /* Now filter by obd_type */
+ if (!glob_match(type,
+ obd->obd_type->typ_name))
+ continue;
+
+ /* Filter by obd_name */
+ if (!glob_match(filter + len,
+ obd->obd_name))
+ continue;
+
+ ltl = genradix_ptr_alloc(&tlist->gol_list,
+ tlist->gol_count++,
+ GFP_ATOMIC);
+ if (!ltl) {
+ NL_SET_ERR_MSG(extack,
+ "failed to allocate target desc");
+ obd_device_unlock();
+ GOTO(report_err, rc = -ENOMEM);
+ }
+ scnprintf(ltl->ltl_src,
+ sizeof(ltl->ltl_src), "%s.%s",
+ obd->obd_type->typ_name,
+ obd->obd_name);
+ ltl->ltl_desc = ltd;
+ }
+ obd_device_unlock();
+ }
+ }
+ if (!tlist->gol_count)
+ rc = -ENOENT;
+ } else {
+ struct obd_device *obd;
+
+ obd_device_lock();
+ obd_device_for_each(idx, obd) {
+ struct lu_tgt_descs *ltd = NULL;
+ struct lu_tgt_list *ltl;
+
+ if (strcmp(obd->obd_type->typ_name,
+ LUSTRE_LMV_NAME) == 0)
+ ltd = &obd->u.lmv.lmv_mdt_descs;
+ else if (strcmp(obd->obd_type->typ_name,
+ LUSTRE_LOV_NAME) == 0)
+ ltd = &obd->u.lov.lov_ost_descs;
+ if (!ltd)
+ continue;
+
+ ltl = genradix_ptr_alloc(&tlist->gol_list,
+ tlist->gol_count++,
+ GFP_ATOMIC);
+ if (!ltl) {
+ NL_SET_ERR_MSG(extack,
+ "failed to allocate target desc");
+ obd_device_unlock();
+ GOTO(report_err, rc = -ENOMEM);
+ }
+
+ ltl->ltl_desc = ltd;
+ }
+ obd_device_unlock();
+ }
+report_err:
+ if (rc < 0)
+ lustre_targets_done(cb);
+
+ return rc;
+}
+
+static struct ln_key_list tgt_keys = {
+ .lkl_maxattr = LUSTRE_TARGET_ATTR_MAX,
+ .lkl_list = {
+ [LUSTRE_TARGET_ATTR_HDR] = {
+ .lkp_value = "target_obd",
+ .lkp_key_format = LNKF_SEQUENCE | LNKF_MAPPING,
+ .lkp_data_type = NLA_NUL_STRING,
+ },
+ [LUSTRE_TARGET_ATTR_SOURCE] = {
+ .lkp_value = "source",
+ .lkp_data_type = NLA_STRING,
+ },
+ [LUSTRE_TARGET_ATTR_PROP_LIST] = {
+ .lkp_value = "targets",
+ .lkp_key_format = LNKF_SEQUENCE | LNKF_MAPPING,
+ .lkp_data_type = NLA_NESTED,
+ },
+ },
+};
+
+static struct ln_key_list tgt_prop_keys = {
+ .lkl_maxattr = LUSTRE_TARGET_PROP_ATTR_MAX,
+ .lkl_list = {
+ [LUSTRE_TARGET_PROP_ATTR_INDEX] = {
+ .lkp_value = "index",
+ .lkp_data_type = NLA_U16
+ },
+ [LUSTRE_TARGET_PROP_ATTR_UUID] = {
+ .lkp_value = "uuid",
+ .lkp_data_type = NLA_STRING
+ },
+ [LUSTRE_TARGET_PROP_ATTR_STATUS] = {
+ .lkp_value = "status",
+ .lkp_data_type = NLA_STRING
+ },
+ },
+};
+
+static int lustre_targets_dump(struct sk_buff *msg,
+ struct netlink_callback *cb)
+{
+ struct genl_tgts_list *tlist = target_dump_ctx(cb);
+ struct genlmsghdr *gnlh = nlmsg_data(cb->nlh);
+#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;
+ int idx = tlist->gol_index;
+ int rc = 0;
+
+#ifdef HAVE_NL_DUMP_WITH_EXT_ACK
+ extack = cb->extack;
+#endif
+ if (!idx) {
+ const struct ln_key_list *all[] = {
+ &tgt_keys, &tgt_prop_keys, NULL
+ };
+
+ rc = lnet_genl_send_scalar_list(msg, portid, seq,
+ &lustre_family,
+ NLM_F_CREATE | NLM_F_MULTI,
+ LUSTRE_CMD_TARGETS, all);
+ if (rc < 0) {
+ NL_SET_ERR_MSG(extack, "failed to send key table");
+ GOTO(send_error, rc);
+ }
+ rc = 0;
+ }
+
+ while (idx < tlist->gol_count) {
+ struct lu_tgt_list *ltl;
+ struct lu_tgt_desc *tgt;
+ struct nlattr *tgt_list;
+ int j = 1;
+ void *hdr;
+
+ ltl = genradix_ptr(&tlist->gol_list, idx++);
+ if (!ltl)
+ continue;
+
+ hdr = genlmsg_put(msg, portid, seq, &lustre_family,
+ NLM_F_MULTI, LUSTRE_CMD_TARGETS);
+ if (!hdr) {
+ NL_SET_ERR_MSG(extack, "failed to send values");
+ genlmsg_cancel(msg, hdr);
+ GOTO(send_error, rc = -EMSGSIZE);
+ }
+
+ if (idx == 1)
+ nla_put_string(msg, LUSTRE_TARGET_ATTR_HDR, "");
+
+ nla_put_string(msg, LUSTRE_TARGET_ATTR_SOURCE,
+ ltl->ltl_src);
+
+ /* We just want the source */
+ if (!gnlh->version)
+ goto skip_details;
+
+ tgt_list = nla_nest_start(msg, LUSTRE_TARGET_ATTR_PROP_LIST);
+ ltd_foreach_tgt(ltl->ltl_desc, tgt) {
+ struct nlattr *tgt_attr;
+
+ tgt_attr = nla_nest_start(msg, j++);
+ nla_put_u16(msg, LUSTRE_TARGET_PROP_ATTR_INDEX, tgt->ltd_index);
+
+ nla_put_string(msg, LUSTRE_TARGET_PROP_ATTR_STATUS,
+ tgt->ltd_active ? "ACTIVE" : "INACTIVE");
+
+ nla_put_string(msg, LUSTRE_TARGET_PROP_ATTR_UUID,
+ obd_uuid2str(&tgt->ltd_uuid));
+ nla_nest_end(msg, tgt_attr);
+ }
+ nla_nest_end(msg, tgt_list);
+skip_details:
+ genlmsg_end(msg, hdr);
+ }
+
+ tlist->gol_index = idx;
+send_error:
+ return lnet_nl_send_error(cb->skb, portid, seq, rc);
+}
+
+#ifndef HAVE_NETLINK_CALLBACK_START
+int lustre_old_targets_dump(struct sk_buff *msg,
+ struct netlink_callback *cb)
+{
+ if (!cb->args[0]) {
+ int rc = lustre_targets_start(cb);
+
+ if (rc < 0)
+ return rc;
+ }
+
+ return lustre_targets_dump(msg, cb);
+}
+#endif
+
static struct ln_key_list stats_params = {
.lkl_maxattr = LUSTRE_PARAM_ATTR_MAX,
.lkl_list = {
static const struct genl_multicast_group lustre_mcast_grps[] = {
{ .name = "devices", },
+ { .name = "target_obd", },
{ .name = "stats", },
};
.done = lustre_device_done,
},
{
+ .cmd = LUSTRE_CMD_TARGETS,
+#ifdef HAVE_NETLINK_CALLBACK_START
+ .start = lustre_targets_start,
+ .dumpit = lustre_targets_dump,
+#else
+ .dumpit = lustre_old_targets_dump,
+#endif
+ .done = lustre_targets_done,
+ },
+ {
.cmd = LUSTRE_CMD_STATS,
#ifdef HAVE_NETLINK_CALLBACK_START
.start = lustre_stats_start,
return rc;
}
-#define OBD_NOT_FOUND (-1)
-
static bool lmv_is_foreign(__u32 magic)
{
return magic == LMV_MAGIC_FOREIGN;
return rc;
}
-/*
- * If uuidp is NULL, return the number of available obd uuids.
- * If uuidp is non-NULL, then it will return the uuids of the obds. If
- * there are more OSTs than allocated to uuidp, then an error is returned with
- * the ost_count set to number of available obd uuids.
- */
-static int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, int *indices,
- int *ost_count, enum tgt_type type)
-{
- char buf[PATH_MAX], format[32];
- int i, rc = 0;
- struct obd_uuid name;
- glob_t param;
- FILE *fp;
-
- /* Get the lov name */
- rc = llapi_file_fget_type_uuid(fd, type, &name);
- if (rc != 0)
- return rc;
-
- /* Now get the ost uuids */
- rc = get_lustre_param_path(type == LOV_TYPE ? "lov" : "lmv", name.uuid,
- FILTER_BY_EXACT, "target_obd", ¶m);
- if (rc != 0)
- return -ENOENT;
-
- fp = fopen(param.gl_pathv[0], "r");
- if (fp == NULL) {
- rc = -errno;
- llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'",
- param.gl_pathv[0]);
- goto free_param;
- }
-
- snprintf(format, sizeof(format),
- "%%d: %%%zus", sizeof(uuidp[0].uuid) - 1);
- for (i = 0; fgets(buf, sizeof(buf), fp); i++) {
- int index;
-
- if (sscanf(buf, format, &index, name.uuid) < 2)
- break;
-
- if (i < *ost_count) {
- if (uuidp != NULL)
- uuidp[i] = name;
- if (indices != NULL)
- indices[i] = index;
- }
- }
- fclose(fp);
-
- if (uuidp && (i > *ost_count))
- rc = -EOVERFLOW;
-
- *ost_count = i;
-free_param:
- cfs_free_param_data(¶m);
- return rc;
-}
-
-int llapi_lmv_get_uuids(int fd, struct obd_uuid *uuidp, int *mdt_count)
-{
- return llapi_get_target_uuids(fd, uuidp, NULL, mdt_count, LMV_TYPE);
-}
-
-int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count)
-{
- return llapi_get_target_uuids(fd, uuidp, NULL, ost_count, LOV_TYPE);
-}
-
int llapi_get_obd_count(char *mnt, int *count, int is_mdt)
{
int root;
}
/*
- * Here, param->fp_obd_uuid points to a single obduuid, the index of which is
- * returned in param->fp_obd_index
- */
-static int setup_obd_uuid(int fd, char *dname, struct find_param *param)
-{
- struct obd_uuid obd_uuid;
- char buf[PATH_MAX];
- glob_t param_data;
- char format[32];
- int rc = 0;
- FILE *fp;
- enum tgt_type type = param->fp_get_lmv ? LMV_TYPE : LOV_TYPE;
-
- if (param->fp_got_uuids)
- return rc;
-
- /* Get the lov/lmv name */
- rc = llapi_file_fget_type_uuid(fd, type, &obd_uuid);
- if (rc) {
- if (rc != -ENOTTY) {
- llapi_error(LLAPI_MSG_ERROR, rc,
- "error: can't get %s name: %s",
- param->fp_get_lmv ? "lmv" : "lov",
- dname);
- } else {
- rc = 0;
- }
- return rc;
- }
-
- param->fp_got_uuids = 1;
-
- /* Now get the ost uuids */
- rc = get_lustre_param_path(param->fp_get_lmv ? "lmv" : "lov",
- obd_uuid.uuid, FILTER_BY_EXACT,
- "target_obd", ¶m_data);
- if (rc != 0)
- return -ENOENT;
-
- fp = fopen(param_data.gl_pathv[0], "r");
- if (fp == NULL) {
- rc = -errno;
- llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'",
- param_data.gl_pathv[0]);
- goto free_param;
- }
-
- if (!param->fp_obd_uuid && !param->fp_quiet && !param->fp_obds_printed)
- llapi_printf(LLAPI_MSG_NORMAL, "%s:\n",
- param->fp_get_lmv ? "MDTS" : "OBDS");
-
- snprintf(format, sizeof(format),
- "%%d: %%%zus", sizeof(obd_uuid.uuid) - 1);
- while (fgets(buf, sizeof(buf), fp) != NULL) {
- int index;
-
- if (sscanf(buf, format, &index, obd_uuid.uuid) < 2)
- break;
-
- if (param->fp_obd_uuid) {
- if (llapi_uuid_match(obd_uuid.uuid,
- param->fp_obd_uuid->uuid)) {
- param->fp_obd_index = index;
- break;
- }
- } else if (!param->fp_quiet && !param->fp_obds_printed) {
- /* Print everything */
- llapi_printf(LLAPI_MSG_NORMAL, "%s", buf);
- }
- }
- param->fp_obds_printed = 1;
-
- fclose(fp);
-
- if (param->fp_obd_uuid && (param->fp_obd_index == OBD_NOT_FOUND)) {
- llapi_err_noerrno(LLAPI_MSG_ERROR,
- "error: %s: unknown obduuid: %s",
- __func__, param->fp_obd_uuid->uuid);
- rc = -EINVAL;
- }
-free_param:
- cfs_free_param_data(¶m_data);
- return rc;
-}
-
-/*
* In this case, param->fp_obd_uuid will be an array of obduuids and
* obd index for all these obduuids will be returned in
* param->fp_obd_indexes
}
retry_get_uuids:
- ret = llapi_get_target_uuids(d, uuids, indices, &obdcount, type);
+ ret = llapi_get_target_uuids(d, uuids, indices, NULL, &obdcount, type);
if (ret) {
if (ret == -EOVERFLOW) {
struct obd_uuid *uuids_temp;
return ret;
}
-int llapi_ostlist(char *path, struct find_param *param)
-{
- int fd;
- int ret;
-
- fd = open(path, O_RDONLY | O_DIRECTORY);
- if (fd < 0)
- return -errno;
-
- ret = setup_obd_uuid(fd, path, param);
- close(fd);
-
- return ret;
-}
-
/*
* Tries to determine the default stripe attributes for a given filesystem. The
* filesystem to check should be specified by fsname, or will be determined
if (param->fp_obd_uuid) {
param->fp_quiet = 1;
- ret = setup_obd_uuid(d != -1 ? d : p, path, param);
+ ret = llapi_ostlist(path, param);
if (ret)
return ret;
}
return rc;
}
+static int print_out_targets(yaml_parser_t *reply, int version, int flags)
+{
+ char buf[PATH_MAX / 2], *tmp = NULL;
+ size_t buf_len = sizeof(buf);
+ yaml_event_t event;
+ bool done = false;
+ int rc;
+
+ while (!done) {
+ rc = yaml_parser_parse(reply, &event);
+ if (rc == 0)
+ break;
+
+ if (event.type == YAML_SCALAR_EVENT) {
+ char *value = (char *)event.data.scalar.value;
+
+ if (strcmp(value, "source") == 0) {
+ rc = yaml_parser_parse(reply, &event);
+ if (rc == 0)
+ break;
+
+ if (event.type != YAML_SCALAR_EVENT)
+ return -EINVAL;
+
+ value = (char *)event.data.scalar.value;
+
+ if (!version) {
+ fprintf(stdout, "%s.target_obd\n",
+ value);
+ } else if (flags & PARAM_FLAGS_SHOW_SOURCE) {
+ fprintf(stdout, "%s.target_obd=\n",
+ value);
+ }
+ } else if (strcmp(value, "index") == 0 && version) {
+ memset(buf, 0, buf_len);
+ tmp = buf;
+
+ rc = yaml_parser_parse(reply, &event);
+ if (rc == 0)
+ break;
+
+ if (event.type != YAML_SCALAR_EVENT)
+ return -EINVAL;
+
+ value = (char *)event.data.scalar.value;
+ snprintf(tmp, buf_len, "%s: ", value);
+ tmp += strlen(value) + 2;
+ buf_len -= strlen(value) + 2;
+ } else if (strcmp(value, "uuid") == 0 && version) {
+ rc = yaml_parser_parse(reply, &event);
+ if (rc == 0)
+ break;
+
+ if (event.type != YAML_SCALAR_EVENT ||
+ !tmp)
+ return -EINVAL;
+
+ value = (char *)event.data.scalar.value;
+ snprintf(tmp, buf_len, "%s", value);
+ tmp += strlen(value) + 2;
+ buf_len -= strlen(value) + 2;
+ } else if (strcmp(value, "status") == 0 && version) {
+ rc = yaml_parser_parse(reply, &event);
+ if (rc == 0)
+ break;
+
+ if (event.type != YAML_SCALAR_EVENT)
+ return -EINVAL;
+
+ value = (char *)event.data.scalar.value;
+ fprintf(stdout, "%s %s\n", buf, value);
+ }
+ }
+
+ done = (event.type == YAML_DOCUMENT_END_EVENT);
+ yaml_event_delete(&event);
+ }
+ return rc == 1 ? 0 : -EINVAL;
+}
+
static int print_out_stats(yaml_parser_t *reply, int version, int flags)
{
bool show_path = flags & PARAM_FLAGS_SHOW_SOURCE;
if (strcmp(group, "devices") == 0)
cmd = LUSTRE_CMD_DEVICES;
+ else if (strcmp(group, "target_obd") == 0)
+ cmd = LUSTRE_CMD_TARGETS;
else if (strcmp(group, "stats") == 0)
cmd = LUSTRE_CMD_STATS;
if (strcmp(value, "devices") == 0)
rc = print_out_devices(&reply, flags);
+ else if (strcmp(value, "target_obd") == 0)
+ rc = print_out_targets(&reply, version,
+ flags);
else if (strcmp(value, "stats") == 0)
rc = print_out_stats(&reply, version,
flags);
return rc == 1 ? 0 : rc;
}
+/*
+ * If uuidp is NULL, return the number of available obd uuids.
+ * If uuidp is non-NULL, then it will return the uuids of the obds. If
+ * there are more OSTs than allocated to uuidp, then an error is returned with
+ * the ost_count set to number of available obd uuids.
+ */
+int llapi_get_target_uuids(int fd, struct obd_uuid *uuidp, int *indices,
+ char **status, int *ost_count, enum tgt_type type)
+{
+ struct obd_uuid name;
+ char buf[PATH_MAX];
+ int rc = 0, i = 0;
+ glob_t param;
+ FILE *fp;
+
+ /* Get the lov / lmv name */
+ rc = llapi_file_fget_type_uuid(fd, type, &name);
+ if (rc != 0)
+ return rc;
+
+ /* Now get the ost uuids */
+ rc = get_lustre_param_path(type == LOV_TYPE ? "lov" : "lmv", name.uuid,
+ FILTER_BY_EXACT, "target_obd", ¶m);
+ if (rc != 0) {
+ yaml_parser_t reply;
+ yaml_event_t event;
+ struct nl_sock *sk;
+ bool done = false;
+
+ sk = nl_socket_alloc();
+ if (!sk)
+ return -ENOMEM;
+
+ snprintf(buf, sizeof(buf), "%s.%s.target_obd",
+ type == LOV_TYPE ? "lov" : "lmv", name.uuid);
+
+ rc = lcfg_param_get_yaml(&reply, sk, LUSTRE_GENL_VERSION,
+ NLM_F_DUMP, buf);
+ if (rc < 0) {
+ if (rc == -EOPNOTSUPP)
+ goto old_api;
+ return rc;
+ }
+
+ while (!done) {
+ rc = yaml_parser_parse(&reply, &event);
+ if (rc == 0)
+ break;
+
+ if ((!*ost_count || i < *ost_count) &&
+ event.type == YAML_SCALAR_EVENT) {
+ char *value = (char *)event.data.scalar.value;
+
+ if (strcmp(value, "index") == 0) {
+ if (indices != NULL) {
+ yaml_event_delete(&event);
+ rc = yaml_parser_parse(&reply,
+ &event);
+ if (rc == 0)
+ break;
+
+ value = (char *)event.data.scalar.value;
+ indices[i] = strtoul(value, NULL, 10);
+ if (indices[i] == ULONG_MAX)
+ break;
+ }
+ }
+
+ if (strcmp(value, "uuid") == 0) {
+ if (uuidp != NULL) {
+ yaml_event_delete(&event);
+ rc = yaml_parser_parse(&reply,
+ &event);
+ if (rc == 0)
+ break;
+
+ strcpy(uuidp[i].uuid,
+ (char *)event.data.scalar.value);
+ }
+ }
+
+ if (strcmp(value, "status") == 0) {
+ if (status != NULL) {
+ yaml_event_delete(&event);
+ rc = yaml_parser_parse(&reply,
+ &event);
+ if (rc == 0)
+ break;
+
+ value = (char *)event.data.scalar.value;
+ status[i] = strdup(value);
+ }
+ i++; /* status is last */
+ }
+ }
+
+ done = (event.type == YAML_STREAM_END_EVENT);
+ yaml_event_delete(&event);
+ }
+
+ if (rc == 0) {
+ yaml_parser_log_error(&reply, stderr, "llapi_get_target_uuids: ");
+ rc = -EINVAL;
+ }
+
+ if (indices && indices[i] == ULONG_MAX)
+ rc = -ERANGE;
+
+ if (uuidp && (i > *ost_count))
+ rc = -EOVERFLOW;
+
+ if (status && (i > *ost_count))
+ rc = -EOVERFLOW;
+
+ *ost_count = i;
+
+ return rc == 1 ? 0 : rc;
+ }
+old_api:
+ fp = fopen(param.gl_pathv[0], "r");
+ if (fp == NULL) {
+ rc = -errno;
+ llapi_error(LLAPI_MSG_ERROR, rc, "error: opening '%s'",
+ param.gl_pathv[0]);
+ goto free_param;
+ }
+
+ for (i = 0; fgets(buf, sizeof(buf), fp); i++) {
+ char state[10];
+ int index;
+
+ if (sscanf(buf, "%d: %s %s", &index, name.uuid, state) < 3)
+ break;
+
+ if (i < *ost_count) {
+ if (uuidp != NULL)
+ uuidp[i] = name;
+ if (indices != NULL)
+ indices[i] = index;
+ if (status != NULL)
+ status[i] = strdup(state);
+ }
+ }
+
+ if (uuidp && (i > *ost_count))
+ rc = -EOVERFLOW;
+
+ if (status && (i > *ost_count))
+ rc = -EOVERFLOW;
+
+ *ost_count = i;
+free_param:
+ cfs_free_param_data(¶m);
+ return rc;
+}
+
+int llapi_lmv_get_uuids(int fd, struct obd_uuid *uuidp, int *mdt_count)
+{
+ return llapi_get_target_uuids(fd, uuidp, NULL, NULL, mdt_count, LMV_TYPE);
+}
+
+int llapi_lov_get_uuids(int fd, struct obd_uuid *uuidp, int *ost_count)
+{
+ return llapi_get_target_uuids(fd, uuidp, NULL, NULL, ost_count, LOV_TYPE);
+}
+
+int llapi_ostlist(char *path, struct find_param *param)
+{
+ struct obd_uuid *uuidp;
+ int *indices, fd;
+ char **status;
+ int obdcount;
+ int i, rc;
+
+ if (param->fp_got_uuids)
+ return 0;
+
+ rc = llapi_get_obd_count(path, &obdcount, param->fp_get_lmv);
+ if (rc < 0)
+ return rc;
+
+ uuidp = calloc(obdcount, sizeof(*uuidp));
+ if (uuidp == NULL)
+ return -ENOMEM;
+
+ indices = calloc(obdcount, sizeof(*indices));
+ if (indices == NULL) {
+ rc = -ENOMEM;
+ goto out_uuidp;
+ }
+
+ status = calloc(obdcount, sizeof(*status));
+ if (status == NULL) {
+ rc = -ENOMEM;
+ goto out_indices;
+ }
+
+ fd = open(path, O_RDONLY);
+ if (fd < 0) {
+ rc = -errno;
+ goto out_status;
+ }
+
+ rc = llapi_get_target_uuids(fd, uuidp, indices, status, &obdcount,
+ param->fp_get_lmv ? LMV_TYPE : LOV_TYPE);
+ if (rc < 0) {
+ close(fd);
+ goto out_status;
+ }
+
+ param->fp_got_uuids = 1;
+
+ if (!param->fp_obd_uuid && !param->fp_quiet && !param->fp_obds_printed)
+ llapi_printf(LLAPI_MSG_NORMAL, "%s:\n",
+ param->fp_get_lmv ? "MDTS" : "OBDS");
+
+ for (i = 0; i < obdcount; i++) {
+ if (param->fp_obd_uuid) {
+ if (llapi_uuid_match(uuidp[i].uuid,
+ param->fp_obd_uuid->uuid)) {
+ param->fp_obd_index = indices[i];
+ break;
+ }
+ } else if (!param->fp_quiet && !param->fp_obds_printed) {
+ /* Print everything */
+ llapi_printf(LLAPI_MSG_NORMAL, "%d: %s %s\n",
+ indices[i], uuidp[i].uuid, status[i]);
+ }
+ }
+ param->fp_obds_printed = 1;
+
+ if (param->fp_obd_uuid && (param->fp_obd_index == OBD_NOT_FOUND)) {
+ llapi_err_noerrno(LLAPI_MSG_ERROR,
+ "error: %s: unknown obduuid: %s",
+ __func__, param->fp_obd_uuid->uuid);
+ rc = -EINVAL;
+ }
+
+ close(fd);
+out_status:
+ free(status);
+out_indices:
+ free(indices);
+out_uuidp:
+ free(uuidp);
+
+ return rc;
+}
+
/**
* Read the value of the file with location \a path
* into a buffer.
if (rc == 0)
rc = rc2;
- if (rc2 == -ENOENT && getuid() != 0)
+ if (rc2 == -ENOENT && getuid() != 0) {
rc2 = llapi_param_display_value(path, 0,
PARAM_FLAGS_SHOW_SOURCE,
stdout);
+ }
if (rc2 < 0) {
fprintf(stderr, "error: %s: listing '%s': %s\n",
jt_cmdname(argv[0]), path,
#define LUSTRE_ENCRYPTION_UNIT_SIZE ((size_t)1 << LUSTRE_ENCRYPTION_BLOCKBITS)
#define LUSTRE_ENCRYPTION_MASK (~(LUSTRE_ENCRYPTION_UNIT_SIZE - 1))
+#define OBD_NOT_FOUND (-1)
+
/* mount point listings in /proc/mounts */
#ifndef PROC_MOUNTS
#define PROC_MOUNTS "/proc/mounts"