diff -uar -x .svn fusd-1.10/ChangeLog fusd-kor-1.10-10/ChangeLog
--- fusd-1.10/ChangeLog	2003-08-20 16:12:26.000000000 -0600
+++ fusd-kor-1.10-10/ChangeLog	2005-09-16 22:31:33.000000000 -0600
@@ -1,3 +1,26 @@
+
+v kor-1.10-10: Sept 16, 2005
+
+	Modified to work with 2.6.13
+
+v kor-1.10-9: Jun 18, 2005
+
+	Added support for mmap
+	Added support for simultaneous requests on the same file descriptor
+	from separate processes.
+
+v kor-1.10-8: Feb 10, 2005
+
+	Fixed some shutdown issues for non-devfs systems.
+
+v kor-1.10-7: Feb 9, 2005
+
+	Modified to work udev
+
+v kor-1.10-6: Feb 17, 2004.
+
+	Modified to work with the 2.6 kernel and devfs.
+
 v 1.10: August 19, 2003
 
 	First UCLA release -- no longer publically maintained or released
@@ -58,4 +81,4 @@
 	
 v 1.00: September 28, 2001
 	Initial public release.
-	
\ No newline at end of file
+	
diff -uar -x .svn fusd-1.10/examples/console-read.c fusd-kor-1.10-10/examples/console-read.c
--- fusd-1.10/examples/console-read.c	2003-07-11 16:29:38.000000000 -0600
+++ fusd-kor-1.10-10/examples/console-read.c	2005-02-09 19:39:26.000000000 -0700
@@ -88,7 +88,7 @@
     read: do_read,
     close: do_open_or_close };
   
