Whamcloud - gitweb
Branch HEAD
authorliangzhen <liangzhen>
Fri, 21 Sep 2007 14:48:35 +0000 (14:48 +0000)
committerliangzhen <liangzhen>
Fri, 21 Sep 2007 14:48:35 +0000 (14:48 +0000)
Sysctl entries for /proc/sys/lnet (Patch by eeb)

b=12782
i=Liang

lnet/ChangeLog
lnet/include/libcfs/linux/portals_compat25.h
lnet/libcfs/darwin/darwin-proc.c
lnet/libcfs/darwin/darwin-tracefile.c
lnet/libcfs/debug.c
lnet/libcfs/linux/linux-proc.c
lnet/libcfs/linux/linux-tracefile.c
lnet/libcfs/tracefile.c
lnet/libcfs/tracefile.h
lnet/libcfs/winnt/winnt-proc.c
lnet/libcfs/winnt/winnt-tracefile.c

index fcc8312..39b2d31 100644 (file)
@@ -28,6 +28,11 @@ tbd         Cluster File Systems, Inc. <info@clusterfs.com>
        mxlnd     - MX 1.2.1 or later,
        ptllnd    - Portals 3.3 / UNICOS/lc 1.5.x, 2.0.x
 
        mxlnd     - MX 1.2.1 or later,
        ptllnd    - Portals 3.3 / UNICOS/lc 1.5.x, 2.0.x
 
+Severity   : normal
+Bugzilla   : 12782
+Description: /proc/sys/lnet has non-sysctl entries
+Details    : Updating dump_kernel/daemon_file/debug_mb to use sysctl variables
+
 Severity   : major
 Bugzilla   : 13236
 Description: TOE Kernel panic by ksocklnd
 Severity   : major
 Bugzilla   : 13236
 Description: TOE Kernel panic by ksocklnd
index 4caf8c8..e8152bc 100644 (file)
@@ -110,6 +110,7 @@ typedef unsigned long cpumask_t;
 #define LL_PROC_PROTO(name)                                             \
         name(cfs_sysctl_table_t *table, int write, struct file *filp,   \
              void __user *buffer, size_t *lenp)
 #define LL_PROC_PROTO(name)                                             \
         name(cfs_sysctl_table_t *table, int write, struct file *filp,   \
              void __user *buffer, size_t *lenp)
+#define DECLARE_LL_PROC_PPOS_DECL  loff_t *ppos = &filp->f_pos
 #else
 #define ll_proc_dointvec(table, write, filp, buffer, lenp, ppos)        \
         proc_dointvec(table, write, filp, buffer, lenp, ppos);
 #else
 #define ll_proc_dointvec(table, write, filp, buffer, lenp, ppos)        \
         proc_dointvec(table, write, filp, buffer, lenp, ppos);
@@ -118,6 +119,7 @@ typedef unsigned long cpumask_t;
 #define LL_PROC_PROTO(name)                                             \
         name(cfs_sysctl_table_t *table, int write, struct file *filp,   \
              void __user *buffer, size_t *lenp, loff_t *ppos)
 #define LL_PROC_PROTO(name)                                             \
         name(cfs_sysctl_table_t *table, int write, struct file *filp,   \
              void __user *buffer, size_t *lenp, loff_t *ppos)
+#define DECLARE_LL_PROC_PPOS
 #endif
 
 #endif /* _PORTALS_COMPAT_H */
 #endif
 
 #endif /* _PORTALS_COMPAT_H */
index a38902a..a001f5b 100644 (file)
@@ -49,9 +49,86 @@ extern unsigned int libcfs_console_ratelimit;
 extern unsigned int libcfs_catastrophe;
 extern atomic_t libcfs_kmemory;
 
 extern unsigned int libcfs_catastrophe;
 extern atomic_t libcfs_kmemory;
 
-extern long max_debug_mb;
-extern int cfs_trace_daemon SYSCTL_HANDLER_ARGS;
-extern int cfs_debug_mb SYSCTL_HANDLER_ARGS;
+static int sysctl_debug_kernel SYSCTL_HANDLER_ARGS
+{
+#error "Check me"
+        const int  maxstr = 1024;
+        char      *str;
+        int        error;
+
+        if (req->newptr == USER_ADDR_NULL) {
+                /* read request */
+                return -EINVAL;
+        }
+
+        /* write request */
+        error = trace_allocate_string_buffer(&str, maxstr + 1);
+        if (error != 0)
+                return error;
+
+       error = SYSCTL_IN(req, str, maxstr);
+
+        /* NB str guaranteed terminted */
+        if (error == 0)
+                error = tracefile_dump_all_pages(str);
+
+        trace_free_string_buffer(str, maxstr + 1);
+        return error;
+}
+
+static int sysctl_daemon_file SYSCTL_HANDLER_ARGS
+{
+#error "Check me"
+       int   error;
+       char *str;
+
+        if (req->newptr == USER_ADDR_NULL) {
+                /* a read */
+               tracefile_read_lock();
+
+                /* include terminating '\0' */
+               error = SYSCTL_OUT(req, tracefile, strlen(tracefile) + 1);
+
+               tracefile_read_unlock();
+                return error;
+        }
+        
+        /* write request */
+        error = trace_allocate_string_buffer(&str, TRACEFILE_NAME_SIZE);
+        if (error != 0)
+                return error;
+
+       error = SYSCTL_IN(req, str, TRACEFILE_NAME_SIZE - 1);
+
+        /* NB str guaranteed terminted */
+       if (error == 0)
+               error = trace_daemon_command(str);
+
+        trace_free_string_buffer(str, TRACEFILE_NAME_SIZE);
+       return error;
+}
+
+
+static int sysctl_debug_mb SYSCTL_HANDLER_ARGS
+{
+#error "Check me"
+       long mb;
+       int  error;
+       
+       if (req->newptr == USER_ADDR_NULL) {
+               /* read */
+               mb = trace_get_debug_mb();
+               error = SYSCTL_OUT(req, &mb, sizeof(mb));
+       } else {
+               /* write */
+               error = SYSCTL_IN(req, &mb, sizeof(mb));
+               if (error == 0)
+                       error = trace_set_debug_mb(mb);
+       }
+       
+       return error;
+}
+
 /*
  * sysctl table for lnet
  */
 /*
  * sysctl table for lnet
  */
