Whamcloud - gitweb
*** empty log message ***
[fs/lustre-release.git] / lnet / libcfs / linux / linux-proc.c
index 3efdd46..92cc8fe 100644 (file)
@@ -26,7 +26,7 @@
 # define EXPORT_SYMTAB
 #endif
 
-#ifdef HAVE_KERNEL_CONFIG_H
+#ifndef AUTOCONF_INCLUDED
 #include <linux/config.h>
 #endif
 #include <linux/module.h>
@@ -59,7 +59,7 @@
 #include <asm/div64.h>
 #include "tracefile.h"
 
-static struct ctl_table_header *lnet_table_header = NULL;
+static cfs_sysctl_table_header_t *lnet_table_header = NULL;
 extern char lnet_upcall[1024];
 
 #define PSDEV_LNET  (0x100)
@@ -73,145 +73,255 @@ enum {
         PSDEV_LNET_UPCALL,        /* User mode upcall script  */
         PSDEV_LNET_MEMUSED,       /* bytes currently PORTAL_ALLOCated */
         PSDEV_LNET_CATASTROPHE,   /* if we have LBUGged or panic'd */
+        PSDEV_LNET_PANIC_ON_LBUG, /* flag to panic on LBUG */
+        PSDEV_LNET_DUMP_KERNEL,   /* snapshot kernel debug buffer to file */
+        PSDEV_LNET_DAEMON_FILE,   /* spool kernel debug buffer to file */
+        PSDEV_LNET_DEBUG_MB,      /* size of debug buffer */
 };
 
-int LL_PROC_PROTO(proc_dobitmasks);
-
-static struct ctl_table lnet_table[] = {
-        {PSDEV_DEBUG, "debug", &libcfs_debug, sizeof(int), 0644, NULL,
-         &proc_dobitmasks},
-        {PSDEV_SUBSYSTEM_DEBUG, "subsystem_debug", &libcfs_subsystem_debug,
-         sizeof(int), 0644, NULL, &proc_dobitmasks},
-        {PSDEV_PRINTK, "printk", &libcfs_printk, sizeof(int), 0644, NULL,
-         &proc_dobitmasks},
-        {PSDEV_CONSOLE_RATELIMIT, "console_ratelimit",&libcfs_console_ratelimit,
-         sizeof(int), 0644, NULL, &proc_dointvec},
-        {PSDEV_DEBUG_PATH, "debug_path", debug_file_path,
-         sizeof(debug_file_path), 0644, NULL, &proc_dostring, &sysctl_string},
-        {PSDEV_LNET_UPCALL, "upcall", lnet_upcall,
-         sizeof(lnet_upcall), 0644, NULL, &proc_dostring,
-         &sysctl_string},
-        {PSDEV_LNET_MEMUSED, "memused", (int *)&libcfs_kmemory.counter,
-         sizeof(int), 0444, NULL, &proc_dointvec},
-        {PSDEV_LNET_CATASTROPHE, "catastrophe", &libcfs_catastrophe,
-         sizeof(int), 0444, NULL, &proc_dointvec},
-        {0}
-};
-
-static struct ctl_table top_table[2] = {
-        {PSDEV_LNET, "lnet", NULL, 0, 0555, lnet_table},
-        {0}
-};
-
-int LL_PROC_PROTO(proc_dobitmasks)
+static int 
+proc_call_handler(void *data, int write, 
+                  loff_t *ppos, void *buffer, size_t *lenp, 
+                  int (*handler)(void *data, int write,
+                                 loff_t pos, void *buffer, int len))
 {
-        const int     tmpstrlen = 512;
-        char         *str;
-        int           rc = 0;
-        /* the proc filling api stumps me always, coax proc_dointvec
-         * and proc_dostring into doing the drudgery by cheating
-         * with a dummy ctl_table
-         */
-        struct ctl_table dummy = *table;
-        unsigned int *mask = (unsigned int *)table->data;
-        int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
+        int rc = handler(data, write, *ppos, buffer, *lenp);
 
-       str = kmalloc(tmpstrlen, GFP_USER);
-        if (str == NULL)
-                return -ENOMEM;
+        if (rc < 0)
+                return rc;
 
         if (write) {
-                size_t oldlen = *lenp;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
-                loff_t oldpos = *ppos;
-#endif
-
-                dummy.proc_handler = &proc_dointvec;
-
-                /* old proc interface allows user to specify just an int
-                 * value; be compatible and don't break userland.
-                 */
-                rc = ll_proc_dointvec(&dummy, write, filp, buffer, lenp, ppos);
-
-                if (rc != -EINVAL)
-                        goto out;
-
-                /* using new interface */
-                dummy.data = str;
-                dummy.maxlen = tmpstrlen;
-                dummy.proc_handler = &proc_dostring;
-
-                /* proc_dointvec might have changed these */
-                *lenp = oldlen;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,8)
-                *ppos = oldpos;
-#endif
+                *ppos += *lenp;
+        } else {
+                *lenp = rc;
+                *ppos += rc;
+        }
+        return 0;
+}
 