-  if (fusd_register("/dev/console-read", 0666, NULL, &fops) < 0)
+  if (fusd_register("/dev/console-read", "misc", "console-read", 0666, NULL, &fops) < 0)
     perror("Unable to register device");
   else {
     printf("/dev/console-read should now exist - calling fusd_run...\n");
diff -uar -x .svn fusd-1.10/examples/drums2.c fusd-kor-1.10-10/examples/drums2.c
--- fusd-1.10/examples/drums2.c	2003-07-11 16:29:38.000000000 -0600
+++ fusd-kor-1.10-10/examples/drums2.c	2005-02-09 19:39:26.000000000 -0700
@@ -124,10 +124,12 @@
 {
   struct drum_info *d;
   char buf[128];
+  char devname[128];
 
   for (d = drums; d->name != NULL; d++) {
     sprintf(buf, "/dev/drums/%s", d->name);
-    if (fusd_register(buf, 0666, d, &drums_fops) < 0)
+    sprintf(devname, "drum%s", d->name);
+    if (fusd_register(buf, "drums", devname, 0666, d, &drums_fops) < 0)
       fprintf(stderr, "%s register failed: %m\n", d->name);
   }
   /* ... */
diff -uar -x .svn fusd-1.10/examples/drums3.c fusd-kor-1.10-10/examples/drums3.c
--- fusd-1.10/examples/drums3.c	2003-07-11 16:29:38.000000000 -0600
+++ fusd-kor-1.10-10/examples/drums3.c	2005-02-09 19:39:26.000000000 -0700
@@ -155,12 +155,14 @@
 {
   int i;
   char buf[128];
+  char devname[128];
   fd_set fds, tmp;
   int max;
 
   for (i = 0; drums_strings[i] != NULL; i++) {
     sprintf(buf, "/dev/drums/%s", drums_strings[i]);
-    if (fusd_register(buf, 0666, drums_strings[i], &drums_fops) < 0)
+    sprintf(devname, "drum%s", drums_strings[i]);
+    if (fusd_register(buf, "drums", devname, 0666, drums_strings[i], &drums_fops) < 0)
       fprintf(stderr, "%s register failed: %m\n", drums_strings[i]);
   }
 
diff -uar -x .svn fusd-1.10/examples/drums.c fusd-kor-1.10-10/examples/drums.c
--- fusd-1.10/examples/drums.c	2003-07-11 16:29:38.000000000 -0600
+++ fusd-kor-1.10-10/examples/drums.c	2005-02-09 19:39:26.000000000 -0700
@@ -101,10 +101,12 @@
 {
   int i;
   char buf[128];
+  char devname[128];
 
   for (i = 0; drums_strings[i] != NULL; i++) {
     sprintf(buf, "/dev/drums/%s", drums_strings[i]);
-    if (fusd_register(buf, 0666, drums_strings[i], &drums_fops) < 0)
+    sprintf(devname, "drum%s", drums_strings[i]);
+    if (fusd_register(buf, "drums", devname, 0666, drums_strings[i], &drums_fops) < 0)
       fprintf(stderr, "%s register failed: %m\n", drums_strings[i]);
   }
 
diff -uar -x .svn fusd-1.10/examples/echo.c fusd-kor-1.10-10/examples/echo.c
--- fusd-1.10/examples/echo.c	2003-07-11 16:29:38.000000000 -0600
+++ fusd-kor-1.10-10/examples/echo.c	2005-02-09 19:39:26.000000000 -0700
@@ -113,7 +113,7 @@
 
 int main(int argc, char *argv[])
 {
-  if (fusd_register("/dev/echo", 0666, NULL, &echo_fops) < 0) {
+  if (fusd_register("/dev/echo", "misc", "echo", 0666, NULL, &echo_fops) < 0) {
     perror("register of /dev/echo failed");
     exit(1);
   }
diff -uar -x .svn fusd-1.10/examples/helloworld.c fusd-kor-1.10-10/examples/helloworld.c
--- fusd-1.10/examples/helloworld.c	2003-07-11 16:29:38.000000000 -0600
+++ fusd-kor-1.10-10/examples/helloworld.c	2005-02-09 19:39:26.000000000 -0700
@@ -80,7 +80,7 @@
     read: do_read,
     close: do_open_or_close };
   
-  if (fusd_register("/dev/hello-world", 0666, NULL, &fops) < 0)
+  if (fusd_register("/dev/hello-world", "misc", "hello-word", 0666, NULL, &fops) < 0)
     perror("Unable to register device");
   else {
     printf("/dev/hello-world should now exist - calling fusd_run...\n");
diff -uar -x .svn fusd-1.10/examples/logring.c fusd-kor-1.10-10/examples/logring.c
--- fusd-1.10/examples/logring.c	2003-07-11 16:29:39.000000000 -0600
+++ fusd-kor-1.10-10/examples/logring.c	2005-02-09 19:39:26.000000000 -0700
@@ -441,7 +441,7 @@
   }
 
   /* register the fusd device */
-  fusd_simple_register(name, 0666, NULL,
+  fusd_simple_register(name, "misc", "logring", 0666, NULL,
                        open: logring_open, close: logring_close,
                        read: logring_read, write: logring_write,
 		       poll_diff: logring_polldiff);
diff -uar -x .svn fusd-1.10/examples/pager.c fusd-kor-1.10-10/examples/pager.c
--- fusd-1.10/examples/pager.c	2003-07-11 16:29:39.000000000 -0600
+++ fusd-kor-1.10-10/examples/pager.c	2005-02-09 19:39:26.000000000 -0700
@@ -366,12 +366,12 @@
 int main(int argc, char *argv[])
 {
   /* register the input device */
-  fusd_simple_register("/dev/pager/input", 0666, NULL,
+  fusd_simple_register("/dev/pager/input", "pager", "input", 0666, NULL,
                        open: fusd_success, close: fusd_success,
                        write: pager_input_write);
 
   /* register the notification device */
-  fusd_simple_register("/dev/pager/notify", 0666, NULL,
+  fusd_simple_register("/dev/pager/notify", "pager", "notify", 0666, NULL,
                        open: pager_notify_open,
 		       close: pager_notify_close,
                        read: pager_notify_read,
diff -uar -x .svn fusd-1.10/examples/uid-filter.c fusd-kor-1.10-10/examples/uid-filter.c
--- fusd-1.10/examples/uid-filter.c	2003-07-11 16:29:39.000000000 -0600
+++ fusd-kor-1.10-10/examples/uid-filter.c	2005-02-09 19:39:26.000000000 -0700
@@ -103,7 +103,7 @@
     read: do_read,
     close: do_close };
   
-  if (fusd_register("/dev/my-pid", 0666, NULL, &fops) < 0)
+  if (fusd_register("/dev/my-pid", "misc", "my-pid", 0666, NULL, &fops) < 0)
     perror("Unable to register device");
   else {
     printf("/dev/my-pid should now exist - calling fusd_run...\n");
diff -uar -x .svn fusd-1.10/include/fusd.h fusd-kor-1.10-10/include/fusd.h
--- fusd-1.10/include/fusd.h	2003-07-11 16:29:39.000000000 -0600
+++ fusd-kor-1.10-10/include/fusd.h	2005-06-16 21:34:48.000000000 -0600
@@ -64,6 +64,8 @@
 #define FUSD_NOTIFY_EXCEPT  0x4
 
 
+#define FUSD_KOR_HACKED_VERSION
+
 struct fusd_file_info; /* forward decl */
 
 typedef
@@ -76,7 +78,8 @@
 		    size_t length, loff_t *offset);
   int (*ioctl) (struct fusd_file_info *file, int request, void *data);
   int (*poll_diff) (struct fusd_file_info *file, unsigned int cached_state);
-  int (*unblock) (struct fusd_file_info *file);    
+  int (*unblock) (struct fusd_file_info *file);
+  int (*mmap) (struct fusd_file_info *file, int offset, size_t length, int flags, void** addr, size_t* out_length);
 } fusd_file_operations_t;
 
 
@@ -144,15 +147,15 @@
  *    fusd_dispatch).
  */
 
-int fusd_register(const char *name, mode_t mode, void *device_info,
+int fusd_register(const char *name, const char* clazz, const char* devname, mode_t mode, void *device_info,
 		  struct fusd_file_operations *fops);
 
 
 
 /* "simple" interface to fusd_register. */
-#define fusd_simple_register(name, perms, arg, ops...) do { \
+#define fusd_simple_register(name, clazz, devname, perms, arg, ops...) do { \
    struct fusd_file_operations f = { ops } ; \
-   if (fusd_register(name, perms, arg, &f) < 0) \
+   if (fusd_register(name, clazz, devname, perms, arg, &f) < 0) \
       perror("warning: fusd unavailable"); \
 } while(0)
 
diff -uar -x .svn fusd-1.10/include/fusd_msg.h fusd-kor-1.10-10/include/fusd_msg.h
--- fusd-1.10/include/fusd_msg.h	2003-07-11 16:29:39.000000000 -0600
+++ fusd-kor-1.10-10/include/fusd_msg.h	2005-06-16 20:21:13.000000000 -0600
@@ -76,6 +76,7 @@
 #define FUSD_IOCTL                 104
 #define FUSD_POLL_DIFF             105
 #define FUSD_UNBLOCK               106
+#define FUSD_MMAP                  107
 
 /* other constants */
 #define FUSD_MSG_MAGIC      0x7a6b93cd
@@ -83,6 +84,8 @@
 /* user->kernel: register a device */
 typedef struct {
   char name[FUSD_MAX_NAME_LENGTH+1];
+	char clazz[FUSD_MAX_NAME_LENGTH+1];
+	char devname[FUSD_MAX_NAME_LENGTH+1];
   mode_t mode;
   void *device_info;
 } register_msg_t;
diff -uar -x .svn fusd-1.10/include/kfusd.h fusd-kor-1.10-10/include/kfusd.h
--- fusd-1.10/include/kfusd.h	2003-07-11 16:29:39.000000000 -0600
+++ fusd-kor-1.10-10/include/kfusd.h	2005-09-16 18:45:31.000000000 -0600
@@ -74,9 +74,21 @@
   unsigned int peeked:1;	/* has the first half of this been read? */
 };
 
+struct fusd_transaction
+{
+	struct list_head list;
+	long transid;
+	int subcmd;
+	int pid;
+	int size;
+	fusd_msg_t* msg_in;
+};
+
 /* magical forward declarations to break the circular dependency */
 struct fusd_dev_t_s;
 typedef struct fusd_dev_t_s fusd_dev_t;
+struct class;
+struct class_device;
 
 /* state kept per opened file (i.e., an instance of a device) */
 typedef struct {
@@ -94,11 +106,9 @@
   /* structures used for messaging */
   wait_queue_head_t file_wait;	/* Wait on this for a user->kernel msg */
   wait_queue_head_t poll_wait;  /* Given to kernel for poll() queue */
-  long transid_outstanding;	/* transid of msg we are waiting for */
-  int subcmd_outstanding;	/* subcmd of msg we are waiting for */
-  pid_t sys_restarting_pid;	/* PID we just returned -ERESTARTSYS to */
-  int sys_restarting_subcmd;	/* subcmd of restarting syscall */
-  fusd_msg_t *msg_in;		/* A reply we've just received */
+	struct list_head transactions;
+	struct semaphore transactions_sem;
+	
 } fusd_file_t;
 
 
@@ -108,9 +118,19 @@
   long version;			/* Instance number of this device */
   int zombie;			/* Is the device dead? */
   pid_t pid;			/* PID of device driver */
+  struct task_struct* task;
+  
   char *name;			/* Name of the device under devfs (/dev) */
+	char *class_name;
+	char *dev_name;
+	struct class *clazz;
+	int owns_class;
+	struct class_device *class_device;
+	
   void *private_data;		/* User's private data */
-  devfs_handle_t handle;	/* The devfs-provided handle */
+	struct cdev* handle;
+	dev_t dev_id;
+//  devfs_handle_t handle;	/* The devfs-provided handle */
 
   fusd_file_t **files;		/* Array of this device's open files */
   int array_size;		/* Size of the array pointed to by 'files' */
@@ -138,14 +158,18 @@
 STATIC int free_fusd_file(fusd_dev_t *fusd_dev, fusd_file_t *fusd_file);
 
 STATIC int fusd_fops_call_send(fusd_file_t *fusd_file_arg,
-			       fusd_msg_t *fusd_msg);
+			       fusd_msg_t *fusd_msg, struct fusd_transaction** transaction);
 STATIC int fusd_fops_call_wait(fusd_file_t *fusd_file_arg,
-			       fusd_msg_t **reply);
+			       fusd_msg_t **fusd_msg_reply, struct fusd_transaction* transaction);
 STATIC void fusd_fops_call_done(fusd_file_t *fusd_file);
 
 STATIC void fusd_forge_close(fusd_msg_t *msg, fusd_dev_t *fusd_dev);
 
-
+STATIC int fusd_add_transaction(fusd_file_t *fusd_file, int transid, int subcmd, int size, struct fusd_transaction** out_transaction);
+STATIC void fusd_cleanup_transaction(fusd_file_t *fusd_file, struct fusd_transaction* transaction);
+STATIC void fusd_remove_transaction(fusd_file_t *fusd_file, struct fusd_transaction* transaction);
+STATIC struct fusd_transaction* fusd_find_transaction(fusd_file_t *fusd_file, int transid);
+STATIC struct fusd_transaction* fusd_find_transaction_by_pid(fusd_file_t *fusd_file, int pid);
 
 
 
diff -uar -x .svn fusd-1.10/kfusd/kfusd.c fusd-kor-1.10-10/kfusd/kfusd.c
--- fusd-1.10/kfusd/kfusd.c	2005-06-13 22:18:21.000000000 -0600
+++ fusd-kor-1.10-10/kfusd/kfusd.c	2005-09-16 18:50:33.000000000 -0600
@@ -70,15 +70,22 @@
 #include <linux/devfs_fs_kernel.h>
 #include <linux/poll.h>
 #include <linux/version.h>
+#include <linux/major.h>
+#include <linux/uio.h>
+#include <linux/cdev.h>
+#include <linux/device.h>
+#include <linux/highmem.h>
+
 #include <asm/atomic.h>
 #include <asm/uaccess.h>
 #include <asm/ioctl.h>
-
+#include <asm/pgtable.h>
+#include <asm/pgalloc.h>
 
 #define STATIC
 
 /* Define this if you want to emit debug messages (adds ~8K) */
-// #define CONFIG_FUSD_DEBUG
+#define CONFIG_FUSD_DEBUG
 
 /* Default debug level for FUSD messages.  Has no effect unless
  * CONFIG_FUSD_DEBUG is defined. */
@@ -87,7 +94,7 @@
 #endif
 
 /* Define this to check for memory leaks */
-/* #define CONFIG_FUSD_MEMDEBUG */
+/*#define CONFIG_FUSD_MEMDEBUG*/
 
 /* Define this to use the faster wake_up_interruptible_sync instead of
  * the normal wake_up_interruptible.  Note: you can't do this unless
@@ -101,6 +108,15 @@
 # define  snprintf(str, len, args...)      sprintf(str, args)
 #endif
 
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,13)
+
+typedef class_simple class;
+#define class_create class_simple_create
+#define class_destroy class_simple_destroy
+#define class_device_create class_simple_device_add
+#define class_device_destroy(a, b) class_simple_device_remove(b)
+
+#endif
 
 /**************************************************************************/
 
@@ -112,13 +128,18 @@
 # error "***FUSD doesn't work before Linux Kernel v2.4.0"
 #endif
 
-#ifndef CONFIG_DEVFS_FS
-# error "****FUSD needs DEVFS enabled in the kernel!"
-#endif
+STATIC struct cdev* fusd_control_device;
+STATIC struct cdev* fusd_status_device;
+
+STATIC dev_t control_id;
+STATIC dev_t status_id;
 
-/* handles that devfs gives /dev/fusd and /dev/fusd_status */
-STATIC devfs_handle_t fusd_handle = 0;
-STATIC devfs_handle_t fusd_status_handle = 0;
+static struct class *fusd_class;
+
+static struct class_device *fusd_control_class_device;
+static struct class_device *fusd_status_class_device;
+
+extern struct class *sound_class;
 
 /* version number incremented for each registered device */
 STATIC int last_version = 1;
@@ -133,10 +154,10 @@
 LIST_HEAD(fusd_devlist_head);
 DECLARE_MUTEX(fusd_devlist_sem);
 
-#ifdef MODULE_LICENSE
+//#ifdef MODULE_LICENSE
 MODULE_AUTHOR("Jeremy Elson <jelson@acm.org> (c)2001");
 MODULE_LICENSE("GPL");
-#endif
+//#endif
 
 /***************************Debugging Support*****************************/
 
@@ -426,12 +447,25 @@
     next = ptr->next;
     FREE_FUSD_MSGC(ptr);
   }
+  
+     /* free the device's dev name */
+  if (fusd_dev->dev_name != NULL) {
+    KFREE(fusd_dev->dev_name);
+    fusd_dev->dev_name = NULL;
+  }
+  
+    /* free the device's class name */
+  if (fusd_dev->class_name != NULL) {
+    KFREE(fusd_dev->class_name);
+    fusd_dev->class_name = NULL;
+  }
 
   /* free the device's name */
   if (fusd_dev->name != NULL) {
     KFREE(fusd_dev->name);
     fusd_dev->name = NULL;
   }
+  
 
   /* free the array used to store pointers to fusd_file_t's */
   if (fusd_dev->files != NULL) {
@@ -448,7 +482,7 @@
   atomic_inc_and_ret(&last_version);
   wake_up_interruptible(&new_device_wait);
 
-  MOD_DEC_USE_COUNT;
+  //MOD_DEC_USE_COUNT;
   return 1;
 }
 
@@ -513,7 +547,8 @@
 STATIC int free_fusd_file(fusd_dev_t *fusd_dev, fusd_file_t *fusd_file)
 {
   int i;
-
+  struct list_head *tmp, *it;
+   
   /* find the index of the file in the device's file-list... */
   if ((i = find_fusd_file(fusd_dev, fusd_file)) < 0)
     panic("corrupted fusd_dev: releasing a file that we think is closed");
@@ -524,11 +559,19 @@
   /* there might be an incoming message waiting for a restarted system
    * call.  free it -- after possibly forging a close (see
    * fusd_forge_close). */
-  if (fusd_file->msg_in) {
-    if (fusd_file->msg_in->subcmd == FUSD_OPEN && fusd_file->msg_in->parm.fops_msg.retval == 0)
-      fusd_forge_close(fusd_file->msg_in, fusd_dev);
-    free_fusd_msg(&fusd_file->msg_in);
-  }
+   
+   
+	list_for_each_safe(it, tmp, &fusd_file->transactions)
+	{
+		struct fusd_transaction* transaction = list_entry(it, struct fusd_transaction, list);
+		if(transaction->msg_in)
+		{
+      if (transaction->msg_in->subcmd == FUSD_OPEN && transaction->msg_in->parm.fops_msg.retval == 0)
+        fusd_forge_close(transaction->msg_in, fusd_dev);
+      free_fusd_msg(&transaction->msg_in);
+		} 
+		KFREE(transaction);
+	}
   
   /* free state associated with this file */
   memset(fusd_file, 0, sizeof(fusd_file_t));
@@ -553,7 +596,7 @@
 /****************************************************************************/
 
 
-/*
+/* todo
  * fusd_restart_check: Called from the beginning of most system calls
  * to see if we are restarting a system call.
  *
@@ -568,23 +611,24 @@
  * call on that file descriptor -- well, we lose.  Clear state of that
  * old syscall out and continue as usual.
  */
-STATIC int fusd_restart_check(fusd_file_t *fusd_file, int subcmd)
+STATIC struct fusd_transaction* fusd_find_incomplete_transaction(fusd_file_t *fusd_file, int subcmd)
 {
-  if (fusd_file->sys_restarting_pid == 0)
-    return 0;
+  struct fusd_transaction* transaction = fusd_find_transaction_by_pid(fusd_file, current->pid);
+  if(transaction == NULL)
+    return NULL;
 
-  if (fusd_file->sys_restarting_pid == current->pid &&
-      fusd_file->subcmd_outstanding == subcmd) {
-    RDEBUG(4, "pid %d restarting system call with transid %ld", current->pid,
-	   fusd_file->transid_outstanding);
-    return ERESTARTSYS;
-  }
 
-  /* uh oh.  we think we are restarting a syscall but PID does match.
-     give up. */
-  fusd_fops_call_done(fusd_file);
-  free_fusd_msg(&fusd_file->msg_in);
-  return 0;
+  if (transaction->subcmd != subcmd)
+  {
+    RDEBUG(2, "Incomplete transaction %ld thrown out, was expecting subcmd %d but received %d", 
+           transaction->transid, transaction->subcmd, subcmd);
+    fusd_cleanup_transaction(fusd_file, transaction);
+    return NULL;
+  }
+  
+  RDEBUG(4, "pid %d restarting system call with transid %ld", current->pid,
+         transaction->transid);
+  return transaction;
 }
 
 
@@ -651,7 +695,7 @@
  * function is called, but NOT the lock on the fusd_dev
  */
 STATIC int fusd_fops_call_send(fusd_file_t *fusd_file_arg,
-			       fusd_msg_t *fusd_msg)
+			       fusd_msg_t *fusd_msg, struct fusd_transaction** transaction)
 {
   fusd_dev_t *fusd_dev;
   fusd_file_t *fusd_file;
@@ -681,8 +725,7 @@
 
   case FUSD_FOPS_CALL: /* common case */
     fusd_msg->parm.fops_msg.hint = fusd_file->index;
-    fusd_file->transid_outstanding = fusd_msg->parm.fops_msg.transid;
-    fusd_file->subcmd_outstanding = fusd_msg->subcmd;
+     
     break;
 
   case FUSD_FOPS_CALL_DROPREPLY:
@@ -697,7 +740,16 @@
     RDEBUG(0, "whoa - fusd_fops_call_send got msg with unknown cmd!");
     break;
   }
-
+  
+  if(transaction != NULL)
+  {
+    int retval;
+    retval = fusd_add_transaction(fusd_file, fusd_msg->parm.fops_msg.transid, fusd_msg->subcmd,
+                    fusd_msg->parm.fops_msg.length, transaction);
+    if(retval < 0)
+      return retval;
+  }
+  
   /* now add the message to the device's outgoing queue! */
   return send_to_dev(fusd_dev, fusd_msg, 0);
 
@@ -717,7 +769,7 @@
  * function is called, but NOT the lock on the fusd_dev
  */
 STATIC int fusd_fops_call_wait(fusd_file_t *fusd_file_arg,
-			       fusd_msg_t **fusd_msg_reply)
+			       fusd_msg_t **fusd_msg_reply, struct fusd_transaction* transaction)
 {
   fusd_dev_t *fusd_dev;
   fusd_file_t *fusd_file;
@@ -738,14 +790,15 @@
    * sleep condition and sleeping.
    */
   LOCK_FUSD_DEV(fusd_dev);
-  while (fusd_file->msg_in == NULL) {
+  while (transaction->msg_in == NULL) {
     DECLARE_WAITQUEUE(wait, current);
 
-    RDEBUG(10, "pid %d blocking on transid %ld", current->pid,
-	   fusd_file->transid_outstanding);
+    RDEBUG(10, "pid %d blocking on transid %ld", current->pid, transaction->transid);
     current->state = TASK_INTERRUPTIBLE;
     add_wait_queue(&fusd_file->file_wait, &wait);
     UNLOCK_FUSD_DEV(fusd_dev);
+    UNLOCK_FUSD_FILE(fusd_file);
+
     schedule();
     remove_wait_queue(&fusd_file->file_wait, &wait);
     current->state = TASK_RUNNING;
@@ -763,10 +816,11 @@
     if (signal_pending(current)) {
       RDEBUG(5, "blocked pid %d got a signal; sending -ERESTARTSYS",
 	     current->pid);
-      fusd_file->sys_restarting_pid = current->pid;
+			LOCK_FUSD_FILE(fusd_file);
       return -ERESTARTSYS;
     }
 
+    LOCK_FUSD_FILE(fusd_file);
     /* re-lock the device, so we can do our msg_in check again */
     LOCK_FUSD_DEV(fusd_dev);
   }
@@ -774,39 +828,38 @@
 
   /* ok - at this point we are awake due to a message received. */
 
-  if (fusd_file->msg_in->cmd != FUSD_FOPS_REPLY ||
-      fusd_file->msg_in->subcmd != fusd_file->subcmd_outstanding ||
-      fusd_file->msg_in->parm.fops_msg.transid != fusd_file->transid_outstanding ||
-      fusd_file->msg_in->parm.fops_msg.fusd_file != fusd_file) {
+  if (transaction->msg_in->cmd != FUSD_FOPS_REPLY ||
+      transaction->msg_in->subcmd != transaction->subcmd ||
+      transaction->msg_in->parm.fops_msg.transid != transaction->transid ||
+      transaction->msg_in->parm.fops_msg.fusd_file != fusd_file) {
     RDEBUG(2, "fusd_fops_call: invalid reply!");
     goto invalid_reply;
   }
 
   /* copy metadata back from userspace */
-  fusd_file->file->f_flags = fusd_file->msg_in->parm.fops_msg.flags;
-  fusd_file->private_data  = fusd_file->msg_in->parm.fops_msg.private_info;
+  fusd_file->file->f_flags = transaction->msg_in->parm.fops_msg.flags;
+  fusd_file->private_data  = transaction->msg_in->parm.fops_msg.private_info;
   /* note, changes to device_info are NO LONGER honored here */
 
   /* if everything's okay, return the return value.  if caller is
    * willing to take responsibility for freeing the message itself, we
    * return the message too. */
-  retval = fusd_file->msg_in->parm.fops_msg.retval;
+  retval = transaction->msg_in->parm.fops_msg.retval;
   if (fusd_msg_reply != NULL) {
     /* NOW TRANSFERRING RESPONSIBILITY FOR FREEING THIS DATA TO THE CALLER */
-    *fusd_msg_reply = fusd_file->msg_in;
-    fusd_file->msg_in = NULL;
+    *fusd_msg_reply = transaction->msg_in;
+    transaction->msg_in = NULL;
   } else {
     /* free the message ourselves */
-    free_fusd_msg(&fusd_file->msg_in);
+    free_fusd_msg(&transaction->msg_in);
   }
-
+  
   /* success */
-  fusd_fops_call_done(fusd_file);
+  fusd_cleanup_transaction(fusd_file, transaction);
   return retval;
 
  invalid_reply:
-  free_fusd_msg(&fusd_file->msg_in);
-  fusd_fops_call_done(fusd_file);
+  fusd_cleanup_transaction(fusd_file, transaction);
   return -EPIPE;
 
   /* bizarre errors go straight here */
@@ -824,11 +877,10 @@
 
 /* fusd client system call handlers should call this after they call
  * fops_call, to destroy the message that was returned to them. */
-STATIC void fusd_fops_call_done(fusd_file_t *fusd_file)
+STATIC void fusd_transaction_done(struct fusd_transaction *transaction)
 {
-  fusd_file->sys_restarting_pid = 0;
-  fusd_file->transid_outstanding = -1;
-  fusd_file->subcmd_outstanding = -1;
+	transaction->transid = -1;
+	transaction->pid = 0;
 }
 
 
@@ -948,7 +1000,9 @@
   memset(fusd_file, 0, sizeof(fusd_file_t));
   init_waitqueue_head(&fusd_file->file_wait);
   init_waitqueue_head(&fusd_file->poll_wait);
+	INIT_LIST_HEAD(&fusd_file->transactions);
   init_MUTEX(&fusd_file->file_sem);
+  init_MUTEX(&fusd_file->transactions_sem);
   fusd_file->last_poll_sent = -1;
   fusd_file->magic = FUSD_FILE_MAGIC;
   fusd_file->fusd_dev = fusd_dev;
@@ -967,6 +1021,22 @@
   return 0;
 }
 
+STATIC struct fusd_dev_t_s* find_user_device(int dev_id)
+{
+	struct list_head* entry;
+	down(&fusd_devlist_sem);
+	list_for_each(entry, &fusd_devlist_head)
+	{
+    fusd_dev_t *d = list_entry(entry, fusd_dev_t, devlist);
+		if(d->dev_id == dev_id)
+		{
+			up(&fusd_devlist_sem);
+			return d;
+		}
+	}
+	up(&fusd_devlist_sem);
+ return NULL;
+}
 
 /*
  * A client has called open() has been called on a registered device.
@@ -976,10 +1046,11 @@
 {
   int retval;
   int device_freed = 0;
-  fusd_dev_t *fusd_dev = (fusd_dev_t *) file->private_data;
+  fusd_dev_t *fusd_dev = find_user_device(inode->i_rdev);
   fusd_file_t *fusd_file;
   fusd_msg_t fusd_msg;
-
+  struct fusd_transaction* transaction;
+  
   /* If the device wasn't on our valid list, stop here. */
   if (!fusd_dev_is_valid(fusd_dev))
     return -ENOENT;
@@ -1003,7 +1074,7 @@
    *   2) Something failed, so we are returning a failure now and no
    *   longer need the device.
    * Note, open_in_progress must be protected by the global sem, not
-   * the device lock, due to the access of it in fusd_dev_is_valid(). 
+   * the device lock, due to the access of it in fusd_dev_is_valid().
    */
   down(&fusd_devlist_sem);
   fusd_dev->open_in_progress--;
@@ -1026,9 +1097,10 @@
    * locked during that operation. */
 
   UNLOCK_FUSD_DEV(fusd_dev);
-  retval = fusd_fops_call_send(fusd_file, &fusd_msg);
+  retval = fusd_fops_call_send(fusd_file, &fusd_msg, &transaction);
+  
   if (retval >= 0)
-    retval = fusd_fops_call_wait(fusd_file, NULL);
+    retval = fusd_fops_call_wait(fusd_file, NULL, transaction);
   RAWLOCK_FUSD_DEV(fusd_dev);
 
   /* If the device zombified (while we were waiting to reacquire the
@@ -1062,7 +1134,8 @@
   fusd_file_t *fusd_file;
   fusd_dev_t *fusd_dev;
   fusd_msg_t fusd_msg;
-
+  struct fusd_transaction* transaction;
+  
   GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
   LOCK_FUSD_FILE(fusd_file);
 
@@ -1072,10 +1145,12 @@
   /* Tell the driver that the file closed, if it still exists. */
   init_fusd_msg(&fusd_msg);
   fusd_msg.subcmd = FUSD_CLOSE;
-  retval = fusd_fops_call_send(fusd_file, &fusd_msg);
+  retval = fusd_fops_call_send(fusd_file, &fusd_msg, &transaction);
+	RDEBUG(5, "fusd_client_release: send returned %d", retval);
   if (retval >= 0)
-    retval = fusd_fops_call_wait(fusd_file, NULL);
-
+    retval = fusd_fops_call_wait(fusd_file, NULL, transaction);
+	
+	RDEBUG(5, "fusd_client_release: call_wait %d", retval);
   /* delete the file off the device's file-list, and free it.  note
    * that device may be a zombie right now and may be freed when we
    * come back from free_fusd_file.  we only release the lock if the
@@ -1101,6 +1176,7 @@
 {
   fusd_dev_t *fusd_dev;
   fusd_file_t *fusd_file;
+  struct fusd_transaction* transaction;
   fusd_msg_t fusd_msg, *reply = NULL;
   int retval = -EPIPE;
 
@@ -1110,25 +1186,35 @@
   RDEBUG(3, "got a read on /dev/%s (owned by pid %d) from pid %d",
 	 NAME(fusd_dev), fusd_dev->pid, current->pid);
 
-  if (fusd_restart_check(fusd_file, FUSD_READ) == ERESTARTSYS)
-    goto restarted_syscall;
-
-  /* make sure we aren't trying to read too big of a buffer */
-  if (count > MAX_RW_SIZE)
-    count = MAX_RW_SIZE;
-
-  /* send the message */
-  init_fusd_msg(&fusd_msg);
-  fusd_msg.subcmd = FUSD_READ;
-  fusd_msg.parm.fops_msg.length = count;
+  transaction = fusd_find_incomplete_transaction(fusd_file, FUSD_READ);
+  if (transaction && transaction->size > count)
+  {
+    RDEBUG(2, "Incomplete I/O transaction %ld thrown out, as the transaction's size of %d bytes was greater than "
+              "the retry's size of %d bytes", transaction->transid, transaction->size, count);
 
-  /* send message to userspace */
-  if ((retval = fusd_fops_call_send(fusd_file, &fusd_msg)) < 0)
-    goto done;
+    fusd_cleanup_transaction(fusd_file, transaction);
+    transaction = NULL;
+  }
 
- restarted_syscall:
+  if(transaction == NULL)
+  {
+    /* make sure we aren't trying to read too big of a buffer */
+    if (count > MAX_RW_SIZE)
+      count = MAX_RW_SIZE;
+  
+    /* send the message */
+    init_fusd_msg(&fusd_msg);
+    fusd_msg.subcmd = FUSD_READ;
+    fusd_msg.parm.fops_msg.length = count;
+  
+    /* send message to userspace */
+    if ((retval = fusd_fops_call_send(fusd_file, &fusd_msg, &transaction)) < 0)
+      goto done;
+  }
+  
   /* and wait for the reply */
-  retval = fusd_fops_call_wait(fusd_file, &reply);
+  /* todo: store and retrieve the transid from the interrupted messsage */
+  retval = fusd_fops_call_wait(fusd_file, &reply, transaction);
 
   /* return immediately in case of error */
   if (retval < 0 || reply == NULL)
@@ -1178,6 +1264,76 @@
   return -EPIPE;
 }
 
+STATIC int fusd_add_transaction(fusd_file_t *fusd_file, int transid, int subcmd, int size, struct fusd_transaction** out_transaction)
+{
+	struct fusd_transaction* transaction = (struct fusd_transaction*) KMALLOC(sizeof(struct fusd_transaction), GFP_KERNEL);
+	if(transaction == NULL)
+		return -ENOMEM;
+	
+	transaction->msg_in = NULL;
+	transaction->transid = transid;
+	transaction->subcmd = subcmd;
+	transaction->pid = current->pid;
+	transaction->size = size;
+	
+	down(&fusd_file->transactions_sem);
+	list_add_tail(&transaction->list, &fusd_file->transactions);
+	up(&fusd_file->transactions_sem);
+	
+	if(out_transaction != NULL)
+		*out_transaction = transaction;
+	
+	return 0;
+}
+
+STATIC void fusd_cleanup_transaction(fusd_file_t *fusd_file, struct fusd_transaction* transaction)
+{
+  free_fusd_msg(&transaction->msg_in);
+  fusd_remove_transaction(fusd_file, transaction);
+}
+
+STATIC void fusd_remove_transaction(fusd_file_t *fusd_file, struct fusd_transaction* transaction)
+{
+	down(&fusd_file->transactions_sem);
+	list_del(&transaction->list);
+	up(&fusd_file->transactions_sem);
+	
+	KFREE(transaction);
+}
+
+STATIC struct fusd_transaction* fusd_find_transaction(fusd_file_t *fusd_file, int transid)
+{
+	down(&fusd_file->transactions_sem);
+	struct list_head* i;
+	list_for_each(i, &fusd_file->transactions)
+	{
+		struct fusd_transaction* transaction = list_entry(i, struct fusd_transaction, list);
+		if(transaction->transid == transid)
+		{
+			up(&fusd_file->transactions_sem);
+			return transaction;
+		}
+	}
+	up(&fusd_file->transactions_sem);
+	return NULL;
+}
+
+STATIC struct fusd_transaction* fusd_find_transaction_by_pid(fusd_file_t *fusd_file, int pid)
+{
+	down(&fusd_file->transactions_sem);
+	struct list_head* i;
+	list_for_each(i, &fusd_file->transactions)
+	{
+		struct fusd_transaction* transaction = list_entry(i, struct fusd_transaction, list);
+		if(transaction->pid == pid)
+		{
+			up(&fusd_file->transactions_sem);
+			return transaction;
+		}
+	}
+	up(&fusd_file->transactions_sem);
+	return NULL;
+}
 
 STATIC ssize_t fusd_client_write(struct file *file,
     const char *buffer,
@@ -1189,48 +1345,58 @@
   fusd_msg_t fusd_msg;
   fusd_msg_t *reply = NULL;
   int retval = -EPIPE;
-
+  struct fusd_transaction* transaction;
+  
   GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
   LOCK_FUSD_FILE(fusd_file);
 
   RDEBUG(3, "got a write on /dev/%s (owned by pid %d) from pid %d",
 	 NAME(fusd_dev), fusd_dev->pid, current->pid);
 
-  if (fusd_restart_check(fusd_file, FUSD_WRITE) == ERESTARTSYS)
-    goto restarted_syscall;
+  transaction = fusd_find_incomplete_transaction(fusd_file, FUSD_WRITE);
+  if (transaction && transaction->size == length)
+  {
+    RDEBUG(2, "Incomplete I/O transaction %ld thrown out, as the transaction's size of %d bytes was not equal to "
+              "the retry's size of %d bytes", transaction->transid, transaction->size, length);
 
-  if (length < 0) {
-    RDEBUG(2, "fusd_client_write: got invalid length %d", length);
-    retval = -EINVAL;
-    goto done;
+    fusd_cleanup_transaction(fusd_file, transaction);
+    transaction = NULL;
   }
-
-  if (length > MAX_RW_SIZE)
-    length = MAX_RW_SIZE;
-
-  init_fusd_msg(&fusd_msg);
-
-  /* sigh.. i guess zero length writes should be legal */
-  if (length > 0) {
-    if ((fusd_msg.data = VMALLOC(length)) == NULL) {
-      retval = -ENOMEM;
-      goto done;
-    }
-
-    if (copy_from_user(fusd_msg.data, buffer, length)) {
-      retval = -EFAULT;
+  if(transaction == NULL)
+  {
+    if (length < 0) {
+      RDEBUG(2, "fusd_client_write: got invalid length %d", length);
+      retval = -EINVAL;
       goto done;
     }
-    fusd_msg.datalen = length;
-  }
   
-  fusd_msg.subcmd = FUSD_WRITE;
-  fusd_msg.parm.fops_msg.length = length;
+    if (length > MAX_RW_SIZE)
+      length = MAX_RW_SIZE;
   
-  if ((retval = fusd_fops_call_send(fusd_file, &fusd_msg)) < 0)
-    goto done;
- restarted_syscall:
-  retval = fusd_fops_call_wait(fusd_file, &reply);
+    init_fusd_msg(&fusd_msg);
+  
+    /* sigh.. i guess zero length writes should be legal */
+    if (length > 0) {
+      if ((fusd_msg.data = VMALLOC(length)) == NULL) {
+        retval = -ENOMEM;
+        goto done;
+      }
+  
+      if (copy_from_user(fusd_msg.data, buffer, length)) {
+        retval = -EFAULT;
+        goto done;
+      }
+      fusd_msg.datalen = length;
+    }
+    
+    fusd_msg.subcmd = FUSD_WRITE;
+    fusd_msg.parm.fops_msg.length = length;
+    
+    if ((retval = fusd_fops_call_send(fusd_file, &fusd_msg, &transaction)) < 0)
+      goto done;
+  }
+	/* todo: fix transid on restart */
+  retval = fusd_fops_call_wait(fusd_file, &reply, transaction);
 
   if (retval < 0 || reply == NULL)
     goto done;
@@ -1270,7 +1436,8 @@
   fusd_file_t *fusd_file;
   fusd_msg_t fusd_msg, *reply = NULL;
   int retval = -EPIPE, dir, length;
-
+  struct fusd_transaction* transaction;
+  
   GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
   LOCK_FUSD_FILE(fusd_file);
 
@@ -1280,45 +1447,48 @@
   dir = _IOC_DIR(cmd);
   length = _IOC_SIZE(cmd);
 
-  if (fusd_restart_check(fusd_file, FUSD_IOCTL) == ERESTARTSYS)
-    goto restarted_syscall;
+  transaction = fusd_find_incomplete_transaction(fusd_file, FUSD_IOCTL);
+  // todo: Check to make sure the transaction is for the same IOCTL
 
-  /* if we're trying to read or write, make sure length is sane */
-  if ((dir & (_IOC_WRITE | _IOC_READ)) &&
-      (length <= 0 || length > MAX_RW_SIZE))
-    {
-      RDEBUG(2, "client ioctl got crazy IOC_SIZE of %d", length);
-      retval = -EINVAL;
-      goto done;
-    }
-
-  /* fill the struct */
-  init_fusd_msg(&fusd_msg);
-  fusd_msg.subcmd = FUSD_IOCTL;
-  fusd_msg.parm.fops_msg.cmd = cmd;
-  fusd_msg.parm.fops_msg.arg = arg;
-
-  /* get the data if user is trying to write to the driver */
-  if (dir & _IOC_WRITE) {
-    if ((fusd_msg.data = VMALLOC(length)) == NULL) {
-      RDEBUG(2, "can't vmalloc for client ioctl!");
-      retval = -ENOMEM;
-      goto done;
+  if(transaction == NULL)
+  {
+    /* if we're trying to read or write, make sure length is sane */
+    if ((dir & (_IOC_WRITE | _IOC_READ)) &&
+        (length <= 0 || length > MAX_RW_SIZE))
+      {
+        RDEBUG(2, "client ioctl got crazy IOC_SIZE of %d", length);
+        retval = -EINVAL;
+        goto done;
+      }
+  
+    /* fill the struct */
+    init_fusd_msg(&fusd_msg);
+    fusd_msg.subcmd = FUSD_IOCTL;
+    fusd_msg.parm.fops_msg.cmd = cmd;
+    fusd_msg.parm.fops_msg.arg = arg;
+  
+    /* get the data if user is trying to write to the driver */
+    if (dir & _IOC_WRITE) {
+      if ((fusd_msg.data = VMALLOC(length)) == NULL) {
+        RDEBUG(2, "can't vmalloc for client ioctl!");
+        retval = -ENOMEM;
+        goto done;
+      }
+  
+      if (copy_from_user(fusd_msg.data, (void *) arg, length)) {
+        retval = -EFAULT;
+        goto done;
+      }
+      fusd_msg.datalen = length;
     }
-
-    if (copy_from_user(fusd_msg.data, (void *) arg, length)) {
-      retval = -EFAULT;
+  
+    /* send request to the driver */
+    if ((retval = fusd_fops_call_send(fusd_file, &fusd_msg, &transaction)) < 0)
       goto done;
-    }
-    fusd_msg.datalen = length;
   }
-
-  /* send request to the driver */
-  if ((retval = fusd_fops_call_send(fusd_file, &fusd_msg)) < 0)
-    goto done;
- restarted_syscall:
   /* get the response */
-  if ((retval = fusd_fops_call_wait(fusd_file, &reply)) < 0 || reply == NULL)
+	/* todo: fix transid on restart */
+  if ((retval = fusd_fops_call_wait(fusd_file, &reply, transaction)) < 0 || reply == NULL)
     goto done;
 
   /* if user is trying to read from the driver, copy data back */
@@ -1347,6 +1517,139 @@
 	 current->pid);
   return -EPIPE;
 }
+static void fusd_client_mm_open(struct vm_area_struct * vma);
+static void fusd_client_mm_close(struct vm_area_struct * vma);
+static struct page* fusd_client_nopage(struct vm_area_struct* vma, unsigned long address, int* type);
+static struct vm_operations_struct fusd_remap_vm_ops =
+{
+  open: fusd_client_mm_open,
+  close: fusd_client_mm_close,
+  nopage: fusd_client_nopage,
+};
+
+struct fusd_mmap_instance
+{
+  fusd_dev_t* fusd_dev;
+  fusd_file_t* fusd_file;
+  unsigned long addr;
+  int size;
+  atomic_t refcount;
+};
+
+static void fusd_client_mm_open(struct vm_area_struct * vma)
+{
+  struct fusd_mmap_instance* mmap_instance = (struct fusd_mmap_instance*) vma->vm_private_data;
+  atomic_inc(&mmap_instance->refcount);
+  
+}
+
+static void fusd_client_mm_close(struct vm_area_struct * vma)
+{
+  struct fusd_mmap_instance* mmap_instance = (struct fusd_mmap_instance*) vma->vm_private_data;
+  if(atomic_dec_and_test(&mmap_instance->refcount))
+  {
+    KFREE(mmap_instance);
+  }
+}
+
+static int fusd_client_mmap(struct file *file, struct vm_area_struct * vma)
+{
+  fusd_dev_t *fusd_dev;
+  fusd_file_t *fusd_file;
+  struct fusd_transaction* transaction;
+  fusd_msg_t fusd_msg, *reply = NULL;
+  int retval = -EPIPE;
+
+  GET_FUSD_FILE_AND_DEV(file->private_data, fusd_file, fusd_dev);
+  LOCK_FUSD_FILE(fusd_file);
+
+  RDEBUG(3, "got a mmap on /dev/%s (owned by pid %d) from pid %d",
+	 NAME(fusd_dev), fusd_dev->pid, current->pid);
+
+  transaction = fusd_find_incomplete_transaction(fusd_file, FUSD_MMAP);
+
+  if(transaction == NULL)
+  {
+    /* send the message */
+    init_fusd_msg(&fusd_msg);
+    fusd_msg.subcmd = FUSD_MMAP;
+    fusd_msg.parm.fops_msg.offset = vma->vm_pgoff << PAGE_SHIFT;
+    fusd_msg.parm.fops_msg.flags = vma->vm_flags;
+    fusd_msg.parm.fops_msg.length = vma->vm_end - vma->vm_start;
+    
+    /* send message to userspace */
+    if ((retval = fusd_fops_call_send(fusd_file, &fusd_msg, &transaction)) < 0)
+      goto done;
+  }
+  
+  /* and wait for the reply */
+  /* todo: store and retrieve the transid from the interrupted messsage */
+  retval = fusd_fops_call_wait(fusd_file, &reply, transaction);
+  
+  struct fusd_mmap_instance* mmap_instance = 
+    (struct fusd_mmap_instance*) KMALLOC(sizeof(struct fusd_mmap_instance), GFP_KERNEL);
+  // todo: free this thing at some point
+  
+  mmap_instance->fusd_dev = fusd_dev;
+  mmap_instance->fusd_file = fusd_file;
+  mmap_instance->addr = reply->parm.fops_msg.arg;
+  mmap_instance->size = reply->parm.fops_msg.length;
+  atomic_set(&mmap_instance->refcount, 0);
+  
+  retval = reply->parm.fops_msg.retval;
+  
+  vma->vm_private_data = mmap_instance;
+  vma->vm_ops = &fusd_remap_vm_ops;
+  vma->vm_flags |= VM_RESERVED;
+  
+  fusd_client_mm_open(vma);
+  
+ done:
+  free_fusd_msg(&reply);
+  UNLOCK_FUSD_FILE(fusd_file);
+  return retval;
+
+ invalid_file:
+ invalid_dev:
+  RDEBUG(3, "got a mmap on client file from pid %d, driver has disappeared",
+	 current->pid);
+  return -EPIPE;
+}
+
+static struct page* fusd_client_nopage(struct vm_area_struct* vma, unsigned long address,
+                                int* type)
+{
+  struct fusd_mmap_instance* mmap_instance = (struct fusd_mmap_instance*) vma->vm_private_data;
+  unsigned long offset;
+  struct page *page = NOPAGE_SIGBUS;
+  int result;
+  offset = (address - vma->vm_start) + (vma->vm_pgoff << PAGE_SHIFT);
+  // todo: worry about size
+  if(offset > mmap_instance->size)
+    goto out;
+  
+  down_read(&mmap_instance->fusd_dev->task->mm->mmap_sem);
+  result = get_user_pages(mmap_instance->fusd_dev->task, mmap_instance->fusd_dev->task->mm, mmap_instance->addr + offset, 1, 1, 0, &page, NULL);
+  up_read(&mmap_instance->fusd_dev->task->mm->mmap_sem);
+  
+  
+  if(PageAnon(page))
+  {
+    RDEBUG(2, "Cannot mmap anonymous pages. Be sure to allocate your shared buffer with MAP_SHARED | MAP_ANONYMOUS");
+    return NOPAGE_SIGBUS;
+  }
+  
+  if(result > 0)
+  {
+    get_page(page);
+    if (type)
+      *type = VM_FAULT_MINOR;
+  }
+out:
+  return page;
+
+
+}
 
 
 /*
@@ -1425,7 +1728,7 @@
     fusd_msg.cmd = FUSD_FOPS_NONBLOCK;
     fusd_msg.subcmd = FUSD_POLL_DIFF;
     fusd_msg.parm.fops_msg.cmd = fusd_file->cached_poll_state;
-    if (fusd_fops_call_send(fusd_file, &fusd_msg) < 0) {
+    if (fusd_fops_call_send(fusd_file, &fusd_msg, NULL) < 0) {
       /* If poll dispatched failed, set back to -1 so we try again.
        * Not a race (I think), since sending an *extra* polldiff never
        * hurts anything. */
@@ -1454,6 +1757,7 @@
   write:    fusd_client_write,
   ioctl:    fusd_client_ioctl,
   poll:     fusd_client_poll,
+  mmap:     fusd_client_mmap
 };
 
 
@@ -1502,23 +1806,30 @@
   }
 
   /* make sure this is not an old reply going to an old instance that's gone */
+	/* todo: kor fix this */
+/*
   if (fusd_file->fusd_dev_version != fusd_dev->version ||
       msg->parm.fops_msg.transid != fusd_file->transid_outstanding) {
     RDEBUG(2, "fusd_fops_reply: got an old message, discarding");
     goto discard;
-  }
-
-  if (fusd_file->msg_in != NULL) {
-    RDEBUG(1, "fusd_fops_reply: incoming message already exists!!");
-    goto discard;
-  }
-
+  }*/
+  
+  struct fusd_transaction *transaction = fusd_find_transaction(fusd_file, msg->parm.fops_msg.transid);
+	if(transaction == NULL)
+	{
+		RDEBUG(2, "fusd_fops_reply: No transaction found with transid %ld", msg->parm.fops_msg.transid);
+		goto discard;
+	}
+	
   RDEBUG(10, "fusd_fops_reply: /dev/%s completed transid %ld (retval %d)",
 	 NAME(fusd_dev), msg->parm.fops_msg.transid,
 	 msg->parm.fops_msg.retval);
 
-  fusd_file->msg_in = msg;
-  WAKE_UP_INTERRUPTIBLE(&fusd_file->file_wait);
+  transaction->msg_in = msg;
+	mb();
+
+  WAKE_UP_INTERRUPTIBLE_SYNC(&fusd_file->file_wait);
+
   return 0;
 
  discard:
@@ -1559,12 +1870,12 @@
   return 0;
 }
 
-
 STATIC int fusd_register_device(fusd_dev_t *fusd_dev,
 				register_msg_t register_msg)
 {
   int error = 0;
   struct list_head *tmp;
+  int dev_id;
 
   /* make sure args are valid */
   if (fusd_dev == NULL) {
@@ -1573,8 +1884,8 @@
   }
 
   /* user can only register one device per instance */
-  if (fusd_dev->handle != 0)
-    return -EBUSY;
+//  if (fusd_dev->handle != 0)
+//    return -EBUSY;
 
   register_msg.name[FUSD_MAX_NAME_LENGTH] = '\0';
 
@@ -1599,20 +1910,94 @@
      RDEBUG(1, "yikes!  kernel can't allocate memory");
      return -ENOMEM;
   }
+	
   strcpy(fusd_dev->name, register_msg.name);
 
-  /* try to register the requested device */
-  fusd_dev->handle = devfs_register(NULL, register_msg.name,
-				    DEVFS_FL_AUTO_DEVNUM,
-				    0, 0,
-				    S_IFCHR | register_msg.mode,
-				    &fusd_client_fops,
-				    fusd_dev);
-  /* make sure the registration was successful */
+  /* allocate memory for the class name, and copy */
+  if ((fusd_dev->class_name = KMALLOC(strlen(register_msg.clazz)+1, GFP_KERNEL)) == NULL) {
+     RDEBUG(1, "yikes!  kernel can't allocate memory");
+     return -ENOMEM;
+  }
+	
+	strcpy(fusd_dev->class_name, register_msg.clazz);
+	
+  /* allocate memory for the class name, and copy */
+  if ((fusd_dev->dev_name = KMALLOC(strlen(register_msg.devname)+1, GFP_KERNEL)) == NULL) {
+     RDEBUG(1, "yikes!  kernel can't allocate memory");
+     return -ENOMEM;
+  }
+	
+	strcpy(fusd_dev->dev_name, register_msg.devname);
+
+	dev_id = 0;
+
+	if((error = alloc_chrdev_region(&dev_id, 0, 1, fusd_dev->name)) < 0)
+	{
+		printk("alloc_chrdev_region failed status: %d\n", error);
+		goto register_failed;
+	}
+
+	fusd_dev->dev_id = dev_id;
+
+	#ifdef CONFIG_DEVFS_FS
+	if((error = devfs_mk_cdev(dev_id, S_IFCHR | register_msg.mode, fusd_dev->name)) < 0)
+	{
+		printk("devfs_mk_cdev failed status: %d\n", error);
+		goto register_failed2;
+	}
+	#endif
+
+	fusd_dev->handle = cdev_alloc();
+	if(fusd_dev->handle == NULL)
+	{
+		error = -ENOMEM;
+		goto register_failed3;
+	}
+
+	fusd_dev->handle->owner = THIS_MODULE;
+	fusd_dev->handle->ops = &fusd_client_fops;
+
+	kobject_set_name(&fusd_dev->handle->kobj, fusd_dev->name);
+
+	if((error = cdev_add(fusd_dev->handle, dev_id, 1)) < 0)
+	{
+		printk("cdev_add failed status: %d\n", error);
+		kobject_put(&fusd_dev->handle->kobj);
+		goto register_failed3;
+	}
+
+	// Hack to add my class to the sound class
+	if(strcmp("sound", register_msg.clazz) == 0)
+	{
+		fusd_dev->clazz = sound_class;
+		fusd_dev->owns_class = 0;
+	}
+	else
+	{
+		fusd_dev->clazz = class_create(THIS_MODULE, fusd_dev->class_name);
+		if(IS_ERR(fusd_dev->clazz))
+		{
+			error = PTR_ERR(fusd_dev->clazz);
+			goto register_failed4;
+		}
+		fusd_dev->owns_class = 1;
+	}
+	
+	fusd_dev->class_device = class_device_create(fusd_dev->clazz, fusd_dev->dev_id, NULL, fusd_dev->dev_name);
+	if(fusd_dev->class_device == NULL)
+	{
+		error = PTR_ERR(fusd_dev->class_device);
+		printk("class_device_create failed status: %d\n", error);
+		goto register_failed5;
+	}
+	
+	/* make sure the registration was successful */
+  /*
   if (fusd_dev->handle == 0) {
     error = -EIO;
     goto register_failed;
   }
+  */
 
   /* remember the user's private data so we can pass it back later */
   fusd_dev->private_data = register_msg.device_info;
@@ -1624,7 +2009,17 @@
   wake_up_interruptible(&new_device_wait);
   return 0;
 
- register_failed:
+register_failed5:
+	class_destroy(fusd_dev->clazz);
+register_failed4:
+	cdev_del(fusd_dev->handle);
+register_failed3:
+#ifdef CONFIG_DEVFS_FS
+	devfs_remove(fusd_dev->name);
+#endif
+register_failed2:
+	unregister_chrdev_region(dev_id, 1);
+register_failed:
   KFREE(fusd_dev->name);
   fusd_dev->name = NULL;
   return error;
@@ -1643,7 +2038,7 @@
   fusd_file_t **file_array = NULL;
 
   /* keep the module from being unloaded during initialization! */
-  MOD_INC_USE_COUNT;
+  //MOD_INC_USE_COUNT;
 
   /* allocate memory for the device state */
   if ((fusd_dev = KMALLOC(sizeof(fusd_dev_t), GFP_KERNEL)) == NULL)
@@ -1657,6 +2052,7 @@
   init_MUTEX(&fusd_dev->dev_sem);
   fusd_dev->magic = FUSD_DEV_MAGIC;
   fusd_dev->pid = current->pid;
+  fusd_dev->task = current;
   file->private_data = fusd_dev;
 
   /* add to the list of valid devices */
@@ -1671,7 +2067,7 @@
   KFREE(fusd_dev);
  dev_malloc_failed:
   RDEBUG(1, "out of memory in fusd_open!");
-  MOD_DEC_USE_COUNT;
+  //MOD_DEC_USE_COUNT;
   return -ENOMEM;
 }
 
@@ -1704,14 +2100,19 @@
   }
 #endif
 
