]> Zhao Yanbai Git Server - minix.git/commitdiff
PFS: use libchardriver; clean up 70/970/2
authorDavid van Moolenbroek <david@minix3.org>
Tue, 3 Sep 2013 00:00:20 +0000 (02:00 +0200)
committerLionel Sambuc <lionel@minix3.org>
Sat, 1 Mar 2014 08:04:51 +0000 (09:04 +0100)
- simplify and repair UDS request handling state machine;
- simplify interface used between internal modules;
- implement missing support for nonblocking I/O;
- fix select implementation;
- clean up global variables.

Change-Id: Ia82c5c6f05cc3f0a498efc9a26de14b1cde6eace

12 files changed:
servers/pfs/Makefile
servers/pfs/dev_uds.c
servers/pfs/glo.h
servers/pfs/inode.c
servers/pfs/main.c
servers/pfs/open.c
servers/pfs/proto.h
servers/pfs/read.c
servers/pfs/table.c
servers/pfs/uds.c
servers/pfs/uds.h
servers/pfs/utility.c

index f4b0cb699b528bd54354f632febe9427405ed50b..ef3d013e95d517527386d27e3d7b088f41de60be 100644 (file)
@@ -4,8 +4,8 @@ SRCS=   open.c table.c inode.c main.c super.c link.c \
        buffer.c read.c misc.c mount.c utility.c stadir.c \
        uds.c dev_uds.c
 
-DPADD+=        ${LIBSYS}
-LDADD+=        -lsys
+DPADD+=        ${LIBCHARDRIVER} ${LIBSYS}
+LDADD+=        -lchardriver -lsys
 
 LDADD+= -lc
 
index a12f8ac32e2becf2eefec8f6b43c968a46e3c9eb..0caba400cb8274178561959a60cdbd746941a251 100644 (file)
@@ -4,18 +4,11 @@
  *
  * The entry points into this file are...
  *
- *   uds_open:   handles the   open(2) syscall on /dev/uds
- *   uds_close:  handles the  close(2) syscall on /dev/uds
- *   uds_select: handles the select(2) syscall on /dev/uds
- *   uds_read:   handles the   read(2) syscall on /dev/uds
- *   uds_write:  handles the  write(2) syscall on /dev/uds
- *   uds_ioctl:  handles the  ioctl(2) syscall on /dev/uds
- *   uds_status: handles status requests.
- *   uds_cancel: handles cancelled syscalls.
+ *   uds_request: process a character device request
  *
  * Also See...
  *
- *   table.c, uds.c, uds.h
+ *   uds.c, uds.h
  *
  * Overview
  *
 #include "glo.h"
 #include "uds.h"
 
-static int uds_perform_read(int minor, endpoint_t m_source, size_t
-       size, int pretend);
-static int uds_perform_write(int minor, endpoint_t m_source, size_t
-       size, int pretend);
+static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int pretend);
+static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int pretend);
+
+static int uds_open(devminor_t orig_minor, int access, endpoint_t user_endpt);
+static int uds_close(devminor_t minor);
+static ssize_t uds_read(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static ssize_t uds_write(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id);
+static int uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+       cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id);
+static int uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id);
+static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt);
+
+static struct chardriver uds_tab = {
+       .cdr_open       = uds_open,
+       .cdr_close      = uds_close,
+       .cdr_read       = uds_read,
+       .cdr_write      = uds_write,
+       .cdr_ioctl      = uds_ioctl,
+       .cdr_cancel     = uds_cancel,
+       .cdr_select     = uds_select
+};
+
+void uds_request(message *m_ptr, int ipc_status)
+{
+       /* Use libchardriver to process character device requests. */
+       chardriver_process(&uds_tab, m_ptr, ipc_status);
+}
 
-int uds_open(message *dev_m_in, message *dev_m_out)
+static int uds_open(devminor_t UNUSED(orig_minor), int access,
+       endpoint_t user_endpt)
 {
        message fs_m_in, fs_m_out;
        struct uucred ucred;
+       devminor_t minor;
        int rc, i;
-       int minor;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] uds_open() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
-       printf("Endpoint: 0x%x\n", dev_m_in->USER_ENDPT);
+       printf("(uds) [-] uds_open() call_count=%d\n", ++call_count);
+       printf("Endpoint: 0x%x\n", user_endpt);
 #endif
 
        /*
@@ -68,13 +88,8 @@ int uds_open(message *dev_m_in, message *dev_m_out)
                }
        }
 
-       if (minor == -1) {
-
-               /* descriptor table full */
-               uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
-                             (cp_grant_id_t) dev_m_in->IO_GRANT, ENFILE);
+       if (minor == -1)
                return ENFILE;
-       }
 
        /*
         * We found a slot in uds_fd_table, now initialize the descriptor
@@ -85,21 +100,12 @@ int uds_open(message *dev_m_in, message *dev_m_out)
         */
        uds_fd_table[minor].state = UDS_INUSE;
 
-       /* track the system call we are performing in case it gets cancelled */
-       uds_fd_table[minor].call_nr = dev_m_in->m_type;
-       uds_fd_table[minor].ioctl = 0;
-       uds_fd_table[minor].syscall_done = 0;
-
        /* set the socket owner */
-       uds_fd_table[minor].owner = dev_m_in->USER_ENDPT;
-       uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
+       uds_fd_table[minor].owner = user_endpt;
 
        /* setup select(2) framework */
-       uds_fd_table[minor].selecting = 0;
-       uds_fd_table[minor].select_proc = 0;
-       uds_fd_table[minor].sel_ops_in = 0;
-       uds_fd_table[minor].sel_ops_out = 0;
-       uds_fd_table[minor].status_updated = 0;
+       uds_fd_table[minor].sel_endpt = NONE;
+       uds_fd_table[minor].sel_ops = 0;
 
        /* initialize the data pointer (pos) to the start of the PIPE */
        uds_fd_table[minor].pos = 0;
@@ -151,26 +157,15 @@ int uds_open(message *dev_m_in, message *dev_m_out)
        /* Initially the socket isn't suspended. */
        uds_fd_table[minor].suspended = UDS_NOT_SUSPENDED;
 
-       /* and the socket doesn't have an I/O grant initially */
-       uds_fd_table[minor].io_gr = GRANT_INVALID;
-
-       /* since there is no I/O grant it effectively has no size either */
-       uds_fd_table[minor].io_gr_size = 0;
-
-       /* The process isn't suspended so we don't flag it as revivable */
-       uds_fd_table[minor].ready_to_revive = 0;
-
        /* get the effective user id and effective group id from the endpoint */
        /* this is needed in the REQ_NEWNODE request to PFS. */
-       rc = getnucred(uds_fd_table[minor].endpoint, &ucred);
+       rc = getnucred(user_endpt, &ucred);
        if (rc == -1) {
                /* roll back the changes we made to the descriptor */
                memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));
 
                /* likely error: invalid endpoint / proc doesn't exist */
-               uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
-                             (cp_grant_id_t) dev_m_in->IO_GRANT, errno);
-               return errno;
+               return EIO;
        }
 
        /* Prepare Request to the FS side of PFS */
@@ -189,52 +184,34 @@ int uds_open(message *dev_m_in, message *dev_m_out)
                memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));
 
                /* likely error: get_block() failed */
-               uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
-                               (cp_grant_id_t) dev_m_in->IO_GRANT, rc);
                return rc;
        }
 
        /* Process the response */
-
        uds_fd_table[minor].inode_nr = fs_m_out.RES_INODE_NR;
 
-       /* prepare the reply */
-
-       uds_fd_table[minor].syscall_done = 1;
-       uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
-                     (cp_grant_id_t) dev_m_in->IO_GRANT, minor);
-       return minor;
+       return minor;   /* cloned! */
 }
 
-int uds_close(message *dev_m_in, message *dev_m_out)
+static int uds_close(devminor_t minor)
 {
-       int minor;
        message fs_m_in, fs_m_out;
        int rc;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] uds_close() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
-       printf("Endpoint: 0x%x\n", dev_m_in->USER_ENDPT);
+       printf("(uds) [%d] uds_close() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
+       if (minor < 0 || minor >= NR_FDS) return ENXIO;
 
        if (uds_fd_table[minor].state != UDS_INUSE) {
                /* attempted to close a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, DEV_CLOSE_REPL, dev_m_in->USER_ENDPT,
-                             (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
                return EINVAL;
        }
 
-       /* no need to track the syscall in case of cancellation. close() is
-        * atomic and can't be cancelled. no need to update the endpoint here,
-        * we won't be needing it to kill the socket
-        */
-
        /* if the socket is connected, disconnect it */
        if (uds_fd_table[minor].peer != -1) {
                int peer = uds_fd_table[minor].peer;
@@ -246,14 +223,12 @@ int uds_close(message *dev_m_in, message *dev_m_out)
                uds_fd_table[peer].err = ECONNRESET;
 
                /* if peer was blocked on I/O revive peer */
-               if (uds_fd_table[peer].suspended) {
-                       uds_fd_table[peer].ready_to_revive = 1;
-                       uds_unsuspend(dev_m_in->m_source, peer);
-               }
+               if (uds_fd_table[peer].suspended != UDS_NOT_SUSPENDED)
+                       uds_unsuspend(peer);
        }
 
        if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
-               clear_fds(minor, &(uds_fd_table[minor].ancillary_data));
+               uds_clear_fds(minor, &uds_fd_table[minor].ancillary_data);
        }
 
        /* Prepare Request to the FS side of PFS */
@@ -269,90 +244,84 @@ int uds_close(message *dev_m_in, message *dev_m_out)
 
        rc = fs_putnode(&fs_m_in, &fs_m_out);
        if (rc != OK) {
-               perror("fs_putnode");
-               /* likely error: get_block() failed */
+               printf("PFS: fs_putnode returned %d\n", rc);
+
                return rc;
        }
 
-       uds_set_reply(dev_m_out, DEV_CLOSE_REPL, dev_m_in->USER_ENDPT,
-                     (cp_grant_id_t) dev_m_in->IO_GRANT, OK);
        return OK;
 }
 