@@ -80,12 +157,17 @@ SYSCTL_INT(_lnet,                  OID_AUTO,       memused,
 SYSCTL_INT(_lnet,                      OID_AUTO,       catastrophe,
             CTLTYPE_INT | CTLFLAG_RW,                  (int *)&libcfs_catastrophe,
             0,         "catastrophe");
 SYSCTL_INT(_lnet,                      OID_AUTO,       catastrophe,
             CTLTYPE_INT | CTLFLAG_RW,                  (int *)&libcfs_catastrophe,
             0,         "catastrophe");
-SYSCTL_PROC(_lnet,                     OID_AUTO,       trace_daemon,
+
+#error "check me"
+SYSCTL_PROC(_lnet,                     OID_AUTO,       debug_kernel,
+            CTLTYPE_STRING | CTLFLAG_W,                0,
+            0,         &sysctl_debug_kernel,           "A",    "debug_kernel");
+SYSCTL_PROC(_lnet,                     OID_AUTO,       daemon_file,
             CTLTYPE_STRING | CTLFLAG_RW,               0,
             CTLTYPE_STRING | CTLFLAG_RW,               0,
-            0,         &cfs_trace_daemon,              "A",    "trace daemon");
+            0,         &sysctl_daemon_file,            "A",    "daemon_file");
 SYSCTL_PROC(_lnet,                     OID_AUTO,       debug_mb,
 SYSCTL_PROC(_lnet,                     OID_AUTO,       debug_mb,
-            CTLTYPE_INT | CTLFLAG_RW,                  &max_debug_mb,
-            0,         &cfs_debug_mb,                  "L",    "max debug size");
+            CTLTYPE_INT | CTLFLAG_RW,                  0,
+            0,         &sysctl_debug_mb,               "L",    "debug_mb");
 
 
 static cfs_sysctl_table_t      top_table[] = {
 
 
 static cfs_sysctl_table_t      top_table[] = {
@@ -97,7 +179,8 @@ static cfs_sysctl_table_t    top_table[] = {
        &sysctl__lnet_debug_path,
        &sysctl__lnet_memused,
        &sysctl__lnet_catastrophe,
        &sysctl__lnet_debug_path,
        &sysctl__lnet_memused,
        &sysctl__lnet_catastrophe,
-       &sysctl__lnet_trace_daemon,
+       &sysctl__lnet_debug_kernel,
+       &sysctl__lnet_daemon_file,
        &sysctl__lnet_debug_mb,
        NULL
 };
        &sysctl__lnet_debug_mb,
        NULL
 };
index bb1dc72..29dece3 100644 (file)
 
 #define M_TCD_MAX_PAGES (128 * 1280)
 extern union trace_data_union trace_data[NR_CPUS];
 
 #define M_TCD_MAX_PAGES (128 * 1280)
 extern union trace_data_union trace_data[NR_CPUS];
-extern char *tracefile;
-extern long long tracefile_size;
-extern int trace_start_thread(void);
-extern void trace_stop_thread(void);
 
 
-long max_debug_mb = M_TCD_MAX_PAGES;
 static long max_permit_mb = (64 * 1024);
 
 spinlock_t trace_cpu_serializer;
 static long max_permit_mb = (64 * 1024);
 
 spinlock_t trace_cpu_serializer;
@@ -185,95 +180,9 @@ void print_to_console(struct ptldebug_header *hdr, int mask, const char *buf,
        }
 }
 
        }
 }
 