-  if (fusd_dev->handle) {
-    RDEBUG(3, "unregistering /dev/%s from pid %d", NAME(fusd_dev),
-	   fusd_dev->pid);
-    devfs_unregister(fusd_dev->handle);
-    fusd_dev->handle = 0;
-  } else {
-    RDEBUG(2, "pid %d releasing without a registered device!", current->pid);
-  }
+	if(fusd_dev->handle)
+	{
+		class_device_destroy(fusd_dev->clazz, fusd_dev->dev_id);
+		if(fusd_dev->owns_class)
+		{
+			class_destroy(fusd_dev->clazz);
+		}
+		cdev_del(fusd_dev->handle);
+#ifdef CONFIG_DEVFS_FS
+  	devfs_remove(fusd_dev->name);
+#endif
+		unregister_chrdev_region(fusd_dev->dev_id, 1);
+	}
 
   /* mark the driver as being gone */
   zombify_dev(fusd_dev);
@@ -1808,11 +2209,13 @@
   }
 
   /* before device registration, the only command allowed is 'register'. */
+  /*
   if (!fusd_dev->handle && msg->cmd != FUSD_REGISTER_DEVICE) {
     RDEBUG(2, "got a message other than 'register' on a new device!");
     retval = -EINVAL;
     goto out;
   }
+  */
 
   /* now dispatch the command to the appropriate handler */
   switch (msg->cmd) {
@@ -2118,7 +2521,7 @@
   int error = 0;
   fusd_statcontext_t *fs;
 
-  MOD_INC_USE_COUNT;
+  //MOD_INC_USE_COUNT;
 
   if ((fs = KMALLOC(sizeof(fusd_statcontext_t), GFP_KERNEL)) == NULL) {
     RDEBUG(1, "yikes!  kernel can't allocate memory");
@@ -2131,8 +2534,8 @@
   file->private_data = (void *) fs;
 
  out:
-  if (error)
-    MOD_DEC_USE_COUNT;
+  //if (error)
+  //  MOD_DEC_USE_COUNT;
   return error;
 }
 
@@ -2147,7 +2550,7 @@
     KFREE(fs);
   }
 
