* Copyright (c) 2002, 2010, Oracle and/or its affiliates. All rights reserved.
* Use is subject to license terms.
*
- * Copyright (c) 2011, 2016, Intel Corporation.
+ * Copyright (c) 2011, 2017, Intel Corporation.
*/
/*
* This file is part of Lustre, http://www.lustre.org/
}
EXPORT_SYMBOL(lprocfs_seq_release);
+struct dentry *ldebugfs_add_simple(struct dentry *root,
+ char *name, void *data,
+ const struct file_operations *fops)
+{
+ struct dentry *entry;
+ umode_t mode = 0;
+
+ if (!root || !name || !fops)
+ return ERR_PTR(-EINVAL);
+
+ if (fops->read)
+ mode = 0444;
+ if (fops->write)
+ mode |= 0200;
+ entry = debugfs_create_file(name, mode, root, data, fops);
+ if (IS_ERR_OR_NULL(entry)) {
+ CERROR("LprocFS: No memory to create <debugfs> entry %s", name);
+ return entry ?: ERR_PTR(-ENOMEM);
+ }
+ return entry;
+}
+EXPORT_SYMBOL(ldebugfs_add_simple);
+
struct proc_dir_entry *
lprocfs_add_simple(struct proc_dir_entry *root, char *name,
void *data, const struct file_operations *fops)
EXPORT_SYMBOL(lprocfs_register);
/* Generic callbacks */
-int lprocfs_uint_seq_show(struct seq_file *m, void *data)
-{
- seq_printf(m, "%u\n", *(unsigned int *)data);
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_uint_seq_show);
-
-int lprocfs_wr_uint(struct file *file, const char __user *buffer,
- unsigned long count, void *data)
-{
- unsigned *p = data;
- char dummy[MAX_STRING_SIZE + 1];
- char *end;
- unsigned long tmp;
-
- if (count >= sizeof(dummy))
- return -EINVAL;
-
- if (count == 0)
- return 0;
-
- if (copy_from_user(dummy, buffer, count))
- return -EFAULT;
-
- dummy[count] = 0;
-
- tmp = simple_strtoul(dummy, &end, 0);
- if (dummy == end)
- return -EINVAL;
-
- *p = (unsigned int)tmp;
- return count;
-}
-EXPORT_SYMBOL(lprocfs_wr_uint);
-
-ssize_t lprocfs_uint_seq_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *off)
-{
- int *data = ((struct seq_file *)file->private_data)->private;
- int rc;
- __s64 val = 0;
-
- rc = lprocfs_str_to_s64(buffer, count, &val);
- if (rc < 0)
- return rc;
-
- return lprocfs_wr_uint(file, buffer, count, data);
-}
-EXPORT_SYMBOL(lprocfs_uint_seq_write);
-
-int lprocfs_u64_seq_show(struct seq_file *m, void *data)
-{
- LASSERT(data != NULL);
- seq_printf(m, "%llu\n", *(__u64 *)data);
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_u64_seq_show);
-
-int lprocfs_atomic_seq_show(struct seq_file *m, void *data)
-{
- atomic_t *atom = data;
- LASSERT(atom != NULL);
- seq_printf(m, "%d\n", atomic_read(atom));
- return 0;
-}
-EXPORT_SYMBOL(lprocfs_atomic_seq_show);
-
-ssize_t
-lprocfs_atomic_seq_write(struct file *file, const char __user *buffer,
- size_t count, loff_t *off)
-{
- atomic_t *atm = ((struct seq_file *)file->private_data)->private;
- __s64 val = 0;
- int rc;
-
- rc = lprocfs_str_to_s64(buffer, count, &val);
- if (rc < 0)
- return rc;
-
- if (val <= 0 || val > INT_MAX)
- return -ERANGE;
-
- atomic_set(atm, val);
- return count;
-}
-EXPORT_SYMBOL(lprocfs_atomic_seq_write);
-
int lprocfs_uuid_seq_show(struct seq_file *m, void *data)
{
struct obd_device *obd = data;
char *buf)
{
struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
+ obd_kset.kobj);
return sprintf(buf, "%s\n", obd->obd_uuid.uuid);
}
char *buf)
{
struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
+ obd_kset.kobj);
struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc)
return sprintf(buf, "%u\n", osfs.os_bsize);
char *buf)
{
struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
+ obd_kset.kobj);
struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc) {
u32 blk_size = osfs.os_bsize >> 10;
u64 result = osfs.os_blocks;
char *buf)
{
struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
+ obd_kset.kobj);
struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc) {
u32 blk_size = osfs.os_bsize >> 10;
u64 result = osfs.os_bfree;
char *buf)
{
struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
+ obd_kset.kobj);
struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc) {
u32 blk_size = osfs.os_bsize >> 10;
u64 result = osfs.os_bavail;
char *buf)
{
struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
+ obd_kset.kobj);
struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc)
return sprintf(buf, "%llu\n", osfs.os_files);
char *buf)
{
struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
+ obd_kset.kobj);
struct obd_statfs osfs;
- int rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
- cfs_time_shift_64(-OBD_STATFS_CACHE_SECONDS),
- OBD_STATFS_NODELAY);
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc)
return sprintf(buf, "%llu\n", osfs.os_ffree);
}
LUSTRE_RO_ATTR(filesfree);
+ssize_t conn_uuid_show(struct kobject *kobj, struct attribute *attr, char *buf)
+{
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct ptlrpc_connection *conn;
+ ssize_t count;
+
+ LPROCFS_CLIMP_CHECK(obd);
+ conn = obd->u.cli.cl_import->imp_connection;
+ if (conn && obd->u.cli.cl_import)
+ count = sprintf(buf, "%s\n", conn->c_remote_uuid.uuid);
+ else
+ count = sprintf(buf, "%s\n", "<none>");
+
+ LPROCFS_CLIMP_EXIT(obd);
+ return count;
+}
+EXPORT_SYMBOL(conn_uuid_show);
+
int lprocfs_server_uuid_seq_show(struct seq_file *m, void *data)
{
struct obd_device *obd = data;
lprocfs_stats_unlock(stats, LPROCFS_GET_NUM_CPU, &flags);
}
-/**
- * Append a space separated list of current set flags to str.
- */
-#define flag2str(flag) \
- do { \
- if (imp->imp_##flag) { \
- seq_printf(m, "%s" #flag, first ? "" : ", "); \
- first = false; \
- } \
- } while (0)
static void obd_import_flags2str(struct obd_import *imp, struct seq_file *m)
{
bool first = true;
first = false;
}
- flag2str(invalid);
- flag2str(deactive);
- flag2str(replayable);
- flag2str(delayed_recovery);
- flag2str(no_lock_replay);
- flag2str(vbr_failed);
- flag2str(pingable);
- flag2str(resend_replay);
- flag2str(no_pinger_recover);
- flag2str(need_mne_swab);
- flag2str(connect_tried);
+ flag2str(imp, invalid);
+ flag2str(imp, deactive);
+ flag2str(imp, replayable);
+ flag2str(imp, delayed_recovery);
+ flag2str(imp, vbr_failed);
+ flag2str(imp, pingable);
+ flag2str(imp, resend_replay);
+ flag2str(imp, no_pinger_recover);
+ flag2str(imp, connect_tried);
}
-#undef flag2str
static const char *obd_connect_names[] = {
/* flags names */
NULL
};
-static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags,
- __u64 flags2, const char *sep)
+void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, __u64 flags2,
+ const char *sep)
{
bool first = true;
__u64 mask;
first = false;
}
}
+EXPORT_SYMBOL(obd_connect_seq_flags2str);
int obd_connect_flags2str(char *page, int count, __u64 flags, __u64 flags2,
const char *sep)
}
EXPORT_SYMBOL(obd_connect_flags2str);
-static void obd_connect_data_seqprint(struct seq_file *m,
- struct obd_connect_data *ocd)
+void
+obd_connect_data_seqprint(struct seq_file *m, struct obd_connect_data *ocd)
{
__u64 flags;
static void obd_sysfs_release(struct kobject *kobj)
{
struct obd_device *obd = container_of(kobj, struct obd_device,
- obd_kobj);
+ obd_kset.kobj);
complete(&obd->obd_kobj_unregister);
}
-static struct kobj_type obd_ktype = {
- .sysfs_ops = &lustre_sysfs_ops,
- .release = obd_sysfs_release,
-};
-
-int
-lprocfs_obd_setup(struct obd_device *obd, bool uuid_only)
+int lprocfs_obd_setup(struct obd_device *obd, bool uuid_only)
{
- int rc = 0;
+ struct lprocfs_vars *debugfs_vars = NULL;
+ int rc;
- LASSERT(obd != NULL);
- LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
+ if (!obd || obd->obd_magic != OBD_DEVICE_MAGIC)
+ return -ENODEV;
- if (uuid_only)
- obd_ktype.default_attrs = obd_def_uuid_attrs;
- else
- obd_ktype.default_attrs = obd_def_attrs;
+ rc = kobject_set_name(&obd->obd_kset.kobj, "%s", obd->obd_name);
+ if (rc)
+ return rc;
+
+ obd->obd_ktype.sysfs_ops = &lustre_sysfs_ops;
+ obd->obd_ktype.release = obd_sysfs_release;
+ if (obd->obd_attrs)
+ obd->obd_ktype.default_attrs = obd->obd_attrs;
+ obd->obd_kset.kobj.parent = obd->obd_type->typ_kobj;
+ obd->obd_kset.kobj.ktype = &obd->obd_ktype;
init_completion(&obd->obd_kobj_unregister);
- rc = kobject_init_and_add(&obd->obd_kobj, &obd_ktype,
- obd->obd_type->typ_kobj,
- "%s", obd->obd_name);
+ rc = kset_register(&obd->obd_kset);
if (rc)
return rc;
- if (obd->obd_attrs) {
- rc = sysfs_create_group(&obd->obd_kobj, obd->obd_attrs);
- if (rc) {
- kobject_put(&obd->obd_kobj);
- return rc;
- }
+ if (uuid_only)
+ obd->obd_attrs_group.attrs = obd_def_uuid_attrs;
+ else
+ obd->obd_attrs_group.attrs = obd_def_attrs;
+
+ rc = sysfs_create_group(&obd->obd_kset.kobj, &obd->obd_attrs_group);
+ if (rc) {
+ kset_unregister(&obd->obd_kset);
+ return rc;
}
- if (obd->obd_proc_entry)
- GOTO(already_registered, rc);
+ if (!obd->obd_type->typ_procroot)
+ debugfs_vars = obd->obd_vars;
+ obd->obd_debugfs_entry = ldebugfs_register(obd->obd_name,
+ obd->obd_type->typ_debugfs_entry,
+ debugfs_vars, obd);
+ if (IS_ERR_OR_NULL(obd->obd_debugfs_entry)) {
+ rc = obd->obd_debugfs_entry ? PTR_ERR(obd->obd_debugfs_entry)
+ : -ENOMEM;
+ CERROR("error %d setting up debugfs for %s\n",
+ rc, obd->obd_name);
+ obd->obd_debugfs_entry = NULL;
+ lprocfs_obd_cleanup(obd);
+ return rc;
+ }
- LASSERT(obd->obd_type->typ_procroot != NULL);
+ if (obd->obd_proc_entry || !obd->obd_type->typ_procroot)
+ GOTO(already_registered, 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)) {
- kobject_put(&obd->obd_kobj);
rc = PTR_ERR(obd->obd_proc_entry);
CERROR("error %d setting up lprocfs for %s\n",rc,obd->obd_name);
obd->obd_proc_entry = NULL;
+ lprocfs_obd_cleanup(obd);
}
already_registered:
return rc;
obd->obd_proc_entry = NULL;
}
- kobject_put(&obd->obd_kobj);
+ if (!IS_ERR_OR_NULL(obd->obd_debugfs_entry))
+ ldebugfs_remove(&obd->obd_debugfs_entry);
+
+ sysfs_remove_group(&obd->obd_kset.kobj, &obd->obd_attrs_group);
+ kset_unregister(&obd->obd_kset);
wait_for_completion(&obd->obd_kobj_unregister);
+
return 0;
}
EXPORT_SYMBOL(lprocfs_obd_cleanup);
if (rc)
return rc;
seq = file->private_data;
- seq->private = inode->i_private ? : PDE_DATA(inode);
+ seq->private = inode->i_private ? inode->i_private : PDE_DATA(inode);
return 0;
}
/**
* Convert a user string into a signed 64 bit number. This function produces
- * an error when the value parsed from the string underflows or
- * overflows. This function accepts strings which contain digits and
- * optionally a decimal or hex strings which are prefixed with "0x".
- *
- * \param[in] buffer string consisting of numbers and optionally a decimal
- * \param[in] count buffer length
- * \param[in] val if successful, the value represented by the string
- *
- * \retval 0 on success
- * \retval negative number on error
- */
-int lprocfs_str_to_s64(const char __user *buffer, unsigned long count,
- __s64 *val)
-{
- return str_to_s64_internal(buffer, count, val, 1, false);
-}
-EXPORT_SYMBOL(lprocfs_str_to_s64);
-
-/**
- * Convert a user string into a signed 64 bit number. This function produces
* an error when the value parsed from the string times multiplier underflows or
* overflows. This function only accepts strings that contains digits, an
* optional decimal, and a char representing a unit at the end. If a unit is
}
EXPORT_SYMBOL(lprocfs_str_with_units_to_s64);
-static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
+char *lprocfs_strnstr(const char *s1, const char *s2, size_t len)
{
size_t l2;
}
return NULL;
}
+EXPORT_SYMBOL(lprocfs_strnstr);
/**
* Find the string \a name in the input \a buffer, and return a pointer to the
struct client_obd *cli = &dev->u.cli;
struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
int chunk_mask, rc;
- __s64 val;
+ s64 val;
rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '1');
if (rc)
}
EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_write);
+ssize_t short_io_bytes_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct obd_device *dev = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct client_obd *cli = &dev->u.cli;
+ int rc;
+
+ spin_lock(&cli->cl_loi_list_lock);
+ rc = sprintf(buf, "%d\n", cli->cl_short_io_bytes);
+ spin_unlock(&cli->cl_loi_list_lock);
+ return rc;
+}
+EXPORT_SYMBOL(short_io_bytes_show);
+
+/* Used to catch people who think they're specifying pages. */
+#define MIN_SHORT_IO_BYTES 64
+
+ssize_t short_io_bytes_store(struct kobject *kobj, struct attribute *attr,
+ const char *buffer, size_t count)
+{
+ struct obd_device *dev = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct client_obd *cli = &dev->u.cli;
+ u32 val;
+ int rc;
+
+ LPROCFS_CLIMP_CHECK(dev);
+
+ rc = kstrtouint(buffer, 0, &val);
+ if (rc)
+ GOTO(out, rc);
+
+ if (val < MIN_SHORT_IO_BYTES || val > OBD_MAX_SHORT_IO_BYTES)
+ GOTO(out, rc = -ERANGE);
+
+ rc = count;
+
+ spin_lock(&cli->cl_loi_list_lock);
+ if (val > (cli->cl_max_pages_per_rpc << PAGE_SHIFT))
+ rc = -ERANGE;
+ else
+ cli->cl_short_io_bytes = val;
+ spin_unlock(&cli->cl_loi_list_lock);
+
+out:
+ LPROCFS_CLIMP_EXIT(dev);
+ return rc;
+}
+EXPORT_SYMBOL(short_io_bytes_store);
+
int lprocfs_wr_root_squash(const char __user *buffer, unsigned long count,
struct root_squash_info *squash, char *name)
{