-/*
- * Sysctl handle of libcfs
- */
-#define MAX_TRACEFILE_PATH_LEN  256
-int cfs_trace_daemon SYSCTL_HANDLER_ARGS
-{
-       int error = 0;
-       char *name = NULL;
-
-        if (req->newptr == USER_ADDR_NULL) {
-                /* a read */
-                if (tracefile)
-                        error = sysctl_handle_string(oidp, tracefile, 0, req);
-                else
-                        error = sysctl_handle_string(oidp, "NA", 0, req);
-
-                return error;
-        }
-        
-        /* now hanle write requests */
-       MALLOC(name, char *, MAX_TRACEFILE_PATH_LEN + 1, M_TEMP, M_WAITOK | M_ZERO);
-       if (name == NULL)
-               return -ENOMEM;
-        name[0] = '\0';
-       tracefile_write_lock();
-       error = sysctl_handle_string(oidp, name, MAX_TRACEFILE_PATH_LEN + 1, req);
-       if (!error) {
-               if (strcmp(name, "stop") == 0) {
-                       /* stop tracefile daemon */
-                       tracefile = NULL;
-                       trace_stop_thread();
-                       goto out;
-               }else if (strncmp(name, "size=", 5) == 0) {
-                       tracefile_size = simple_strtoul(name + 5, NULL, 0);
-                       if (tracefile_size < 10 || tracefile_size > 20480)
-                               tracefile_size = TRACEFILE_SIZE;
-                       else
-                               tracefile_size <<= 20;
-                       goto out;
-
-               }
-               if (name[0] != '/') {
-                       error = -EINVAL;
-                       goto out;
-               }
-               if (tracefile != NULL)
-                       cfs_free(tracefile);
-               tracefile = name;
-               name = NULL;
-               trace_start_thread();
-       } else {
-               /* Something was wrong with the write request */
-               printf("sysctl debug daemon failed: %d.\n", error);
-               goto out;
-       }
-out:
-       if (name != NULL)
-               FREE(name, M_TEMP);
-       tracefile_write_unlock();
-       return error;
-}
-#undef MAX_TRACEFILE_PATH_LEN
-
-
-int cfs_debug_mb SYSCTL_HANDLER_ARGS
+int trace_max_debug_mb(void)
 {
 {
-       int i;
-       int error = 0;
-
-       error = sysctl_handle_long(oidp, oidp->oid_arg1, oidp->oid_arg2, req);
-       if (!error && req->newptr != USER_ADDR_NULL) {
-               /* We have a new value stored in the standard location */
-               if (max_debug_mb <= 0)
-                       return -EINVAL;
-               if (max_debug_mb > max_permit_mb) {
-                       printf("sysctl debug_mb is too big: %d.\n", max_debug_mb);
-                       return 0;
-               }
-               for (i = 0; i < NR_CPUS; i++) {
-                       struct trace_cpu_data *tcd;
-                       tcd = &trace_data[i].tcd;
-                       tcd->tcd_max_pages = max_debug_mb;
-               }
-       } else if (req->newptr != USER_ADDR_NULL) {
-               /* Something was wrong with the write request */
-               printf ("sysctl debug_mb fault: %d.\n", error);
-       }
-
-       return error;
+       return max_permit_mb;
 }
 
 void
 }
 
 void
index 1af9c13..58ef681 100644 (file)
@@ -296,17 +296,31 @@ int
 libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
 {
         int         m = 0;
 libcfs_debug_str2mask(int *mask, const char *str, int is_subsys)
 {
         int         m = 0;
-        int         matched = 0;
         char        op = 0;
         char        op = 0;
+        int         matched;
         int         n;
         int         t;
 
         int         n;
         int         t;
 
+        /* Allow a number for backwards compatibility */
+
+        for (n = strlen(str); n > 0; n--)
+                if (!isspace(str[n-1]))
+                        break;
+        matched = n;
+
+        if ((t = sscanf(str, "%i%n", &m, &matched)) >= 1 &&
+            matched == n) {
+                *mask = m;
+                return 0;
+        }
+
         /* <str> must be a list of debug tokens or numbers separated by
          * whitespace and optionally an operator ('+' or '-').  If an operator
          * appears first in <str>, '*mask' is used as the starting point
          * (relative), otherwise 0 is used (absolute).  An operator applies to
          * all following tokens up to the next operator. */
 
         /* <str> must be a list of debug tokens or numbers separated by
          * whitespace and optionally an operator ('+' or '-').  If an operator
          * appears first in <str>, '*mask' is used as the starting point
          * (relative), otherwise 0 is used (absolute).  An operator applies to
          * all following tokens up to the next operator. */
 
+        matched = 0;
         while (*str != 0) {
                 while (isspace(*str)) /* skip whitespace */
                         str++;
         while (*str != 0) {
                 while (isspace(*str)) /* skip whitespace */
                         str++;
index 987eed7..55b6809 100644 (file)
@@ -74,11 +74,132 @@ enum {
         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_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 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))
+{
+        int rc = handler(data, write, *ppos, buffer, *lenp);
+
+        if (rc < 0)
+                return rc;
+
+        if (write) {
+                *ppos += *lenp;
+        } else {
+                *lenp = rc;
+                *ppos += rc;
+        }
+        return 0;
+}
+
+#define DECLARE_PROC_HANDLER(name)                      \
+static int                                              \
+LL_PROC_PROTO(name)                                     \
+{                                                       \
+        DECLARE_LL_PROC_PPOS;                           \
+                                                        \
+        return proc_call_handler(table->data, write,    \
+                                 ppos, buffer, lenp,    \
+                                 __##name);             \
+}
+
+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 = 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 {
+                rc = trace_copyin_string(tmpstr, tmpstrlen, buffer, nob);
+                if (rc < 0)
+                        return rc;
+                
+                rc = libcfs_debug_str2mask(mask, tmpstr, is_subsys);
+        }
+
+        trace_free_string_buffer(tmpstr, tmpstrlen);
+        return rc;
+}
+
+DECLARE_PROC_HANDLER(proc_dobitmasks)
+
+static int __proc_dump_kernel(void *data, int write,
+                              loff_t pos, void *buffer, int nob)
+{
+        if (!write)
+                return 0;
+        
+        return trace_dump_debug_buffer_usrstr(buffer, nob);
+}
+
+DECLARE_PROC_HANDLER(proc_dump_kernel)
+
+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");
+        }
+        
+        return trace_daemon_command_usrstr(buffer, nob);
+}
+
+DECLARE_PROC_HANDLER(proc_daemon_file)
+
+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");
+        }
+        
+        return trace_set_debug_mb_usrstr(buffer, nob);
+}
+
+DECLARE_PROC_HANDLER(proc_debug_mb)
 
 static cfs_sysctl_table_t lnet_table[] = {
 
 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",
         {
                 .ctl_name = PSDEV_DEBUG,
                 .procname = "debug",
@@ -119,7 +240,6 @@ static cfs_sysctl_table_t lnet_table[] = {
                 .maxlen   = sizeof(debug_file_path),
                 .mode     = 0644,
                 .proc_handler = &proc_dostring,
                 .maxlen   = sizeof(debug_file_path),
                 .mode     = 0644,
                 .proc_handler = &proc_dostring,
-                .strategy =  &sysctl_string
         },
 
         {
         },
 
         {
@@ -129,7 +249,6 @@ static cfs_sysctl_table_t lnet_table[] = {
                 .maxlen   = sizeof(lnet_upcall),
                 .mode     = 0644,
                 .proc_handler = &proc_dostring,
                 .maxlen   = sizeof(lnet_upcall),
                 .mode     = 0644,
                 .proc_handler = &proc_dostring,
-                .strategy =  &sysctl_string
         },
         {
                 .ctl_name = PSDEV_LNET_MEMUSED,
         },
         {
                 .ctl_name = PSDEV_LNET_MEMUSED,
@@ -155,6 +274,24 @@ static cfs_sysctl_table_t lnet_table[] = {
                 .mode     = 0644,
                 .proc_handler = &proc_dointvec
         },
                 .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}
 };
 
         {0}
 };
 
@@ -170,115 +307,21 @@ static cfs_sysctl_table_t top_table[2] = {
         {0}
 };
 
         {0}
 };
 