-  MOD_DEC_USE_COUNT;
+  //MOD_DEC_USE_COUNT;
   return 0;
 }
 
@@ -2243,9 +2646,9 @@
   }
 
   len += snprintf(buf + len, buf_size - len,
-		  "\nFUSD $Revision: 1.97 $ - %d devices used by %d clients\n",
+		  "\nFUSD $Revision: 1.97-kor-hacked-8 $ - %d devices used by %d clients\n",
 		  total_files, total_clients);
-  
+
  out:
   fs->last_version_seen = last_version;
   up(&fusd_devlist_sem);
@@ -2383,15 +2786,16 @@
 
 STATIC int init_fusd(void)
 {
-#ifdef CONFIG_FUSD_MEMDEBUG
-  int retval;
+	int retval;
 
+#ifdef CONFIG_FUSD_MEMDEBUG
   if ((retval = fusd_mem_init()) < 0)
     return retval;
 #endif
 
+
   printk(KERN_INFO
-	 "fusd: starting, $Revision: 1.97 $, $Date: 2003/07/11 22:29:39 $");
+	 "fusd: starting, $Revision: 1.97-kor-hacked-8 $, $Date: 2003/07/11 22:29:39 $");
 #ifdef CVSTAG
   printk(", release %s", CVSTAG);
 #endif
