vserver 1.9.5.x5
[linux-2.6.git] / arch / s390 / kernel / debug.c
index f1e538c..7cf71af 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/errno.h>
 #include <linux/slab.h>
 #include <linux/ctype.h>
+#include <linux/sysctl.h>
 #include <asm/uaccess.h>
 #include <asm/semaphore.h>
 
@@ -24,7 +25,6 @@
 
 #include <asm/debug.h>
 
-#define MIN(a,b) (((a)<(b))?(a):(b))
 #define DEBUG_PROLOG_ENTRY -1
 
 /* typedefs */
@@ -435,7 +435,7 @@ static ssize_t debug_output(struct file *file,              /* file descriptor */
 
        while(count < len){
                size = debug_format_entry(p_info);
-               size = MIN((len - count), (size - entry_offset));
+               size = min((len - count), (size - entry_offset));
 
                if(size){
                        if (copy_to_user(user_buf + count, 
@@ -709,6 +709,70 @@ extern inline void debug_finish_entry(debug_info_t * id, debug_entry_t* active,
                proceed_active_area(id);
 }
 
+static int debug_stoppable=1;
+static int debug_active=1;
+
+#define CTL_S390DBF 5677
+#define CTL_S390DBF_STOPPABLE 5678
+#define CTL_S390DBF_ACTIVE 5679
+
+/*
+ * proc handler for the running debug_active sysctl
+ * always allow read, allow write only if debug_stoppable is set or
+ * if debug_active is already off
+ */
+static int s390dbf_procactive(ctl_table *table, int write, struct file *filp,
+                     void __user *buffer, size_t *lenp, loff_t *ppos)
+{
+       if (!write || debug_stoppable || !debug_active)
+               return proc_dointvec(table, write, filp, buffer, lenp, ppos);
+       else
+               return 0;
+}
+
+
+static struct ctl_table s390dbf_table[] = {
+       {
+               .ctl_name       = CTL_S390DBF_STOPPABLE,
+               .procname       = "debug_stoppable",
+               .data           = &debug_stoppable,
+               .maxlen         = sizeof(int),
+               .mode           = S_IRUGO | S_IWUSR,
+               .proc_handler   = &proc_dointvec,
+               .strategy       = &sysctl_intvec,
+       },
+        {
+               .ctl_name       = CTL_S390DBF_ACTIVE,
+               .procname       = "debug_active",
+               .data           = &debug_active,
+               .maxlen         = sizeof(int),
+               .mode           = S_IRUGO | S_IWUSR,
+               .proc_handler   = &s390dbf_procactive,
+               .strategy       = &sysctl_intvec,
+       },
+       { .ctl_name = 0 }
+};
+
+static struct ctl_table s390dbf_dir_table[] = {
+       {
+               .ctl_name       = CTL_S390DBF,
+               .procname       = "s390dbf",
+               .maxlen         = 0,
+               .mode           = S_IRUGO | S_IXUGO,
+               .child          = s390dbf_table,
+       },
+       { .ctl_name = 0 }
+};
+
+struct ctl_table_header *s390dbf_sysctl_header;
+
+void debug_stop_all(void)
+{
+       if (debug_stoppable)
+               debug_active = 0;
+}
+
+
 /*
  * debug_event_common:
  * - write debug entry with given size
@@ -720,10 +784,12 @@ debug_entry_t *debug_event_common(debug_info_t * id, int level, const void *buf,
        unsigned long flags;
        debug_entry_t *active;
 
+       if (!debug_active)
+               return NULL;
        spin_lock_irqsave(&id->lock, flags);
        active = get_active_entry(id);
        memset(DEBUG_DATA(active), 0, id->buf_size);
-       memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+       memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
        debug_finish_entry(id, active, level, 0);
        spin_unlock_irqrestore(&id->lock, flags);
 
@@ -741,10 +807,12 @@ debug_entry_t *debug_exception_common(debug_info_t * id, int level,
        unsigned long flags;
        debug_entry_t *active;
 
+       if (!debug_active)
+               return NULL;
        spin_lock_irqsave(&id->lock, flags);
        active = get_active_entry(id);
        memset(DEBUG_DATA(active), 0, id->buf_size);
-       memcpy(DEBUG_DATA(active), buf, MIN(len, id->buf_size));
+       memcpy(DEBUG_DATA(active), buf, min(len, id->buf_size));
        debug_finish_entry(id, active, level, 1);
        spin_unlock_irqrestore(&id->lock, flags);
 
@@ -781,7 +849,8 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id,
 
        if((!id) || (level > id->level))
                return NULL;
-
+       if (!debug_active)
+               return NULL;
        numargs=debug_count_numargs(string);
 
        spin_lock_irqsave(&id->lock, flags);
@@ -789,7 +858,7 @@ debug_entry_t *debug_sprintf_event(debug_info_t* id,
        curr_event=(debug_sprintf_entry_t *) DEBUG_DATA(active);
        va_start(ap,string);
        curr_event->string=string;
-       for(idx=0;idx<MIN(numargs,((id->buf_size / sizeof(long))-1));idx++)
+       for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
                curr_event->args[idx]=va_arg(ap,long);
        va_end(ap);
        debug_finish_entry(id, active, level, 0);
@@ -813,6 +882,8 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id,
 
        if((!id) || (level > id->level))
                return NULL;
+       if (!debug_active)
+               return NULL;
 
        numargs=debug_count_numargs(string);
 
@@ -821,7 +892,7 @@ debug_entry_t *debug_sprintf_exception(debug_info_t* id,
        curr_event=(debug_sprintf_entry_t *)DEBUG_DATA(active);
        va_start(ap,string);
        curr_event->string=string;
-       for(idx=0;idx<MIN(numargs,((id->buf_size / sizeof(long))-1));idx++)
+       for(idx=0;idx<min(numargs,(int)(id->buf_size / sizeof(long))-1);idx++)
                curr_event->args[idx]=va_arg(ap,long);
        va_end(ap);
        debug_finish_entry(id, active, level, 1);
@@ -839,6 +910,7 @@ static int __init debug_init(void)
 {
        int rc = 0;
 
+       s390dbf_sysctl_header = register_sysctl_table(s390dbf_dir_table, 1);
        down(&debug_lock);
 #ifdef CONFIG_PROC_FS
        debug_proc_root_entry = proc_mkdir(DEBUG_DIR_ROOT, NULL);
@@ -859,7 +931,7 @@ int debug_register_view(debug_info_t * id, struct debug_view *view)
        int rc = 0;
        int i;
        unsigned long flags;
-       mode_t mode = S_IFREG;
+       mode_t mode = S_IFREG | S_IRUSR | S_IWUSR;
        struct proc_dir_entry *pde;
 
        if (!id)
@@ -1157,7 +1229,7 @@ int debug_sprintf_format_fn(debug_info_t * id, struct debug_view *view,
        }
 
        /* number of arguments used for sprintf (without the format string) */
-       num_used_args   = MIN(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
+       num_used_args   = min(DEBUG_SPRINTF_MAX_ARGS, (num_longs - 1));
 
        memset(index,0, DEBUG_SPRINTF_MAX_ARGS * sizeof(int));
 
@@ -1187,6 +1259,7 @@ void __exit debug_exit(void)
 #ifdef CONFIG_PROC_FS
        remove_proc_entry(debug_proc_root_entry->name, NULL);
 #endif /* CONFIG_PROC_FS */
+       unregister_sysctl_table(s390dbf_sysctl_header);
        return;
 }
 
@@ -1200,6 +1273,7 @@ MODULE_LICENSE("GPL");
 EXPORT_SYMBOL(debug_register);
 EXPORT_SYMBOL(debug_unregister); 
 EXPORT_SYMBOL(debug_set_level);
+EXPORT_SYMBOL(debug_stop_all);
 EXPORT_SYMBOL(debug_register_view);
 EXPORT_SYMBOL(debug_unregister_view);
 EXPORT_SYMBOL(debug_event_common);