-int LL_PROC_PROTO(proc_dobitmasks)
-{
-        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
-         */
-        cfs_sysctl_table_t dummy = *table;
-        unsigned int *mask = (unsigned int *)table->data;
-        int           is_subsys = (mask == &libcfs_subsystem_debug) ? 1 : 0;
-
-        str = kmalloc(tmpstrlen, GFP_USER);
-        if (str == NULL)
-                return -ENOMEM;
-
-        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
-
-                rc = ll_proc_dostring(&dummy, write, filp, buffer, lenp, ppos);
-
-                if (rc != 0)
-                        goto out;
-
-                rc = libcfs_debug_str2mask(mask, dummy.data, is_subsys);
-        } 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);
-        }
-
-out:
-        kfree(str);
-        return rc;
-}
-
 int insert_proc(void)
 {
 int insert_proc(void)
 {
-        struct proc_dir_entry *ent;
-
 #ifdef CONFIG_SYSCTL
 #ifdef CONFIG_SYSCTL
-        if (!lnet_table_header)
+        if (lnet_table_header == NULL)
                 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
 #endif
                 lnet_table_header = cfs_register_sysctl_table(top_table, 0);
 #endif
-
-        ent = create_proc_entry("sys/lnet/dump_kernel", 0, NULL);
-        if (ent == NULL) {
-                CERROR("couldn't register dump_kernel\n");
-                return -1;
-        }
-        ent->write_proc = trace_dk;
-
-        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;
-
-        ent = create_proc_entry("sys/lnet/debug_mb", 0, NULL);
-        if (ent == NULL) {
-                CERROR("couldn't register debug_mb\n");
-                return -1;
-        }
-        ent->write_proc = trace_write_debug_mb;
-        ent->read_proc = trace_read_debug_mb;
-
         return 0;
 }
 
 void remove_proc(void)
 {
         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
 #ifdef CONFIG_SYSCTL
-        if (lnet_table_header)
+        if (lnet_table_header != NULL)
                 cfs_unregister_sysctl_table(lnet_table_header);
                 cfs_unregister_sysctl_table(lnet_table_header);
+
         lnet_table_header = NULL;
 #endif
 }
         lnet_table_header = NULL;
 #endif
 }
index 1fb38cf..a3a3aad 100644 (file)
@@ -11,8 +11,6 @@
 #endif
 
 extern union trace_data_union trace_data[NR_CPUS];
 #endif
 
 extern union trace_data_union trace_data[NR_CPUS];
-extern char *tracefile;
-extern long long tracefile_size;
 
 char *trace_console_buffers[NR_CPUS][3];
 
 
 char *trace_console_buffers[NR_CPUS][3];
 
@@ -181,126 +179,11 @@ void print_to_console(struct ptldebug_header *hdr, int mask, const char *buf,
        return;
 }
 
        return;
 }
 