@@ -2401,40 +2805,148 @@
   printk(", debugging messages disabled\n");
 #endif
 
-  /* register the control channel with devfs */
-  fusd_handle =
-    devfs_register(NULL, FUSD_CONTROL_FILENAME,
-		   DEVFS_FL_AUTO_DEVNUM, 0, 0,
-		   S_IFCHR | 0666, &fusd_fops, NULL);
-
-  if (fusd_handle == NULL) {
-    printk("fusd: unable to register fusd control device!\n");
-    return -EIO;
-  }
-
-
-  /* register the status device with devfs */
-  fusd_status_handle =
-    devfs_register(NULL, FUSD_STATUS_FILENAME,
-		   DEVFS_FL_AUTO_DEVNUM, 0, 0,
-		   S_IFCHR | 0666, &fusd_status_fops, (void *) 0);
+	fusd_control_device = NULL;
+	fusd_status_device = NULL;
+	
+	fusd_class = class_create(THIS_MODULE, "fusd");
+	if(IS_ERR(fusd_class))
+	{
+		retval = PTR_ERR(fusd_class);
+		printk("class_create failed status: %d\n", retval);
+		goto fail0;
+	}
+	
+	control_id = 0;
+
+	if((retval = alloc_chrdev_region(&control_id, 0, 1, FUSD_CONTROL_FILENAME)) < 0)
+	{
+		printk("alloc_chrdev_region failed status: %d\n", retval);
+		goto fail1;
+	}
+#ifdef CONFIG_DEVFS_FS
+	if((retval = devfs_mk_cdev(control_id, S_IFCHR | 0666, FUSD_CONTROL_FILENAME)) < 0)
+	{
+		printk("devfs_mk_cdev failed status: %d\n", retval);
+		goto fail2;
+	}
+#endif
 