-                rc = ll_proc_dostring(&dummy, write, filp, buffer, lenp, ppos);
+#define DECLARE_PROC_HANDLER(name)                      \
+static int                                              \
+LL_PROC_PROTO(name)                                     \
+{                                                       \
+        DECLARE_LL_PROC_PPOS_DECL;                      \
+                                                        \
+        return proc_call_handler(table->data, write,    \
+                                 ppos, buffer, lenp,    \
+                                 __##name);             \
+}
 
-                if (rc != 0)
-                        goto out;
+static int __proc_dobitmasks(void *data, int write, 
+                             loff_t pos, void *buffer, int nob)
+{
+        const int     tmpstrlen = 512;
+        char         *tmpstr;
+        int           rc;
+        unsigned int *mask = data;
+        int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
 
-                rc = libcfs_debug_str2mask(mask, dummy.data, is_subsys);
+        rc = trace_allocate_string_buffer(&tmpstr, tmpstrlen);
+        if (rc < 0)
+                return rc;
+        
+        if (!write) {
+                libcfs_debug_mask2str(tmpstr, tmpstrlen, *mask, is_subsys);
+                rc = strlen(tmpstr);
+
+                if (pos >= rc) {
+                        rc = 0;
+                } else {
+                        rc = trace_copyout_string(buffer, nob,
+                                                  tmpstr + pos, "\n");
+                }
         } else {
-                dummy.data = str;
-                dummy.maxlen = tmpstrlen;
-                dummy.proc_handler = &proc_dostring;
-
-                libcfs_debug_mask2str(dummy.data, dummy.maxlen,*mask,is_subsys);
-
-                rc = ll_proc_dostring(&dummy, write, filp, buffer, lenp, ppos);
+                rc = trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
+                if (rc < 0)
+                        return rc;
+                
+                rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
         }
 
-out:
-        kfree(str);
+        trace_free_string_buffer(tmpstr, tmpstrlen);
         return rc;
 }
 
-int insert_proc(void)
+DECLARE_PROC_HANDLER(proc_dobitmasks)
+
+static int __proc_dump_kernel(void *data, int write,
+                              loff_t pos, void *buffer, int nob)
 {
-        struct proc_dir_entry *ent;
+        if (!write)
+                return 0;
+        
+        return trace_dump_debug_buffer_usrstr(buffer, nob);
+}
 
-#ifdef CONFIG_SYSCTL
-        if (!lnet_table_header)
-                lnet_table_header = register_sysctl_table(top_table, 0);
-#endif
+DECLARE_PROC_HANDLER(proc_dump_kernel)
 
-        ent = create_proc_entry("sys/lnet/dump_kernel", 0, NULL);
-        if (ent == NULL) {
-                CERROR("couldn't register dump_kernel\n");
-                return -1;
+static int __proc_daemon_file(void *data, int write,
+                              loff_t pos, void *buffer, int nob)
+{
+        if (!write) {
+                int len = strlen(tracefile);
+                
+                if (pos >= len)
+                        return 0;
+                
+                return trace_copyout_string(buffer, nob, 
+                                            tracefile + pos, "\n");
         }
-        ent->write_proc = trace_dk;
+        
+        return trace_daemon_command_usrstr(buffer, nob);
+}
 
-        ent = create_proc_entry("sys/lnet/daemon_file", 0, NULL);
-        if (ent == NULL) {
-                CERROR("couldn't register daemon_file\n");
-                return -1;
-        }
-        ent->write_proc = trace_write_daemon_file;
-        ent->read_proc = trace_read_daemon_file;
+DECLARE_PROC_HANDLER(proc_daemon_file)
 
-        ent = create_proc_entry("sys/lnet/debug_mb", 0, NULL);
-        if (ent == NULL) {
-                CERROR("couldn't register debug_mb\n");
-                return -1;
+static int __proc_debug_mb(void *data, int write,
+                           loff_t pos, void *buffer, int nob)
+{
+        if (!write) {
+                char tmpstr[32];
+                int  len = snprintf(tmpstr, sizeof(tmpstr), "%d",
+                                    trace_get_debug_mb());
+
+                if (pos >= len)
+                        return 0;
+                
+                return trace_copyout_string(buffer, nob, tmpstr + pos, "\n");
         }
-        ent->write_proc = trace_write_debug_mb;
-        ent->read_proc = trace_read_debug_mb;
+        
+        return trace_set_debug_mb_usrstr(buffer, nob);
+}
+
+DECLARE_PROC_HANDLER(proc_debug_mb)
 
+static cfs_sysctl_table_t lnet_table[] = {
+        /*
+         * NB No .strategy entries have been provided since sysctl(8) prefers
+         * to go via /proc for portability.
+         */
+        {
+                .ctl_name = PSDEV_DEBUG,
+                .procname = "debug",
+                .data     = &libcfs_debug,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dobitmasks
+        },
+        {
+                .ctl_name = PSDEV_SUBSYSTEM_DEBUG,
+                .procname = "subsystem_debug",
+                .data     = &libcfs_subsystem_debug,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dobitmasks
+        },
+        {
+                .ctl_name = PSDEV_PRINTK,
+                .procname = "printk",
+                .data     = &libcfs_printk,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dobitmasks
+        },
+        {
+                .ctl_name = PSDEV_CONSOLE_RATELIMIT,
+                .procname = "console_ratelimit",
+                .data     = &libcfs_console_ratelimit,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec
+        },
+
+        {
+                .ctl_name = PSDEV_DEBUG_PATH,
+                .procname = "debug_path",
+                .data     = debug_file_path,
+                .maxlen   = sizeof(debug_file_path),
+                .mode     = 0644,
+                .proc_handler = &proc_dostring,
+        },
+
+        {
+                .ctl_name = PSDEV_LNET_UPCALL,
+                .procname = "upcall",
+                .data     = lnet_upcall,
+                .maxlen   = sizeof(lnet_upcall),
+                .mode     = 0644,
+                .proc_handler = &proc_dostring,
+        },
+        {
+                .ctl_name = PSDEV_LNET_MEMUSED,
+                .procname = "memused",
+                .data     = (int *)&libcfs_kmemory.counter,
+                .maxlen   = sizeof(int),
+                .mode     = 0444,
+                .proc_handler = &proc_dointvec
+        },
+        {
+                .ctl_name = PSDEV_LNET_CATASTROPHE,
+                .procname = "catastrophe",
+                .data     = &libcfs_catastrophe,
+                .maxlen   = sizeof(int),
+                .mode     = 0444,
+                .proc_handler = &proc_dointvec
+        },
+        {
+                .ctl_name = PSDEV_LNET_PANIC_ON_LBUG,
+                .procname = "panic_on_lbug",
+                .data     = &libcfs_panic_on_lbug,
+                .maxlen   = sizeof(int),
+                .mode     = 0644,
+                .proc_handler = &proc_dointvec
+        },
+        {
+                .ctl_name = PSDEV_LNET_DUMP_KERNEL,
+                .procname = "dump_kernel",
+                .mode     = 0200,
+                .proc_handler = &proc_dump_kernel,
+        },
+        {
+                .ctl_name = PSDEV_LNET_DAEMON_FILE,
+                .procname = "daemon_file",
+                .mode     = 0644,
+                .proc_handler = &proc_daemon_file,
+        },
+        {
+                .ctl_name = PSDEV_LNET_DEBUG_MB,
+                .procname = "debug_mb",
+                .mode     = 0644,
+                .proc_handler = &proc_debug_mb,
+        },
+        {0}
+};
+
+static cfs_sysctl_table_t top_table[2] = {
+        {
+                .ctl_name = PSDEV_LNET,
+                .procname = "lnet",
+                .data     = NULL,
+                .maxlen   = 0,
+                .mode     = 0555,
+                .child    = lnet_table
+        },
+        {0}
+};
+
+int insert_proc(void)
+{
+#ifdef CONFIG_SYSCTL
+        if (lnet_table_header == NULL)
+                lnet_table_header = cfs_register_sysctl_table(top_table, 0);
+#endif
         return 0;
 }
 
 void remove_proc(void)
 {
-        remove_proc_entry("sys/lnet/dump_kernel", NULL);
-        remove_proc_entry("sys/lnet/daemon_file", NULL);
-        remove_proc_entry("sys/lnet/debug_mb", NULL);
-
 #ifdef CONFIG_SYSCTL
-        if (lnet_table_header)
-                unregister_sysctl_table(lnet_table_header);
+        if (lnet_table_header != NULL)
+                cfs_unregister_sysctl_table(lnet_table_header);
+
         lnet_table_header = NULL;
 #endif
 }