-int trace_write_daemon_file(struct file *file, const char *buffer,
-                           unsigned long count, void *data)
+int trace_max_debug_mb(void)
 {
 {
-       char *name;
-       unsigned long off;
-       int rc;
-
-       name = kmalloc(count + 1, GFP_KERNEL);
-       if (name == NULL)
-               return -ENOMEM;
-
-       if (copy_from_user(name, buffer, count)) {
-               rc = -EFAULT;
-               goto out;
-       }
-
-       /* be nice and strip out trailing '\n' */
-       for (off = count ; off > 2 && isspace(name[off - 1]); off--)
-               ;
-
-       name[off] = '\0';
-
-       tracefile_write_lock();
-       if (strcmp(name, "stop") == 0) {
-               tracefile = NULL;
-               trace_stop_thread();
-               goto out_sem;
-       } else if (strncmp(name, "size=", 5) == 0) {
-               tracefile_size = simple_strtoul(name + 5, NULL, 0);
-               if (tracefile_size < 10 || tracefile_size > 20480)
-                       tracefile_size = TRACEFILE_SIZE;
-               else
-                       tracefile_size <<= 20;
-               goto out_sem;
-       }
-
-       if (name[0] != '/') {
-               rc = -EINVAL;
-               goto out_sem;
-       }
-
-       if (tracefile != NULL)
-               kfree(tracefile);
-
-       tracefile = name;
-       name = NULL;
-       printk(KERN_INFO "Lustre: debug daemon will attempt to start writing "
-              "to %s (%lukB max)\n", tracefile, (long)(tracefile_size >> 10));
-
-       trace_start_thread();
-out_sem:
-       tracefile_write_unlock();
-out:
-       kfree(name);
-       return count;
-}
-
-int trace_read_daemon_file(char *page, char **start, off_t off, int count,
-                          int *eof, void *data)
-{
-       int rc;
-
-       tracefile_read_lock();
-       rc = snprintf(page, count, "%s", tracefile);
-       tracefile_read_unlock();
-
-       return rc;
-}
-
-int trace_write_debug_mb(struct file *file, const char *buffer,
-                        unsigned long count, void *data)
-{
-       char string[32];
-       int i;
-       unsigned max;
-
-       if (count >= sizeof(string)) {
-               printk(KERN_ERR "Lustre: value too large (length %lu bytes)\n",
-                      count);
-               return -EOVERFLOW;
-       }
-
-       if (copy_from_user(string, buffer, count))
-               return -EFAULT;
-
-       max = simple_strtoul(string, NULL, 0);
-       if (max == 0)
-               return -EINVAL;
-
-       if (max > (num_physpages >> (20 - 2 - CFS_PAGE_SHIFT)) / 5 || max >= 512) {
-               printk(KERN_ERR "Lustre: Refusing to set debug buffer size to "
-                      "%dMB, which is more than 80%% of available RAM (%lu)\n",
-                      max, (num_physpages >> (20 - 2 - CFS_PAGE_SHIFT)) / 5);
-               return -EINVAL;
-       }
-
-       max /= smp_num_cpus;
-
-       for (i = 0; i < NR_CPUS; i++) {
-               struct trace_cpu_data *tcd;
-               tcd = &trace_data[i].tcd;
-               tcd->tcd_max_pages = max << (20 - CFS_PAGE_SHIFT);
-       }
-       return count;
-}
-
-int trace_read_debug_mb(char *page, char **start, off_t off, int count,
-                                       int *eof, void *data)
-{
-       struct trace_cpu_data *tcd;
-       int rc;
-
-       tcd = trace_get_tcd();
-       __LASSERT (tcd != NULL);
-
-       rc = snprintf(page, count, "%lu\n",
-                     (tcd->tcd_max_pages >> (20 - CFS_PAGE_SHIFT)) * smp_num_cpus);
-
-       trace_put_tcd(tcd);
-       return rc;
+       int  total_mb = (num_physpages >> (20 - CFS_PAGE_SHIFT));
+       
+       return MAX(512, (total_mb * 80)/100);
 }
 
 void
 }
 
 void
index 4bf6693..45b3640 100644 (file)
@@ -32,7 +32,7 @@
 /* XXX move things up to the top, comment */
 union trace_data_union trace_data[NR_CPUS] __cacheline_aligned;
 
 /* XXX move things up to the top, comment */
 union trace_data_union trace_data[NR_CPUS] __cacheline_aligned;
 
-char *tracefile = NULL;
+char tracefile[TRACEFILE_NAME_SIZE];
 int64_t tracefile_size = TRACEFILE_SIZE;
 static struct tracefiled_ctl trace_tctl;
 struct semaphore trace_thread_sem;
 int64_t tracefile_size = TRACEFILE_SIZE;
 static struct tracefiled_ctl trace_tctl;
 struct semaphore trace_thread_sem;
@@ -718,41 +718,213 @@ void trace_flush_pages(void)
         }
 }
 
         }
 }
 