-int uds_select(message *dev_m_in, message *dev_m_out)
+static int uds_select(devminor_t minor, unsigned int ops, endpoint_t endpt)
 {
-       int i, bytes;
-       int minor;
+       unsigned int ready_ops;
+       int i, bytes, watch;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] uds_select() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
-       printf("Endpoint: 0x%x\n", dev_m_in->USER_ENDPT);
+       printf("(uds) [%d] uds_select() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
+       if (minor < 0 || minor >= NR_FDS) return ENXIO;
 
        if (uds_fd_table[minor].state != UDS_INUSE) {
-
-               /* attempted to close a socket that hasn't been opened --
+               /* attempted to select on a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-
-               uds_sel_reply(dev_m_out, DEV_SEL_REPL1, minor, EINVAL);
                return EINVAL;
        }
 
-       /* setup select(2) framework */
-       uds_fd_table[minor].selecting = 1;
-       uds_fd_table[minor].select_proc = dev_m_in->m_source;
-
-       /* track the system call we are performing in case it gets cancelled */
-       uds_fd_table[minor].call_nr = dev_m_in->m_type;
-       uds_fd_table[minor].ioctl = 0;
-       uds_fd_table[minor].syscall_done = 0;
-
-       /* Can't update the process endpoint here, no info.  */
+       watch = (ops & SEL_NOTIFY);
+       ops &= (SEL_RD | SEL_WR | SEL_ERR);
 
-       uds_fd_table[minor].sel_ops_in = dev_m_in->USER_ENDPT;
-       uds_fd_table[minor].sel_ops_out = 0;
+       ready_ops = 0;
 
        /* check if there is data available to read */
-       bytes = uds_perform_read(minor, dev_m_in->m_source, 1, 1);
-       if (bytes > 0) {
-
-               /* there is data in the pipe for us to read */
-               uds_fd_table[minor].sel_ops_out |= SEL_RD;
-
-       } else if (uds_fd_table[minor].listening == 1) {
-
-               /* check for pending connections */
-               for (i = 0; i < uds_fd_table[minor].backlog_size; i++) {
-                       if (uds_fd_table[minor].backlog[i] != -1) {
-                               uds_fd_table[minor].sel_ops_out |= SEL_RD;
-                               break;
+       if (ops & SEL_RD) {
+               bytes = uds_perform_read(minor, NONE, GRANT_INVALID, 1, 1);
+               if (bytes > 0) {
+                       /* there is data in the pipe for us to read */
+                       ready_ops |= SEL_RD;
+               } else if (uds_fd_table[minor].listening == 1) {
+                       /* check for pending connections */
+                       for (i = 0; i < uds_fd_table[minor].backlog_size; i++)
+                       {
+                               if (uds_fd_table[minor].backlog[i] != -1) {
+                                       ready_ops |= SEL_RD;
+                                       break;
+                               }
                        }
+               } else if (bytes != SUSPEND) {
+                       ready_ops |= SEL_RD;
                }
-       } else if (bytes != SUSPEND) {
-               uds_fd_table[minor].sel_ops_out |= SEL_RD;
        }
 
        /* check if we can write without blocking */
-       bytes = uds_perform_write(minor, dev_m_in->m_source, PIPE_BUF, 1);
-       if (bytes != 0 && bytes != SUSPEND) {
-               /* There is room to write or there is an error condition */
-               uds_fd_table[minor].sel_ops_out |= SEL_WR;
+       if (ops & SEL_WR) {
+               bytes = uds_perform_write(minor, NONE, GRANT_INVALID, PIPE_BUF,
+                       1);
+               if (bytes != 0 && bytes != SUSPEND) {
+                       /* There is room to write or there is an error
+                        * condition.
+                        */
+                       ready_ops |= SEL_WR;
+               }
        }
 
-       uds_fd_table[minor].syscall_done = 1;
-       uds_sel_reply(dev_m_out, DEV_SEL_REPL1, minor,
-                     uds_fd_table[minor].sel_ops_out);
+       /* If not all requested ops were ready, and the caller requests to be
+        * notified about changes, we add the remaining ops to the saved set.
+        */
+       ops &= ~ready_ops;
+       if (ops && watch) {
+               uds_fd_table[minor].sel_endpt = endpt;
+               uds_fd_table[minor].sel_ops |= ops;
+       }
 
-       return uds_fd_table[minor].sel_ops_out;
+       return ready_ops;
 }
 
-static int uds_perform_read(int minor, endpoint_t m_source,
-       size_t size, int pretend)
+static ssize_t uds_perform_read(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int pretend)
 {
        int rc, peer;
        message fs_m_in;
@@ -366,20 +335,18 @@ static int uds_perform_read(int minor, endpoint_t m_source,
 
        peer = uds_fd_table[minor].peer;
 
+       /* skip reads and writes of 0 (or less!) bytes */
        if (size <= 0) {
                return 0;
        }
 
        /* check if we are allowed to read */
        if (!(uds_fd_table[minor].mode & S_IRUSR)) {
-
                /* socket is shutdown for reading */
                return EPIPE;
        }
 
-       /* skip reads and writes of 0 (or less!) bytes */
        if (uds_fd_table[minor].size == 0) {
-
                if (peer == -1) {
                        /* We're not connected. That's only a problem when this
                         * socket is connection oriented. */
@@ -400,7 +367,6 @@ static int uds_perform_read(int minor, endpoint_t m_source,
                        return 0;
                }
 
-
                if (pretend) {
                        return SUSPEND;
                }
@@ -408,10 +374,9 @@ static int uds_perform_read(int minor, endpoint_t m_source,
                /* maybe a process is blocked waiting to write? if
                 * needed revive the writer
                 */
-               if (peer != -1 && uds_fd_table[peer].suspended) {
-                       uds_fd_table[peer].ready_to_revive = 1;
-                       uds_unsuspend(m_source, peer);
-               }
+               if (peer != -1 &&
+                       uds_fd_table[peer].suspended == UDS_SUSPENDED_WRITE)
+                       uds_unsuspend(peer);
 
 #if DEBUG == 1
                printf("(uds) [%d] suspending read request\n", minor);
@@ -419,21 +384,19 @@ static int uds_perform_read(int minor, endpoint_t m_source,
                /* Process is reading from an empty pipe,
                 * suspend it so some bytes can be written
                 */
-               uds_fd_table[minor].suspended = UDS_SUSPENDED_READ;
-               return SUSPEND;
+               return EDONTREPLY;
        }
 
        if (pretend) {
-
                return (size > uds_fd_table[minor].size) ?
                                uds_fd_table[minor].size : size;
        }
 
-
        /* Prepare Request to the FS side of PFS */
+       fs_m_in.m_source = endpt;
        fs_m_in.m_type = REQ_READ;
        fs_m_in.REQ_INODE_NR = uds_fd_table[minor].inode_nr;
-       fs_m_in.REQ_GRANT = uds_fd_table[minor].io_gr;
+       fs_m_in.REQ_GRANT = grant;
        fs_m_in.REQ_SEEK_POS_HI = 0;
        fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[minor].pos;
        fs_m_in.REQ_NBYTES = (size > uds_fd_table[minor].size) ?
@@ -442,7 +405,7 @@ static int uds_perform_read(int minor, endpoint_t m_source,
        /* perform the read */
        rc = fs_readwrite(&fs_m_in, &fs_m_out);
        if (rc != OK) {
-               perror("fs_readwrite");
+               printf("PFS: fs_readwrite returned %d\n", rc);
                return rc;
        }
 
@@ -469,35 +432,26 @@ static int uds_perform_read(int minor, endpoint_t m_source,
        /* maybe a big write was waiting for us to read some data, if
         * needed revive the writer
         */
-       if (peer != -1 && uds_fd_table[peer].suspended) {
-               uds_fd_table[peer].ready_to_revive = 1;
-               uds_unsuspend(m_source, peer);
-       }
+       if (peer != -1 && uds_fd_table[peer].suspended == UDS_SUSPENDED_WRITE)
+               uds_unsuspend(peer);
 
-       /* see if peer is blocked on select() and a write is possible
-        * (from peer to minor)
+       /* see if peer is blocked on select() and a write is possible (from
+        * peer to minor); if the peer wants to know about write being possible
+        * and it doesn't know about it already, then let the peer know.
         */
-       if (peer != -1 && uds_fd_table[peer].selecting == 1 &&
+       if (peer != -1 && (uds_fd_table[peer].sel_ops & SEL_WR) &&
            (uds_fd_table[minor].size+uds_fd_table[minor].pos + 1 < PIPE_BUF)){
-
-               /* if the peer wants to know about write being possible
-                * and it doesn't know about it already, then let the peer know.
-                */
-               if (peer != -1 && (uds_fd_table[peer].sel_ops_in & SEL_WR) &&
-                   !(uds_fd_table[peer].sel_ops_out & SEL_WR)) {
-
-                       /* a write on peer is possible now */
-                       uds_fd_table[peer].sel_ops_out |= SEL_WR;
-                       uds_fd_table[peer].status_updated = 1;
-                       uds_unsuspend(m_source, peer);
-               }
+               /* a write on peer is possible now */
+               chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
+                       SEL_WR);
+               uds_fd_table[peer].sel_ops &= ~SEL_WR;
        }
 
        return fs_m_out.RES_NBYTES; /* return number of bytes read */
 }
 
-static int uds_perform_write(int minor, endpoint_t m_source,
-                                               size_t size, int pretend)
+static ssize_t uds_perform_write(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int pretend)
 {
        int rc, peer, i;
        message fs_m_in;
@@ -516,20 +470,17 @@ static int uds_perform_write(int minor, endpoint_t m_source,
 
        /* check if we are allowed to write */
        if (!(uds_fd_table[minor].mode & S_IWUSR)) {
-
                /* socket is shutdown for writing */
                return EPIPE;
        }
 
        if (size > PIPE_BUF) {
-
                /* message is too big to ever write to the PIPE */
                return EMSGSIZE;
        }
 
        if (uds_fd_table[minor].type == SOCK_STREAM ||
                        uds_fd_table[minor].type == SOCK_SEQPACKET) {
-
                /* if we're writing with a connection oriented socket,
                 * then it needs a peer to write to
                 */
@@ -542,12 +493,9 @@ static int uds_perform_write(int minor, endpoint_t m_source,
                                return ENOTCONN;
                        }
                } else {
-
                        peer = uds_fd_table[minor].peer;
                }
-
        } else /* uds_fd_table[minor].type == SOCK_DGRAM */ {
-
                peer = -1;
 
                /* locate the "peer" we want to write to */
@@ -601,10 +549,8 @@ static int uds_perform_write(int minor, endpoint_t m_source,
                }
 
                /* if needed revive the reader */
-               if (uds_fd_table[peer].suspended) {
-                       uds_fd_table[peer].ready_to_revive = 1;
-                       uds_unsuspend(m_source, peer);
-               }
+               if (uds_fd_table[peer].suspended == UDS_SUSPENDED_READ)
+                       uds_unsuspend(peer);
 
 #if DEBUG == 1
        printf("(uds) [%d] suspending write request\n", minor);
@@ -613,8 +559,7 @@ static int uds_perform_write(int minor, endpoint_t m_source,
                /* Process is reading from an empty pipe,
                 * suspend it so some bytes can be written
                 */
-               uds_fd_table[minor].suspended = UDS_SUSPENDED_WRITE;
-               return SUSPEND;
+               return EDONTREPLY;
        }
 
        if (pretend) {
@@ -622,9 +567,10 @@ static int uds_perform_write(int minor, endpoint_t m_source,
        }
 
        /* Prepare Request to the FS side of PFS */
+       fs_m_in.m_source = endpt;
        fs_m_in.m_type = REQ_WRITE;
        fs_m_in.REQ_INODE_NR = uds_fd_table[peer].inode_nr;
-       fs_m_in.REQ_GRANT = uds_fd_table[minor].io_gr;
+       fs_m_in.REQ_GRANT = grant;
        fs_m_in.REQ_SEEK_POS_HI = 0;
        fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[peer].pos +
                                        uds_fd_table[peer].size;
@@ -633,7 +579,7 @@ static int uds_perform_write(int minor, endpoint_t m_source,
        /* Request the write */
        rc = fs_readwrite(&fs_m_in, &fs_m_out);
        if (rc != OK) {
-               perror("fs_readwrite");
+               printf("PFS: fs_readwrite returned %d\n", rc);
                return rc;
        }
 
@@ -644,7 +590,6 @@ static int uds_perform_write(int minor, endpoint_t m_source,
        /* increase the count of unread bytes */
        uds_fd_table[peer].size += fs_m_out.RES_NBYTES;
 
-
        /* fill in the source address to be returned by recvfrom & recvmsg */
        if (uds_fd_table[minor].type == SOCK_DGRAM) {
                memcpy(&uds_fd_table[peer].source, &uds_fd_table[minor].addr,
@@ -652,541 +597,269 @@ static int uds_perform_write(int minor, endpoint_t m_source,
        }
 
        /* revive peer that was waiting for us to write */
-       if (uds_fd_table[peer].suspended) {
-               uds_fd_table[peer].ready_to_revive = 1;
-               uds_unsuspend(m_source, peer);
-       }
-
-       /* see if peer is blocked on select()*/
-       if (uds_fd_table[peer].selecting == 1 && fs_m_out.RES_NBYTES > 0) {
-
-               /* if the peer wants to know about data ready to read
-                * and it doesn't know about it already, then let the peer
-                * know we have data for it.
-                */
-               if ((uds_fd_table[peer].sel_ops_in & SEL_RD) &&
-                               !(uds_fd_table[peer].sel_ops_out & SEL_RD)) {
+       if (uds_fd_table[peer].suspended == UDS_SUSPENDED_READ)
+               uds_unsuspend(peer);
 
-                       /* a read on peer is possible now */
-                       uds_fd_table[peer].sel_ops_out |= SEL_RD;
-                       uds_fd_table[peer].status_updated = 1;
-                       uds_unsuspend(m_source, peer);
-               }
+       /* see if peer is blocked on select(); if the peer wants to know about
+        * data ready to read and it doesn't know about it already, then let
+        * the peer know we have data for it.
+        */
+       if ((uds_fd_table[peer].sel_ops & SEL_RD) && fs_m_out.RES_NBYTES > 0) {
+               /* a read on peer is possible now */
+               chardriver_reply_select(uds_fd_table[peer].sel_endpt, peer,
+                       SEL_RD);
+               uds_fd_table[peer].sel_ops &= ~SEL_RD;
        }
 
        return fs_m_out.RES_NBYTES; /* return number of bytes written */
 }
 
-int uds_read(message *dev_m_in, message *dev_m_out)
+static ssize_t uds_read(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
 {
-       int bytes;
-       int minor;
+       ssize_t rc;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] uds_read() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
-       printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->USER_ENDPT,
-                                                       dev_m_in->POSITION);
+       printf("(uds) [%d] uds_read() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
+       if (minor < 0 || minor >= NR_FDS) return ENXIO;
 
        if (uds_fd_table[minor].state != UDS_INUSE) {
-
-               /* attempted to close a socket that hasn't been opened --
+               /* attempted to read from a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
-                             (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
-
                return EINVAL;
        }
 
-       /* track the system call we are performing in case it gets cancelled */
-       uds_fd_table[minor].call_nr = dev_m_in->m_type;
-       uds_fd_table[minor].ioctl = 0;
-       uds_fd_table[minor].syscall_done = 0;
+       rc = uds_perform_read(minor, endpt, grant, size, 0);
 
-       /* Update the process endpoint. */
-       uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
-
-       /* setup select(2) framework */
-       uds_fd_table[minor].selecting = 0;
-
-       /* save I/O Grant info */
-       uds_fd_table[minor].io_gr = (cp_grant_id_t) dev_m_in->IO_GRANT;
-       uds_fd_table[minor].io_gr_size = dev_m_in->COUNT;
+       /* If the call couldn't complete, suspend the caller. */
+       if (rc == EDONTREPLY) {
+               uds_fd_table[minor].suspended = UDS_SUSPENDED_READ;
+               uds_fd_table[minor].susp_endpt = endpt;
+               uds_fd_table[minor].susp_grant = grant;
+               uds_fd_table[minor].susp_size = size;
+               uds_fd_table[minor].susp_id = id;
 
-       bytes = uds_perform_read(minor, dev_m_in->m_source,
-                                       uds_fd_table[minor].io_gr_size, 0);
+               /* If the call wasn't supposed to block, cancel immediately. */
+               if (flags & FLG_OP_NONBLOCK) {
+                       uds_cancel(minor, endpt, id);
 
-       uds_set_reply(dev_m_out, DEV_REVIVE, uds_fd_table[minor].endpoint,
-                     uds_fd_table[minor].io_gr, bytes);
+                       rc = EAGAIN;
+               }
+       }
 
-       return bytes;
+       return rc;
 }
 
-int uds_write(message *dev_m_in, message *dev_m_out)
+static ssize_t uds_write(devminor_t minor, u64_t position, endpoint_t endpt,
+       cp_grant_id_t grant, size_t size, int flags, cdev_id_t id)
 {
-       int bytes;
-       int minor;
+       ssize_t rc;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] uds_write() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
-       printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->USER_ENDPT,
-                                                       dev_m_in->POSITION);
+       printf("(uds) [%d] uds_write() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
+       if (minor < 0 || minor >= NR_FDS) return ENXIO;
 
        if (uds_fd_table[minor].state != UDS_INUSE) {
-
                /* attempted to write to a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
-                             (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
-
                return EINVAL;
        }
 
-       /* track the system call we are performing in case it gets cancelled */
-       uds_fd_table[minor].call_nr = dev_m_in->m_type;
-       uds_fd_table[minor].ioctl = 0;
-       uds_fd_table[minor].syscall_done = 0;
-
-       /* Update the process endpoint. */
-       uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
-
-       /* setup select(2) framework */
-       uds_fd_table[minor].selecting = 0;
+       rc = uds_perform_write(minor, endpt, grant, size, 0);
 
-       /* save I/O Grant info */
-       uds_fd_table[minor].io_gr = (cp_grant_id_t) dev_m_in->IO_GRANT;
-       uds_fd_table[minor].io_gr_size = dev_m_in->COUNT;
+       /* If the call couldn't complete, suspend the caller. */
+       if (rc == EDONTREPLY) {
+               uds_fd_table[minor].suspended = UDS_SUSPENDED_WRITE;
+               uds_fd_table[minor].susp_endpt = endpt;
+               uds_fd_table[minor].susp_grant = grant;
+               uds_fd_table[minor].susp_size = size;
+               uds_fd_table[minor].susp_id = id;
 
-       bytes = uds_perform_write(minor, dev_m_in->m_source,
-                                       uds_fd_table[minor].io_gr_size, 0);
+               /* If the call wasn't supposed to block, cancel immediately. */
+               if (flags & FLG_OP_NONBLOCK) {
+                       uds_cancel(minor, endpt, id);
 
-       uds_set_reply(dev_m_out, DEV_REVIVE, uds_fd_table[minor].endpoint,
-                     uds_fd_table[minor].io_gr, bytes);
+                       rc = EAGAIN;
+               }
+       }
 
-       return bytes;
+       return rc;
 }
 
-int uds_ioctl(message *dev_m_in, message *dev_m_out)
+static int uds_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+       cp_grant_id_t grant, int flags, endpoint_t user_endpt, cdev_id_t id)
 {
-       int rc, minor;
+       int rc;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] uds_ioctl() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
-       printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->USER_ENDPT,
-                                                       dev_m_in->POSITION);
+       printf("(uds) [%d] uds_ioctl() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
+       if (minor < 0 || minor >= NR_FDS) return ENXIO;
 
        if (uds_fd_table[minor].state != UDS_INUSE) {
-
-               /* attempted to close a socket that hasn't been opened --
-                * something is very wrong :(
+               /* attempted to perform I/O control on a socket that hasn't
+                * been opened -- something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
-                             (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
-
                return EINVAL;
        }
 
-       /* track the system call we are performing in case it gets cancelled */
-       uds_fd_table[minor].call_nr = dev_m_in->m_type;
-       uds_fd_table[minor].ioctl = dev_m_in->COUNT;
-       uds_fd_table[minor].syscall_done = 0;
-
-       /* setup select(2) framework */
-       uds_fd_table[minor].selecting = 0;
-
-       /* update the owner endpoint - yes it's really stored in POSITION */
-       uds_fd_table[minor].owner = dev_m_in->POSITION;
-
-       /* update the process endpoint, which may well be different */
-       uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
-
-       /* save I/O Grant info */
-       uds_fd_table[minor].io_gr = (cp_grant_id_t) dev_m_in->IO_GRANT;
-       uds_fd_table[minor].io_gr_size = 0; /* should not be used here */
-
-       switch (dev_m_in->COUNT) {      /* Handle the ioctl(2) command */
-
-               case NWIOSUDSCONN:
-
-                       /* connect to a listening socket -- connect() */
-                       rc = do_connect(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSACCEPT:
-
-                       /* accept an incoming connection -- accept() */
-                       rc = do_accept(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSBLOG:
-
-                       /* set the backlog_size and put the socket into the
-                        * listening state -- listen()
-                        */
-                       rc = do_listen(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSTYPE:
-
-                       /* set the type for this socket (i.e.
-                        * SOCK_STREAM, SOCK_DGRAM, etc) -- socket()
-                        */
-                       rc = do_socket(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSADDR:
-
-                       /* set the address for this socket -- bind() */
-                       rc = do_bind(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSADDR:
-
-                       /* get the address for this socket -- getsockname() */
-                       rc = do_getsockname(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSPADDR:
-
-                       /* get the address for the peer -- getpeername() */
-                       rc = do_getpeername(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSSHUT:
-
-                       /* shutdown a socket for reading, writing, or
-                        * both -- shutdown()
-                        */
-                       rc = do_shutdown(dev_m_in, dev_m_out);
+       /* update the owner endpoint */
+       uds_fd_table[minor].owner = user_endpt;
 
-                       break;
-
-               case NWIOSUDSPAIR:
-
-                       /* connect two sockets -- socketpair() */
-                       rc = do_socketpair(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSSOTYPE:
+       /* let the UDS subsystem handle the actual request */
+       rc = uds_do_ioctl(minor, request, endpt, grant);
 
-                       /* get socket type -- getsockopt(SO_TYPE) */
-                       rc = do_getsockopt_sotype(dev_m_in, dev_m_out);
-
-                       break;
+       /* If the call couldn't complete, suspend the caller. */
+       if (rc == EDONTREPLY) {
+               /* The suspension type is already set by the IOCTL handler. */
+               if (uds_fd_table[minor].suspended == UDS_NOT_SUSPENDED)
+                       panic("IOCTL did not actually suspend?");
+               uds_fd_table[minor].susp_endpt = endpt;
+               uds_fd_table[minor].susp_grant = grant;
+               uds_fd_table[minor].susp_size = 0; /* irrelevant */
+               uds_fd_table[minor].susp_id = id;
 
-               case NWIOGUDSPEERCRED:
-
-                       /* get peer endpoint -- getsockopt(SO_PEERCRED) */
-                       rc = do_getsockopt_peercred(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSTADDR:
-
-                       /* set target address -- sendto() */
-                       rc = do_sendto(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSFADDR:
-
-                       /* get from address -- recvfrom() */
-                       rc = do_recvfrom(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSSNDBUF:
-
-                       /* get the send buffer size -- getsockopt(SO_SNDBUF) */
-                       rc = do_getsockopt_sndbuf(dev_m_in, dev_m_out);
-
-                       break;
+               /* If the call wasn't supposed to block, cancel immediately. */
+               if (flags & FLG_OP_NONBLOCK) {
+                       uds_cancel(minor, endpt, id);
 
-               case NWIOSUDSSNDBUF:
-
-                       /* set the send buffer size -- setsockopt(SO_SNDBUF) */
-                       rc = do_setsockopt_sndbuf(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSRCVBUF:
-
-                       /* get the send buffer size -- getsockopt(SO_SNDBUF) */
-                       rc = do_getsockopt_rcvbuf(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSRCVBUF:
-
-                       /* set the send buffer size -- setsockopt(SO_SNDBUF) */
-                       rc = do_setsockopt_rcvbuf(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSCTRL:
-
-                       /* set the control data -- sendmsg() */
-                       rc = do_sendmsg(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSCTRL:
-
-                       /* set the control data -- recvmsg() */
-                       rc = do_recvmsg(dev_m_in, dev_m_out);
-
-                       break;
-
-               default:
-
-                       /* the IOCTL command is not valid for /dev/uds --
-                        * this happens a lot and is normal. a lot of
-                        * libc functions determine the socket type with
-                        * IOCTLs. Any not for us simply get a EBADIOCTL
-                        * response.
-                        */
-
-                       rc = EBADIOCTL;
+                       rc = EAGAIN;
+               }
        }
 
-       if (rc != SUSPEND)
-               uds_fd_table[minor].syscall_done = 1;
-
-       uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
-                     (cp_grant_id_t) dev_m_in->IO_GRANT, rc);
-
        return rc;
 }
 
-int uds_unsuspend(endpoint_t m_source, int minor)
+void uds_unsuspend(devminor_t minor)
 {
-       int r = OK, bytes;
-       message m_out;
+       int r;
        uds_fd_t *fdp;
 
        fdp = &uds_fd_table[minor];
 
-       if (fdp->status_updated == 1) {
-
-               /* clear the status_updated flag */
-               fdp->status_updated = 0;
-               fdp->selecting = 0;
+       switch (fdp->suspended) {
+       case UDS_SUSPENDED_READ:
+               r = uds_perform_read(minor, fdp->susp_endpt, fdp->susp_grant,
+                       fdp->susp_size, 0);
 
-               /* prepare the response */
-               uds_sel_reply(&m_out, DEV_SEL_REPL2, minor, fdp->sel_ops_out);
-       } else if (fdp->ready_to_revive == 1) {
+               if (r == EDONTREPLY)
+                       return;
 
-               /* clear the ready to revive flag */
-               fdp->ready_to_revive = 0;
+               break;
 
-               switch (fdp->suspended) {
+       case UDS_SUSPENDED_WRITE:
+               r = uds_perform_write(minor, fdp->susp_endpt, fdp->susp_grant,
+                       fdp->susp_size, 0);
 
-                       case UDS_SUSPENDED_READ:
+               if (r == EDONTREPLY)
+                       return;
 
-                               bytes = uds_perform_read(minor, m_source,
-                                                        fdp->io_gr_size, 0);
-
-                               if (bytes == SUSPEND) {
-                                       r = SUSPEND;
-                                       break;
-                               }
+               break;
 
-                               fdp->suspended = UDS_NOT_SUSPENDED;
-
-                               uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
-                                             fdp->io_gr, bytes);
-
-                               break;
-
-                       case UDS_SUSPENDED_WRITE:
-
-                               bytes = uds_perform_write(minor, m_source,
-                                                         fdp->io_gr_size, 0);
-
-                               if (bytes == SUSPEND) {
-                                       r = SUSPEND;
-                                       break;
-                               }
-
-                               fdp->suspended = UDS_NOT_SUSPENDED;
-
-                               uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
-                                             fdp->io_gr, bytes);
-
-                               break;
-
-                       case UDS_SUSPENDED_CONNECT:
-                       case UDS_SUSPENDED_ACCEPT:
-
-                               /* In both cases, the process
-                                * that send the notify()
-                                * already performed the connection.
-                                * The only thing to do here is
-                                * unblock.
-                                */
-
-                               fdp->suspended = UDS_NOT_SUSPENDED;
-
-                               uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
-                                             fdp->io_gr, OK);
-
-                               break;
+       case UDS_SUSPENDED_CONNECT:
+       case UDS_SUSPENDED_ACCEPT:
+               /* In both cases, the caller already set up the connection.
+                * The only thing to do here is unblock.
+                */
+               r = OK;
 
-                       default:
-                               return(OK);
-               }
+               break;
 
+       default:
+               panic("unknown suspension type %d", fdp->suspended);
        }
 
-       if (r == OK) reply(m_source, &m_out);
-       return(r);
+       chardriver_reply_task(fdp->susp_endpt, fdp->susp_id, r);
+
+       fdp->suspended = UDS_NOT_SUSPENDED;
 }
 
-int uds_cancel(message *dev_m_in, message *dev_m_out)
+static int uds_cancel(devminor_t minor, endpoint_t endpt, cdev_id_t id)
 {
+       uds_fd_t *fdp;
        int i, j;
-       int minor;
-       /* XXX: should become a noop? */
+
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] uds_cancel() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
-       printf("Endpoint: 0x%x\n", dev_m_in->USER_ENDPT);
+       printf("(uds) [%d] uds_cancel() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
+       if (minor < 0 || minor >= NR_FDS) return EDONTREPLY;
 
-       if (uds_fd_table[minor].state != UDS_INUSE) {
-               /* attempted to cancel an unknown request - this happens */
-               return SUSPEND;
-       }
+       fdp = &uds_fd_table[minor];
 
-       /* Update the process endpoint. */
-       uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
+       if (fdp->state != UDS_INUSE) {
+               printf("PFS: cancel request for closed minor %d\n", minor);
+               return EDONTREPLY;
+       }
 
-       /* setup select(2) framework */
-       uds_fd_table[minor].selecting = 0;
+       /* Make sure the cancel request is for a request we're hanging on. */
+       if (fdp->suspended == UDS_NOT_SUSPENDED || fdp->susp_endpt != endpt ||
+                       fdp->susp_id != id) {
+               return EDONTREPLY;      /* this happens. */
+       }
 
-       /* the system call was cancelled, so if the socket was suspended
-        * (which is likely the case), then it is not suspended anymore.
+       /* The system call was cancelled, so the socket is not suspended
+        * anymore.
         */
-       uds_fd_table[minor].suspended = UDS_NOT_SUSPENDED;
-
-       /* If there is a system call and it isn't complete, roll back */
-       if (uds_fd_table[minor].call_nr && !uds_fd_table[minor].syscall_done) {
-
-
-               if  (uds_fd_table[minor].call_nr == DEV_IOCTL_S) {
-
-                       switch (uds_fd_table[minor].ioctl) {
-
-                               case NWIOSUDSACCEPT:    /* accept() */
-
-                                       /* partial accept() only changes
-                                        * uds_fd_table[minorparent].child
-                                        */
-
-                                       for (i = 0; i < NR_FDS; i++) {
-                                               if (uds_fd_table[i].child ==
-                                                       minor) {
-
-                                               uds_fd_table[i].child = -1;
-
-                                               }
-                                       }
-
-                                       break;
-
-                               case NWIOSUDSCONN:      /* connect() */
+       switch (fdp->suspended) {
+       case UDS_SUSPENDED_ACCEPT:      /* accept() */
+               /* partial accept() only changes
+                * uds_fd_table[minorparent].child
+                */
+               for (i = 0; i < NR_FDS; i++) {
+                       if (uds_fd_table[i].child == minor) {
+                               uds_fd_table[i].child = -1;
+                       }
+               }
 
-                                       /* partial connect() sets addr
-                                        * and adds minor to server backlog
-                                        */
+               break;
 
-                                       for (i = 0; i < NR_FDS; i++) {
+       case UDS_SUSPENDED_CONNECT:     /* connect() */
+               /* partial connect() sets addr and adds minor to server backlog
+                */
 
-                                               /* find a socket that is in
-                                                * use.
-                                                */
-                                               if (uds_fd_table[i].state ==
-                                                       UDS_INUSE) {
+               for (i = 0; i < NR_FDS; i++) {
+                       /* find a socket that is in use. */
+                       if (uds_fd_table[i].state != UDS_INUSE)
+                               continue;
 
-                                                       /* see if minor is in
-                                                        * the backlog
-                                                        */
+                       /* see if minor is in the backlog */
                        for (j = 0; j < uds_fd_table[i].backlog_size; j++) {
-
                                if (uds_fd_table[i].backlog[j] == minor) {
 
                                        /* remove from backlog */
                                        uds_fd_table[i].backlog[j] = -1;
                                }
                        }
+               }
 
-                                               }
-                                       }
-
-                                       /* clear the address */
-                                       memset(&(uds_fd_table[minor].addr),
-                                               '\0',
-                                               sizeof(struct sockaddr_un));
-
-                                       break;
+               /* clear the address */
+               memset(&(uds_fd_table[minor].addr), '\0',
+                       sizeof(struct sockaddr_un));
 
-                               case NWIOSUDSTADDR:     /* sendto() */
-                               case NWIOSUDSADDR:      /* bind() */
-                               case NWIOGUDSADDR:      /* getsockname() */
-                               case NWIOGUDSPADDR:     /* getpeername() */
-                               case NWIOSUDSTYPE:      /* socket() */
-                               case NWIOSUDSBLOG:      /* listen() */
-                               case NWIOSUDSSHUT:      /* shutdown() */
-                               case NWIOSUDSPAIR:      /* socketpair() */
-                               case NWIOGUDSSOTYPE:    /* SO_TYPE */
-                               case NWIOGUDSPEERCRED:  /* SO_PEERCRED */
-                               default:
-                                       /* these are atomic, never suspend,
-                                        * and can't be cancelled once called
-                                        */
-                                       break;
-                       }
+               break;
 
-               }
-
-               /* DEV_READ_S or DEV_WRITE_S don't need to do anything
-                * when cancelled. DEV_OPEN, DEV_REOPEN, DEV_SELECT,
-                * DEV_CLOSE are atomic, never suspend, and can't
-                * be cancelled once called.
-                */
+       case UDS_SUSPENDED_READ:
+       case UDS_SUSPENDED_WRITE:
+               /* Nothing more to do. */
+               break;
 
-               uds_fd_table[minor].syscall_done = 1;
+       default:
+               panic("unknown suspension type %d", fdp->suspended);
        }
 
-       uds_set_reply(dev_m_out, DEV_REVIVE, dev_m_in->USER_ENDPT,
-                       (cp_grant_id_t) dev_m_in->IO_GRANT, EINTR);
+       fdp->suspended = UDS_NOT_SUSPENDED;
 
-       return EINTR;
+       return EINTR;   /* reply to the original request */
 }
index fd0db90756130b67a9a137a5b596b5f1074cc4fc..96ca9c42eab0090c43b47e6c9d863a3fbc9115d0 100644 (file)
 EXTERN int err_code;           /* temporary storage for error number */
 
 EXTERN int(*fs_call_vec[]) (message *fs_m_in, message *fs_m_out);
-EXTERN int(*dev_call_vec[]) (message *fs_m_in, message *fs_m_out);
 
-EXTERN uid_t caller_uid;
-EXTERN gid_t caller_gid;
-EXTERN int req_nr;
-EXTERN int SELF_E;
 EXTERN int exitsignaled;
 EXTERN int busy;
 EXTERN int unmountdone;
index 7045d118e711e9787588031d91034c9e347a359f..e81cad202217f27cd856ba1ef48845a15bf27945 100644 (file)
@@ -237,7 +237,7 @@ struct inode *rip;  /* pointer to inode to be released */
 /*===========================================================================*
  *                             alloc_inode                                  *
  *===========================================================================*/
-struct inode *alloc_inode(dev_t dev, pmode_t bits)
+struct inode *alloc_inode(dev_t dev, pmode_t bits, uid_t uid, gid_t gid)
 {
 /* Allocate a free inode on 'dev', and return a pointer to it. */
 
@@ -267,8 +267,8 @@ struct inode *alloc_inode(dev_t dev, pmode_t bits)
 
        rip->i_mode = bits;             /* set up RWX bits */
        rip->i_nlinks = NO_LINK;        /* initial no links */
-       rip->i_uid = caller_uid;        /* file's uid is owner's */
-       rip->i_gid = caller_gid;        /* ditto group id */
+       rip->i_uid = uid;               /* set file user id */
+       rip->i_gid = gid;               /* ditto group id */
 
        /* Fields not cleared already are cleared in wipe_inode().  They have
         * been put there because truncate() needs to clear the same fields if
index f88fe0cb247ed176616f5eeb02abb451678c28b1..72b987597b5f191c1906b8e27c8910404005004e 100644 (file)
@@ -12,7 +12,7 @@
 #include "inode.h"
 #include "uds.h"
 
-static void get_work(message *m_in);
+static void get_work(message *m_in, int *status);
 
 /* SEF functions and variables. */
 static void sef_local_startup(void);
@@ -28,20 +28,25 @@ int main(int argc, char *argv[])
  * three major activities: getting new work, processing the work, and
  * sending the reply. The loop never terminates, unless a panic occurs.
  */
-  int ind, do_reply, transid;
+  int ind, transid, req_nr, ipc_status;
   message pfs_m_in;
   message pfs_m_out;
+  endpoint_t src;
 
   /* SEF local startup. */
   env_setargs(argc, argv);
   sef_local_startup();
 
   while(!unmountdone || !exitsignaled) {
-       endpoint_t src;
-
-       do_reply = 1;
        /* Wait for request message. */
-       get_work(&pfs_m_in);
+       get_work(&pfs_m_in, &ipc_status);
+
+       /* If this is a UDS device request, process it and continue. */
+       if (IS_DEV_RQ(pfs_m_in.m_type)) {
+               uds_request(&pfs_m_in, ipc_status);
+
+               continue;
+       }
 
        transid = TRNS_GET_ID(pfs_m_in.m_type);
        pfs_m_in.m_type = TRNS_DEL_ID(pfs_m_in.m_type);
@@ -53,25 +58,9 @@ int main(int argc, char *argv[])
                assert(IS_VFS_FS_TRANSID(transid) || transid == 0);
 
        src = pfs_m_in.m_source;
-       caller_uid = INVAL_UID; /* To trap errors */
-       caller_gid = INVAL_GID;
        req_nr = pfs_m_in.m_type;
 
-       if (IS_DEV_RQ(req_nr)) {
-               ind = req_nr - DEV_RQ_BASE;
-               if (ind < 0 || ind >= DEV_CALL_VEC_SIZE) {
-                       printf("pfs: bad DEV request %d\n", req_nr);
-                       pfs_m_out.m_type = EINVAL;
-               } else {
-                       int result;
-                       result = (*dev_call_vec[ind])(&pfs_m_in, &pfs_m_out);
-                       if (pfs_m_out.REP_STATUS == SUSPEND ||
-                           result == SUSPEND) {
-                               /* Nothing to tell, so not replying */
-                               do_reply = 0;
-                       }
-               }
-       } else if (IS_VFS_RQ(req_nr)) {
+       if (IS_VFS_RQ(req_nr)) {
                ind = req_nr - VFS_BASE;
                if (ind < 0 || ind >= FS_CALL_VEC_SIZE) {
                        printf("pfs: bad FS request %d\n", req_nr);
@@ -85,13 +74,10 @@ int main(int argc, char *argv[])
                pfs_m_out.m_type = EINVAL;
        }
 
-       if (do_reply) {
-               if (IS_VFS_RQ(req_nr) && IS_VFS_FS_TRANSID(transid)) {
-                       pfs_m_out.m_type = TRNS_ADD_ID(pfs_m_out.m_type,
-                                                       transid);
-               }
-               reply(src, &pfs_m_out);
+       if (IS_VFS_RQ(req_nr) && IS_VFS_FS_TRANSID(transid)) {
+               pfs_m_out.m_type = TRNS_ADD_ID(pfs_m_out.m_type, transid);
        }
+       reply(src, &pfs_m_out);
   }
   return(OK);
 }
@@ -145,8 +131,6 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info)
        panic("unable to drop privileges");
   }
 
-  SELF_E = getprocnr();
-
   return(OK);
 }
 
@@ -165,15 +149,14 @@ static void sef_cb_signal_handler(int signo)
 /*===========================================================================*
  *                             get_work                                     *
  *===========================================================================*/
-static void get_work(m_in)
-message *m_in;                         /* pointer to message */
+static void get_work(message * m_in, int *status)
 {
-  int r, srcok = 0, status;
+  int r, srcok = 0;
   endpoint_t src;
 
   do {
        /* wait for a message */
-       if ((r = sef_receive_status(ANY, m_in, &status)) != OK)
+       if ((r = sef_receive_status(ANY, m_in, status)) != OK)
                panic("sef_receive_status failed: %d", r);
        src = m_in->m_source;
 
@@ -192,6 +175,8 @@ void reply(who, m_out)
 endpoint_t who;
 message *m_out;                        /* report result */
 {
-  if (OK != send(who, m_out))  /* send the message */
-       printf("PFS(%d) was unable to send reply\n", SELF_E);
+  int r;
+
+  if (OK != (r = send(who, m_out)))    /* send the message */
+       printf("PFS: unable to send reply: %d\n", r);
 }
index 1a6c33b77f3c8e42a172ae868eda66d0c54aed68..b7fc0a57f8adeef8e2512c39dd28e9185c5d513d 100644 (file)
@@ -13,15 +13,17 @@ int fs_newnode(message *fs_m_in, message *fs_m_out)
   register int r = OK;
   pmode_t bits;
   struct inode *rip;
+  uid_t uid;
+  gid_t gid;
   dev_t dev;
 
-  caller_uid = (uid_t) fs_m_in->REQ_UID;
-  caller_gid = (gid_t) fs_m_in->REQ_GID;
+  uid = (uid_t) fs_m_in->REQ_UID;
+  gid = (gid_t) fs_m_in->REQ_GID;
   bits = (pmode_t) fs_m_in->REQ_MODE;
   dev = (dev_t) fs_m_in->REQ_DEV;
 
   /* Try to allocate the inode */
-  if( (rip = alloc_inode(dev, bits) ) == NULL) return(err_code);
+  if( (rip = alloc_inode(dev, bits, uid, gid) ) == NULL) return(err_code);
 
   switch (bits & S_IFMT) {
        case S_IFBLK:
index 1491cc272fbf96c15ca77c07a1d28b0d5d12a11f..b6dc5a9c426a31ff24c57d70a57b50f3262a30aa 100644 (file)
@@ -17,7 +17,7 @@ void put_block(dev_t dev, pino_t inum);
 void buf_pool(void);
 
 /* inode.c */
-struct inode *alloc_inode(dev_t dev, pmode_t mode);
+struct inode *alloc_inode(dev_t dev, pmode_t mode, uid_t uid, gid_t gid);
 void dup_inode(struct inode *ip);
 struct inode *find_inode(pino_t numb);
 void free_inode(struct inode *rip);
@@ -61,37 +61,12 @@ bit_t alloc_bit(void);
 void free_bit(bit_t bit_returned);
 
 /* dev_uds.c */
-int uds_open(message *dev_m_in, message *dev_m_out);
-int uds_close(message *dev_m_in, message *dev_m_out);
-int uds_read(message *dev_m_in, message *dev_m_out);
-int uds_write(message *dev_m_in, message *dev_m_out);
-int uds_ioctl(message *dev_m_in, message *dev_m_out);
-int uds_select(message *dev_m_in, message *dev_m_out);
-int uds_unsuspend(endpoint_t m_source, int minor);
-int uds_cancel(message *dev_m_in, message *dev_m_out);
+void uds_request(message *m_ptr, int ipc_status);
+void uds_unsuspend(devminor_t minor);
 
 /* uds.c */
 void uds_init(void);
-int do_accept(message *dev_m_in, message *dev_m_out);
-int do_connect(message *dev_m_in, message *dev_m_out);
-int do_listen(message *dev_m_in, message *dev_m_out);
-int do_socket(message *dev_m_in, message *dev_m_out);
-int do_bind(message *dev_m_in, message *dev_m_out);
-int do_getsockname(message *dev_m_in, message *dev_m_out);
-int do_getpeername(message *dev_m_in, message *dev_m_out);
-int do_shutdown(message *dev_m_in, message *dev_m_out);
-int do_socketpair(message *dev_m_in, message *dev_m_out);
-int do_getsockopt_sotype(message *dev_m_in, message *dev_m_out);
-int do_getsockopt_peercred(message *dev_m_in, message *dev_m_out);
-int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out);
-int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out);
-int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out);
-int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out);
-int do_sendto(message *dev_m_in, message *dev_m_out);
-int do_recvfrom(message *dev_m_in, message *dev_m_out);
-int do_sendmsg(message *dev_m_in, message *dev_m_out);
-int do_recvmsg(message *dev_m_in, message *dev_m_out);
-int perform_connection(message *dev_m_in, message *dev_m_out, struct
-       sockaddr_un *addr, int minorx, int minory);
-int clear_fds(int minor, struct ancillary *data);
+int uds_clear_fds(devminor_t minor, struct ancillary *data);
+int uds_do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+       cp_grant_id_t grant);
 #endif
index a4a5af325b06566992a2ca3655b11bbd306393f4..f5359a096d0b19c3e45d246ca2a6ac4721b45abf 100644 (file)
@@ -63,11 +63,11 @@ int fs_readwrite(message *fs_m_in, message *fs_m_out)
 
   if (rw_flag == READING) {
        /* Copy a chunk from the block buffer to user space. */
-       r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
+       r = sys_safecopyto(fs_m_in->m_source, gid, (vir_bytes) 0,
                (vir_bytes) (bp->b_data+position), (size_t) nrbytes);
   } else {
        /* Copy a chunk from user space to the block buffer. */
-       r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) 0,
+       r = sys_safecopyfrom(fs_m_in->m_source, gid, (vir_bytes) 0,
                (vir_bytes) (bp->b_data+position), (size_t) nrbytes);
   }
 
index af1e754ca015729b3a29f8f2504d7fe4f9243fc0..0169b0b25a20b965dbd00c18f79e7e4ab865f766 100644 (file)
@@ -1,10 +1,11 @@
 
-/* This file contains the table used to map system call numbers onto the
+/* This file contains the table used to map VFS/FS call numbers onto the
  * routines that perform them.
  */
 
 #define _TABLE
 
+#include "inc.h"
 #include "fs.h"
 #include "inode.h"
 #include "buf.h"
@@ -12,7 +13,6 @@
 
 /* File System Handlers (pfs) */
 int (*fs_call_vec[])(message *fs_m_in, message *fs_m_out) = {
-
         no_sys,             /* 0   not used */
         no_sys,             /* 1   */
         fs_putnode,         /* 2   */
@@ -47,34 +47,3 @@ int (*fs_call_vec[])(message *fs_m_in, message *fs_m_out) = {
         no_sys,                    /* 31  */
        no_sys,             /* 32 */
 };
-
-/* Device Handlers (/dev/uds) */
-int (*dev_call_vec[])(message *dev_m_in, message *dev_m_out) = {
-
-        uds_cancel,         /* 0  CANCEL */
-        no_sys,             /* 1   */
-        no_sys,             /* 2   */
-        no_sys,             /* 3   */
-        no_sys,             /* 4   */
-        no_sys,             /* 5   */
-       uds_open,           /* 6  DEV_OPEN */
-        uds_close,          /* 7  DEV_CLOSE */
-        no_sys,             /* 8   */
-        no_sys,             /* 9   */
-        no_sys,             /* 10  */
-        no_sys,             /* 11  */
-        uds_select,         /* 12 DEV_SELECT */
-        no_sys,             /* 13  */
-        uds_open,           /* 14 DEV_REOPEN */
-        no_sys,             /* 15  */
-       no_sys,             /* 16  */
-        no_sys,             /* 17  */
-        no_sys,                    /* 18  */
-        no_sys,                    /* 19  */
-        uds_read,          /* 20 DEV_READ_S */
-        uds_write,          /* 21 DEV_WRITE_S */
-        no_sys,             /* 22 DEV_SCATTER_S */
-        no_sys,             /* 23 DEV_GATHER_S */
-        uds_ioctl,          /* 24 DEV_IOCTL_S */
-        no_sys,             /* 25 DEV_MMAP_S */
-};
index 9142a87bb8820c2ee4b966d52c8b2d598f9d8b5d..b6d6b17cc69af195a367334435ef8cd12d5b717d 100644 (file)
@@ -6,31 +6,12 @@
  * The entry points into this file are...
  *
  *   uds_init:               initialize the descriptor table.
- *   do_accept:              handles the      accept(2) syscall.
- *   do_connect:             handles the     connect(2) syscall.
- *   do_listen:              handles the      listen(2) syscall.
- *   do_socket:              handles the      socket(2) syscall.
- *   do_bind:                handles the        bind(2) syscall.
- *   do_getsockname:         handles the getsockname(2) syscall.
- *   do_getpeername:         handles the getpeername(2) syscall.
- *   do_shutdown:            handles the    shutdown(2) syscall.
- *   do_socketpair:          handles the  socketpair(2) syscall.
- *   do_getsockopt_sotype:   handles the  getsockopt(2) syscall.
- *   do_getsockopt_peercred: handles the  getsockopt(2) syscall.
- *   do_getsockopt_sndbuf:   handles the  getsockopt(2) syscall.
- *   do_setsockopt_sndbuf:   handles the  setsockopt(2) syscall.
- *   do_getsockopt_rcvbuf:   handles the  getsockopt(2) syscall.
- *   do_setsockopt_rcvbuf:   handles the  setsockopt(2) syscall.
- *   do_sendto:              handles the      sendto(2) syscall.
- *   do_recvfrom:            handles the    recvfrom(2) syscall.
- *   do_sendmsg:             handles the     sendmsg(2) syscall.
- *   do_recvmsg:             handles the     recvmsg(2) syscall.
- *   perform_connection:     performs the connection of two descriptors.
- *   clear_fds:              calls put_filp for undelivered FDs.
+ *   uds_do_ioctl:           process an IOCTL request.
+ *   uds_clear_fds:          calls put_filp for undelivered FDs.
  *
  * Also see...
  *
- *   table.c, dev_uds.c, uds.h
+ *   dev_uds.c, uds.h
  */
 
 #define DEBUG 0
@@ -54,7 +35,7 @@ void uds_init(void)
 }
 
 /* check the permissions of a socket file */
-static int check_perms(int minor, struct sockaddr_un *addr)
+static int check_perms(devminor_t minor, struct sockaddr_un *addr)
 {
        int rc;
        message vfs_m;
@@ -126,7 +107,7 @@ static int set_filp(filp_id_t sfilp)
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) set_filp(0x%x) call_count=%d\n", sfilp, ++call_count);
+       printf("(uds) set_filp(%p) call_count=%d\n", sfilp, ++call_count);
 #endif
 
        memset(&vfs_m, '\0', sizeof(message));
@@ -154,7 +135,7 @@ static int copy_filp(endpoint_t to_ep, filp_id_t cfilp)
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) copy_filp(%d, 0x%x) call_count=%d\n",to_ep, cfilp,
+       printf("(uds) copy_filp(%d, %p) call_count=%d\n",to_ep, cfilp,
                                                        ++call_count);
 #endif
 
@@ -184,7 +165,7 @@ static int put_filp(filp_id_t pfilp)
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) put_filp(0x%x) call_count=%d\n", pfilp, ++call_count);
+       printf("(uds) put_filp(%p) call_count=%d\n", pfilp, ++call_count);
 #endif
 
        memset(&vfs_m, '\0', sizeof(message));
@@ -234,8 +215,8 @@ static int cancel_fd(endpoint_t ep, int fd)
        return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
 }
 
-int perform_connection(message *dev_m_in, message *dev_m_out,
-                       struct sockaddr_un *addr, int minorx, int minory)
+static int perform_connection(devminor_t minorx, devminor_t minory,
+       struct sockaddr_un *addr)
 {
        /* there are several places were a connection is established. */
        /* accept(2), connect(2), uds_status(2), socketpair(2)        */
@@ -244,8 +225,8 @@ int perform_connection(message *dev_m_in, message *dev_m_out,
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] perform_connection() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] perform_connection() call_count=%d\n", minorx,
+               ++call_count);
 #endif
 
        /* only connection oriented types are acceptable and only like
@@ -270,19 +251,16 @@ int perform_connection(message *dev_m_in, message *dev_m_out,
        return OK;
 }
 
-
-int do_accept(message *dev_m_in, message *dev_m_out)
+static int do_accept(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor;
-       int minorparent; /* minor number of parent (server) */
-       int minorpeer;
+       devminor_t minorparent; /* minor number of parent (server) */
+       devminor_t minorpeer;
        int rc, i;
        struct sockaddr_un addr;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_accept() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_accept() call_count=%d\n", minor, ++call_count);
 #endif
 
        /* Somewhat weird logic is used in this function, so here's an
@@ -294,16 +272,14 @@ int do_accept(message *dev_m_in, message *dev_m_out)
         * connection or suspend and wait for a connect().
         */
 
-       minor = uds_minor(dev_m_in);
-
        if (uds_fd_table[minor].type != -1) {
                /* this IOCTL must be called on a 'fresh' socket */
                return EINVAL;
        }
 
        /* Get the server's address */
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+               sizeof(struct sockaddr_un));
 
        if (rc != OK) {
                return EIO;
@@ -313,7 +289,6 @@ int do_accept(message *dev_m_in, message *dev_m_out)
        rc = -1; /* to trap error */
 
        for (i = 0; i < NR_FDS; i++) {
-
                if (uds_fd_table[i].addr.sun_family == AF_UNIX &&
                                !strncmp(addr.sun_path,
                                uds_fd_table[i].addr.sun_path,
@@ -364,7 +339,7 @@ int do_accept(message *dev_m_in, message *dev_m_out)
                 */
                uds_fd_table[minor].suspended = UDS_SUSPENDED_ACCEPT;
 
-               return SUSPEND;
+               return EDONTREPLY;
        }
 
 #if DEBUG == 1
@@ -372,7 +347,7 @@ int do_accept(message *dev_m_in, message *dev_m_out)
                                                minorpeer, minorparent);
 #endif
 
-       rc = perform_connection(dev_m_in, dev_m_out, &addr, minor, minorpeer);
+       rc = perform_connection(minor, minorpeer, &addr);
        if (rc != OK) {
 #if DEBUG == 1
                printf("(uds) [%d] {do_accept} connection not performed\n",
@@ -389,27 +364,23 @@ int do_accept(message *dev_m_in, message *dev_m_out)
                printf("(uds) [%d] {do_accept} revive %d\n", minor,
                                                                minorpeer);
 #endif
-               uds_fd_table[minorpeer].ready_to_revive = 1;
-               uds_unsuspend(dev_m_in->m_source, minorpeer);
+               uds_unsuspend(minorpeer);
        }
 
        return OK;
 }
 
-int do_connect(message *dev_m_in, message *dev_m_out)
+static int do_connect(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor, child;
+       int child;
        struct sockaddr_un addr;
        int rc, i, j;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_connect() call_count=%d\n", uds_minor(dev_m_in),
-                                                               ++call_count);
+       printf("(uds) [%d] do_connect() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        /* only connection oriented sockets can connect */
        if (uds_fd_table[minor].type != SOCK_STREAM &&
                        uds_fd_table[minor].type != SOCK_SEQPACKET) {
@@ -421,9 +392,8 @@ int do_connect(message *dev_m_in, message *dev_m_out)
                return EISCONN;
        }
 
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                               (vir_bytes) 0, (vir_bytes) &addr,
-                               sizeof(struct sockaddr_un));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+               sizeof(struct sockaddr_un));
 
        if (rc != OK) {
                return EIO;
@@ -439,7 +409,6 @@ int do_connect(message *dev_m_in, message *dev_m_out)
         * address we want to connect to
         */
        for (i = 0; i < NR_FDS; i++) {
-
                if (uds_fd_table[minor].type == uds_fd_table[i].type &&
                        uds_fd_table[i].listening &&
                        uds_fd_table[i].addr.sun_family == AF_UNIX &&
@@ -452,11 +421,9 @@ int do_connect(message *dev_m_in, message *dev_m_out)
                                 * perform connection to the child
                                 */
 
-                               rc = perform_connection(dev_m_in, dev_m_out,
-                                       &addr, minor, child);
+                               rc = perform_connection(minor, child, &addr);
 
                                if (rc == OK) {
-
                                        uds_fd_table[i].child = -1;
 
 #if DEBUG == 1
@@ -464,16 +431,11 @@ int do_connect(message *dev_m_in, message *dev_m_out)
 #endif
 
                                        /* wake the parent (server) */
-                                       uds_fd_table[child].ready_to_revive =
-                                               1;
-                                       uds_unsuspend(dev_m_in->m_source,
-                                               child);
+                                       uds_unsuspend(child);
                                }
 
                                return rc;
-
                        } else {
-
 #if DEBUG == 1
                                printf("(uds) [%d] adding to %d's backlog\n",
                                                                minor, i);
@@ -497,33 +459,23 @@ int do_connect(message *dev_m_in, message *dev_m_out)
                                }
 
                                if (rc == -1) {
-
                                        /* backlog is full */
                                        break;
                                }
 
                                /* see if the server is blocked on select() */
-                               if (uds_fd_table[i].selecting == 1) {
-
-                                       /* if the server wants to know
-                                        * about data ready to read and
-                                        * it doesn't know about it
-                                        * already, then let the server
-                                        * know we have data for it.
+                               if (uds_fd_table[i].sel_ops & SEL_RD) {
+                                       /* if the server wants to know about
+                                        * data ready to read and it doesn't
+                                        * doesn't know about it already, then
+                                        * let the server know we have data for
+                                        * it.
                                         */
-                                       if ((uds_fd_table[i].sel_ops_in &
-                                               SEL_RD) &&
-                                               !(uds_fd_table[i].sel_ops_out &
-                                               SEL_RD)) {
-
-                                               uds_fd_table[i].sel_ops_out |=
-                                                       SEL_RD;
-                                               uds_fd_table[i].status_updated
-                                                       = 1;
-
-                                               uds_unsuspend(
-                                               dev_m_in->m_source, i);
-                                       }
+                                       chardriver_reply_select(
+                                               uds_fd_table[i].sel_endpt, i,
+                                               SEL_RD);
+
+                                       uds_fd_table[i].sel_ops &= ~SEL_RD;
                                }
 
                                /* we found our server */
@@ -554,23 +506,19 @@ int do_connect(message *dev_m_in, message *dev_m_out)
 
        uds_fd_table[minor].suspended = UDS_SUSPENDED_CONNECT;
 
-       return SUSPEND;
+       return EDONTREPLY;
 }
 
-int do_listen(message *dev_m_in, message *dev_m_out)
+static int do_listen(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor;
        int rc;
        int backlog_size;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_listen() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
+       printf("(uds) [%d] do_listen() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        /* ensure the socket has a type and is bound */
        if (uds_fd_table[minor].type == -1 ||
                uds_fd_table[minor].addr.sun_family != AF_UNIX) {
@@ -594,8 +542,8 @@ int do_listen(message *dev_m_in, message *dev_m_out)
         * let it happen, but if listen() has already been called, we
         * don't allow the backlog to shrink
         */
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &backlog_size, sizeof(int));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &backlog_size,
+               sizeof(int));
 
        if (rc != OK) {
                return EIO;
@@ -637,19 +585,15 @@ int do_listen(message *dev_m_in, message *dev_m_out)
        return OK;
 }
 
-int do_socket(message *dev_m_in, message *dev_m_out)
+static int do_socket(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
        int rc;
-       int minor;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_socket() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
+       printf("(uds) [%d] do_socket() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        /* see if this socket already has a type */
        if (uds_fd_table[minor].type != -1) {
                /* socket type can only be set once */
@@ -657,12 +601,10 @@ int do_socket(message *dev_m_in, message *dev_m_out)
        }
 
        /* get the requested type */
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
-               sizeof(int));
+       rc = sys_safecopyfrom(endpt, grant, 0,
+               (vir_bytes) &uds_fd_table[minor].type, sizeof(int));
 
        if (rc != OK) {
-
                /* something went wrong and we couldn't get the type */
                return EIO;
        }
@@ -672,12 +614,10 @@ int do_socket(message *dev_m_in, message *dev_m_out)
                case SOCK_STREAM:
                case SOCK_DGRAM:
                case SOCK_SEQPACKET:
-
                        /* the type is one of the 3 valid socket types */
                        return OK;
 
                default:
-
                        /* if the type isn't one of the 3 valid socket
                         * types, then it must be invalid.
                         */
@@ -689,20 +629,16 @@ int do_socket(message *dev_m_in, message *dev_m_out)
        }
 }
 
-int do_bind(message *dev_m_in, message *dev_m_out)
+static int do_bind(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor;
        struct sockaddr_un addr;
        int rc, i;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_bind() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
+       printf("(uds) [%d] do_bind() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        if ((uds_fd_table[minor].type == -1) ||
                (uds_fd_table[minor].addr.sun_family == AF_UNIX &&
                uds_fd_table[minor].type != SOCK_DGRAM)) {
@@ -713,8 +649,8 @@ int do_bind(message *dev_m_in, message *dev_m_out)
                return EINVAL;
        }
 
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+               sizeof(struct sockaddr_un));
 
        if (rc != OK) {
                return EIO;
@@ -722,13 +658,11 @@ int do_bind(message *dev_m_in, message *dev_m_out)
 
        /* do some basic sanity checks on the address */
        if (addr.sun_family != AF_UNIX) {
-
                /* bad family */
                return EAFNOSUPPORT;
        }
 
        if (addr.sun_path[0] == '\0') {
-
                /* bad address */
                return ENOENT;
        }
@@ -756,45 +690,41 @@ int do_bind(message *dev_m_in, message *dev_m_out)
        return OK;
 }
 
-int do_getsockname(message *dev_m_in, message *dev_m_out)
+static int do_getsockname(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
-       int minor;
        int rc;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_getsockname() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_getsockname() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        /* Unconditionally send the address we have assigned to this socket.
         * The POSIX standard doesn't say what to do if the address
         * hasn't been set. If the address isn't currently set, then
         * the user will get NULL bytes. Note: libc depends on this
         * behavior.
         */
-       rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].addr),
+       rc = sys_safecopyto(endpt, grant, 0,
+               (vir_bytes) &uds_fd_table[minor].addr,
                sizeof(struct sockaddr_un));
 
        return rc ? EIO : OK;
 }
 
-int do_getpeername(message *dev_m_in, message *dev_m_out)
+static int do_getpeername(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
-       int minor;
        int rc;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_getpeername() call_count=%d\n",
-                               uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_getpeername() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        /* check that the socket is connected with a valid peer */
        if (uds_fd_table[minor].peer != -1) {
                int peer_minor;
@@ -802,9 +732,8 @@ int do_getpeername(message *dev_m_in, message *dev_m_out)
                peer_minor = uds_fd_table[minor].peer;
 
                /* copy the address from the peer */
-               rc = sys_safecopyto(VFS_PROC_NR,
-                       (cp_grant_id_t) dev_m_in->IO_GRANT, (vir_bytes) 0,
-                       (vir_bytes) &(uds_fd_table[peer_minor].addr),
+               rc = sys_safecopyto(endpt, grant, 0,
+                       (vir_bytes) &uds_fd_table[peer_minor].addr,
                        sizeof(struct sockaddr_un));
 
                return rc ? EIO : OK;
@@ -819,19 +748,16 @@ int do_getpeername(message *dev_m_in, message *dev_m_out)
        }
 }
 
-int do_shutdown(message *dev_m_in, message *dev_m_out)
+static int do_shutdown(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor;
        int rc, how;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_shutdown() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_shutdown() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        if (uds_fd_table[minor].type != SOCK_STREAM &&
                        uds_fd_table[minor].type != SOCK_SEQPACKET) {
 
@@ -849,8 +775,7 @@ int do_shutdown(message *dev_m_in, message *dev_m_out)
        }
 
        /* get the 'how' parameter from the process */
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                       (vir_bytes) 0, (vir_bytes) &how, sizeof(int));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &how, sizeof(int));
 
        if (rc != OK) {
                return EIO;
@@ -880,25 +805,23 @@ int do_shutdown(message *dev_m_in, message *dev_m_out)
        return OK;
 }
 
-int do_socketpair(message *dev_m_in, message *dev_m_out)
+static int do_socketpair(devminor_t minorx, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
        int rc;
        dev_t minorin;
-       int minorx, minory;
+       devminor_t minory;
        struct sockaddr_un addr;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_socketpair() call_count=%d\n",
-                               uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_socketpair() call_count=%d\n", minorx,
+               ++call_count);
 #endif
 
-       /* first ioctl param is the first socket */
-       minorx = uds_minor(dev_m_in);
-
-       /* third ioctl param is the minor number of the second socket */
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                       (vir_bytes) 0, (vir_bytes) &minorin, sizeof(dev_t));
+       /* ioctl argument is the minor number of the second socket */
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &minorin,
+               sizeof(dev_t));
 
        if (rc != OK) {
                return EIO;
@@ -912,7 +835,6 @@ int do_socketpair(message *dev_m_in, message *dev_m_out)
 
        /* security check - both sockets must have the same endpoint (owner) */
        if (uds_fd_table[minorx].owner != uds_fd_table[minory].owner) {
-
                /* we won't allow you to magically connect your socket to
                 * someone elses socket
                 */
@@ -923,53 +845,46 @@ int do_socketpair(message *dev_m_in, message *dev_m_out)
        addr.sun_path[0] = 'X';
        addr.sun_path[1] = '\0';
 
-       uds_fd_table[minorx].syscall_done = 1;
-       return perform_connection(dev_m_in, dev_m_out, &addr, minorx, minory);
+       return perform_connection(minorx, minory, &addr);
 }
 
-int do_getsockopt_sotype(message *dev_m_in, message *dev_m_out)
+static int do_getsockopt_sotype(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
-       int minor;
        int rc;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_getsockopt_sotype() call_count=%d\n",
-                               uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_getsockopt_sotype() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        if (uds_fd_table[minor].type == -1) {
-
                /* the type hasn't been set yet. instead of returning an
                 * invalid type, we fail with EINVAL
                 */
                return EINVAL;
        }
 
-       rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
-               sizeof(int));
+       rc = sys_safecopyto(endpt, grant, 0,
+               (vir_bytes) &uds_fd_table[minor].type, sizeof(int));
 
        return rc ? EIO : OK;
 }
 
-int do_getsockopt_peercred(message *dev_m_in, message *dev_m_out)
+static int do_getsockopt_peercred(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
-       int minor;
        int peer_minor;
        int rc;
        struct uucred cred;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_getsockopt_peercred() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        if (uds_fd_table[minor].peer == -1) {
 
                if (uds_fd_table[minor].err == ECONNRESET) {
@@ -990,43 +905,44 @@ int do_getsockopt_peercred(message *dev_m_in, message *dev_m_out)
                return errno;
        }
 
-       rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &cred, sizeof(struct uucred));
+       rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &cred,
+               sizeof(struct uucred));
 
        return rc ? EIO : OK;
 }
 
-int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
+static int do_getsockopt_sndbuf(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
        int rc;
        size_t sndbuf = PIPE_BUF;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_getsockopt_sndbuf() call_count=%d\n",
-                               uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_getsockopt_sndbuf() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &(sndbuf), sizeof(size_t));
+       rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &sndbuf,
+               sizeof(size_t));
 
        return rc ? EIO : OK;
 }
 
-int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
+static int do_setsockopt_sndbuf(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
        int rc;
        size_t sndbuf;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n",
-                               uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                               (vir_bytes) 0, (vir_bytes) &sndbuf,
-                               sizeof(size_t));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &sndbuf,
+               sizeof(size_t));
 
        if (rc != OK) {
                return EIO;
@@ -1043,37 +959,38 @@ int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
        return OK;
 }
 
-int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
+static int do_getsockopt_rcvbuf(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
        int rc;
        size_t rcvbuf = PIPE_BUF;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_getsockopt_rcvbuf() call_count=%d\n",
-                               uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_getsockopt_rcvbuf() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &(rcvbuf), sizeof(size_t));
+       rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &rcvbuf,
+               sizeof(size_t));
 
        return rc ? EIO : OK;
 }
 
-int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
+static int do_setsockopt_rcvbuf(devminor_t minor, endpoint_t endpt,
+       cp_grant_id_t grant)
 {
        int rc;
        size_t rcvbuf;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n",
-                               uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_setsockopt_rcvbuf() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                               (vir_bytes) 0, (vir_bytes) &rcvbuf,
-                               sizeof(size_t));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &rcvbuf,
+               sizeof(size_t));
 
        if (rc != OK) {
                return EIO;
@@ -1090,28 +1007,23 @@ int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
        return OK;
 }
 
-
-int do_sendto(message *dev_m_in, message *dev_m_out)
+static int do_sendto(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor;
        int rc;
        struct sockaddr_un addr;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_sendto() call_count=%d\n", uds_minor(dev_m_in),
-                                                       ++call_count);
+       printf("(uds) [%d] do_sendto() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        if (uds_fd_table[minor].type != SOCK_DGRAM) {
                /* This IOCTL is only for SOCK_DGRAM sockets */
                return EINVAL;
        }
 
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &addr,
+               sizeof(struct sockaddr_un));
 
        if (rc != OK) {
                return EIO;
@@ -1134,28 +1046,25 @@ int do_sendto(message *dev_m_in, message *dev_m_out)
        return OK;
 }
 
-int do_recvfrom(message *dev_m_in, message *dev_m_out)
+static int do_recvfrom(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor;
        int rc;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_recvfrom() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_recvfrom() call_count=%d\n", minor,
+               ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
-       rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].source),
+       rc = sys_safecopyto(endpt, grant, 0,
+               (vir_bytes) &uds_fd_table[minor].source,
                sizeof(struct sockaddr_un));
 
        return rc ? EIO : OK;
 }
 
-int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
-                                                       int minor)
+static int msg_control_read(struct msg_control *msg_ctrl,
+       struct ancillary *data, devminor_t minor)
 {
        int rc;
        struct msghdr msghdr;
@@ -1213,7 +1122,7 @@ int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
        return OK;
 }
 
-static int send_fds(int minor, struct ancillary *data)
+static int send_fds(devminor_t minor, struct ancillary *data)
 {
        int rc, i, j;
 
@@ -1247,7 +1156,7 @@ static int send_fds(int minor, struct ancillary *data)
        return OK;
 }
 
-int clear_fds(int minor, struct ancillary *data)
+int uds_clear_fds(devminor_t minor, struct ancillary *data)
 {
 /* This function calls put_filp() for all of the FDs in data.
  * This is used when a Unix Domain Socket is closed and there
@@ -1258,14 +1167,14 @@ int clear_fds(int minor, struct ancillary *data)
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
+       printf("(uds) [%d] uds_clear_fds() call_count=%d\n", minor,
                                                        ++call_count);
 #endif
 
        for (i = 0; i < data->nfiledes; i++) {
                put_filp(data->filps[i]);
 #if DEBUG == 1
-               printf("(uds) clear_fds() => %d\n", data->fds[i]);
+               printf("(uds) uds_clear_fds() => %d\n", data->fds[i]);
 #endif
                data->fds[i] = -1;
                data->filps[i] = NULL;
@@ -1276,7 +1185,7 @@ int clear_fds(int minor, struct ancillary *data)
        return OK;
 }
 
-static int recv_fds(int minor, struct ancillary *data,
+static int recv_fds(devminor_t minor, struct ancillary *data,
                                        struct msg_control *msg_ctrl)
 {
        int rc, i, j;
@@ -1332,7 +1241,7 @@ static int recv_fds(int minor, struct ancillary *data,
        return OK;
 }
 
-static int recv_cred(int minor, struct ancillary *data,
+static int recv_cred(devminor_t minor, struct ancillary *data,
                                        struct msg_control *msg_ctrl)
 {
        struct msghdr msghdr;
@@ -1360,24 +1269,20 @@ static int recv_cred(int minor, struct ancillary *data,
        return OK;
 }
 
-int do_sendmsg(message *dev_m_in, message *dev_m_out)
+static int do_sendmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor, peer, rc, i;
+       int peer, rc, i;
        struct msg_control msg_ctrl;
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_sendmsg() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
+       printf("(uds) [%d] do_sendmsg() call_count=%d\n", minor, ++call_count);
 #endif
 
-       minor = uds_minor(dev_m_in);
-
        memset(&msg_ctrl, '\0', sizeof(struct msg_control));
 
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                                       (vir_bytes) 0, (vir_bytes) &msg_ctrl,
-                                       sizeof(struct msg_control));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &msg_ctrl,
+               sizeof(struct msg_control));
 
        if (rc != OK) {
                return EIO;
@@ -1434,9 +1339,8 @@ int do_sendmsg(message *dev_m_in, message *dev_m_out)
        return send_fds(minor, &uds_fd_table[peer].ancillary_data);
 }
 
-int do_recvmsg(message *dev_m_in, message *dev_m_out)
+static int do_recvmsg(devminor_t minor, endpoint_t endpt, cp_grant_id_t grant)
 {
-       int minor;
        int rc;
        struct msg_control msg_ctrl;
        socklen_t controllen_avail = 0;
@@ -1445,14 +1349,7 @@ int do_recvmsg(message *dev_m_in, message *dev_m_out)
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_sendmsg() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-
-#if DEBUG == 1
+       printf("(uds) [%d] do_sendmsg() call_count=%d\n", minor, ++call_count);
        printf("(uds) [%d] CREDENTIALS {pid:%d,uid:%d,gid:%d}\n", minor,
                                uds_fd_table[minor].ancillary_data.cred.pid,
                                uds_fd_table[minor].ancillary_data.cred.uid,
@@ -1464,9 +1361,8 @@ int do_recvmsg(message *dev_m_in, message *dev_m_out)
        /* get the msg_control from the user, it will include the
         * amount of space the user has allocated for control data.
         */
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                                       (vir_bytes) 0, (vir_bytes) &msg_ctrl,
-                                       sizeof(struct msg_control));
+       rc = sys_safecopyfrom(endpt, grant, 0, (vir_bytes) &msg_ctrl,
+               sizeof(struct msg_control));
 
        if (rc != OK) {
                return EIO;
@@ -1501,9 +1397,147 @@ int do_recvmsg(message *dev_m_in, message *dev_m_out)
        }
 
        /* send the user the control data */
-       rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &msg_ctrl,
+       rc = sys_safecopyto(endpt, grant, 0, (vir_bytes) &msg_ctrl,
                sizeof(struct msg_control));
 
        return rc ? EIO : OK;
 }
+
+int uds_do_ioctl(devminor_t minor, unsigned long request, endpoint_t endpt,
+       cp_grant_id_t grant)
+{
+       int rc;
+
+       switch (request) {      /* Handle the ioctl(2) command */
+       case NWIOSUDSCONN:
+               /* connect to a listening socket -- connect() */
+               rc = do_connect(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSACCEPT:
+               /* accept an incoming connection -- accept() */
+               rc = do_accept(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSBLOG:
+               /* set the backlog_size and put the socket into the listening
+                * state -- listen()
+                */
+               rc = do_listen(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSTYPE:
+               /* set the type for this socket (i.e. SOCK_STREAM, SOCK_DGRAM,
+                * etc) -- socket()
+                */
+               rc = do_socket(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSADDR:
+               /* set the address for this socket -- bind() */
+               rc = do_bind(minor, endpt, grant);
+
+               break;
+
+       case NWIOGUDSADDR:
+               /* get the address for this socket -- getsockname() */
+               rc = do_getsockname(minor, endpt, grant);
+
+               break;
+
+       case NWIOGUDSPADDR:
+               /* get the address for the peer -- getpeername() */
+               rc = do_getpeername(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSSHUT:
+               /* shutdown a socket for reading, writing, or both --
+                * shutdown()
+                */
+               rc = do_shutdown(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSPAIR:
+               /* connect two sockets -- socketpair() */
+               rc = do_socketpair(minor, endpt, grant);
+
+               break;
+
+       case NWIOGUDSSOTYPE:
+               /* get socket type -- getsockopt(SO_TYPE) */
+               rc = do_getsockopt_sotype(minor, endpt, grant);
+
+               break;
+
+       case NWIOGUDSPEERCRED:
+               /* get peer endpoint -- getsockopt(SO_PEERCRED) */
+               rc = do_getsockopt_peercred(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSTADDR:
+               /* set target address -- sendto() */
+               rc = do_sendto(minor, endpt, grant);
+
+               break;
+
+       case NWIOGUDSFADDR:
+               /* get from address -- recvfrom() */
+               rc = do_recvfrom(minor, endpt, grant);
+
+               break;
+
+       case NWIOGUDSSNDBUF:
+               /* get the send buffer size -- getsockopt(SO_SNDBUF) */
+               rc = do_getsockopt_sndbuf(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSSNDBUF:
+               /* set the send buffer size -- setsockopt(SO_SNDBUF) */
+               rc = do_setsockopt_sndbuf(minor, endpt, grant);
+
+               break;
+
+       case NWIOGUDSRCVBUF:
+               /* get the send buffer size -- getsockopt(SO_SNDBUF) */
+               rc = do_getsockopt_rcvbuf(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSRCVBUF:
+               /* set the send buffer size -- setsockopt(SO_SNDBUF) */
+               rc = do_setsockopt_rcvbuf(minor, endpt, grant);
+
+               break;
+
+       case NWIOSUDSCTRL:
+               /* set the control data -- sendmsg() */
+               rc = do_sendmsg(minor, endpt, grant);
+
+               break;
+
+       case NWIOGUDSCTRL:
+               /* set the control data -- recvmsg() */
+               rc = do_recvmsg(minor, endpt, grant);
+
+               break;
+
+       default:
+               /* the IOCTL command is not valid for /dev/uds -- this happens
+                * a lot and is normal. a lot of libc functions determine the
+                * socket type with IOCTLs. Any not for us simply get an ENOTTY
+                * response.
+                */
+
+               rc = ENOTTY;
+       }
+
+       return rc;
+}
index 93b2ee347514d6a2faee7186203e5c993fd2cc72..cc51efdcc99bd388278687a0b8e7f55509db02a7 100644 (file)
@@ -15,6 +15,7 @@
 #include <sys/un.h>
 
 #include <minix/endpoint.h>
+#include <minix/chardriver.h>
 
 /* max connection backlog for incoming connections */
 #define UDS_SOMAXCONN 64
@@ -54,9 +55,6 @@ struct uds_fd {
        /* Socket Owner */
        endpoint_t owner;
 
-       /* endpoint for suspend/resume */
-       endpoint_t endpoint;
-
 /* Pipe Housekeeping */
 
        /* inode number on PFS -- each descriptor is backed by 1
@@ -82,7 +80,6 @@ struct uds_fd {
 
 /* Socket Info */
 
-
        /* socket type - SOCK_STREAM, SOCK_DGRAM, or SOCK_SEQPACKET
         * Set by uds_ioctl(NWIOSUDSTYPE). It defaults to -1 in
         * uds_open(). Any action on a socket with type -1 besides
@@ -144,7 +141,6 @@ struct uds_fd {
 
 /* Suspend/Revive Housekeeping */
 
-
        /* SUSPEND State Flags */
        enum UDS_SUSPENDED {
 
@@ -164,56 +160,27 @@ struct uds_fd {
                UDS_SUSPENDED_ACCEPT  = 8
        } suspended;
 
-       /* Flag (1 or 0) - thing socket was waiting for is ready.
-        * If 1, then uds_status() will attempt the operation that
-        * the socket was blocked on.
-        */
-       int ready_to_revive;
+       /* source endpoint, saved for later use by suspended procs */
+       endpoint_t susp_endpt;
 
        /* i/o grant, saved for later use by suspended procs */
-       cp_grant_id_t io_gr;
-
-       /* is of i/o grant, saved for later use by suspended procs */
-       size_t io_gr_size;
-
-       /* Save the call number so that uds_cancel() can unwind the
-        * call properly.
-        */
-       int call_nr;
+       cp_grant_id_t susp_grant;
 
-       /* Save the IOCTL so uds_cancel() knows what got cancelled. */
-       int ioctl;
+       /* size of request, saved for later use by suspended procs */
+       size_t susp_size;
 
-       /* Flag (1 or 0) - the system call completed.
-        * A doc I read said DEV_CANCEL might be called even though
-        * the operation is finished. We use this variable to
-        * determine if we should rollback the changes or not.
-        */
-       int syscall_done;
+       /* request ID, saved for later use by suspended procs */
+       cdev_id_t susp_id;
 
 /* select() */
 
-       /* Flag (1 or 0) - the process blocked on select(2). When
-        * selecting is 1 and I/O happens on this socket, then
-        * select_proc should be notified.
-        */
-       int selecting;
-
        /* when a select is in progress, we notify() this endpoint
         * of new data.
         */
-       endpoint_t select_proc;
+       endpoint_t sel_endpt;
 
        /* Options (SEL_RD, SEL_WR, SEL_ERR) that are requested. */
-       int sel_ops_in;
-
-       /* Options that are available for this socket. */
-       int sel_ops_out;
-
-       /* Flag (1 or 0) to be set to one before calling notify().
-        * uds_status() will use the flag to locate this descriptor.
-        */
-       int status_updated;
+       unsigned int sel_ops;
 };
 
 typedef struct uds_fd uds_fd_t;
@@ -221,30 +188,4 @@ typedef struct uds_fd uds_fd_t;
 /* File Descriptor Table -- Defined in uds.c */
 EXTERN uds_fd_t uds_fd_table[NR_FDS];
 
-/*
- * Take message m and get the index in uds_fd_table.
- */
-#define uds_minor(m)           (minor((dev_t) m->DEVICE))
-
-/*
- * Fill in a reply message.
- */
-#define uds_set_reply(msg,type,endpoint,io_gr,status)  \
-       do {                                            \
-               (msg)->m_type = type;                   \
-               (msg)->REP_ENDPT = endpoint;            \
-               (msg)->REP_IO_GRANT = io_gr;            \
-               (msg)->REP_STATUS = status;             \
-       } while (0)
-
-#define uds_sel_reply(msg,type,minor,ops)              \
-       do {                                            \
-               (msg)->m_type = type;                   \
-               (msg)->DEV_MINOR = minor;                       \
-               (msg)->DEV_SEL_OPS = ops;                       \
-       } while (0)
-
-
-
-
 #endif
index f1c4849abc3da43255d1166fbb59011568953061..4109d83d0a6f0cbde42a4f21d0f08d7085a1cded 100644 (file)
@@ -7,7 +7,7 @@
 int no_sys(message *pfs_m_in, message *pfs_m_out)
 {
 /* Somebody has used an illegal system call number */
-  printf("no_sys: invalid call 0x%x to pfs\n", req_nr);
+  printf("no_sys: invalid call 0x%x to pfs\n", pfs_m_in->m_type);
   return(EINVAL);
 }