-  if (fusd_status_handle == NULL)
-    printk("fusd: warning: unable to register status device\n");
+	fusd_control_device = cdev_alloc();
+	if(fusd_control_device == NULL)
+	{
+		retval = -ENOMEM;
+		goto fail3;
+	}
+
+	fusd_control_device->owner = THIS_MODULE;
+	fusd_control_device->ops = &fusd_fops;
+	kobject_set_name(&fusd_control_device->kobj, FUSD_CONTROL_FILENAME);
+
+	printk("cdev control id: %d\n", control_id);
+	if((retval = cdev_add(fusd_control_device, control_id, 1)) < 0)
+	{
+		printk("cdev_add failed status: %d\n", retval);
+		kobject_put(&fusd_control_device->kobj);
+		goto fail4;
+	}
+	
+	fusd_control_class_device = class_device_create(fusd_class, control_id, NULL, "control");
+	if(fusd_control_class_device == NULL)
+	{
+		retval = PTR_ERR(fusd_control_class_device);
+		printk("class_device_create failed status: %d\n", retval);
+		goto fail5;
+	}
+
+	status_id = 0;
+
+	if((retval = alloc_chrdev_region(&status_id, 0, 1, FUSD_STATUS_FILENAME)) < 0)
+	{
+		printk("alloc_chrdev_region failed status: %d\n", retval);
+		goto fail6;
+	}
+#ifdef CONFIG_DEVFS_FS
+	if((retval = devfs_mk_cdev(status_id, S_IFCHR | 0666, FUSD_STATUS_FILENAME)) < 0)
+	{
+		printk("devfs_mk_cdev failed status: %d\n", retval);
+		goto fail7;
+	}
+#endif
 
