for (count = 1; count <= list->lkl_maxattr; count++) {
struct nlattr *key = nla_nest_start(msg, count);
+ int end, start = msg->len;
if (!key)
return -EMSGSIZE;
idx = rc;
}
- nla_nest_end(msg, key);
+ end = nla_nest_end(msg, key);
+ CDEBUG(D_INFO, "nest attr[%d] length = %d\n", count, end - start);
}
nla_nest_end(msg, node);
struct lprocfs_stats {
/* source for the stats */
- char *ls_source;
+ char ls_source[MAX_OBD_NAME * 4];
/* index in Xarray */
unsigned int ls_index;
/* # of counters */
extern void lprocfs_init_ldlm_stats(struct lprocfs_stats *ldlm_stats);
struct lprocfs_stats *ldebugfs_stats_alloc(int num, char *name,
struct dentry *entry,
- struct kobject *kobj,
enum lprocfs_stats_flags flags);
extern int ldebugfs_alloc_obd_stats(struct obd_device *obd,
unsigned int num_stats);
struct ldlm_namespace *ns = ldlm_pl2ns(pl);
struct dentry *debugfs_ns_parent;
struct ldebugfs_vars pool_vars[2];
+ char param[MAX_OBD_NAME * 4];
int rc = 0;
ENTRY;
-
debugfs_ns_parent = ns->ns_debugfs_entry;
if (IS_ERR_OR_NULL(debugfs_ns_parent)) {
CERROR("%s: debugfs entry is not initialized\n",
ldlm_add_var(&pool_vars[0], pl->pl_debugfs_entry, "state", pl,
&lprocfs_pool_state_fops);
+ scnprintf(param, sizeof(param), "ldlm.namespaces.%s.pool.stats",
+ ldlm_ns_name(ns));
pl->pl_stats = ldebugfs_stats_alloc(LDLM_POOL_LAST_STAT -
- LDLM_POOL_FIRST_STAT, "stats",
- pl->pl_debugfs_entry,
- &pl->pl_kobj, 0);
+ LDLM_POOL_FIRST_STAT, param,
+ pl->pl_debugfs_entry, 0);
if (!pl->pl_stats)
GOTO(out, rc = -ENOMEM);
int ll_debugfs_register_super(struct super_block *sb, const char *name)
{
struct ll_sb_info *sbi = ll_s2sbi(sb);
+ char param[MAX_OBD_NAME * 4];
int err, id;
ENTRY;
&ll_rw_offset_stats_fops);
/* File operations stats */
- sbi->ll_stats = ldebugfs_stats_alloc(LPROC_LL_FILE_OPCODES, "stats",
+ scnprintf(param, sizeof(param), "llite.%s.stats", name);
+ sbi->ll_stats = ldebugfs_stats_alloc(LPROC_LL_FILE_OPCODES, param,
sbi->ll_debugfs_entry,
- &sbi->ll_kset.kobj,
LPROCFS_STATS_FLAG_NONE);
if (!sbi->ll_stats)
GOTO(out_debugfs, err = -ENOMEM);
}
EXPORT_SYMBOL(lustre_stats_done);
-/* Min size for key table and its matching values:
+/* Min size for key table and its matching values. Key value
+ * measurements are collected from lnet_genl_parse_list:
+ *
* header strlen("stats")
- * source strlen("source") + MAX_OBD_NAME * 2
+ * source strlen("source") + MAX_OBD_NAME * 4
* timestamp strlen("snapshot_time") + s64
* start time strlen("start time") + s64
* elapsed_time strlen("elapse time") + s64
*/
-#define STATS_MSG_MIN_SIZE (267 + 58)
+#define STATS_MSG_MIN_SIZE (44 + 28 + 36 + 32 + 36 + 536)
-/* key table + values for each dataset entry:
+/* key table + values for each dataset entry. Key value
+ * measurements are collected from lnet_genl_parse_list:
+ *
* dataset name 25
* dataset count strlen("samples") + u64
* dataset units strlen("units") + 5
* dataset sum strlen("sum") + u64
* dataset stdev strlen("stddev") + u64
*/
-#define STATS_MSG_DATASET_SIZE (97)
+#define STATS_MSG_DATASET_SIZE (236 + 25 + 5 + 8 * 5)
static int lustre_stats_start(struct netlink_callback *cb)
{
int rem2;
nla_for_each_nested(item, dev, rem2) {
- char filter[MAX_OBD_NAME * 2];
+ char filter[MAX_OBD_NAME * 4];
if (nla_type(item) != LN_SCALAR_ATTR_VALUE ||
nla_strcmp(item, "source") != 0)
continue;
item = nla_next(item, &rem2);
- if (nla_type(item) != LN_SCALAR_ATTR_VALUE) {
+ if (!nla_ok(item, rem2) ||
+ nla_type(item) != LN_SCALAR_ATTR_VALUE) {
NL_SET_ERR_MSG(extack,
"source has invalid value");
GOTO(report_err, rc = -EINVAL);
rc = nla_strscpy(filter, item, sizeof(filter));
if (rc < 0) {
NL_SET_ERR_MSG(extack,
- "source key string is invalud");
+ "source key string is invalid");
GOTO(report_err, rc);
}
continue;
nla_for_each_nested(prop, attr, rem2) {
- char source[MAX_OBD_NAME * 2];
+ char source[MAX_OBD_NAME * 4];
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)
+ if (!nla_ok(prop, rem2) ||
+ nla_type(prop) != LN_SCALAR_ATTR_VALUE)
GOTO(report_err, rc = -EINVAL);
memset(source, 0, sizeof(source));
stats->ls_init = ktime_get_real();
spin_lock_init(&stats->ls_lock);
kref_init(&stats->ls_refcount);
- stats->ls_source = NULL;
stats->ls_index = -1;
/* alloc num of counter headers */
struct lprocfs_stats *ldebugfs_stats_alloc(int num, char *name,
struct dentry *debugfs_entry,
- struct kobject *kobj,
enum lprocfs_stats_flags flags)
{
struct lprocfs_stats *stats = lprocfs_stats_alloc(num, flags);
+ size_t len = strlen(name);
char *param;
int rc;
atomic_inc(&lstats_count);
xa_unlock(&lstats_list);
- stats->ls_source = kobject_get_path(kobj, GFP_KERNEL);
- if (!stats->ls_source) {
- lprocfs_stats_free(&stats);
- return NULL;
+ param = strrchr(name, '.');
+ if (param) {
+ len -= strlen(param);
+ param++;
+ } else {
+ param = name;
}
- param = stats->ls_source;
- while ((param = strchr(param, '/')) != NULL)
- *param = '.';
-
- debugfs_create_file(name, 0644, debugfs_entry, stats,
+ strscpy(stats->ls_source, name, len + 1);
+ debugfs_create_file(param, 0644, debugfs_entry, stats,
&ldebugfs_stats_seq_fops);
return stats;
}
xa_unlock(&lstats_list);
}
- kfree(stats->ls_source); /* allocated by kobject_get_path */
-
LIBCFS_FREE(stats, offsetof(typeof(*stats), ls_percpu[num_entry]));
}
unsigned int lustre_stats_scan(struct lustre_stats_list *slist, const char *source)
{
struct lprocfs_stats *item, **stats;
- unsigned int cnt = 0, snum;
- const char *tmp = source;
+ unsigned int cnt = 0, snum = 0, i;
unsigned long idx = 0;
- if (source)
- for (snum = 0; tmp[snum]; tmp[snum] == '.' ? snum++ : *tmp++);
+ if (source) {
+ for (i = 0; source[i]; i++) {
+ if (source[i] == '.')
+ snum++;
+ }
+ }
xa_for_each(&lstats_list, idx, item) {
if (!kref_get_unless_zero(&item->ls_refcount))
}
if (source) {
- char filter[PATH_MAX / 8], *src = item->ls_source;
- unsigned int num;
-
- if (strstarts(src, ".fs.lustre."))
- src += strlen(".fs.lustre.");
+ char filter[MAX_OBD_NAME * 4], *src = item->ls_source;
+ unsigned int num = 0;
/* glob_match() has a hard time telling *.* from *.*.*
* from *.*.* so we need to compare the number of '.'
* and filter on that as well. This actually avoids
* the overhead of calling glob_match() every time.
*/
- tmp = src;
- for (num = 0; tmp[num]; tmp[num] == '.' ? num++ : *tmp++);
+ for (i = 0; src[i]; i++) {
+ if (src[i] == '.')
+ num++;
+ }
+
if (snum != num) {
lprocfs_stats_free(&item);
continue;
} else {
strscpy(filter, source, strlen(source) + 1);
}
+
if (!glob_match(filter, src)) {
lprocfs_stats_free(&item);
continue;
int ldebugfs_alloc_obd_stats(struct obd_device *obd, unsigned int num_stats)
{
+ char param[MAX_OBD_NAME * 4];
+
LASSERT(!obd->obd_stats);
- obd->obd_stats = ldebugfs_stats_alloc(num_stats, "stats",
- obd->obd_debugfs_entry,
- &obd->obd_type->typ_kobj, 0);
+ scnprintf(param, sizeof(param), "%s.%s.stats", obd->obd_type->typ_name,
+ obd->obd_name);
+ obd->obd_stats = ldebugfs_stats_alloc(num_stats, param,
+ obd->obd_debugfs_entry, 0);
return obd->obd_stats ? 0 : -ENOMEM;
}
EXPORT_SYMBOL(ldebugfs_alloc_obd_stats);
* to /proc incrementally as the ofd is setup
*/
obd->obd_ktype.default_groups = KOBJ_ATTR_GROUPS(ofd);
+ obd->obd_debugfs_vars = ldebugfs_ofd_obd_vars;
obd->obd_vars = lprocfs_ofd_obd_vars;
rc = lprocfs_obd_setup(obd, false);
if (rc) {
obd->obd_name, rc);
RETURN(rc);
}
- ldebugfs_add_vars(obd->obd_debugfs_entry, ldebugfs_ofd_obd_vars, obd);
rc = tgt_tunables_init(&ofd->ofd_lut);
if (rc) {
static int osd_stats_init(struct osd_device *osd)
{
+ char param[MAX_OBD_NAME * 4];
int result = -ENOMEM;
ENTRY;
- osd->od_stats = ldebugfs_stats_alloc(LPROC_OSD_LAST, "stats",
+ scnprintf(param, sizeof(param), "osd-zfs.%s.stats", osd_name(osd));
+ osd->od_stats = ldebugfs_stats_alloc(LPROC_OSD_LAST, param,
osd->od_dt_dev.dd_debugfs_entry,
- &osd->od_dt_dev.dd_kobj, 0);
+ 0);
if (osd->od_stats) {
lprocfs_counter_init(osd->od_stats, LPROC_OSD_GET_PAGE,
LPROCFS_TYPE_LATENCY, "get_page");
static int osd_stats_init(struct osd_device *osd)
{
+ char param[MAX_OBD_NAME * 4];
int result = -ENOMEM;
ENTRY;
- osd->od_stats = ldebugfs_stats_alloc(LPROC_OSD_LAST, "stats",
+ scnprintf(param, sizeof(param), "osd-zfs.%s.stats", osd_name(osd));
+ osd->od_stats = ldebugfs_stats_alloc(LPROC_OSD_LAST, param,
osd->od_dt_dev.dd_debugfs_entry,
- &osd->od_dt_dev.dd_kobj, 0);
+ 0);
if (osd->od_stats) {
lprocfs_counter_init(osd->od_stats, LPROC_OSD_GET_PAGE,
LPROCFS_CNTR_AVGMINMAX | LPROCFS_CNTR_STDDEV |
/* Since we register the obd device with ptlrpc / sptlrpc we
* have to register debugfs with obd_device
*/
- obd->obd_debugfs_entry = debugfs_create_dir(
- obd->obd_name, obd->obd_type->typ_debugfs_entry);
+ obd->obd_debugfs_entry = debugfs_create_dir(obd->obd_name,
+ obd->obd_type->typ_debugfs_entry);
ldebugfs_add_vars(obd->obd_debugfs_entry, obd->obd_debugfs_vars, obd);
sptlrpc_lprocfs_cliobd_attach(obd);
static void
ptlrpc_ldebugfs_register(struct dentry *root, char *dir, char *name,
struct dentry **debugfs_root_ret,
- struct kobject *kobj,
struct lprocfs_stats **stats_ret)
{
struct dentry *svc_debugfs_entry;
LPROCFS_CNTR_STDDEV;
int i;
- LASSERT(!*debugfs_root_ret);
LASSERT(!*stats_ret);
-
if (dir)
svc_debugfs_entry = debugfs_create_dir(dir, root);
else
svc_debugfs_entry = root;
svc_stats = ldebugfs_stats_alloc(EXTRA_MAX_OPCODES + LUSTRE_MAX_OPCODES,
- name, svc_debugfs_entry, kobj, 0);
+ name, svc_debugfs_entry, 0);
if (!svc_stats)
return;
&parent->kobj, "%s", svc->srv_name);
}
-void ptlrpc_ldebugfs_register_service(struct dentry *entry,
+void ptlrpc_ldebugfs_register_service(struct dentry *entry, char *param,
struct ptlrpc_service *svc)
{
struct ldebugfs_vars ldebugfs_vars[] = {
.release = lprocfs_seq_release,
};
- ptlrpc_ldebugfs_register(entry, svc->srv_name, "stats",
- &svc->srv_debugfs_entry,
- &svc->srv_kobj, &svc->srv_stats);
+ ptlrpc_ldebugfs_register(entry, svc->srv_name, param,
+ &svc->srv_debugfs_entry, &svc->srv_stats);
if (!svc->srv_debugfs_entry)
return;
void ptlrpc_lprocfs_register_obd(struct obd_device *obd)
{
- ptlrpc_ldebugfs_register(obd->obd_debugfs_entry, NULL, "stats",
+ char param[MAX_OBD_NAME * 4];
+
+ scnprintf(param, sizeof(param), "%s.%s.stats",
+ kobject_name(&obd->obd_type->typ_kobj), obd->obd_name);
+ ptlrpc_ldebugfs_register(obd->obd_debugfs_entry, NULL, param,
&obd->obd_svc_debugfs_entry,
- &obd->obd_kset.kobj,
&obd->obd_svc_stats);
}
EXPORT_SYMBOL(ptlrpc_lprocfs_register_obd);
void ptlrpc_sysfs_unregister_service(struct ptlrpc_service *svc);
void ptlrpc_ldebugfs_register_service(struct dentry *debugfs_entry,
+ char *param,
struct ptlrpc_service *svc);
-#ifdef CONFIG_PROC_FS
void ptlrpc_lprocfs_unregister_service(struct ptlrpc_service *svc);
void ptlrpc_lprocfs_rpc_sent(struct ptlrpc_request *req, long amount);
void ptlrpc_lprocfs_do_request_stat (struct ptlrpc_request *req,
long q_usec, long work_usec);
-#else
-#define ptlrpc_lprocfs_unregister_service(params...) do{}while(0)
-#define ptlrpc_lprocfs_rpc_sent(params...) do{}while(0)
-#define ptlrpc_lprocfs_do_request_stat(params...) do{}while(0)
-#endif /* CONFIG_PROC_FS */
/* NRS */
struct ptlrpc_service *service;
struct ptlrpc_service_part *svcpt;
struct cfs_cpt_table *cptable;
- __u32 *cpts = NULL;
+ char param[MAX_OBD_NAME * 4];
+ u32 *cpts = NULL;
int ncpts;
int cpt;
int rc;
mutex_unlock(&ptlrpc_all_services_mutex);
if (parent) {
+ char *path, *tmp;
+
rc = ptlrpc_sysfs_register_service(parent, service);
if (rc)
GOTO(failed, rc);
+
+ path = kobject_get_path(&parent->kobj, GFP_KERNEL);
+ if (path) {
+ tmp = path + strlen("/fs/lustre/");
+ scnprintf(param, sizeof(param), "%s.%s.stats",
+ tmp, service->srv_name);
+ tmp = param;
+ while ((tmp = strchr(tmp, '/')) != NULL)
+ *tmp = '.';
+ }
}
- if (debugfs_entry != NULL)
- ptlrpc_ldebugfs_register_service(debugfs_entry, service);
+ ptlrpc_ldebugfs_register_service(debugfs_entry, param, service);
rc = ptlrpc_service_nrs_setup(service);
if (rc != 0)