-int trace_dk(struct file *file, const char *buffer, unsigned long count,
-             void *data)
+int trace_copyin_string(char *knl_buffer, int knl_buffer_nob,
+                        const char *usr_buffer, int usr_buffer_nob)
 {
 {
-        char *name;
-        unsigned long off;
-        int rc;
+        int    nob;
+        
+        if (usr_buffer_nob > knl_buffer_nob)
+                return -EOVERFLOW;
+        
+        if (copy_from_user((void *)knl_buffer, 
+                           (void *)usr_buffer, usr_buffer_nob))
+                return -EFAULT;
+
+        nob = strnlen(knl_buffer, usr_buffer_nob);
+        while (nob-- >= 0)                      /* strip trailing whitespace */
+                if (!isspace(knl_buffer[nob]))
+                        break;
+
+        if (nob < 0)                            /* empty string */
+                return -EINVAL;
+
+        if (nob == knl_buffer_nob)              /* no space to terminate */
+                return -EOVERFLOW;
+
+        knl_buffer[nob + 1] = 0;                /* terminate */
+        return 0;
+}
+
+int trace_copyout_string(char *usr_buffer, int usr_buffer_nob,
+                         const char *knl_buffer, char *append)
+{
+        /* NB if 'append' != NULL, it's a single character to append to the
+         * copied out string - usually "\n", for /proc entries and "" (i.e. a
+         * terminating zero byte) for sysctl entries */
+        int   nob = strlen(knl_buffer);
+        
+        if (nob > usr_buffer_nob)
+                nob = usr_buffer_nob;
+        
+        if (copy_to_user(usr_buffer, knl_buffer, nob))
+                return -EFAULT;
+        
+        if (append != NULL && nob < usr_buffer_nob) {
+                if (copy_to_user(usr_buffer + nob, append, 1))
+                        return -EFAULT;
+                
+                nob++;
+        }
+
+        return nob;
+}
 
 
-        name = cfs_alloc(count + 1, CFS_ALLOC_STD);
-        if (name == NULL)
+int trace_allocate_string_buffer(char **str, int nob)
+{
+        if (nob > 2 * CFS_PAGE_SIZE)            /* string must be "sensible" */
+                return -EINVAL;
+        
+        *str = cfs_alloc(nob, CFS_ALLOC_STD | CFS_ALLOC_ZERO);
+        if (*str == NULL)
                 return -ENOMEM;
 
                 return -ENOMEM;
 
-        if (copy_from_user((void *)name, (void *)buffer, count)) {
-                rc = -EFAULT;
+        return 0;
+}
+
+void trace_free_string_buffer(char *str, int nob)
+{
+        cfs_free(str);
+}
+
+int trace_dump_debug_buffer_usrstr(void *usr_str, int usr_str_nob)
+{
+        char         *str;
+        int           rc;
+
+        rc = trace_allocate_string_buffer(&str, usr_str_nob + 1);
+        if (rc != 0)
+                return rc;
+
+        rc = trace_copyin_string(str, usr_str_nob + 1,
+                                 usr_str, usr_str_nob);
+        if (rc != 0)
                 goto out;
                 goto out;
-        }
 
 #if !defined(__WINNT__)
 
 #if !defined(__WINNT__)
-        if (name[0] != '/') {
+        if (str[0] != '/') {
                 rc = -EINVAL;
                 goto out;
         }
 #endif
                 rc = -EINVAL;
                 goto out;
         }
 #endif
+        rc = tracefile_dump_all_pages(str);
+out:
+        trace_free_string_buffer(str, usr_str_nob + 1);
+        return rc;
+}
+
+int trace_daemon_command(char *str)
+{
+        int       rc = 0;
+        
+       tracefile_write_lock();
+
+       if (strcmp(str, "stop") == 0) {
+               trace_stop_thread();
+                memset(tracefile, 0, sizeof(tracefile));
+
+       } else if (strncmp(str, "size=", 5) == 0) {
+               tracefile_size = simple_strtoul(str + 5, NULL, 0);
+               if (tracefile_size < 10 || tracefile_size > 20480)
+                       tracefile_size = TRACEFILE_SIZE;
+               else
+                       tracefile_size <<= 20;
+
+       } else if (strlen(str) >= sizeof(tracefile)) {
+                rc = -ENAMETOOLONG;
+#ifndef __WINNT__
+        } else if (str[0] != '/') {
+                rc = -EINVAL;
+#endif
+        } else {
+                strcpy(tracefile, str);
 
 
-        /* be nice and strip out trailing '\n' */
-        for (off = count ; off > 2 && isspace(name[off - 1]); off--)
-                ;
+                printk(KERN_INFO "Lustre: debug daemon will attempt to start writing "
+                       "to %s (%lukB max)\n", tracefile,
+                       (long)(tracefile_size >> 10));
 
 
-        name[off] = '\0';
-        rc = tracefile_dump_all_pages(name);
-out:
-        if (name)
-                cfs_free(name);
-        return count;
+                trace_start_thread();
+        }
+
+       tracefile_write_unlock();
+       return rc;
+}
+
+int trace_daemon_command_usrstr(void *usr_str, int usr_str_nob)
+{
+       char *str;
+       int   rc;
+
+        rc = trace_allocate_string_buffer(&str, usr_str_nob + 1);
+        if (rc != 0)
+                return rc;
+
+        rc = trace_copyin_string(str, usr_str_nob + 1,
+                                 usr_str, usr_str_nob);
+        if (rc == 0)
+                rc = trace_daemon_command(str);
+
+        trace_free_string_buffer(str, usr_str_nob + 1);
+       return rc;
+}
+
+int trace_set_debug_mb(int mb)
+{
+       int i;
+        int limit = trace_max_debug_mb();
+        
+       if (mb <= 0)
+               return -EINVAL;
+
+       if (mb > limit) {
+               printk(KERN_ERR "Lustre: Refusing to set debug buffer size to "
+                      "%dMB - limit is %d\n", mb, limit);
+               return -EINVAL;
+       }
+
+       mb /= smp_num_cpus;
+
+        tracefile_write_lock();
+
+       for (i = 0; i < NR_CPUS; i++) {
+               struct trace_cpu_data *tcd = &trace_data[i].tcd;
+
+               tcd->tcd_max_pages = mb << (20 - CFS_PAGE_SHIFT);
+       }
+
+        tracefile_write_unlock();
+
+       return 0;
+}
+
+int trace_set_debug_mb_usrstr(void *usr_str, int usr_str_nob)
+{
+       char     str[32];
+        int      rc;
+
+        rc = trace_copyin_string(str, sizeof(str), usr_str, usr_str_nob);
+        if (rc < 0)
+                return rc;
+
+       return trace_set_debug_mb(simple_strtoul(str, NULL, 0));
+}
+
+int trace_get_debug_mb(void)
+{
+       int i;
+        int total_pages = 0;
+        
+        tracefile_read_lock();
+
+       for (i = 0; i < NR_CPUS; i++) {
+               struct trace_cpu_data *tcd = &trace_data[i].tcd;
+
+                total_pages += tcd->tcd_max_pages;
+       }
+
+        tracefile_read_unlock();
+
+        return total_pages >> (20 - CFS_PAGE_SHIFT);
 }
 }
