X-Git-Url: https://git.whamcloud.com/?a=blobdiff_plain;f=lustre%2Fobdclass%2Flprocfs_status.c;h=0c434f21640136c50a849ae33bb1215f52774ef0;hb=a0c644fde3405bba6752885481f0fdfe05da1bcd;hp=6d0ed9ff6964192ee3f548bc4b17db000e651293;hpb=7d5bc476d4420c04c53b82e66647d1cb2319da3e;p=fs%2Flustre-release.git diff --git a/lustre/obdclass/lprocfs_status.c b/lustre/obdclass/lprocfs_status.c index 6d0ed9f..0c434f2 100644 --- a/lustre/obdclass/lprocfs_status.c +++ b/lustre/obdclass/lprocfs_status.c @@ -23,7 +23,7 @@ * 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/ @@ -38,7 +38,6 @@ #include #include -#include #ifdef CONFIG_PROC_FS @@ -60,6 +59,29 @@ int lprocfs_seq_release(struct inode *inode, struct file *file) } 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 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) @@ -186,7 +208,7 @@ EXPORT_SYMBOL(lprocfs_add_vars); void ldebugfs_remove(struct dentry **entryp) { - debugfs_remove(*entryp); + debugfs_remove_recursive(*entryp); *entryp = NULL; } EXPORT_SYMBOL_GPL(ldebugfs_remove); @@ -347,93 +369,6 @@ lprocfs_register(const char *name, struct proc_dir_entry *parent, 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; @@ -444,6 +379,16 @@ int lprocfs_uuid_seq_show(struct seq_file *m, void *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; @@ -454,104 +399,153 @@ int lprocfs_name_seq_show(struct seq_file *m, void *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", ""); + + LPROCFS_CLIMP_EXIT(obd); + return count; +} +EXPORT_SYMBOL(conn_uuid_show); int lprocfs_server_uuid_seq_show(struct seq_file *m, void *data) { @@ -719,16 +713,6 @@ void lprocfs_stats_collect(struct lprocfs_stats *stats, int idx, 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; @@ -738,19 +722,16 @@ static void obd_import_flags2str(struct obd_import *imp, struct seq_file *m) 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 */ @@ -814,17 +795,18 @@ static const char *obd_connect_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; @@ -861,6 +843,7 @@ static void obd_connect_seq_flags2str(struct seq_file *m, __u64 flags, first = false; } } +EXPORT_SYMBOL(obd_connect_seq_flags2str); int obd_connect_flags2str(char *page, int count, __u64 flags, __u64 flags2, const char *sep) @@ -897,8 +880,8 @@ int obd_connect_flags2str(char *page, int count, __u64 flags, __u64 flags2, } 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; @@ -1140,7 +1123,6 @@ int lprocfs_timeouts_seq_show(struct seq_file *m, void *data) struct obd_import *imp; unsigned int cur, worst; time64_t now, worstt; - struct dhms ts; int i; LASSERT(obd != NULL); @@ -1150,16 +1132,15 @@ int lprocfs_timeouts_seq_show(struct seq_file *m, void *data) 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++) { @@ -1168,10 +1149,9 @@ int lprocfs_timeouts_seq_show(struct seq_file *m, void *data) 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]); } @@ -1198,14 +1178,82 @@ int lprocfs_connect_flags_seq_show(struct seq_file *m, void *data) } 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, @@ -1214,25 +1262,37 @@ lprocfs_obd_setup(struct obd_device *obd) 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); @@ -1496,7 +1556,7 @@ static int lprocfs_stats_seq_open(struct inode *inode, struct file *file) 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; } @@ -2081,26 +2141,6 @@ static int str_to_s64_internal(const char __user *buffer, unsigned long count, /** * 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 @@ -2132,7 +2172,7 @@ int lprocfs_str_with_units_to_s64(const char __user *buffer, } 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; @@ -2147,6 +2187,7 @@ static char *lprocfs_strnstr(const char *s1, const char *s2, size_t len) } return NULL; } +EXPORT_SYMBOL(lprocfs_strnstr); /** * Find the string \a name in the input \a buffer, and return a pointer to the @@ -2291,31 +2332,109 @@ const struct sysfs_ops lustre_sysfs_ops = { }; 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)