+	fusd_status_device = cdev_alloc();
+	if(fusd_status_device == NULL)
+	{
+		retval = -ENOMEM;
+		goto fail8;
+	}
+
+	fusd_status_device->owner = THIS_MODULE;
+	fusd_status_device->ops = &fusd_status_fops;
+	kobject_set_name(&fusd_status_device->kobj, FUSD_STATUS_FILENAME);
+
+	if((retval = cdev_add(fusd_status_device, status_id, 1)) < 0)
+	{
+		printk("cdev_add failed status: %d\n", retval);
+		kobject_put(&fusd_status_device->kobj);
+		goto fail9;
+	}
+	
+	fusd_status_class_device = class_device_create(fusd_class, status_id, NULL, "status");
+	if(fusd_status_class_device == NULL)
+	{
+		printk("class_device_create failed status: %d\n", retval);
+		retval = PTR_ERR(fusd_status_class_device);
+		goto fail10;
+	}
+	
   RDEBUG(1, "registration successful");
   return 0;
+
+fail10:
+	cdev_del(fusd_status_device);
+fail9:
+	kfree(fusd_status_device);
+fail8:
+#ifdef CONFIG_DEVFS_FS
+	devfs_remove(FUSD_STATUS_FILENAME);
+#endif
+fail7:
+	unregister_chrdev_region(status_id, 1);
+fail6:
+	class_device_destroy(fusd_class, control_id);
+fail5:
+	cdev_del(fusd_control_device);
+fail4:
+	kfree(fusd_control_device);
+fail3:
+#ifdef CONFIG_DEVFS_FS
+	devfs_remove(FUSD_CONTROL_FILENAME);
+#endif
+fail2:
+	unregister_chrdev_region(control_id, 1);
+
+fail1:
+	class_destroy(fusd_class);
+fail0:
+	return retval;
 }
 
 STATIC void cleanup_fusd(void)
 {
   RDEBUG(1, "cleaning up");
 
-  devfs_unregister(fusd_handle);
+	class_device_destroy(fusd_class, status_id);
+	class_device_destroy(fusd_class, control_id);
+	
+	cdev_del(fusd_control_device);
+	cdev_del(fusd_status_device);
+
+  devfs_remove(FUSD_CONTROL_FILENAME);
+  devfs_remove(FUSD_STATUS_FILENAME);
 
-  if (fusd_status_handle)
-    devfs_unregister(fusd_status_handle);
 
+	class_destroy(fusd_class);
+	
 #ifdef CONFIG_FUSD_MEMDEBUG
   fusd_mem_cleanup();
 #endif
Only in fusd-1.10/kfusd: kfusd.c~
Only in fusd-kor-1.10-10/kfusd: .kfusd.ko.cmd
Only in fusd-kor-1.10-10/kfusd: .kfusd.mod.o.cmd
Only in fusd-kor-1.10-10/kfusd: .kfusd.o.cmd
Only in fusd-kor-1.10-10/kfusd: Makefile
Only in fusd-kor-1.10-10/kfusd: .tmp_versions
diff -uar -x .svn fusd-1.10/libfusd/libfusd.c fusd-kor-1.10-10/libfusd/libfusd.c
--- fusd-1.10/libfusd/libfusd.c	2003-07-11 16:29:39.000000000 -0600
+++ fusd-kor-1.10-10/libfusd/libfusd.c	2005-06-16 22:07:31.000000000 -0600
@@ -101,7 +101,6 @@
 
   if (fusd_init_needed) {
     int i;
-    struct stat statbuf;
 
     fusd_init_needed = 0;
 
@@ -109,19 +108,12 @@
       FUSD_SET_FOPS(i, &null_fops);
     FD_ZERO(&fusd_fds);
 
-    /* test to see if devfs is actually mounted where we think it is */
-    if (stat(DEFAULT_DEV_ROOT ".devfsd", &statbuf) < 0) {
-      fprintf(stderr, "libfusd: devfs doesn't seem mounted under %s!\n",
-	      DEFAULT_DEV_ROOT);
-      dev_root = NULL;
-    } else {
-      dev_root = DEFAULT_DEV_ROOT;
-    }
+    dev_root = DEFAULT_DEV_ROOT;
   }
 }
 
 