-EXPORT_SYMBOL(trace_dk);
 
 static int tracefiled(void *arg)
 {
 
 static int tracefiled(void *arg)
 {
@@ -793,12 +965,13 @@ static int tracefiled(void *arg)
 
                 filp = NULL;
                 tracefile_read_lock();
 
                 filp = NULL;
                 tracefile_read_lock();
-                if (tracefile != NULL) {
+                if (tracefile[0] != 0) {
                         filp = cfs_filp_open(tracefile,
                                              O_CREAT | O_RDWR | O_LARGEFILE,
                                              0600, &rc);
                         if (!(filp))
                         filp = cfs_filp_open(tracefile,
                                              O_CREAT | O_RDWR | O_LARGEFILE,
                                              0600, &rc);
                         if (!(filp))
-                                printk("couldn't open %s: %d\n", tracefile, rc);
+                                printk(KERN_WARNING "couldn't open %s: %d\n",
+                                       tracefile, rc);
                 }
                 tracefile_read_unlock();
                 if (filp == NULL) {
                 }
                 tracefile_read_unlock();
                 if (filp == NULL) {
@@ -877,7 +1050,7 @@ void trace_stop_thread(void)
 
         mutex_down(&trace_thread_sem);
         if (thread_running) {
 
         mutex_down(&trace_thread_sem);
         if (thread_running) {
-                printk(KERN_INFO "Shutting down debug daemon thread...\n");
+                printk(KERN_INFO "Lustre: shutting down debug daemon thread...\n");
                 atomic_set(&tctl->tctl_shutdown, 1);
                 wait_for_completion(&tctl->tctl_stop);
                 thread_running = 0;
                 atomic_set(&tctl->tctl_shutdown, 1);
                 wait_for_completion(&tctl->tctl_stop);
                 thread_running = 0;
index f3568e9..8b09d6e 100644 (file)
@@ -5,6 +5,10 @@
 
 /* trace file lock routines */
 
 
 /* trace file lock routines */
 
+#define TRACEFILE_NAME_SIZE 1024
+extern char      tracefile[TRACEFILE_NAME_SIZE];
+extern long long tracefile_size;
+
 int  tracefile_init_arch(void);
 void tracefile_fini_arch(void);
 
 int  tracefile_init_arch(void);
 void tracefile_fini_arch(void);
 
@@ -20,16 +24,21 @@ int trace_start_thread(void);
 void trace_stop_thread(void);
 int tracefile_init(void);
 void tracefile_exit(void);
 void trace_stop_thread(void);
 int tracefile_init(void);
 void tracefile_exit(void);
-int trace_write_daemon_file(struct file *file, const char *buffer,
-                           unsigned long count, void *data);
-int trace_read_daemon_file(char *page, char **start, off_t off, int count,
-                          int *eof, void *data);
-int trace_write_debug_mb(struct file *file, const char *buffer,
-                        unsigned long count, void *data);
-int trace_read_debug_mb(char *page, char **start, off_t off, int count,
-                       int *eof, void *data);
-int trace_dk(struct file *file, const char *buffer, unsigned long count,
-             void *data);
+
+
+
+int trace_copyin_string(char *knl_buffer, int knl_buffer_nob,
+                        const char *usr_buffer, int usr_buffer_nob);
+int trace_copyout_string(char *usr_buffer, int usr_buffer_nob,
+                         const char *knl_str, char *append);
+int trace_allocate_string_buffer(char **str, int nob);
+void trace_free_string_buffer(char *str, int nob);
+int trace_dump_debug_buffer_usrstr(void *usr_str, int usr_str_nob);
+int trace_daemon_command(char *str);
+int trace_daemon_command_usrstr(void *usr_str, int usr_str_nob);
+int trace_set_debug_mb(int mb);
+int trace_set_debug_mb_usrstr(void *usr_str, int usr_str_nob);
+int trace_get_debug_mb(void);
 
 extern void libcfs_debug_dumplog_internal(void *arg);
 extern void libcfs_register_panic_notifier(void);
 
 extern void libcfs_debug_dumplog_internal(void *arg);
 extern void libcfs_register_panic_notifier(void);
@@ -37,6 +46,7 @@ extern void libcfs_unregister_panic_notifier(void);
 extern int  libcfs_panic_in_progress;
 
 #ifdef LUSTRE_TRACEFILE_PRIVATE
 extern int  libcfs_panic_in_progress;
 
 #ifdef LUSTRE_TRACEFILE_PRIVATE
+
 /*
  * Private declare for tracefile
  */
 /*
  * Private declare for tracefile
  */
@@ -179,6 +189,8 @@ extern void trace_put_console_buffer(char *buffer);
 
 extern void trace_call_on_all_cpus(void (*fn)(void *arg), void *arg);
 
 
 extern void trace_call_on_all_cpus(void (*fn)(void *arg), void *arg);
 
+extern int  trace_max_debug_mb(void);
+
 int trace_refill_stock(struct trace_cpu_data *tcd, int gfp,
                       struct list_head *stock);
 
 int trace_refill_stock(struct trace_cpu_data *tcd, int gfp,
                       struct list_head *stock);
 
index ebce30d..cfb8d38 100644 (file)
@@ -1449,6 +1449,55 @@ static struct ctl_table top_table[2] = {
         {0}
 };
 
         {0}
 };
 
+
+int trace_write_dump_kernel(struct file *file, const char *buffer,
+                             unsigned long count, void *data)
+{
+        int rc = trace_dump_debug_buffer_usrstr(buffer, count);
+        
+        return (rc < 0) ? rc : count;
+}
+
+int trace_write_daemon_file(struct file *file, const char *buffer,
+                            unsigned long count, void *data)
+{
+        int rc = trace_daemon_command_usrstr(buffer, count);
+
+        return (rc < 0) ? rc : count;
+}
+
+int trace_read_daemon_file(char *page, char **start, off_t off, int count,
+                           int *eof, void *data)
+{
+       int rc;
+
+       tracefile_read_lock();
+
+        rc = trace_copyout_string(page, count, tracefile, "\n");
+
+        tracefile_read_unlock();
+
+       return rc;
+}
+
+int trace_write_debug_mb(struct file *file, const char *buffer,
+                         unsigned long count, void *data)
+{
+        int rc = trace_set_debug_mb_userstr(buffer, count);
+        
+        return (rc < 0) ? rc : count;
+}
+
+int trace_read_debug_mb(char *page, char **start, off_t off, int count,
+                        int *eof, void *data)
+{
+        char   str[32];
+
+        snprintf(str, sizeof(str), "%d\n", trace_get_debug_mb());
+
+        return trace_copyout_string(page, count, str, NULL);
+}
+
 int insert_proc(void)
 {
         cfs_proc_entry_t *ent;
 int insert_proc(void)
 {
         cfs_proc_entry_t *ent;
@@ -1458,7 +1507,7 @@ int insert_proc(void)
                 CERROR(("couldn't register dump_kernel\n"));
                 return -1;
         }
                 CERROR(("couldn't register dump_kernel\n"));
                 return -1;
         }
-        ent->write_proc = trace_dk;
+        ent->write_proc = trace_write_dump_kernel;
 
         ent = create_proc_entry("sys/lnet/daemon_file", 0, NULL);
         if (ent == NULL) {
 
         ent = create_proc_entry("sys/lnet/daemon_file", 0, NULL);
         if (ent == NULL) {
index d172bff..c8ec79c 100644 (file)
@@ -29,8 +29,6 @@
 #endif
 
 extern union trace_data_union trace_data[NR_CPUS];
 #endif
 
 extern union trace_data_union trace_data[NR_CPUS];
-extern char *tracefile;
-extern int64_t tracefile_size;
 
 event_t     tracefile_event;
 
 
 event_t     tracefile_event;
 
@@ -175,121 +173,11 @@ int tcd_owns_tage(struct trace_cpu_data *tcd, struct trace_page *tage)
        return 1;
 }
 
        return 1;
 }
 
-
-int trace_write_daemon_file(struct file *file, const char *buffer,
-                            unsigned long count, void *data)
-{
-       char *name;
-       unsigned long off;
-       int rc;
-
-       name =cfs_alloc(count + 1, 0);
-       if (name == NULL)
-               return -ENOMEM;
-
-       if (copy_from_user((void *)name, (void*)buffer, count)) {
-               rc = -EFAULT;
-               goto out;
-       }
-
-       /* be nice and strip out trailing '\n' */
-       for (off = count ; off > 2 && isspace(name[off - 1]); off--)
-               ;
-
-       name[off] = '\0';
-
-       tracefile_write_lock();
-       if (strcmp(name, "stop") == 0) {
-               tracefile = NULL;
-               trace_stop_thread();
-               goto out_sem;
-       } else if (strncmp(name, "size=", 5) == 0) {
-               tracefile_size = simple_strtoul(name + 5, NULL, 0);
-               if (tracefile_size < 10 || tracefile_size > 20480)
-                       tracefile_size = TRACEFILE_SIZE;
-               else
-                       tracefile_size <<= 20;
-               goto out_sem;
-       }
-
-       if (tracefile != NULL)
-               cfs_free(tracefile);
-
-       tracefile = name;
-       name = NULL;
-       printk(KERN_INFO "Lustre: debug daemon will attempt to start writing "
-              "to %s (%lukB max)\n", tracefile, (long)(tracefile_size >> 10));
-
-       trace_start_thread();
-out_sem:
-    tracefile_write_unlock();
-out:
-    if (name != NULL)
-           cfs_free(name);
-       return count;
-}
-
-int trace_read_daemon_file(char *page, char **start, off_t off, int count,
-                           int *eof, void *data)
-{
-       int rc;
-
-       tracefile_read_lock();
-       rc = snprintf(page, count, "%s", tracefile);
-       tracefile_read_unlock();
-
-       return rc;
-}
-
-int trace_write_debug_mb(struct file *file, const char *buffer,
-                         unsigned long count, void *data)
-{
-       char string[32];
-       int i;
-       unsigned max;
-
-       if (count >= sizeof(string)) {
-               printk(KERN_ERR "Lustre: value too large (length %lu bytes)\n",
-                      count);
-               return -EOVERFLOW;
-       }
-
-       if (copy_from_user((void *)string, (void *)buffer, count))
-               return -EFAULT;
-
-       max = simple_strtoul(string, NULL, 0);
-       if (max == 0)
-               return -EINVAL;
-
-       if (max > (num_physpages >> (20 - 2 - CFS_PAGE_SHIFT)) / 5 || max >= 512) {
-               printk(KERN_ERR "Lustre: Refusing to set debug buffer size to "
-                      "%dMB, which is more than 80%% of available RAM (%lu)\n",
-                      max, (num_physpages >> (20 - 2 - CFS_PAGE_SHIFT)) / 5);
-               return -EINVAL;
-       }
-
-       max /= smp_num_cpus;
-
-       for (i = 0; i < NR_CPUS; i++) {
-               struct trace_cpu_data *tcd;
-               tcd = &trace_data[i].tcd;
-               tcd->tcd_max_pages = max << (20 - CFS_PAGE_SHIFT);
-       }
-       return count;
-}
-
-int trace_read_debug_mb(char *page, char **start, off_t off, int count,
-                        int *eof, void *data)
+int trace_max_debug_mb(void)
 {
 {
-       struct trace_cpu_data *tcd;
-       int rc;
-
-       tcd = trace_get_tcd();
-        LASSERT (tcd != NULL);
-       rc = snprintf(page, count, "%lu\n",
-                     (tcd->tcd_max_pages >> (20 - CFS_PAGE_SHIFT)) * smp_num_cpus);
-       trace_put_tcd(tcd);
-       return rc;
+       int  total_mb = (num_physpages >> (20 - CFS_PAGE_SHIFT));
+       
+       return MAX(512, (total_mb * 80)/100);
 }
 
 void
 }
 
 void