# This is a little logger which dumps stuff out to a host file.  Used for 
# tracking down otherwise intractable bugs.
Index: linux-2.6.17/arch/um/os-Linux/util.c
===================================================================
--- linux-2.6.17.orig/arch/um/os-Linux/util.c	2007-10-24 10:04:50.000000000 -0400
+++ linux-2.6.17/arch/um/os-Linux/util.c	2007-11-19 11:57:40.000000000 -0500
@@ -7,20 +7,21 @@
 #include <stdlib.h>
 #include <unistd.h>
 #include <limits.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/utsname.h>
-#include <sys/param.h>
-#include <sys/time.h>
-#include "asm/types.h"
 #include <ctype.h>
 #include <signal.h>
+#include <fcntl.h>
 #include <wait.h>
 #include <errno.h>
 #include <stdarg.h>
 #include <sched.h>
 #include <termios.h>
 #include <string.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/utsname.h>
+#include <sys/param.h>
+#include <sys/time.h>
+#include "asm/types.h"
 #include "kern_util.h"
 #include "user.h"
 #include "mem_user.h"
@@ -146,3 +147,31 @@ void os_dump_core(void)
 
 	abort();
 }
+
+int logging = 1;
+int logging_fd = -1;
+
+int logging_line = 0;
+char logging_buf[512];
+
+void os_log_info(char *fmt, va_list ap)
+{
+	struct timeval tv;
+	int len;
+
+	if(logging == 0)
+		return;
+
+	if(logging_fd < 0){
+		sprintf(logging_buf, "log-%s", get_umid());
+		logging_fd = open(logging_buf, O_RDWR | O_TRUNC | O_CREAT,
+				  0644);
+	}
+
+	gettimeofday(&tv, NULL);
+	sprintf(logging_buf, "%d\t %u.%u  ", logging_line++,
+		(unsigned int) tv.tv_sec, (unsigned int) tv.tv_usec);
+	len = strlen(logging_buf);
+	vsnprintf(&logging_buf[len], sizeof(logging_buf) - len, fmt, ap);
+	write(logging_fd, logging_buf, strlen(logging_buf));
+}
Index: linux-2.6.17/arch/um/include/os.h
===================================================================
--- linux-2.6.17.orig/arch/um/include/os.h	2007-11-19 11:56:18.000000000 -0500
+++ linux-2.6.17/arch/um/include/os.h	2007-11-19 11:57:40.000000000 -0500
@@ -297,6 +297,7 @@ extern void setup_machinename(char *mach
 extern void setup_hostinfo(char *buf, int len);
 extern int setjmp_wrapper(void (*proc)(void *, void *), ...);
 extern void os_dump_core(void);
+extern void os_log_info(char *fmt, va_list ap);
 
 /* time.c */
 extern void idle_sleep(unsigned long long nsecs);
Index: linux-2.6.17/arch/um/include/kern_util.h
===================================================================
--- linux-2.6.17.orig/arch/um/include/kern_util.h	2007-11-19 11:13:31.000000000 -0500
+++ linux-2.6.17/arch/um/include/kern_util.h	2007-11-19 11:57:40.000000000 -0500
@@ -105,6 +105,10 @@ extern int cpu(void);
 
 extern void time_init_kern(void);
 
+extern void log_info(char *fmt, ...) __attribute__ ((format (printf, 1, 2)));
+extern void log_info_nolock(char *fmt, ...)
+	__attribute__ ((format (printf, 1, 2)));
+
 /* Are we disallowed to sleep? Used to choose between GFP_KERNEL and GFP_ATOMIC. */
 extern int __cant_sleep(void);
 extern void sigio_handler(int sig, struct uml_pt_regs *regs);
Index: linux-2.6.17/arch/um/kernel/um_arch.c
===================================================================
--- linux-2.6.17.orig/arch/um/kernel/um_arch.c	2007-11-19 11:22:17.000000000 -0500
+++ linux-2.6.17/arch/um/kernel/um_arch.c	2007-11-19 11:57:40.000000000 -0500
@@ -412,3 +412,27 @@ void alternatives_smp_module_del(struct 
 {
 }
 #endif
+
+static DEFINE_SPINLOCK(log_lock);
+
+void log_info(char *fmt, ...)
+{
+	unsigned long flags;
+	va_list ap;
+
+	va_start(ap, fmt);
+	spin_lock_irqsave(&log_lock, flags);
+
+	os_log_info(fmt, ap);
+
+	spin_unlock_irqrestore(&log_lock, flags);
+}
+
+void log_info_nolock(char *fmt, ...)
+{
+	va_list ap;
+
+	va_start(ap, fmt);
+	os_log_info(fmt, ap);
+}
+