-int fusd_register(const char *name, mode_t mode, void *device_info,
+int fusd_register(const char *name, const char* clazz, const char* devname, mode_t mode, void *device_info,
 		  struct fusd_file_operations *fops)
 {
   int fd = -1, retval = 0;
@@ -181,6 +173,8 @@
   message.cmd = FUSD_REGISTER_DEVICE;
   message.datalen = 0;
   strcpy(message.parm.register_msg.name, name);
+	strcpy(message.parm.register_msg.clazz, clazz);
+	strcpy(message.parm.register_msg.devname, devname);
   message.parm.register_msg.mode = mode;
   message.parm.register_msg.device_info = device_info;
 
@@ -443,6 +437,13 @@
       user_retval = fops->write(file, msg->data, msg->datalen,
 				&msg->parm.fops_msg.offset);
     break;
+  case FUSD_MMAP:
+    if (fops && fops->mmap)
+    {
+      user_retval = fops->mmap(file, msg->parm.fops_msg.offset, msg->parm.fops_msg.length, msg->parm.fops_msg.flags,
+                               (void**) &msg->parm.fops_msg.arg, &msg->parm.fops_msg.length);
+    }
+    break;
   case FUSD_IOCTL:
     if (fops && fops->ioctl) {
       /* in the case of an ioctl read, allocate a buffer for the
diff -uar -x .svn fusd-1.10/Makefile fusd-kor-1.10-10/Makefile
--- fusd-1.10/Makefile	2001-09-29 13:23:26.000000000 -0600
+++ fusd-kor-1.10-10/Makefile	2005-06-17 00:16:22.000000000 -0600
@@ -4,14 +4,14 @@
 #
 
 # Change this to reflect where your kernel sources are
-KERNEL_HOME := /usr/src/linux
+KERNEL_HOME := /lib/modules/$(shell uname -r)/build
 
 ##################################################################
 
 
 TARGETS := \
 	libfusd.a \
-	kfusd.o \
+	kfusd.ko \
 	regdevice \
 	opentest \
 	simpleopen \
@@ -46,9 +46,11 @@
 
 ####################################################
 
+KDIR	:= /lib/modules/$(shell uname -r)/build
 
-$(OBJDIR)/kfusd.o: $(MODPATH)/kfusd/kfusd.c fusd_msg.h kfusd.h
-	$(CC) $(KCFLAGS) -c $(MODPATH)/kfusd/kfusd.c -o $(OBJDIR)/kfusd.o
+$(OBJDIR)/kfusd.ko: $(MODPATH)/kfusd/kfusd.c fusd_msg.h kfusd.h
+	$(MAKE) -C $(MODPATH)/kfusd
+#	$(CC) $(KCFLAGS) -c $(MODPATH)/kfusd/kfusd.c -o $(OBJDIR)/kfusd.o
 
 $(OBJDIR)/libfusd.a: $(OBJDIR)/libfusd.o
 	$(AR) -cr $(OBJDIR)/libfusd.a $(OBJDIR)/libfusd.o
@@ -64,3 +66,4 @@
 install:
 	cp $(OBJDIR)/libfusd.a /usr/local/lib
 	cp include/*.h /usr/local/include
+	$(MAKE) -C $(MODPATH)/kfusd install
diff -uar -x .svn fusd-1.10/make.include fusd-kor-1.10-10/make.include
--- fusd-1.10/make.include	2001-09-29 13:27:16.000000000 -0600
+++ fusd-kor-1.10-10/make.include	2005-06-17 00:16:25.000000000 -0600
@@ -72,7 +72,7 @@
 KERNEL_INCLUDE := $(KERNEL_HOME)/include
 BINSTRIP := strip
 
-KCFLAGS += -I$(KERNEL_INCLUDE) $(INCLUDEPATH)
+KCFLAGS += $(INCLUDEPATH)
 CFLAGS += $(INCLUDEPATH) $(LIBPATH)
 
 CCFLAGS += $(CFLAGS)
Only in fusd-kor-1.10-10: obj.i686-linux
diff -uar -x .svn fusd-1.10/test/ioctl.c fusd-kor-1.10-10/test/ioctl.c
--- fusd-1.10/test/ioctl.c	2003-07-11 16:29:39.000000000 -0600
+++ fusd-kor-1.10-10/test/ioctl.c	2005-02-09 19:39:06.000000000 -0700
@@ -195,7 +195,7 @@
     /* ioctl server */
     struct fusd_file_operations f = { open: zeroreturn, close: zeroreturn,
 				      ioctl: do_ioctl};
-    if (fusd_register("ioctltest", 0666, NULL, &f) < 0)
+    if (fusd_register("ioctltest", "misc", "ioctltest", 0666, NULL, &f) < 0)
       perror("registering ioctltest");
     printf("server starting\n");
     fusd_run();
diff -uar -x .svn fusd-1.10/test/opentest.c fusd-kor-1.10-10/test/opentest.c
--- fusd-1.10/test/opentest.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/opentest.c	2005-02-09 19:39:06.000000000 -0700
@@ -98,7 +98,7 @@
   int f;
 
   if (argc != 2) {
-    fprintf(stderr, "usage: %s <device-to-create>\n", argv[0]);
+    fprintf(stderr, "usage: %s <devfs path> <device class> <device name> \n", argv[0]);
     exit(0);
   }
 
@@ -124,7 +124,7 @@
       };
 
     int fd;
-    if ((fd = fusd_register(argv[1], 0666, 0, &fops)) < 0) {
+    if ((fd = fusd_register(argv[1], argv[2], argv[3], 0666, 0, &fops)) < 0) {
       perror("Register failed");
     } 
     
diff -uar -x .svn fusd-1.10/test/oracle.c fusd-kor-1.10-10/test/oracle.c
--- fusd-1.10/test/oracle.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/oracle.c	2005-02-09 19:39:06.000000000 -0700
@@ -116,7 +116,7 @@
   struct fusd_file_operations f = { open: do_open, close: do_close,
 				    read: do_read, write: do_write };
 
-  if (fusd_register("oracle", 0666, NULL, &f) < 0)
+  if (fusd_register("oracle", "misc", "oracle", 0666, NULL, &f) < 0)
     perror("/dev/oracle");
   else {
     printf("oracle ready to answer queries\n");
diff -uar -x .svn fusd-1.10/test/regdevice.c fusd-kor-1.10-10/test/regdevice.c
--- fusd-1.10/test/regdevice.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/regdevice.c	2005-02-09 19:39:06.000000000 -0700
@@ -37,12 +37,12 @@
 
 int main(int argc, char *argv[])
 {
-  if (argc != 2) {
-    fprintf(stderr, "usage: %s <device-to-create>\n", argv[0]);
+  if (argc != 4) {
+    fprintf(stderr, "usage: %s <devfs path> <device class> <device name> \n", argv[0]);
     exit(0);
   }
 
-  if (fusd_register(argv[1], 0666, 0, NULL) < 0) {
+  if (fusd_register(argv[1], argv[2], argv[3], 0666, 0, NULL) < 0) {
     perror("Register failed");
   } else {
     printf("Registered %s - sleeping 10 seconds\n", argv[1]);
diff -uar -x .svn fusd-1.10/test/rwtest.c fusd-kor-1.10-10/test/rwtest.c
--- fusd-1.10/test/rwtest.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/rwtest.c	2005-02-09 19:39:06.000000000 -0700
@@ -99,8 +99,8 @@
 {
   int f;
 
-  if (argc != 2) {
-    fprintf(stderr, "usage: %s <device-to-create>\n", argv[0]);
+  if (argc != 4) {
+    fprintf(stderr, "usage: %s <device-to-create> <class> <devicename>\n", argv[0]);
     exit(0);
   }
 
@@ -123,7 +123,7 @@
 	      NULL,
 	      NULL};
     
-    if (fusd_register(argv[1], 0666, 0, &fops) < 0) {
+    if (fusd_register(argv[1], argv[2], argv[3], 0666, 0, &fops) < 0) {
       perror("Register failed");
     } else {
       fusd_run();
diff -uar -x .svn fusd-1.10/test/select_test.c fusd-kor-1.10-10/test/select_test.c
--- fusd-1.10/test/select_test.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/select_test.c	2005-02-09 19:39:06.000000000 -0700
@@ -180,19 +180,19 @@
 
 int main(int argc, char *argv[])
 {
-  if (argc != 3) {
-    fprintf(stderr, "usage: %s <file-to-read-using-select> <client|server>\n",
+  if (argc != 5) {
+    fprintf(stderr, "usage: %s <file-to-read-using-select> <dev-class> <dev-name> <client|server>\n",
 	    argv[0]);
     exit(1);
   }
 
-  if (!strcmp(argv[2], "server")) {
+  if (!strcmp(argv[4], "server")) {
     /* server */
     struct fusd_file_operations f = { open: zeroreturn, close: zeroreturn,
 				      read: do_read, write: do_write,
 				      poll_diff: do_poll_diff};
     printf("server starting\n");
-    if (fusd_register(argv[1], 0666, NULL, &f) < 0)
+    if (fusd_register(argv[1], argv[2], argv[3], 0666, NULL, &f) < 0)
       perror(argv[1]);
     else
       fusd_run();
diff -uar -x .svn fusd-1.10/test/simpleopen.c fusd-kor-1.10-10/test/simpleopen.c
--- fusd-1.10/test/simpleopen.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/simpleopen.c	2005-02-09 19:39:06.000000000 -0700
@@ -92,7 +92,7 @@
   struct fusd_file_operations f = { open: do_open, close: do_close,
 				    read: do_read, write: do_write };
 
-  fd = fusd_register("/dev/open", 0666, NULL, &f);
+  fd = fusd_register("/dev/open", "misc", "open", 0666, NULL, &f);
 
   if (fd < 0) {
     perror("trying to register /dev/open");
diff -uar -x .svn fusd-1.10/test/statetest.c fusd-kor-1.10-10/test/statetest.c
--- fusd-1.10/test/statetest.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/statetest.c	2005-02-09 19:39:06.000000000 -0700
@@ -90,12 +90,15 @@
     struct fusd_file_operations f = { open: do_close, close: do_close,
 				      read: do_read };
     char *buf;
+    char *devname;
     int i;
     
     for (i = 0; i < n; i++) {
       buf = malloc(100);
+      devname = malloc(100);
       sprintf(buf, "/dev/fusd-test/state%03d", i);
-      if (fusd_register(buf, 0666, buf+strlen("/dev/fusd-test/state"), &f) < 0)
+      sprintf(devname, "state%03d", i);
+      if (fusd_register(buf, "fusd-test", devname, 0666, buf+strlen("/dev/fusd-test/state"), &f) < 0)
 	perror(buf);
     }
     printf("server starting\n");
diff -uar -x .svn fusd-1.10/test/torturetest.c fusd-kor-1.10-10/test/torturetest.c
--- fusd-1.10/test/torturetest.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/torturetest.c	2005-02-09 19:39:06.000000000 -0700
@@ -80,6 +80,8 @@
   int num;
   int retval;
   char **devs;
+  char **classes;
+  char **devnames;
   pid_t *pids;
 
   // init function table
@@ -100,6 +102,8 @@
   num = atoi(argv[1]);
 
   devs = (char**)malloc(sizeof(char *)*num);
+  classes = (char**)malloc(sizeof(char *)*num);
+  devnames = (char**)malloc(sizeof(char *)*num);
   pids = (pid_t *)malloc(sizeof(pid_t)*num);
 
 
@@ -108,6 +112,10 @@
     char dev[30];
     sprintf(dev,"/dev/fusd-test/test%d",i);
     devs[i] = strdup(dev);
+    sprintf(dev,"fusd-test");
+    classes[i] = strdup(dev);
+    sprintf(dev,"test%d",i);
+    devnames[i] = strdup(dev);
   }
 
   /* create devices; 2 devices handled per process */
@@ -116,7 +124,7 @@
 
     if (fork2 == 0) {
 
-      if (fusd_register(devs[i], 0666, 0, &fops) < 0) {
+      if (fusd_register(devs[i], classes[i], devnames[i], 0666, 0, &fops) < 0) {
 	perror("Register failed");
 	exit(1);
       } else {
@@ -126,7 +134,7 @@
       i++;
 
       if (i < num) {
-	if (fusd_register(devs[i], 0666, 0, &fops) < 0) {
+	if (fusd_register(devs[i], classes[i], devnames[i], 0666, 0, &fops) < 0) {
 	  perror("Register failed");
 	  exit(1);
 	} else {
diff -uar -x .svn fusd-1.10/test/zero-fusd.c fusd-kor-1.10-10/test/zero-fusd.c
--- fusd-1.10/test/zero-fusd.c	2003-07-11 16:29:40.000000000 -0600
+++ fusd-kor-1.10-10/test/zero-fusd.c	2005-02-09 19:39:06.000000000 -0700
@@ -54,7 +54,7 @@
   struct fusd_file_operations f = { open: return_zero, close: return_zero,
 				    read: do_read };
 
-  fd = fusd_register("zero-fusd", 0666, NULL, &f);
+  fd = fusd_register("zero-fusd", "misc", "zero-fusd", 0666, NULL, &f);
 
   if (fd < 0) {
     perror("trying to register /dev/zero-fusd");
