* 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/
#include <obd_class.h>
#include <lprocfs_status.h>
-#include <lustre/lustre_idl.h>
#ifdef CONFIG_PROC_FS
}
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)
void ldebugfs_remove(struct dentry **entryp)
{
- debugfs_remove(*entryp);
+ debugfs_remove_recursive(*entryp);
*entryp = NULL;
}
EXPORT_SYMBOL_GPL(ldebugfs_remove);
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;
}
EXPORT_SYMBOL(lprocfs_uuid_seq_show);
+static ssize_t uuid_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
+{
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+
+ return sprintf(buf, "%s\n", obd->obd_uuid.uuid);
+}
+LUSTRE_RO_ATTR(uuid);
+
int lprocfs_name_seq_show(struct seq_file *m, void *data)
{
struct obd_device *dev = data;
}
EXPORT_SYMBOL(lprocfs_name_seq_show);
-int lprocfs_blksize_seq_show(struct seq_file *m, void *data)
+static ssize_t blocksize_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct obd_device *obd = data;
- 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);
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct obd_statfs osfs;
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc)
- seq_printf(m, "%u\n", osfs.os_bsize);
+ return sprintf(buf, "%u\n", osfs.os_bsize);
+
return rc;
}
-EXPORT_SYMBOL(lprocfs_blksize_seq_show);
+LUSTRE_RO_ATTR(blocksize);
-int lprocfs_kbytestotal_seq_show(struct seq_file *m, void *data)
+static ssize_t kbytestotal_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct obd_device *obd = data;
- 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);
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct obd_statfs osfs;
+ 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;
+ u32 blk_size = osfs.os_bsize >> 10;
+ u64 result = osfs.os_blocks;
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, "%llu\n", result);
+ return sprintf(buf, "%llu\n", result);
}
+
return rc;
}
-EXPORT_SYMBOL(lprocfs_kbytestotal_seq_show);
+LUSTRE_RO_ATTR(kbytestotal);
-int lprocfs_kbytesfree_seq_show(struct seq_file *m, void *data)
+static ssize_t kbytesfree_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct obd_device *obd = data;
- 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);
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct obd_statfs osfs;
+ 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;
+ u32 blk_size = osfs.os_bsize >> 10;
+ u64 result = osfs.os_bfree;
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, "%llu\n", result);
+ return sprintf(buf, "%llu\n", result);
}
+
return rc;
}
-EXPORT_SYMBOL(lprocfs_kbytesfree_seq_show);
+LUSTRE_RO_ATTR(kbytesfree);
-int lprocfs_kbytesavail_seq_show(struct seq_file *m, void *data)
+static ssize_t kbytesavail_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct obd_device *obd = data;
- 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);
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct obd_statfs osfs;
+ 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;
+ u32 blk_size = osfs.os_bsize >> 10;
+ u64 result = osfs.os_bavail;
while (blk_size >>= 1)
result <<= 1;
- seq_printf(m, "%llu\n", result);
+ return sprintf(buf, "%llu\n", result);
}
+
return rc;
}
-EXPORT_SYMBOL(lprocfs_kbytesavail_seq_show);
+LUSTRE_RO_ATTR(kbytesavail);
-int lprocfs_filestotal_seq_show(struct seq_file *m, void *data)
+static ssize_t filestotal_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct obd_device *obd = data;
- 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);
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct obd_statfs osfs;
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc)
- seq_printf(m, "%llu\n", osfs.os_files);
+ return sprintf(buf, "%llu\n", osfs.os_files);
+
return rc;
}
-EXPORT_SYMBOL(lprocfs_filestotal_seq_show);
+LUSTRE_RO_ATTR(filestotal);
-int lprocfs_filesfree_seq_show(struct seq_file *m, void *data)
+static ssize_t filesfree_show(struct kobject *kobj, struct attribute *attr,
+ char *buf)
{
- struct obd_device *obd = data;
- 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);
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
+ struct obd_statfs osfs;
+ int rc;
+
+ rc = obd_statfs(NULL, obd->obd_self_export, &osfs,
+ ktime_get_seconds() - OBD_STATFS_CACHE_SECONDS,
+ OBD_STATFS_NODELAY);
if (!rc)
- seq_printf(m, "%llu\n", osfs.os_ffree);
+ return sprintf(buf, "%llu\n", osfs.os_ffree);
+
return rc;
}
-EXPORT_SYMBOL(lprocfs_filesfree_seq_show);
+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)
{
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 */
"multi_mod_rpcs",
"dir_stripe",
"subtree",
- "lock_ahead",
+ "lockahead",
"bulk_mbits",
"compact_obdo",
"second_flags",
/* flags2 names */
"file_secctx",
+ "lockaheadv2",
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;
struct obd_import *imp;
unsigned int cur, worst;
time64_t now, worstt;
- struct dhms ts;
int i;
LASSERT(obd != NULL);
now = ktime_get_real_seconds();
/* Some network health info for kicks */
- s2dhms(&ts, now - imp->imp_last_reply_time);
- seq_printf(m, "%-10s : %lld, "DHMS_FMT" ago\n",
- "last reply", (s64)imp->imp_last_reply_time, DHMS_VARS(&ts));
+ seq_printf(m, "%-10s : %lld, %llds ago\n",
+ "last reply", (s64)imp->imp_last_reply_time,
+ (s64)(now - imp->imp_last_reply_time));
cur = at_get(&imp->imp_at.iat_net_latency);
worst = imp->imp_at.iat_net_latency.at_worst_ever;
worstt = imp->imp_at.iat_net_latency.at_worst_time;
- s2dhms(&ts, now - worstt);
- seq_printf(m, "%-10s : cur %3u worst %3u (at %lld, "DHMS_FMT" ago) ",
- "network", cur, worst, (s64)worstt, DHMS_VARS(&ts));
+ seq_printf(m, "%-10s : cur %3u worst %3u (at %lld, %llds ago) ",
+ "network", cur, worst, (s64)worstt, (s64)(now - worstt));
lprocfs_at_hist_helper(m, &imp->imp_at.iat_net_latency);
for(i = 0; i < IMP_AT_MAX_PORTALS; i++) {
cur = at_get(&imp->imp_at.iat_service_estimate[i]);
worst = imp->imp_at.iat_service_estimate[i].at_worst_ever;
worstt = imp->imp_at.iat_service_estimate[i].at_worst_time;
- s2dhms(&ts, now - worstt);
- seq_printf(m, "portal %-2d : cur %3u worst %3u (at %lld, "
- DHMS_FMT" ago) ", imp->imp_at.iat_portal[i],
- cur, worst, (s64)worstt, DHMS_VARS(&ts));
+ seq_printf(m, "portal %-2d : cur %3u worst %3u (at %lld, %llds ago) ",
+ imp->imp_at.iat_portal[i], cur, worst, (s64)worstt,
+ (s64)(now - worstt));
lprocfs_at_hist_helper(m, &imp->imp_at.iat_service_estimate[i]);
}
}
EXPORT_SYMBOL(lprocfs_connect_flags_seq_show);
-int
-lprocfs_obd_setup(struct obd_device *obd)
+static struct attribute *obd_def_uuid_attrs[] = {
+ &lustre_attr_uuid.attr,
+ NULL,
+};
+
+static struct attribute *obd_def_attrs[] = {
+ &lustre_attr_blocksize.attr,
+ &lustre_attr_kbytestotal.attr,
+ &lustre_attr_kbytesfree.attr,
+ &lustre_attr_kbytesavail.attr,
+ &lustre_attr_filestotal.attr,
+ &lustre_attr_filesfree.attr,
+ &lustre_attr_uuid.attr,
+ NULL,
+};
+
+static void obd_sysfs_release(struct kobject *kobj)
{
- int rc = 0;
+ struct obd_device *obd = container_of(kobj, struct obd_device,
+ obd_kset.kobj);
- LASSERT(obd != NULL);
- LASSERT(obd->obd_magic == OBD_DEVICE_MAGIC);
- LASSERT(obd->obd_type->typ_procroot != NULL);
+ complete(&obd->obd_kobj_unregister);
+}
+
+int lprocfs_obd_setup(struct obd_device *obd, bool uuid_only)
+{
+ struct lprocfs_vars *debugfs_vars = NULL;
+ int rc;
+
+ if (!obd || obd->obd_magic != OBD_DEVICE_MAGIC)
+ return -ENODEV;
+
+ 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 = kset_register(&obd->obd_kset);
+ if (rc)
+ 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_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;
+ }
+
+ 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,
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;
}
EXPORT_SYMBOL(lprocfs_obd_setup);
int lprocfs_obd_cleanup(struct obd_device *obd)
{
- if (!obd)
- return -EINVAL;
- if (obd->obd_proc_exports_entry) {
- /* Should be no exports left */
- lprocfs_remove(&obd->obd_proc_exports_entry);
- obd->obd_proc_exports_entry = NULL;
- }
- if (obd->obd_proc_entry) {
- lprocfs_remove(&obd->obd_proc_entry);
- obd->obd_proc_entry = NULL;
- }
- return 0;
+ if (!obd)
+ return -EINVAL;
+
+ if (obd->obd_proc_exports_entry) {
+ /* Should be no exports left */
+ lprocfs_remove(&obd->obd_proc_exports_entry);
+ obd->obd_proc_exports_entry = NULL;
+ }
+
+ if (obd->obd_proc_entry) {
+ lprocfs_remove(&obd->obd_proc_entry);
+ obd->obd_proc_entry = NULL;
+ }
+
+ 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
};
EXPORT_SYMBOL_GPL(lustre_sysfs_ops);
-int lprocfs_obd_rd_max_pages_per_rpc(char *page, char **start, off_t off,
- int count, int *eof, void *data)
+int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
{
struct obd_device *dev = data;
struct client_obd *cli = &dev->u.cli;
- int rc;
spin_lock(&cli->cl_loi_list_lock);
- rc = snprintf(page, count, "%d\n", cli->cl_max_pages_per_rpc);
+ seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
spin_unlock(&cli->cl_loi_list_lock);
+ return 0;
+}
+EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);
+
+ssize_t lprocfs_obd_max_pages_per_rpc_seq_write(struct file *file,
+ const char __user *buffer,
+ size_t count, loff_t *off)
+{
+ struct obd_device *dev =
+ ((struct seq_file *)file->private_data)->private;
+ struct client_obd *cli = &dev->u.cli;
+ struct obd_connect_data *ocd = &cli->cl_import->imp_connect_data;
+ int chunk_mask, rc;
+ s64 val;
+ rc = lprocfs_str_with_units_to_s64(buffer, count, &val, '1');
+ if (rc)
+ return rc;
+ if (val < 0)
+ return -ERANGE;
+
+ /* if the max_pages is specified in bytes, convert to pages */
+ if (val >= ONE_MB_BRW_SIZE)
+ val >>= PAGE_SHIFT;
+
+ LPROCFS_CLIMP_CHECK(dev);
+
+ chunk_mask = ~((1 << (cli->cl_chunkbits - PAGE_SHIFT)) - 1);
+ /* max_pages_per_rpc must be chunk aligned */
+ val = (val + ~chunk_mask) & chunk_mask;
+ if (val == 0 || (ocd->ocd_brw_size != 0 &&
+ val > ocd->ocd_brw_size >> PAGE_SHIFT)) {
+ LPROCFS_CLIMP_EXIT(dev);
+ return -ERANGE;
+ }
+ spin_lock(&cli->cl_loi_list_lock);
+ cli->cl_max_pages_per_rpc = val;
+ client_adjust_max_dirty(cli);
+ spin_unlock(&cli->cl_loi_list_lock);
+
+ LPROCFS_CLIMP_EXIT(dev);
+ return count;
+}
+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);
-int lprocfs_obd_max_pages_per_rpc_seq_show(struct seq_file *m, void *data)
+/* 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 = data;
+ 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);
- seq_printf(m, "%d\n", cli->cl_max_pages_per_rpc);
+ 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);
- return 0;
+
+out:
+ LPROCFS_CLIMP_EXIT(dev);
+ return rc;
}
-EXPORT_SYMBOL(lprocfs_obd_max_pages_per_rpc_seq_show);
+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)