extern int lprocfs_add_clear_entry(struct obd_device * obd,
struct proc_dir_entry *entry);
#ifdef HAVE_SERVER_SUPPORT
+void lprocfs_kset_unregister(struct obd_device *obj, struct kset *kset);
+int lprocfs_kset_register(struct obd_device *obd, struct kset **kset);
extern int lprocfs_exp_setup(struct obd_export *exp, lnet_nid_t *peer_nid);
extern int lprocfs_exp_cleanup(struct obd_export *exp);
#else
*
* @{
*/
-
+#include <linux/kobject.h>
#include <linux/uio.h>
#include <libcfs/libcfs.h>
#include <lnet/nidstr.h>
int srv_cpt_bits;
/** CPT table this service is running over */
struct cfs_cpt_table *srv_cptable;
+
+ /* sysfs object */
+ struct kobject srv_kobj;
+ struct completion srv_kobj_unregister;
/**
* partition data for ptlrpc service
*/
int ptlrpc_hpreq_handler(struct ptlrpc_request *req);
struct ptlrpc_service *ptlrpc_register_service(
struct ptlrpc_service_conf *conf,
+ struct kset *parent,
struct proc_dir_entry *proc_entry);
void ptlrpc_stop_all_threads(struct ptlrpc_service *svc);
},
};
ldlm_state->ldlm_cb_service = \
- ptlrpc_register_service(&conf, ldlm_svc_proc_dir);
+ ptlrpc_register_service(&conf, ldlm_svc_kset,
+ ldlm_svc_proc_dir);
if (IS_ERR(ldlm_state->ldlm_cb_service)) {
CERROR("failed to start service\n");
rc = PTR_ERR(ldlm_state->ldlm_cb_service);
},
};
ldlm_state->ldlm_cancel_service = \
- ptlrpc_register_service(&conf, ldlm_svc_proc_dir);
+ ptlrpc_register_service(&conf, ldlm_svc_kset,
+ ldlm_svc_proc_dir);
if (IS_ERR(ldlm_state->ldlm_cancel_service)) {
CERROR("failed to start service\n");
rc = PTR_ERR(ldlm_state->ldlm_cancel_service);
struct ptlrpc_service *mds_mdss_service;
struct ptlrpc_service *mds_fld_service;
struct mutex mds_health_mutex;
+ struct kset *mds_kset;
};
/*
.so_hpreq_handler = ptlrpc_hpreq_handler,
},
};
- m->mds_regular_service = ptlrpc_register_service(&conf, procfs_entry);
+ m->mds_regular_service = ptlrpc_register_service(&conf, m->mds_kset,
+ procfs_entry);
if (IS_ERR(m->mds_regular_service)) {
rc = PTR_ERR(m->mds_regular_service);
CERROR("failed to start regular mdt service: %d\n", rc);
.so_req_printer = target_print_req,
},
};
- m->mds_readpage_service = ptlrpc_register_service(&conf, procfs_entry);
+ m->mds_readpage_service = ptlrpc_register_service(&conf, m->mds_kset,
+ procfs_entry);
if (IS_ERR(m->mds_readpage_service)) {
rc = PTR_ERR(m->mds_readpage_service);
CERROR("failed to start readpage service: %d\n", rc);
.so_hpreq_handler = NULL,
},
};
- m->mds_setattr_service = ptlrpc_register_service(&conf, procfs_entry);
+ m->mds_setattr_service = ptlrpc_register_service(&conf, m->mds_kset,
+ procfs_entry);
if (IS_ERR(m->mds_setattr_service)) {
rc = PTR_ERR(m->mds_setattr_service);
CERROR("failed to start setattr service: %d\n", rc);
.so_hpreq_handler = NULL,
},
};
- m->mds_out_service = ptlrpc_register_service(&conf, procfs_entry);
+ m->mds_out_service = ptlrpc_register_service(&conf, m->mds_kset,
+ procfs_entry);
if (IS_ERR(m->mds_out_service)) {
rc = PTR_ERR(m->mds_out_service);
CERROR("failed to start out service: %d\n", rc);
.so_hpreq_handler = NULL,
},
};
- m->mds_mdsc_service = ptlrpc_register_service(&conf, procfs_entry);
+ m->mds_mdsc_service = ptlrpc_register_service(&conf, m->mds_kset,
+ procfs_entry);
if (IS_ERR(m->mds_mdsc_service)) {
rc = PTR_ERR(m->mds_mdsc_service);
CERROR("failed to start seq controller service: %d\n", rc);
.so_hpreq_handler = NULL,
},
};
- m->mds_mdss_service = ptlrpc_register_service(&conf, procfs_entry);
+ m->mds_mdss_service = ptlrpc_register_service(&conf, m->mds_kset,
+ procfs_entry);
if (IS_ERR(m->mds_mdss_service)) {
rc = PTR_ERR(m->mds_mdss_service);
CERROR("failed to start metadata seq server service: %d\n", rc);
.so_hpreq_handler = NULL,
},
};
- m->mds_fld_service = ptlrpc_register_service(&conf, procfs_entry);
+ m->mds_fld_service = ptlrpc_register_service(&conf, m->mds_kset,
+ procfs_entry);
if (IS_ERR(m->mds_fld_service)) {
rc = PTR_ERR(m->mds_fld_service);
CERROR("failed to start fld service: %d\n", rc);
ENTRY;
mds_stop_ptlrpc_service(m);
- lprocfs_obd_cleanup(obd);
+ lprocfs_kset_unregister(obd, m->mds_kset);
RETURN(NULL);
}
/* set this lu_device to obd, because error handling need it */
obd->obd_lu_dev = l;
- rc = lprocfs_obd_setup(obd, true);
+ rc = lprocfs_kset_register(obd, &m->mds_kset);
if (rc != 0) {
mds_device_free(env, l);
l = ERR_PTR(rc);
mutex_init(&m->mds_health_mutex);
rc = mds_start_ptlrpc_service(m);
-
if (rc != 0) {
+ lprocfs_kset_unregister(obd, m->mds_kset);
mds_device_free(env, l);
l = ERR_PTR(rc);
return l;
int rc;
obd->obd_vars = lprocfs_mgs_obd_vars;
- rc = lprocfs_obd_setup(obd, true);
+ rc = lprocfs_kset_register(obd, &mgs->mgs_kset);
if (rc != 0)
GOTO(out, rc);
}
lprocfs_free_per_client_stats(obd);
- lprocfs_obd_cleanup(obd);
+ lprocfs_kset_unregister(obd, mgs->mgs_kset);
lprocfs_free_obd_stats(obd);
lprocfs_free_md_stats(obd);
}
};
/* Start the service threads */
- mgs->mgs_service = ptlrpc_register_service(&conf, obd->obd_proc_entry);
+ mgs->mgs_service = ptlrpc_register_service(&conf, mgs->mgs_kset,
+ obd->obd_proc_entry);
if (IS_ERR(mgs->mgs_service)) {
rc = PTR_ERR(mgs->mgs_service);
CERROR("failed to start mgs service: %d\n", rc);
struct proc_dir_entry *mgs_proc_mntdev;
cfs_time_t mgs_start_time;
struct obd_device *mgs_obd;
+ struct kset *mgs_kset;
struct local_oid_storage *mgs_los;
struct mutex mgs_mutex;
struct mutex mgs_health_mutex;
#define DEBUG_SUBSYSTEM S_CLASS
+#include <linux/kobject.h>
+#include <linux/sysfs.h>
#include <obd_class.h>
#include <lprocfs_status.h>
#include <lustre/lustre_idl.h>
#include <lustre_nodemap.h>
+static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct obd_device *obd = class_name2obd(kobj->name);
+
+ return sprintf(buf, "%s\n", obd->obd_uuid.uuid);
+}
+LUSTRE_RO_ATTR(uuid);
+
+static struct attribute *server_uuid_attrs[] = {
+ &lustre_attr_uuid.attr,
+ NULL,
+};
+
+static struct attribute_group server_def_attr_group = {
+ .attrs = server_uuid_attrs,
+};
+
+void lprocfs_kset_unregister(struct obd_device *obd, struct kset *kset)
+{
+ if (obd->obd_proc_entry) {
+ lprocfs_remove(&obd->obd_proc_entry);
+ obd->obd_proc_entry = NULL;
+ }
+
+ if (kset)
+ kset_unregister(kset);
+}
+EXPORT_SYMBOL(lprocfs_kset_unregister);
+
+int lprocfs_kset_register(struct obd_device *obd, struct kset **kset)
+{
+ struct kset *obd_kset;
+ int rc = 0;
+
+ obd_kset = kset_create_and_add(obd->obd_name, NULL,
+ obd->obd_type->typ_kobj);
+ if (!obd_kset) {
+ CERROR("%s: cannot add new kset: rc = %d\n", obd->obd_name, rc);
+ rc = -ENOMEM;
+ }
+
+ if (!obd->obd_attrs)
+ obd->obd_attrs = &server_def_attr_group;
+
+ rc = sysfs_create_group(&obd_kset->kobj, obd->obd_attrs);
+ if (rc) {
+ CERROR("%s: cannot create attr group: rc = %d\n", obd->obd_name,
+ rc);
+ kset_unregister(obd_kset);
+ obd_kset = NULL;
+ return rc;
+ }
+
+ obd->obd_proc_entry = lprocfs_register(obd->obd_name,
+ obd->obd_type->typ_procroot,
+ obd->obd_vars, obd);
+ if (IS_ERR(obd->obd_proc_entry)) {
+ rc = PTR_ERR(obd->obd_proc_entry);
+ CERROR("%s: error %d setting up lprocfs\n", obd->obd_name, rc);
+ obd->obd_proc_entry = NULL;
+
+ kset_unregister(obd_kset);
+ obd_kset = NULL;
+ }
+ *kset = obd_kset;
+ return rc;
+}
+EXPORT_SYMBOL(lprocfs_kset_register);
+
#ifdef CONFIG_PROC_FS
int lprocfs_evict_client_open(struct inode *inode, struct file *f)
static struct cfs_cpt_table *ost_io_cptable;
+static struct kset *oss_kset;
+
/* Sigh - really, this is an OSS, the _server_, not the _target_ */
static int ost_setup(struct obd_device *obd, struct lustre_cfg* lcfg)
{
int rc;
ENTRY;
- lprocfs_obd_setup(obd, true);
+ rc = lprocfs_kset_register(obd, &oss_kset);
+ if (rc)
+ return rc;
mutex_init(&ost->ost_health_mutex);
.so_hpreq_handler = ptlrpc_hpreq_handler,
},
};
- ost->ost_service = ptlrpc_register_service(&svc_conf,
+ ost->ost_service = ptlrpc_register_service(&svc_conf, oss_kset,
obd->obd_proc_entry);
if (IS_ERR(ost->ost_service)) {
rc = PTR_ERR(ost->ost_service);
.so_req_printer = target_print_req,
},
};
- ost->ost_create_service = ptlrpc_register_service(&svc_conf,
+ ost->ost_create_service = ptlrpc_register_service(&svc_conf, oss_kset,
obd->obd_proc_entry);
if (IS_ERR(ost->ost_create_service)) {
rc = PTR_ERR(ost->ost_create_service);
.so_req_printer = target_print_req,
},
};
- ost->ost_io_service = ptlrpc_register_service(&svc_conf,
+ ost->ost_io_service = ptlrpc_register_service(&svc_conf, oss_kset,
obd->obd_proc_entry);
if (IS_ERR(ost->ost_io_service)) {
rc = PTR_ERR(ost->ost_io_service);
.so_hpreq_handler = NULL,
},
};
- ost->ost_seq_service = ptlrpc_register_service(&svc_conf,
+ ost->ost_seq_service = ptlrpc_register_service(&svc_conf, oss_kset,
obd->obd_proc_entry);
if (IS_ERR(ost->ost_seq_service)) {
rc = PTR_ERR(ost->ost_seq_service);
.so_hpreq_handler = NULL,
},
};
- ost->ost_out_service = ptlrpc_register_service(&svc_conf,
+ ost->ost_out_service = ptlrpc_register_service(&svc_conf, oss_kset,
obd->obd_proc_entry);
if (IS_ERR(ost->ost_out_service)) {
rc = PTR_ERR(ost->ost_out_service);
ptlrpc_unregister_service(ost->ost_service);
ost->ost_service = NULL;
out_lprocfs:
- lprocfs_obd_cleanup(obd);
+ lprocfs_kset_unregister(obd, oss_kset);
RETURN(rc);
}
mutex_unlock(&ost->ost_health_mutex);
- lprocfs_obd_cleanup(obd);
+ lprocfs_kset_unregister(obd, oss_kset);
if (ost_io_cptable != NULL) {
cfs_cpt_table_free(ost_io_cptable);
}
LPROC_SEQ_FOPS(ptlrpc_lprocfs_req_history_max);
-static int
-ptlrpc_lprocfs_threads_min_seq_show(struct seq_file *m, void *n)
+static ssize_t threads_min_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct ptlrpc_service *svc = m->private;
+ struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
+ srv_kobj);
- seq_printf(m, "%d\n",
- svc->srv_nthrs_cpt_init * svc->srv_ncpts);
- return 0;
+ return sprintf(buf, "%d\n", svc->srv_nthrs_cpt_init * svc->srv_ncpts);
}
-static ssize_t
-ptlrpc_lprocfs_threads_min_seq_write(struct file *file,
- const char __user *buffer,
- size_t count, loff_t *off)
+static ssize_t threads_min_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
{
- struct seq_file *m = file->private_data;
- struct ptlrpc_service *svc = m->private;
- __s64 val;
- int rc = lprocfs_str_to_s64(buffer, count, &val);
+ struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
+ srv_kobj);
+ unsigned long val;
+ int rc;
+ rc = kstrtoul(buffer, 10, &val);
if (rc < 0)
return rc;
return count;
}
-LPROC_SEQ_FOPS(ptlrpc_lprocfs_threads_min);
+LUSTRE_RW_ATTR(threads_min);
-static int
-ptlrpc_lprocfs_threads_started_seq_show(struct seq_file *m, void *n)
+static ssize_t threads_started_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
{
- struct ptlrpc_service *svc = m->private;
- struct ptlrpc_service_part *svcpt;
- int total = 0;
- int i;
+ struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
+ srv_kobj);
+ struct ptlrpc_service_part *svcpt;
+ int total = 0;
+ int i;
ptlrpc_service_for_each_part(svcpt, i, svc)
total += svcpt->scp_nthrs_running;
- seq_printf(m, "%d\n", total);
- return 0;
+ return sprintf(buf, "%d\n", total);
}
-LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_threads_started);
+LUSTRE_RO_ATTR(threads_started);
-static int
-ptlrpc_lprocfs_threads_max_seq_show(struct seq_file *m, void *n)
+static ssize_t threads_max_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct ptlrpc_service *svc = m->private;
+ struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
+ srv_kobj);
- seq_printf(m, "%d\n",
- svc->srv_nthrs_cpt_limit * svc->srv_ncpts);
- return 0;
+ return sprintf(buf, "%d\n", svc->srv_nthrs_cpt_limit * svc->srv_ncpts);
}
-static ssize_t
-ptlrpc_lprocfs_threads_max_seq_write(struct file *file,
- const char __user *buffer,
- size_t count, loff_t *off)
+static ssize_t threads_max_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
{
- struct seq_file *m = file->private_data;
- struct ptlrpc_service *svc = m->private;
- __s64 val;
- int rc = lprocfs_str_to_s64(buffer, count, &val);
+ struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
+ srv_kobj);
+ unsigned long val;
+ int rc;
+ rc = kstrtoul(buffer, 10, &val);
if (rc < 0)
return rc;
return count;
}
-LPROC_SEQ_FOPS(ptlrpc_lprocfs_threads_max);
+LUSTRE_RW_ATTR(threads_max);
/**
* Translates \e ptlrpc_nrs_pol_state values to human-readable strings.
}
LPROC_SEQ_FOPS_RO(ptlrpc_lprocfs_timeouts);
-static int ptlrpc_lprocfs_hp_ratio_seq_show(struct seq_file *m, void *v)
+static ssize_t high_priority_ratio_show(struct kobject *kobj,
+ struct attribute *attr,
+ char *buf)
{
- struct ptlrpc_service *svc = m->private;
- seq_printf(m, "%d\n", svc->srv_hpreq_ratio);
- return 0;
+ struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
+ srv_kobj);
+
+ return sprintf(buf, "%d\n", svc->srv_hpreq_ratio);
}
-static ssize_t
-ptlrpc_lprocfs_hp_ratio_seq_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *off)
+static ssize_t high_priority_ratio_store(struct kobject *kobj,
+ struct attribute *attr,
+ const char *buffer,
+ size_t count)
{
- struct seq_file *m = file->private_data;
- struct ptlrpc_service *svc = m->private;
+ struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
+ srv_kobj);
int rc;
- __s64 val;
+ unsigned long val;
- rc = lprocfs_str_to_s64(buffer, count, &val);
+ rc = kstrtoul(buffer, 10, &val);
if (rc < 0)
return rc;
- if (val < 0 || val > INT_MAX)
- return -ERANGE;
-
spin_lock(&svc->srv_lock);
svc->srv_hpreq_ratio = val;
spin_unlock(&svc->srv_lock);
return count;
}
-LPROC_SEQ_FOPS(ptlrpc_lprocfs_hp_ratio);
+LUSTRE_RW_ATTR(high_priority_ratio);
+
+static struct attribute *ptlrpc_svc_attrs[] = {
+ &lustre_attr_threads_min.attr,
+ &lustre_attr_threads_started.attr,
+ &lustre_attr_threads_max.attr,
+ &lustre_attr_high_priority_ratio.attr,
+ NULL,
+};
+
+static void ptlrpc_sysfs_svc_release(struct kobject *kobj)
+{
+ struct ptlrpc_service *svc = container_of(kobj, struct ptlrpc_service,
+ srv_kobj);
+
+ complete(&svc->srv_kobj_unregister);
+}
+
+static struct kobj_type ptlrpc_svc_ktype = {
+ .default_attrs = ptlrpc_svc_attrs,
+ .sysfs_ops = &lustre_sysfs_ops,
+ .release = ptlrpc_sysfs_svc_release,
+};
+
+void ptlrpc_sysfs_unregister_service(struct ptlrpc_service *svc)
+{
+ /* Let's see if we had a chance at initialization first */
+ if (svc->srv_kobj.kset) {
+ kobject_put(&svc->srv_kobj);
+ wait_for_completion(&svc->srv_kobj_unregister);
+ }
+}
+
+int ptlrpc_sysfs_register_service(struct kset *parent,
+ struct ptlrpc_service *svc)
+{
+ int rc;
+
+ svc->srv_kobj.kset = parent;
+ init_completion(&svc->srv_kobj_unregister);
+ rc = kobject_init_and_add(&svc->srv_kobj, &ptlrpc_svc_ktype, NULL,
+ "%s", svc->srv_name);
+
+ return rc;
+}
void ptlrpc_lprocfs_register_service(struct proc_dir_entry *entry,
struct ptlrpc_service *svc)
{
struct lprocfs_vars lproc_vars[] = {
- { .name = "high_priority_ratio",
- .fops = &ptlrpc_lprocfs_hp_ratio_fops,
- .data = svc },
{ .name = "req_buffer_history_len",
.fops = &ptlrpc_lprocfs_req_history_len_fops,
.data = svc },
{ .name = "req_buffer_history_max",
.fops = &ptlrpc_lprocfs_req_history_max_fops,
.data = svc },
- { .name = "threads_min",
- .fops = &ptlrpc_lprocfs_threads_min_fops,
- .data = svc },
- { .name = "threads_max",
- .fops = &ptlrpc_lprocfs_threads_max_fops,
- .data = svc },
- { .name = "threads_started",
- .fops = &ptlrpc_lprocfs_threads_started_fops,
- .data = svc },
{ .name = "timeouts",
.fops = &ptlrpc_lprocfs_timeouts_fops,
.data = svc },
int lustre_unpack_req_ptlrpc_body(struct ptlrpc_request *req, int offset);
int lustre_unpack_rep_ptlrpc_body(struct ptlrpc_request *req, int offset);
+int ptlrpc_sysfs_register_service(struct kset *parent,
+ struct ptlrpc_service *svc);
+void ptlrpc_sysfs_unregister_service(struct ptlrpc_service *svc);
+
#ifdef CONFIG_PROC_FS
void ptlrpc_lprocfs_register_service(struct proc_dir_entry *proc_entry,
struct ptlrpc_service *svc);
*/
struct ptlrpc_service *
ptlrpc_register_service(struct ptlrpc_service_conf *conf,
+ struct kset *parent,
struct proc_dir_entry *proc_entry)
{
struct ptlrpc_service_cpt_conf *cconf = &conf->psc_cpt;
list_add(&service->srv_list, &ptlrpc_all_services);
mutex_unlock(&ptlrpc_all_services_mutex);
+ if (parent) {
+ rc = ptlrpc_sysfs_register_service(parent, service);
+ if (rc)
+ GOTO(failed, rc);
+ }
+
if (proc_entry != NULL)
ptlrpc_lprocfs_register_service(proc_entry, service);
ptlrpc_service_nrs_cleanup(service);
ptlrpc_lprocfs_unregister_service(service);
+ ptlrpc_sysfs_unregister_service(service);
ptlrpc_service_free(service);