From: Dmitry Eremin Date: Fri, 28 Jul 2017 20:51:52 +0000 (-0400) Subject: LU-8066 libcfs: migrate to debugfs X-Git-Tag: 2.10.52~35 X-Git-Url: https://git.whamcloud.com/?p=fs%2Flustre-release.git;a=commitdiff_plain;h=7092309f32516cbfb95a964c87b8030129edeb27 LU-8066 libcfs: migrate to debugfs move /proc/sys/lnet to debugfs Parameters in lnet sysctl are of debug quality, so let's move them to debugfs instead. Linux-commit: 0871d551af37c72c308397c16c31bae945e6a79d Remove redundant lnet debugfs variables /proc/sys/lnet/console_ratelimit, debug_path and panic_on_lbug are module parameters with no special magic accessible via /sys/module/libcfs/parameters/libcfs_console_ratelimit, /sys/module/libcfs/parameters/libcfs_debug_file_path and /sys/module/libcfs/parameters/libcfs_panic_on_lbug respectively. As such just replace them with corresponding symlinks Linux-commit: 1b4d97b6c6ca05446ff33843a7b174cdd765df5a get rid of debugfs/lnet/console_backoff module parameter libcfs_console_backoff accessible through /sys/module/libcfs/parameters/libcfs_console_backoff would do the same thing, just add a special "uintpos" parameter type to disallow 0 values too. Also add a symlink to the module parameter variable for backwards compatibility Linux-commit: 8710427dd68f4dff8976d221e220317cea20ecec get rid of debugfs/lnet/debug_mb It's just a fancy libcfs_debug_mb module parameter wrapper, so just add debug buffer size check and resizing and the same functionality now would be accessible via /sys/module/libcfs/parameters/libcfs_debug_mb Also add a symlink for backwards compatibility. Linux-commit: 8dc08446d0671709bdec9e037845b014e33663b1 get rid of debugfs/lnet/console_{min, max}_delay_centisecs They are just fancy module parameters wrappers, so just the same functionality now would be accessible via /sys/module/libcfs/parameters/libcfs_console_{min,max}_delay Also install compatibility symlinks Linux-commit: 35ca907d245e8c218f39b6ed8bd6a1c656d056cc Fix kstrtouint return value check fix Apparently kstrtouint could return not just -EINVAL, but also -ERANGE, so make sure we just check the return value for something negative. Noticed by Dan Carpenter Linux-commit: aa66d6f87f300b15ac2efdcde9e198bf5a9020ce Properly handle debugfs read- and write-only files It turns out that unlike procfs, debugfs does not really enforce permissions for root (similar to regular filesystems), so we need to ensure we are not providing ->write() method to read-only files and ->read() method for write-only files at registration. This fixes a couple of crashes on unexpected access. Linux-commit:49a76d7040b466dd92f198ded4aba3cd3569d48f Change-Id: I69ff4d9766969f2ca5d5478d4e822879ee78b467 Signed-off-by: Dmitry Eremin Signed-off-by: Oleg Drokin Signed-off-by: Greg Kroah-Hartman Signed-off-by: James Simmons Reviewed-on: https://review.whamcloud.com/24688 Tested-by: Jenkins Tested-by: Maloo Reviewed-by: Olaf Weber --- diff --git a/libcfs/autoconf/lustre-libcfs.m4 b/libcfs/autoconf/lustre-libcfs.m4 index 1e6f326..f61f728 100644 --- a/libcfs/autoconf/lustre-libcfs.m4 +++ b/libcfs/autoconf/lustre-libcfs.m4 @@ -137,6 +137,24 @@ ctl_table_ctl_name, [ ]) # LIBCFS_SYSCTL_CTLNAME # +# LIBCFS_MODULE_LOCKING +# +# 2.6.36 introduced locking to module params. RHEL6 lacks this support +# +AC_DEFUN([LIBCFS_MODULE_LOCKING],[ +LB_CHECK_COMPILE([does the kernel support module param locking], +module_param_locking, [ + #include +],[ + __kernel_param_lock(NULL); + __kernel_param_unlock(NULL); +],[ + AC_DEFINE(HAVE_MODULE_PARAM_LOCKING, 1, + [locking module param is supported]) +]) +]) # LIBCFS_MODULE_LOCKING + +# # LIBCFS_KSTRTOUL # # 2.6.38 kstrtoul is added @@ -295,6 +313,23 @@ ktime_get_ts64, [ ]) # LIBCFS_KTIME_GET_TS64 # +# Linux kernel 3.12 introduced struct kernel_param_ops +# This has been backported to all lustre supported +# clients expect RHEL6. We have to handle the differences. +# +AC_DEFUN([LIBCFS_KERNEL_PARAM_OPS],[ +LB_CHECK_COMPILE([does 'struct kernel_param_ops' exist], +kernel_param_ops, [ + #include +],[ + struct kernel_param_ops ops; +],[ + AC_DEFINE(HAVE_KERNEL_PARAM_OPS, 1, + ['struct kernel_param_ops' is available]) +]) +]) # LIBCFS_KERNEL_PARAM_OPS + +# # Kernel version 3.12 introduced ktime_add # AC_DEFUN([LIBCFS_KTIME_ADD],[ @@ -524,6 +559,25 @@ cpumap_print_to_pagebuf, [ ]) # LIBCFS_HAVE_CPUMASK_PRINT_TO_PAGEBUF # +# Kernel version 4.1 commit b51d23e4e9fea6f264d39535c2a62d1f51e7ccc3 +# create per module locks which added kernel_param_[un]lock(). Older +# kernels you have to use __kernel_param_[un]lock(). In that case its +# a global lock for all modules but that is okay since its a rare event. +# +AC_DEFUN([LIBCFS_KERNEL_PARAM_LOCK],[ +LB_CHECK_COMPILE([does function 'kernel_param_[un]lock' exist], +kernel_param_lock, [ + #include +],[ + kernel_param_lock(NULL); + kernel_param_unlock(NULL); +],[ + AC_DEFINE(HAVE_KERNEL_PARAM_LOCK, 1, + ['kernel_param_[un]lock' is available]) +]) +]) # LIBCFS_KERNEL_PARAM_LOCK + +# # Kernel version 4.2 changed topology_thread_cpumask # to topology_sibling_cpumask # @@ -685,6 +739,8 @@ LIBCFS_STACKTRACE_OPS_HAVE_WALK_STACK LC_SHRINKER_WANT_SHRINK_PTR # 2.6.33 LIBCFS_SYSCTL_CTLNAME +# 2.6.36 +LIBCFS_MODULE_LOCKING # 2.6.38 LIBCFS_KSTRTOUL # 2.6.39 @@ -707,6 +763,7 @@ LIBCFS_ENABLE_CRC32C_ACCEL # 3.11 LIBCFS_KTIME_GET_TS64 # 3.12 +LIBCFS_KERNEL_PARAM_OPS LIBCFS_KTIME_ADD LIBCFS_KTIME_AFTER LIBCFS_SHRINKER_COUNT @@ -722,6 +779,8 @@ LIBCFS_TIMESPEC64_TO_KTIME # 3.19 LIBCFS_KTIME_GET_SECONDS LIBCFS_HAVE_CPUMASK_PRINT_TO_PAGEBUF +# 4.1 +LIBCFS_KERNEL_PARAM_LOCK # 4.2 LIBCFS_HAVE_TOPOLOGY_SIBLING_CPUMASK LIBCFS_FPU_API diff --git a/libcfs/include/libcfs/libcfs.h b/libcfs/include/libcfs/libcfs.h index b33243a..59453fa 100644 --- a/libcfs/include/libcfs/libcfs.h +++ b/libcfs/include/libcfs/libcfs.h @@ -128,4 +128,12 @@ static inline void *__container_of(const void *ptr, unsigned long shift) #define container_of0(ptr, type, member) \ ((type *)__container_of((ptr), offsetof(type, member))) +struct lnet_debugfs_symlink_def { + const char *name; + const char *target; +}; + +void lnet_insert_debugfs(struct ctl_table *table, + const struct lnet_debugfs_symlink_def *symlinks); + #endif /* _LIBCFS_LIBCFS_H_ */ diff --git a/libcfs/include/libcfs/linux/linux-misc.h b/libcfs/include/libcfs/linux/linux-misc.h index e111193..c3b85fd 100644 --- a/libcfs/include/libcfs/linux/linux-misc.h +++ b/libcfs/include/libcfs/linux/linux-misc.h @@ -41,6 +41,10 @@ #define INIT_STRATEGY #endif +#ifndef HAVE_MODULE_PARAM_LOCKING +static DEFINE_MUTEX(param_lock); +#endif + #ifndef HAVE_UIDGID_HEADER #ifndef _LINUX_UIDGID_H @@ -105,6 +109,38 @@ static inline bool gid_valid(kgid_t gid) int cfs_get_environ(const char *key, char *value, int *val_len); +/* + * For RHEL6 struct kernel_parm_ops doesn't exist. Also + * the arguments for .set and .get take different + * parameters which is handled below + */ +#ifdef HAVE_KERNEL_PARAM_OPS +#define cfs_kernel_param_arg_t const struct kernel_param +#else +#define cfs_kernel_param_arg_t struct kernel_param_ops +#define kernel_param_ops kernel_param +#endif /* ! HAVE_KERNEL_PARAM_OPS */ + +#ifndef HAVE_KERNEL_PARAM_LOCK +static inline void kernel_param_unlock(struct module *mod) +{ +#ifndef HAVE_MODULE_PARAM_LOCKING + mutex_unlock(¶m_lock); +#else + __kernel_param_unlock(); +#endif +} + +static inline void kernel_param_lock(struct module *mod) +{ +#ifndef HAVE_MODULE_PARAM_LOCKING + mutex_lock(¶m_lock); +#else + __kernel_param_lock(); +#endif +} +#endif /* ! HAVE_KERNEL_PARAM_LOCK */ + #ifndef HAVE_KSTRTOUL static inline int kstrtoul(const char *s, unsigned int base, unsigned long *res) { diff --git a/libcfs/libcfs/debug.c b/libcfs/libcfs/debug.c index 1d7360a0..f923842 100644 --- a/libcfs/libcfs/debug.c +++ b/libcfs/libcfs/debug.c @@ -54,8 +54,58 @@ module_param(libcfs_debug, int, 0644); MODULE_PARM_DESC(libcfs_debug, "Lustre kernel debug mask"); EXPORT_SYMBOL(libcfs_debug); +static int libcfs_param_debug_mb_set(const char *val, + cfs_kernel_param_arg_t *kp) +{ + int rc; + unsigned int num; + + rc = kstrtouint(val, 0, &num); + if (rc < 0) + return rc; + +/* + * RHEL6 does not support any kind of locking so we have to provide + * our own + */ +#ifndef HAVE_MODULE_PARAM_LOCKING + kernel_param_lock(THIS_MODULE); +#endif + if (!*((unsigned int *)kp->arg)) { + *((unsigned int *)kp->arg) = num; + return 0; + } + + rc = cfs_trace_set_debug_mb(num); + + if (!rc) + *((unsigned int *)kp->arg) = cfs_trace_get_debug_mb(); + +#ifndef HAVE_MODULE_PARAM_LOCKING + kernel_param_unlock(THIS_MODULE); +#endif + return rc; +} + +/* While debug_mb setting look like unsigned int, in fact + * it needs quite a bunch of extra processing, so we define special + * debug_mb parameter type with corresponding methods to handle this case + */ +static struct kernel_param_ops param_ops_debug_mb = { + .set = libcfs_param_debug_mb_set, + .get = param_get_uint, +}; + +#define param_check_debug_mb(name, p) \ + __param_check(name, p, unsigned int) + static unsigned int libcfs_debug_mb; -module_param(libcfs_debug_mb, uint, 0644); +#ifdef HAVE_KERNEL_PARAM_OPS +module_param(libcfs_debug_mb, debug_mb, 0644); +#else +module_param_call(libcfs_debug_mb, libcfs_param_debug_mb_set, param_get_uint, + ¶m_ops_debug_mb, 0644); +#endif MODULE_PARM_DESC(libcfs_debug_mb, "Total debug buffer size."); unsigned int libcfs_printk = D_CANTMASK; @@ -66,16 +116,123 @@ unsigned int libcfs_console_ratelimit = 1; module_param(libcfs_console_ratelimit, uint, 0644); MODULE_PARM_DESC(libcfs_console_ratelimit, "Lustre kernel debug console ratelimit (0 to disable)"); +static int param_set_delay_minmax(const char *val, + cfs_kernel_param_arg_t *kp, + long min, long max) +{ + long d; + int sec; + int rc; + + rc = kstrtoint(val, 0, &sec); + if (rc) + return -EINVAL; + + /* The sysfs setting is in centiseconds */ + d = cfs_time_seconds(sec) / 100; + if (d < min || d > max) + return -EINVAL; + + *((unsigned int *)kp->arg) = d; + + return 0; +} + +static int param_get_delay(char *buffer, cfs_kernel_param_arg_t *kp) +{ + unsigned int d = *(unsigned int *)kp->arg; + + return sprintf(buffer, "%u", (unsigned int)cfs_duration_sec(d * 100)); +} + unsigned int libcfs_console_max_delay; -module_param(libcfs_console_max_delay, uint, 0644); +unsigned int libcfs_console_min_delay; + +static int param_set_console_max_delay(const char *val, + cfs_kernel_param_arg_t *kp) +{ + return param_set_delay_minmax(val, kp, + libcfs_console_min_delay, INT_MAX); +} + +static struct kernel_param_ops param_ops_console_max_delay = { + .set = param_set_console_max_delay, + .get = param_get_delay, +}; + +#define param_check_console_max_delay(name, p) \ + __param_check(name, p, unsigned int) + +#ifdef HAVE_KERNEL_PARAM_OPS +module_param(libcfs_console_max_delay, console_max_delay, 0644); +#else +module_param_call(libcfs_console_max_delay, param_set_console_max_delay, + param_get_delay, ¶m_ops_console_max_delay, 0644); +#endif MODULE_PARM_DESC(libcfs_console_max_delay, "Lustre kernel debug console max delay (jiffies)"); -unsigned int libcfs_console_min_delay; -module_param(libcfs_console_min_delay, uint, 0644); +static int param_set_console_min_delay(const char *val, + cfs_kernel_param_arg_t *kp) +{ + return param_set_delay_minmax(val, kp, + 1, libcfs_console_max_delay); +} + +static struct kernel_param_ops param_ops_console_min_delay = { + .set = param_set_console_min_delay, + .get = param_get_delay, +}; + +#define param_check_console_min_delay(name, p) \ + __param_check(name, p, unsigned int) + +#ifdef HAVE_KERNEL_PARAM_OPS +module_param(libcfs_console_min_delay, console_min_delay, 0644); +#else +module_param_call(libcfs_console_min_delay, param_set_console_min_delay, + param_get_delay, ¶m_ops_console_min_delay, 0644); +#endif MODULE_PARM_DESC(libcfs_console_min_delay, "Lustre kernel debug console min delay (jiffies)"); +static int param_set_uint_minmax(const char *val, + cfs_kernel_param_arg_t *kp, + unsigned int min, unsigned int max) +{ + unsigned int num; + int ret; + + if (!val) + return -EINVAL; + + ret = kstrtouint(val, 0, &num); + if (ret < 0 || num < min || num > max) + return -EINVAL; + + *((unsigned int *)kp->arg) = num; + return 0; +} + +static int param_set_uintpos(const char *val, + cfs_kernel_param_arg_t *kp) +{ + return param_set_uint_minmax(val, kp, 1, -1); +} + +static struct kernel_param_ops param_ops_uintpos = { + .set = param_set_uintpos, + .get = param_get_uint, +}; + +#define param_check_uintpos(name, p) \ + __param_check(name, p, unsigned int) + unsigned int libcfs_console_backoff = CDEBUG_DEFAULT_BACKOFF; -module_param(libcfs_console_backoff, uint, 0644); +#ifdef HAVE_KERNEL_PARAM_OPS +module_param(libcfs_console_backoff, uintpos, 0644); +#else +module_param_call(libcfs_console_backoff, param_set_uintpos, param_get_uint, + ¶m_ops_uintpos, 0644); +#endif MODULE_PARM_DESC(libcfs_console_backoff, "Lustre kernel debug console backoff factor"); unsigned int libcfs_debug_binary = 1; @@ -101,7 +258,7 @@ char libcfs_debug_file_path_arr[PATH_MAX] = LIBCFS_DEBUG_FILE_PATH_DEFAULT; EXPORT_SYMBOL(libcfs_debug_file_path_arr); /* We need to pass a pointer here, but elsewhere this must be a const */ -static char *libcfs_debug_file_path; +static char *libcfs_debug_file_path = LIBCFS_DEBUG_FILE_PATH_DEFAULT; module_param(libcfs_debug_file_path, charp, 0644); MODULE_PARM_DESC(libcfs_debug_file_path, "Path for dumping debug logs, set 'NONE' to prevent log dumping"); @@ -300,19 +457,25 @@ int libcfs_debug_init(unsigned long bufsize) max = (max / num_possible_cpus()); max = (max << (20 - PAGE_SHIFT)); } - rc = cfs_tracefile_init(max); - if (rc == 0) - libcfs_register_panic_notifier(); - - return rc; + rc = cfs_tracefile_init(max); + if (rc) + return rc; + + libcfs_register_panic_notifier(); + kernel_param_lock(THIS_MODULE); + libcfs_debug_mb = cfs_trace_get_debug_mb(); + kernel_param_unlock(THIS_MODULE); + return rc; } int libcfs_debug_cleanup(void) { - libcfs_unregister_panic_notifier(); - cfs_tracefile_exit(); - return 0; + libcfs_unregister_panic_notifier(); + kernel_param_lock(THIS_MODULE); + cfs_tracefile_exit(); + kernel_param_unlock(THIS_MODULE); + return 0; } int libcfs_debug_clear_buffer(void) diff --git a/libcfs/libcfs/module.c b/libcfs/libcfs/module.c index e8080f3..2018789 100644 --- a/libcfs/libcfs/module.c +++ b/libcfs/libcfs/module.c @@ -45,7 +45,7 @@ #include #include -#include +#include #include #define DEBUG_SUBSYSTEM S_LNET @@ -55,9 +55,7 @@ #include #include "tracefile.h" -#ifdef CONFIG_SYSCTL -static struct ctl_table_header *lnet_table_header; -#endif +static struct dentry *lnet_debugfs_root; static DECLARE_RWSEM(ioctl_list_sem); static LIST_HEAD(ioctl_list); @@ -156,11 +154,10 @@ out: RETURN(err); } -int -lprocfs_call_handler(void *data, int write, loff_t *ppos, - void __user *buffer, size_t *lenp, - int (*handler)(void *data, int write, loff_t pos, - void __user *buffer, int len)) +int lprocfs_call_handler(void *data, int write, loff_t *ppos, + void __user *buffer, size_t *lenp, + int (*handler)(void *data, int write, loff_t pos, + void __user *buffer, int len)) { int rc = handler(data, write, *ppos, buffer, *lenp); @@ -218,9 +215,8 @@ static int __proc_dobitmasks(void *data, int write, return rc; } -static int -proc_dobitmasks(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) +static int proc_dobitmasks(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, __proc_dobitmasks); @@ -238,9 +234,8 @@ static int __proc_dump_kernel(void *data, int write, return cfs_trace_dump_debug_buffer_usrstr(buffer, nob); } -static int -proc_dump_kernel(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_dump_kernel(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, __proc_dump_kernel); @@ -262,148 +257,24 @@ static int __proc_daemon_file(void *data, int write, return cfs_trace_daemon_command_usrstr(buffer, nob); } -static int -proc_daemon_file(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_daemon_file(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, __proc_daemon_file); } -static int __proc_debug_mb(void *data, int write, - loff_t pos, void __user *buffer, int nob) -{ - if (!write) { - char tmpstr[32]; - int len = snprintf(tmpstr, sizeof(tmpstr), "%d", - cfs_trace_get_debug_mb()); - - if (pos >= len) - return 0; - - return cfs_trace_copyout_string(buffer, nob, tmpstr + pos, - "\n"); - } - - return cfs_trace_set_debug_mb_usrstr(buffer, nob); -} - -static int -proc_debug_mb(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) -{ - return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, - __proc_debug_mb); -} - -static int -proc_console_max_delay_cs(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) -{ - int rc, max_delay_cs; - struct ctl_table dummy = *table; - cfs_duration_t d; - - dummy.data = &max_delay_cs; - dummy.proc_handler = &proc_dointvec; - - if (!write) { /* read */ - max_delay_cs = cfs_duration_sec(libcfs_console_max_delay * 100); - rc = proc_dointvec(&dummy, write, buffer, lenp, ppos); - return rc; - } - - /* write */ - max_delay_cs = 0; - rc = proc_dointvec(&dummy, write, buffer, lenp, ppos); - if (rc < 0) - return rc; - if (max_delay_cs <= 0) - return -EINVAL; - - d = cfs_time_seconds(max_delay_cs) / 100; - if (d == 0 || d < libcfs_console_min_delay) - return -EINVAL; - libcfs_console_max_delay = d; - - return rc; -} - -static int -proc_console_min_delay_cs(struct ctl_table *table, int write, - void __user *buffer, size_t *lenp, loff_t *ppos) -{ - int rc, min_delay_cs; - struct ctl_table dummy = *table; - cfs_duration_t d; - - dummy.data = &min_delay_cs; - dummy.proc_handler = &proc_dointvec; - - if (!write) { /* read */ - min_delay_cs = cfs_duration_sec(libcfs_console_min_delay * 100); - rc = proc_dointvec(&dummy, write, buffer, lenp, ppos); - return rc; - } - - /* write */ - min_delay_cs = 0; - rc = proc_dointvec(&dummy, write, buffer, lenp, ppos); - if (rc < 0) - return rc; - if (min_delay_cs <= 0) - return -EINVAL; - - d = cfs_time_seconds(min_delay_cs) / 100; - if (d == 0 || d > libcfs_console_max_delay) - return -EINVAL; - libcfs_console_min_delay = d; - - return rc; -} - -static int -proc_console_backoff(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) -{ - int rc, backoff; - struct ctl_table dummy = *table; - - dummy.data = &backoff; - dummy.proc_handler = &proc_dointvec; - - if (!write) { /* read */ - backoff = libcfs_console_backoff; - rc = proc_dointvec(&dummy, write, buffer, lenp, ppos); - return rc; - } - - /* write */ - backoff = 0; - rc = proc_dointvec(&dummy, write, buffer, lenp, ppos); - if (rc < 0) - return rc; - - if (backoff <= 0) - return -EINVAL; - - libcfs_console_backoff = backoff; - - return rc; -} - -static int -libcfs_force_lbug(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int libcfs_force_lbug(struct ctl_table *table, int write, + void __user *buffer, + size_t *lenp, loff_t *ppos) { if (write) LBUG(); return 0; } -static int -proc_fail_loc(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_fail_loc(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { int rc; long old_fail_loc = cfs_fail_loc; @@ -455,9 +326,8 @@ out: return rc; } -static int -proc_cpt_table(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_cpt_table(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, __proc_cpt_table); @@ -504,19 +374,14 @@ static int __proc_cpt_distance(void *data, int write, return rc; } -static int -proc_cpt_distance(struct ctl_table *table, int write, void __user *buffer, - size_t *lenp, loff_t *ppos) +static int proc_cpt_distance(struct ctl_table *table, int write, + void __user *buffer, size_t *lenp, loff_t *ppos) { return lprocfs_call_handler(table->data, write, ppos, buffer, lenp, __proc_cpt_distance); } static struct ctl_table lnet_table[] = { - /* - * NB No .strategy entries have been provided since sysctl(8) prefers - * to go via /proc for portability. - */ { INIT_CTL_NAME .procname = "debug", @@ -543,43 +408,6 @@ static struct ctl_table lnet_table[] = { }, { INIT_CTL_NAME - .procname = "console_ratelimit", - .data = &libcfs_console_ratelimit, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec - }, - { - INIT_CTL_NAME - .procname = "console_max_delay_centisecs", - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_console_max_delay_cs - }, - { - INIT_CTL_NAME - .procname = "console_min_delay_centisecs", - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_console_min_delay_cs - }, - { - INIT_CTL_NAME - .procname = "console_backoff", - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_console_backoff - }, - { - INIT_CTL_NAME - .procname = "debug_path", - .data = libcfs_debug_file_path_arr, - .maxlen = sizeof(libcfs_debug_file_path_arr), - .mode = 0644, - .proc_handler = &proc_dostring, - }, - { - INIT_CTL_NAME .procname = "cpu_partition_table", .maxlen = 128, .mode = 0444, @@ -618,14 +446,6 @@ static struct ctl_table lnet_table[] = { }, { INIT_CTL_NAME - .procname = "panic_on_lbug", - .data = &libcfs_panic_on_lbug, - .maxlen = sizeof(int), - .mode = 0644, - .proc_handler = &proc_dointvec, - }, - { - INIT_CTL_NAME .procname = "dump_kernel", .maxlen = 256, .mode = 0200, @@ -640,12 +460,6 @@ static struct ctl_table lnet_table[] = { }, { INIT_CTL_NAME - .procname = "debug_mb", - .mode = 0644, - .proc_handler = &proc_debug_mb, - }, - { - INIT_CTL_NAME .procname = "watchdog_ratelimit", .data = &libcfs_watchdog_ratelimit, .maxlen = sizeof(int), @@ -690,37 +504,109 @@ static struct ctl_table lnet_table[] = { } }; -#ifdef CONFIG_SYSCTL -static struct ctl_table top_table[] = { - { - INIT_CTL_NAME - .procname = "lnet", - .mode = 0555, - .data = NULL, - .maxlen = 0, - .child = lnet_table, - }, - { 0 } +static const struct lnet_debugfs_symlink_def lnet_debugfs_symlinks[] = { + { .name = "console_ratelimit", + .target = "../../../module/libcfs/parameters/libcfs_console_ratelimit" }, + { .name = "debug_path", + .target = "../../../module/libcfs/parameters/libcfs_debug_file_path" }, + { .name = "panic_on_lbug", + .target = "../../../module/libcfs/parameters/libcfs_panic_on_lbug" }, + { .name = "console_backoff", + .target = "../../../module/libcfs/parameters/libcfs_console_backoff" }, + { .name = "debug_mb", + .target = "../../../module/libcfs/parameters/libcfs_debug_mb" }, + { .name = "console_min_delay_centisecs", + .target = "../../../module/libcfs/parameters/libcfs_console_min_delay" }, + { .name = "console_max_delay_centisecs", + .target = "../../../module/libcfs/parameters/libcfs_console_max_delay" }, + { .name = NULL }, }; -#endif -static int insert_proc(void) +static ssize_t lnet_debugfs_read(struct file *filp, char __user *buf, + size_t count, loff_t *ppos) { -#ifdef CONFIG_SYSCTL - if (lnet_table_header == NULL) - lnet_table_header = register_sysctl_table(top_table); -#endif - return 0; + struct ctl_table *table = filp->private_data; + ssize_t rc; + + rc = table->proc_handler(table, 0, buf, &count, ppos); + if (!rc) + rc = count; + + return rc; +} + +static ssize_t lnet_debugfs_write(struct file *filp, const char __user *buf, + size_t count, loff_t *ppos) +{ + struct ctl_table *table = filp->private_data; + ssize_t rc; + + rc = table->proc_handler(table, 1, (void __user *)buf, &count, ppos); + if (!rc) + rc = count; + + return rc; +} + +static const struct file_operations lnet_debugfs_file_operations_rw = { + .open = simple_open, + .read = lnet_debugfs_read, + .write = lnet_debugfs_write, + .llseek = default_llseek, +}; + +static const struct file_operations lnet_debugfs_file_operations_ro = { + .open = simple_open, + .read = lnet_debugfs_read, + .llseek = default_llseek, +}; + +static const struct file_operations lnet_debugfs_file_operations_wo = { + .open = simple_open, + .write = lnet_debugfs_write, + .llseek = default_llseek, +}; + +static const struct file_operations *lnet_debugfs_fops_select(umode_t mode) +{ + if (!(mode & S_IWUGO)) + return &lnet_debugfs_file_operations_ro; + + if (!(mode & S_IRUGO)) + return &lnet_debugfs_file_operations_wo; + + return &lnet_debugfs_file_operations_rw; +} + +void lnet_insert_debugfs(struct ctl_table *table, + const struct lnet_debugfs_symlink_def *symlinks) +{ + if (!lnet_debugfs_root) + lnet_debugfs_root = debugfs_create_dir("lnet", NULL); + + /* Even if we cannot create, just ignore it altogether) */ + if (IS_ERR_OR_NULL(lnet_debugfs_root)) + return; + + /* We don't save the dentry returned in next two calls, because + * we don't call debugfs_remove() but rather remove_recursive() + */ + for (; table && table->procname; table++) + debugfs_create_file(table->procname, table->mode, + lnet_debugfs_root, table, + lnet_debugfs_fops_select(table->mode)); + + for (; symlinks && symlinks->name; symlinks++) + debugfs_create_symlink(symlinks->name, lnet_debugfs_root, + symlinks->target); } +EXPORT_SYMBOL_GPL(lnet_insert_debugfs); -static void remove_proc(void) +static void lnet_remove_debugfs(void) { -#ifdef CONFIG_SYSCTL - if (lnet_table_header != NULL) - unregister_sysctl_table(lnet_table_header); + debugfs_remove_recursive(lnet_debugfs_root); - lnet_table_header = NULL; -#endif + lnet_debugfs_root = NULL; } static int __init libcfs_init(void) @@ -764,17 +650,10 @@ static int __init libcfs_init(void) goto cleanup_wi; } - - rc = insert_proc(); - if (rc) { - CERROR("insert_proc: error %d\n", rc); - goto cleanup_crypto; - } + lnet_insert_debugfs(lnet_table, lnet_debugfs_symlinks); CDEBUG (D_OTHER, "portals setup OK\n"); return 0; -cleanup_crypto: - cfs_crypto_unregister(); cleanup_wi: cfs_wi_shutdown(); cleanup_deregister: @@ -790,7 +669,7 @@ static void __exit libcfs_exit(void) { int rc; - remove_proc(); + lnet_remove_debugfs(); CDEBUG(D_MALLOC, "before Portals cleanup: kmem %d\n", atomic_read(&libcfs_kmemory)); diff --git a/libcfs/libcfs/tracefile.c b/libcfs/libcfs/tracefile.c index 8dba1da..805cb8c 100644 --- a/libcfs/libcfs/tracefile.c +++ b/libcfs/libcfs/tracefile.c @@ -911,18 +911,6 @@ int cfs_trace_set_debug_mb(int mb) return 0; } -int cfs_trace_set_debug_mb_usrstr(void __user *usr_str, int usr_str_nob) -{ - char str[32]; - int rc; - - rc = cfs_trace_copyin_string(str, sizeof(str), usr_str, usr_str_nob); - if (rc < 0) - return rc; - - return cfs_trace_set_debug_mb(simple_strtoul(str, NULL, 0)); -} - int cfs_trace_get_debug_mb(void) { int i; diff --git a/libcfs/libcfs/tracefile.h b/libcfs/libcfs/tracefile.h index 2f5dc4f..14e3311 100644 --- a/libcfs/libcfs/tracefile.h +++ b/libcfs/libcfs/tracefile.h @@ -82,7 +82,6 @@ int cfs_trace_dump_debug_buffer_usrstr(void __user *usr_str, int usr_str_nob); int cfs_trace_daemon_command(char *str); int cfs_trace_daemon_command_usrstr(void __user *usr_str, int usr_str_nob); int cfs_trace_set_debug_mb(int mb); -int cfs_trace_set_debug_mb_usrstr(void __user *usr_str, int usr_str_nob); int cfs_trace_get_debug_mb(void); extern void libcfs_debug_dumplog_internal(void *arg);