]> Zhao Yanbai Git Server - minix.git/commitdiff
VFS: replace VFS with AVFS
authorThomas Veerman <thomas@minix3.org>
Mon, 13 Feb 2012 15:28:04 +0000 (15:28 +0000)
committerThomas Veerman <thomas@minix3.org>
Mon, 13 Feb 2012 16:53:21 +0000 (16:53 +0000)
142 files changed:
docs/UPDATING
servers/Makefile
servers/apfs/Makefile [deleted file]
servers/apfs/buf.h [deleted file]
servers/apfs/buffer.c [deleted file]
servers/apfs/const.h [deleted file]
servers/apfs/dev_uds.c [deleted file]
servers/apfs/fs.h [deleted file]
servers/apfs/glo.h [deleted file]
servers/apfs/inc.h [deleted file]
servers/apfs/inode.c [deleted file]
servers/apfs/inode.h [deleted file]
servers/apfs/link.c [deleted file]
servers/apfs/main.c [deleted file]
servers/apfs/misc.c [deleted file]
servers/apfs/open.c [deleted file]
servers/apfs/proto.h [deleted file]
servers/apfs/read.c [deleted file]
servers/apfs/stadir.c [deleted file]
servers/apfs/super.c [deleted file]
servers/apfs/table.c [deleted file]
servers/apfs/uds.c [deleted file]
servers/apfs/uds.h [deleted file]
servers/apfs/utility.c [deleted file]
servers/avfs/Makefile [deleted file]
servers/avfs/const.h [deleted file]
servers/avfs/device.c [deleted file]
servers/avfs/dmap.c [deleted file]
servers/avfs/dmap.h [deleted file]
servers/avfs/exec.c [deleted file]
servers/avfs/exec.h [deleted file]
servers/avfs/file.h [deleted file]
servers/avfs/filedes.c [deleted file]
servers/avfs/fproc.h [deleted file]
servers/avfs/fs.h [deleted file]
servers/avfs/fscall.c [deleted file]
servers/avfs/gcov.c [deleted file]
servers/avfs/glo.h [deleted file]
servers/avfs/link.c [deleted file]
servers/avfs/lock.c [deleted file]
servers/avfs/lock.h [deleted file]
servers/avfs/main.c [deleted file]
servers/avfs/misc.c [deleted file]
servers/avfs/mount.c [deleted file]
servers/avfs/open.c [deleted file]
servers/avfs/param.h [deleted file]
servers/avfs/path.c [deleted file]
servers/avfs/pipe.c [deleted file]
servers/avfs/protect.c [deleted file]
servers/avfs/proto.h [deleted file]
servers/avfs/read.c [deleted file]
servers/avfs/request.c [deleted file]
servers/avfs/request.h [deleted file]
servers/avfs/select.c [deleted file]
servers/avfs/select.h [deleted file]
servers/avfs/stadir.c [deleted file]
servers/avfs/table.c [deleted file]
servers/avfs/time.c [deleted file]
servers/avfs/utility.c [deleted file]
servers/avfs/vmnt.c [deleted file]
servers/avfs/vmnt.h [deleted file]
servers/avfs/vnode.c [deleted file]
servers/avfs/vnode.h [deleted file]
servers/avfs/write.c [deleted file]
servers/is/Makefile
servers/is/dmp_fs.c
servers/pfs/Makefile
servers/pfs/buf.h
servers/pfs/buffer.c
servers/pfs/const.h
servers/pfs/dev_uds.c
servers/pfs/glo.h
servers/pfs/inc.h
servers/pfs/inode.c
servers/pfs/inode.h
servers/pfs/link.c
servers/pfs/main.c
servers/pfs/misc.c
servers/pfs/mount.c [moved from servers/apfs/mount.c with 100% similarity]
servers/pfs/open.c
servers/pfs/proto.h
servers/pfs/read.c
servers/pfs/stadir.c
servers/pfs/super.c
servers/pfs/table.c
servers/pfs/uds.c
servers/pfs/uds.h
servers/pfs/utility.c
servers/procfs/Makefile
servers/procfs/inc.h
servers/vfs/Makefile
servers/vfs/comm.c [moved from servers/avfs/comm.c with 100% similarity]
servers/vfs/comm.h [moved from servers/avfs/comm.h with 100% similarity]
servers/vfs/const.h
servers/vfs/coredump.c [moved from servers/avfs/coredump.c with 100% similarity]
servers/vfs/device.c
servers/vfs/dmap.c
servers/vfs/dmap.h
servers/vfs/elf_core_dump.c [deleted file]
servers/vfs/exec.c
servers/vfs/file.h
servers/vfs/filedes.c
servers/vfs/fproc.h
servers/vfs/fs.h
servers/vfs/fscall.c
servers/vfs/gcov.c
servers/vfs/glo.h
servers/vfs/job.h [moved from servers/avfs/job.h with 100% similarity]
servers/vfs/link.c
servers/vfs/lock.c
servers/vfs/lock.h
servers/vfs/main.c
servers/vfs/misc.c
servers/vfs/mount.c
servers/vfs/open.c
servers/vfs/param.h
servers/vfs/path.c
servers/vfs/path.h [moved from servers/avfs/path.h with 100% similarity]
servers/vfs/pipe.c
servers/vfs/protect.c
servers/vfs/proto.h
servers/vfs/read.c
servers/vfs/request.c
servers/vfs/request.h
servers/vfs/scratchpad.h [moved from servers/avfs/scratchpad.h with 100% similarity]
servers/vfs/select.c
servers/vfs/select.h
servers/vfs/stadir.c
servers/vfs/table.c
servers/vfs/threads.h [moved from servers/avfs/threads.h with 100% similarity]
servers/vfs/time.c
servers/vfs/tll.c [moved from servers/avfs/tll.c with 100% similarity]
servers/vfs/tll.h [moved from servers/avfs/tll.h with 100% similarity]
servers/vfs/utility.c
servers/vfs/vmnt.c
servers/vfs/vmnt.h
servers/vfs/vnode.c
servers/vfs/vnode.h
servers/vfs/worker.c [moved from servers/avfs/worker.c with 100% similarity]
servers/vfs/write.c
share/mk/bsd.own.mk
tools/Makefile

index 53f5544eaed7b814d8e1f39eea98f862a076bcd6..195edad462de743868e4190236638fe6b48bd9e8 100644 (file)
@@ -1,3 +1,10 @@
+20120213
+       Replace VFS with AVFS
+
+       In case you were running AVFS by doing
+       'BUILDAVFS=yes make clean world', you now have to do a
+       'make clean cleandepend world' instead of a normal 'make clean world'.
+
 20120202
        Rename installboot to installboot_minix.
 
index 05a2bc6cea52ac4ceebf548ea2792b24b7aa5329..f5e7140e7e7d4776ce02639dba3b244f61296500 100644 (file)
@@ -3,22 +3,14 @@
 
 .include <bsd.own.mk>
 
-.if ${BUILDAVFS} == "yes"
-VFS= "avfs"
-PFS= "apfs"
-.else
-VFS= "vfs"
-PFS= "pfs"
-.endif
-
 .if ${MKIMAGEONLY} == "yes"
 
-SUBDIR=        ds init mfs ${PFS} pm rs sched ${VFS} vm
+SUBDIR=        ds init mfs pfs pm rs sched vfs vm
 
 .else
 
 SUBDIR=        ds ext2 hgfs inet init ipc is iso9660fs \
-       mfs ${PFS} pm procfs rs sched ${VFS} vm devman
+       mfs pfs pm procfs rs sched vfs vm devman
 
 .endif
 
diff --git a/servers/apfs/Makefile b/servers/apfs/Makefile
deleted file mode 100644 (file)
index 18f5305..0000000
+++ /dev/null
@@ -1,18 +0,0 @@
-# Makefile for Pipe File System (PFS)
-PROG=  pfs
-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
-
-.if ${COMPILER_TYPE} == "gnu"
-LDADD+= -lc
-.endif
-
-MAN=
-
-BINDIR?= /usr/sbin
-
-.include <minix.bootprog.mk>
diff --git a/servers/apfs/buf.h b/servers/apfs/buf.h
deleted file mode 100644 (file)
index cd31f7e..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __PFS_BUF_H__
-#define __PFS_BUF_H__
-
-/* Buffer (block) cache.
- */
-
-struct buf {
-  /* Data portion of the buffer. */
-  char b_data[PIPE_BUF];     /* ordinary user data */
-
-  /* Header portion of the buffer. */
-  struct buf *b_next;           /* used to link all free bufs in a chain */
-  struct buf *b_prev;           /* used to link all free bufs the other way */
-  ino_t b_num;                 /* inode number on minor device */
-  dev_t b_dev;                  /* major | minor device where block resides */
-  int b_bytes;                  /* Number of bytes allocated in bp */
-  int b_count;                 /* Number of users of this buffer */
-};
-
-/* A block is free if b_dev == NO_DEV. */
-
-
-EXTERN struct buf *front;      /* points to least recently used free block */
-EXTERN struct buf *rear;       /* points to most recently used free block */
-
-#endif
diff --git a/servers/apfs/buffer.c b/servers/apfs/buffer.c
deleted file mode 100644 (file)
index a5c77b4..0000000
+++ /dev/null
@@ -1,103 +0,0 @@
-#include "fs.h"
-#include "buf.h"
-#include "inode.h"
-#include <sys/types.h>
-#include <stdlib.h>
-#include <string.h>
-
-FORWARD _PROTOTYPE( struct buf *new_block, (dev_t dev, ino_t inum)                     );
-
-/*===========================================================================*
- *                              buf_pool                                     *
- *===========================================================================*/
-PUBLIC void buf_pool(void)
-{
-/* Initialize the buffer pool. */
-
-  front = NULL;
-  rear = NULL;
-}
-
-
-
-/*===========================================================================*
- *                             get_block                                    *
- *===========================================================================*/
-PUBLIC struct buf *get_block(dev_t dev, ino_t inum)
-{
-  struct buf *bp = front;
-
-  while(bp != NULL) {
-       if (bp->b_dev == dev && bp->b_num == inum) {
-               bp->b_count++;
-               return(bp);
-       }
-       bp = bp->b_next;
-  }
-
-  /* Buffer was not found. Try to allocate a new one */
-  return new_block(dev, inum);
-}
-
-
-/*===========================================================================*
- *                             new_block                                    *
- *===========================================================================*/
-PRIVATE struct buf *new_block(dev_t dev, ino_t inum)
-{
-/* Allocate a new buffer and add it to the double linked buffer list */
-  struct buf *bp;
-
-  bp = malloc(sizeof(struct buf));
-  if (bp == NULL) {
-       err_code = ENOSPC;
-       return(NULL);
-  }
-  bp->b_num = inum;
-  bp->b_dev = dev;
-  bp->b_bytes = 0;
-  bp->b_count = 1;
-  memset(bp->b_data, 0 , PIPE_BUF);
-
-  /* Add at the end of the buffer */
-  if (front == NULL) { /* Empty list? */
-       front = bp;
-       bp->b_prev = NULL;
-  } else {
-       rear->b_next = bp;
-       bp->b_prev = rear;
-  }
-  bp->b_next = NULL;
-  rear = bp;
-
-  return(bp);
-}
-
-
-/*===========================================================================*
- *                             put_block                                    *
- *===========================================================================*/
-PUBLIC void put_block(dev_t dev, ino_t inum)
-{
-  struct buf *bp;
-
-  bp = get_block(dev, inum);
-  if (bp == NULL) return; /* We didn't find the block. Nothing to put. */
-
-  bp->b_count--;       /* Compensate for above 'get_block'. */
-  if (--bp->b_count > 0) return;
-
-  /* Cut bp out of the loop */
-  if (bp->b_prev == NULL)
-       front = bp->b_next;
-  else
-       bp->b_prev->b_next = bp->b_next;
-
-  if (bp->b_next == NULL)
-       rear = bp->b_prev;
-  else
-       bp->b_next->b_prev = bp->b_prev;
-
-  /* Buffer administration is done. Now it's safe to free up bp. */
-  free(bp);
-}
diff --git a/servers/apfs/const.h b/servers/apfs/const.h
deleted file mode 100644 (file)
index f89a239..0000000
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef __PFS_CONST_H__
-#define __PFS_CONST_H__
-
-#define NR_INODES        256   /* # slots in "in core" inode table */
-
-/* Size of descriptor table for unix domain sockets. This should be
- * equal to the maximum number of minor devices (currently 256).
- */
-#define NR_FDS           256
-
-#define INODE_HASH_LOG2   7     /* 2 based logarithm of the inode hash size */
-#define INODE_HASH_SIZE   ((unsigned long)1<<INODE_HASH_LOG2)
-#define INODE_HASH_MASK   (((unsigned long)1<<INODE_HASH_LOG2)-1)
-
-
-/* The type of sizeof may be (unsigned) long.  Use the following macro for
- * taking the sizes of small objects so that there are no surprises like
- * (small) long constants being passed to routines expecting an int.
- */
-#define usizeof(t) ((unsigned) sizeof(t))
-
-/* Miscellaneous constants */
-#define INVAL_UID ((uid_t) -1) /* Invalid user ID */
-#define INVAL_GID ((gid_t) -1) /* Invalid group ID */
-#define NORMAL            0    /* forces get_block to do disk read */
-#define NO_READ            1   /* prevents get_block from doing disk read */
-#define PREFETCH           2   /* tells get_block not to read or mark dev */
-
-#define NO_BIT   ((bit_t) 0)   /* returned by alloc_bit() to signal failure */
-
-#define ATIME            002   /* set if atime field needs updating */
-#define CTIME            004   /* set if ctime field needs updating */
-#define MTIME            010   /* set if mtime field needs updating */
-
-#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk   */
-#define FS_BITCHUNK_BITS               (usizeof(bitchunk_t) * CHAR_BIT)
-#define FS_BITS_PER_BLOCK(b)   (FS_BITMAP_CHUNKS(b) * FS_BITCHUNK_BITS)
-
-#define FS_CALL_VEC_SIZE 31
-#define DEV_CALL_VEC_SIZE 25
-
-#endif
diff --git a/servers/apfs/dev_uds.c b/servers/apfs/dev_uds.c
deleted file mode 100644 (file)
index 7250f07..0000000
+++ /dev/null
@@ -1,1177 +0,0 @@
-/*
- * Unix Domain Sockets Implementation (PF_UNIX, PF_LOCAL)
- * This code handles requests generated by operations on /dev/uds
- *
- * 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.
- *
- * Also See...
- *
- *   table.c, uds.c, uds.h
- *
- * Overview
- *
- * The interface to unix domain sockets is similar to the
- * the interface to network sockets. There is a character
- * device (/dev/uds) that uses STYLE_CLONE and this server
- * is a 'driver' for that device.
- */
-
-#define DEBUG 0
-
-#include "inc.h"
-#include "const.h"
-#include "glo.h"
-#include "uds.h"
-
-FORWARD _PROTOTYPE( int uds_perform_read, (int minor, endpoint_t m_source,
-       size_t size, int pretend));
-FORWARD _PROTOTYPE( int uds_perform_write, (int minor, endpoint_t m_source,
-       size_t size, int pretend));
-
-PUBLIC int uds_open(message *dev_m_in, message *dev_m_out)
-{
-       message fs_m_in, fs_m_out;
-       struct ucred ucred;
-       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);
-#endif
-
-       /*
-        * Find a slot in the descriptor table for the new descriptor.
-        * The index of the descriptor in the table will be returned.
-        * Subsequent calls to read/write/close/ioctl/etc will use this
-        * minor number. The minor number must be different from the
-        * the /dev/uds device's minor number (currently 0).
-        */
-
-       minor = -1; /* to trap error */
-
-       for (i = 1; i < NR_FDS; i++) {
-               if (uds_fd_table[i].state == UDS_FREE) {
-                       minor = i;
-                       break;
-               }
-       }
-
-       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);
-               return ENFILE;
-       }
-
-       /*
-        * We found a slot in uds_fd_table, now initialize the descriptor
-        */
-
-       /* mark this one as 'in use' so that it doesn't get assigned to
-        * another socket
-        */
-       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;
-
-       /* 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;
-
-       /* initialize the data pointer (pos) to the start of the PIPE */
-       uds_fd_table[minor].pos = 0;
-
-       /* the PIPE is initially empty */
-       uds_fd_table[minor].size = 0;
-
-       /* the default for a new socket is to allow reading and writing.
-        * shutdown(2) will remove one or both flags.
-        */
-       uds_fd_table[minor].mode = S_IRUSR|S_IWUSR;
-
-       /* In libc socket(2) sets this to the actual value later with the
-        * NWIOSUDSTYPE ioctl().
-        */
-       uds_fd_table[minor].type = -1;
-
-       /* Clear the backlog by setting each entry to -1 */
-       for (i = 0; i < UDS_SOMAXCONN; i++) {
-               /* initially no connections are pending */
-               uds_fd_table[minor].backlog[i] = -1;
-       }
-
-       memset(&uds_fd_table[minor].ancillary_data, '\0', sizeof(struct
-                                                               ancillary));
-       for (i = 0; i < OPEN_MAX; i++) {
-               uds_fd_table[minor].ancillary_data.fds[i] = -1;
-       }
-
-       /* default the size to UDS_SOMAXCONN */
-       uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;
-
-       /* the socket isn't listening for incoming connections until
-        * listen(2) is called
-        */
-       uds_fd_table[minor].listening = 0;
-
-       /* initially the socket is not connected to a peer */
-       uds_fd_table[minor].peer = -1;
-
-       /* there isn't a child waiting to be accept(2)'d */
-       uds_fd_table[minor].child = -1;
-
-       /* initially the socket is not bound or listening on an address */
-       memset(&(uds_fd_table[minor].addr), '\0', sizeof(struct sockaddr_un));
-       memset(&(uds_fd_table[minor].source), '\0', sizeof(struct sockaddr_un));
-       memset(&(uds_fd_table[minor].target), '\0', sizeof(struct sockaddr_un));
-
-       /* 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 = (cp_grant_id_t) 0;
-
-       /* 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);
-       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;
-       }
-
-       /* Prepare Request to the FS side of PFS */
-
-       fs_m_in.m_type = REQ_NEWNODE;
-       fs_m_in.REQ_MODE = I_NAMED_PIPE;
-       fs_m_in.REQ_DEV = NO_DEV;
-       fs_m_in.REQ_UID = ucred.uid;
-       fs_m_in.REQ_GID = ucred.gid;
-
-       /* Request a new inode on the pipe file system */
-
-       rc = fs_newnode(&fs_m_in, &fs_m_out);
-       if (rc != OK) {
-               /* roll back the changes we made to the descriptor */
-               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;
-}
-
-PUBLIC int uds_close(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       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) {
-
-               /* set peer of this peer to -1 */
-               uds_fd_table[uds_fd_table[minor].peer].peer = -1;
-
-               /* error to pass to peer */
-               uds_fd_table[uds_fd_table[minor].peer].err = ECONNRESET;
-
-               /* if peer was blocked on I/O revive peer */
-               if (uds_fd_table[uds_fd_table[minor].peer].suspended) {
-                       int peer = uds_fd_table[minor].peer;
-
-                       uds_fd_table[peer].ready_to_revive = 1;
-                       uds_unsuspend(dev_m_in->m_source, peer);
-               }
-       }
-
-       if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
-               clear_fds(minor, &(uds_fd_table[minor].ancillary_data));
-       }
-
-       /* Prepare Request to the FS side of PFS */
-
-       fs_m_in.m_type = REQ_PUTNODE;
-       fs_m_in.REQ_INODE_NR = uds_fd_table[minor].inode_nr;
-       fs_m_in.REQ_COUNT = 1;
-
-       /* set the socket back to its original UDS_FREE state */
-       memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));
-
-       /* Request the removal of the inode from the pipe file system */
-
-       rc = fs_putnode(&fs_m_in, &fs_m_out);
-       if (rc != OK) {
-               perror("fs_putnode");
-               /* likely error: get_block() failed */
-               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;
-}
-
-PUBLIC int uds_select(message *dev_m_in, message *dev_m_out)
-{
-       int i, bytes;
-       int minor;
-
-#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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       if (uds_fd_table[minor].state != UDS_INUSE) {
-
-               /* attempted to close 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.  */
-
-       uds_fd_table[minor].sel_ops_in = dev_m_in->USER_ENDPT;
-       uds_fd_table[minor].sel_ops_out = 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;
-                       }
-               }
-       }
-
-       /* check if we can write without blocking */
-       bytes = uds_perform_write(minor, dev_m_in->m_source, PIPE_BUF, 1);
-       if (bytes > 0) {
-               uds_fd_table[minor].sel_ops_out |= 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);
-
-       return uds_fd_table[minor].sel_ops_out;
-}
-
-PRIVATE int uds_perform_read(int minor, endpoint_t m_source,
-       size_t size, int pretend)
-{
-       int rc;
-       message fs_m_in;
-       message fs_m_out;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] uds_perform_read() call_count=%d\n", minor,
-                                                       ++call_count);
-#endif
-
-       /* 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;
-       }
-
-       if (uds_fd_table[minor].size == 0) {
-
-               if (pretend) {
-                       return SUSPEND;
-               }
-
-               /* maybe a process is blocked waiting to write? if
-                * needed revive the writer
-                */
-               if (uds_fd_table[minor].peer != -1 &&
-                       uds_fd_table[uds_fd_table[minor].peer].suspended) {
-                       int peer = uds_fd_table[minor].peer;
-
-                       uds_fd_table[peer].ready_to_revive = 1;
-                       uds_unsuspend(m_source, peer);
-               }
-
-#if DEBUG == 1
-               printf("(uds) [%d] suspending read request\n", minor);
-#endif
-
-               /* 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;
-       }
-
-       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_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_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) ?
-                               uds_fd_table[minor].size : size;
-
-       /* perform the read */
-       rc = fs_readwrite(&fs_m_in, &fs_m_out);
-       if (rc != OK) {
-               perror("fs_readwrite");
-               return rc;
-       }
-
-       /* Process the response */
-#if DEBUG == 1
-       printf("(uds) [%d] read complete\n", minor);
-#endif
-
-       /* move the position of the data pointer up to data we haven't
-        * read yet
-        */
-       uds_fd_table[minor].pos += fs_m_out.RES_NBYTES;
-
-       /* decrease the number of unread bytes */
-       uds_fd_table[minor].size -= fs_m_out.RES_NBYTES;
-
-       /* if we have 0 unread bytes, move the data pointer back to the
-        * start of the buffer
-        */
-       if (uds_fd_table[minor].size == 0) {
-               uds_fd_table[minor].pos = 0;
-       }
-
-       /* maybe a big write was waiting for us to read some data, if
-        * needed revive the writer
-        */
-       if (uds_fd_table[minor].peer != -1 &&
-                       uds_fd_table[uds_fd_table[minor].peer].suspended) {
-               int peer = uds_fd_table[minor].peer;
-
-               uds_fd_table[peer].ready_to_revive = 1;
-               uds_unsuspend(m_source, peer);
-       }
-
-       /* see if peer is blocked on select() and a write is possible
-        * (from peer to minor)
-        */
-       if (uds_fd_table[minor].peer != -1 &&
-               uds_fd_table[uds_fd_table[minor].peer].selecting == 1 &&
-               (uds_fd_table[minor].size + uds_fd_table[minor].pos + 1
-               < PIPE_BUF)) {
-
-               int peer = uds_fd_table[minor].peer;
-
-               /* if the peer wants to know about write being possible
-                * and it doesn't know about it already, then let the peer know.
-                */
-               if ((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);
-               }
-       }
-
-       return fs_m_out.RES_NBYTES; /* return number of bytes read */
-}
-
-PRIVATE int uds_perform_write(int minor, endpoint_t m_source,
-                                               size_t size, int pretend)
-{
-       int rc, peer, i;
-       message fs_m_in;
-       message fs_m_out;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] uds_perform_write() call_count=%d\n", minor,
-                                                       ++call_count);
-#endif
-
-       /* skip reads and writes of 0 (or less!) bytes */
-       if (size <= 0) {
-               return 0;
-       }
-
-       /* 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
-                */
-               if (uds_fd_table[minor].peer == -1) {
-                       if (uds_fd_table[minor].err == ECONNRESET) {
-
-                               uds_fd_table[minor].err = 0;
-                               return ECONNRESET;
-                       } else {
-                               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 */
-               for (i = 0; i < NR_FDS; i++) {
-
-                       /* look for a SOCK_DGRAM socket that is bound on
-                        * the target address
-                        */
-                       if (uds_fd_table[i].type == SOCK_DGRAM &&
-                               uds_fd_table[i].addr.sun_family == AF_UNIX &&
-                               !strncmp(uds_fd_table[minor].target.sun_path,
-                               uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {
-
-                               peer = i;
-                               break;
-                       }
-               }
-
-               if (peer == -1) {
-                       return ENOENT;
-               }
-       }
-
-       /* check if write would overrun buffer. check if message
-        * boundry preserving types (SEQPACKET and DGRAM) wouldn't write
-        * to an empty buffer. check if connectionless sockets have a
-        * target to write to.
-        */
-       if ((uds_fd_table[peer].pos+uds_fd_table[peer].size+size > PIPE_BUF) ||
-               ((uds_fd_table[minor].type == SOCK_SEQPACKET ||
-               uds_fd_table[minor].type == SOCK_DGRAM) &&
-               uds_fd_table[peer].size > 0) || (peer == -1)) {
-
-               if (pretend) {
-                       return SUSPEND;
-               }
-
-               /* 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 DEBUG == 1
-       printf("(uds) [%d] suspending write request\n", minor);
-#endif
-
-               /* 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;
-       }
-
-       if (pretend) {
-               return size;
-       }
-
-       /* Prepare Request to the FS side of PFS */
-       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_SEEK_POS_HI = 0;
-       fs_m_in.REQ_SEEK_POS_LO = uds_fd_table[peer].pos +
-                                       uds_fd_table[peer].size;
-       fs_m_in.REQ_NBYTES = size;
-
-       /* Request the write */
-       rc = fs_readwrite(&fs_m_in, &fs_m_out);
-       if (rc != OK) {
-               perror("fs_readwrite");
-               return rc;
-       }
-
-       /* Process the response */
-#if DEBUG == 1
-       printf("(uds) [%d] write complete\n", minor);
-#endif
-       /* 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,
-                                               sizeof(struct sockaddr_un));
-       }
-
-       /* 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)) {
-
-                       /* 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);
-               }
-       }
-
-       return fs_m_out.RES_NBYTES; /* return number of bytes written */
-}
-
-PUBLIC int uds_read(message *dev_m_in, message *dev_m_out)
-{
-       int bytes;
-       int minor;
-
-#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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       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_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;
-
-       /* 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;
-
-       bytes = uds_perform_read(minor, dev_m_in->m_source,
-                                       uds_fd_table[minor].io_gr_size, 0);
-
-       uds_set_reply(dev_m_out, DEV_REVIVE, uds_fd_table[minor].endpoint,
-                     uds_fd_table[minor].io_gr, bytes);
-
-       return bytes;
-}
-
-PUBLIC int uds_write(message *dev_m_in, message *dev_m_out)
-{
-       int bytes;
-       int minor;
-
-#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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       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_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;
-
-       /* 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;
-
-       bytes = uds_perform_write(minor, dev_m_in->m_source,
-                                       uds_fd_table[minor].io_gr_size, 0);
-
-       uds_set_reply(dev_m_out, DEV_REVIVE, uds_fd_table[minor].endpoint,
-                     uds_fd_table[minor].io_gr, bytes);
-
-       return bytes;
-}
-
-PUBLIC int uds_ioctl(message *dev_m_in, message *dev_m_out)
-{
-       int rc, minor;
-
-#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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       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_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;
-
-       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);
-
-                       break;
-
-               case NWIOSUDSPAIR:
-
-                       /* connect two sockets -- socketpair() */
-                       rc = do_socketpair(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOSUDSPAIROLD:
-
-                       /* connect two sockets -- socketpair() */
-                       rc = do_socketpair_old(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSSOTYPE:
-
-                       /* get socket type -- getsockopt(SO_TYPE) */
-                       rc = do_getsockopt_sotype(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSPEERCRED:
-
-                       /* get peer endpoint -- getsockopt(SO_PEERCRED) */
-                       rc = do_getsockopt_peercred(dev_m_in, dev_m_out);
-
-                       break;
-
-               case NWIOGUDSPEERCREDOLD:
-
-                       /* get peer endpoint -- getsockopt(SO_PEERCRED) */
-                       rc = do_getsockopt_peercred_old(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;
-
-               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;
-       }
-
-       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;
-}
-
-PUBLIC int uds_unsuspend(endpoint_t m_source, int minor)
-{
-       int r = OK, bytes;
-       message m_out;
-       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;
-
-               /* prepare the response */
-               uds_sel_reply(&m_out, DEV_SEL_REPL2, minor, fdp->sel_ops_out);
-       } else if (fdp->ready_to_revive == 1) {
-
-               /* clear the ready to revive flag */
-               fdp->ready_to_revive = 0;
-
-               switch (fdp->suspended) {
-
-                       case UDS_SUSPENDED_READ:
-
-                               bytes = uds_perform_read(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_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;
-
-                       default:
-                               return(OK);
-               }
-
-       }
-
-       if (r == OK) reply(m_source, &m_out);
-       return(r);
-}
-
-PUBLIC int uds_cancel(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       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_NO_STATUS, dev_m_in->USER_ENDPT,
-                             (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
-
-               return EINVAL;
-       }
-
-       /* Update the process endpoint. */
-       uds_fd_table[minor].endpoint = dev_m_in->USER_ENDPT;
-
-       /* setup select(2) framework */
-       uds_fd_table[minor].selecting = 0;
-
-       /* the system call was cancelled, so if the socket was suspended
-        * (which is likely the case), then it 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() */
-
-                                       /* partial connect() sets addr
-                                        * and adds minor to server backlog
-                                        */
-
-                                       for (i = 0; i < NR_FDS; i++) {
-
-                                               /* find a socket that is in
-                                                * use.
-                                                */
-                                               if (uds_fd_table[i].state ==
-                                                       UDS_INUSE) {
-
-                                                       /* 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;
-
-                               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;
-                       }
-
-               }
-
-               /* 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.
-                */
-
-               uds_fd_table[minor].syscall_done = 1;
-       }
-
-
-       uds_set_reply(dev_m_out, DEV_NO_STATUS, dev_m_in->USER_ENDPT,
-                       (cp_grant_id_t) dev_m_in->IO_GRANT, EINTR);
-
-       return EINTR;
-}
diff --git a/servers/apfs/fs.h b/servers/apfs/fs.h
deleted file mode 100644 (file)
index 2bc006a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-#ifndef __PFS_FS_H__
-#define __PFS_FS_H__
-
-/* This is the master header for pfs.  It includes some other files
- * and defines the principal constants.
- */
-#define _POSIX_SOURCE      1   /* tell headers to include POSIX stuff */
-#define _MINIX             1   /* tell headers to include MINIX stuff */
-#define _SYSTEM            1   /* tell headers that this is the kernel */
-
-/* The following are so basic, all the *.c files get them automatically. */
-#include <minix/config.h>      /* MUST be first */
-#include <minix/ansi.h>                /* MUST be second */
-#include <sys/types.h>
-#include <minix/const.h>
-#include <minix/type.h>
-#include <minix/dmap.h>
-#include <minix/vfsif.h>
-#include <limits.h>
-#include <errno.h>
-#include <minix/syslib.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <minix/sysutil.h>
-
-#include "const.h"
-#include "proto.h"
-#include "glo.h"
-
-#endif
diff --git a/servers/apfs/glo.h b/servers/apfs/glo.h
deleted file mode 100644 (file)
index 175b4fc..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef __PFS_GLO_H__
-#define __PFS_GLO_H__
-
-/* EXTERN should be extern except for the table file */
-#ifdef _TABLE
-#undef EXTERN
-#define EXTERN
-#endif
-
-#include <minix/vfsif.h>
-
-/* The following variables are used for returning results to the caller. */
-EXTERN int err_code;           /* temporary storage for error number */
-
-EXTERN _PROTOTYPE (int (*fs_call_vec[]), (message *fs_m_in, message *fs_m_out) ); /* fs call table */
-EXTERN _PROTOTYPE (int (*dev_call_vec[]), (message *fs_m_in, message *fs_m_out) ); /* dev call table */
-
-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;
-
-/* Inode map. */
-EXTERN bitchunk_t inodemap[FS_BITMAP_CHUNKS(NR_INODES)];
-
-#endif
diff --git a/servers/apfs/inc.h b/servers/apfs/inc.h
deleted file mode 100644 (file)
index 4484e80..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-
-#define _SYSTEM            1    /* get OK and negative error codes */
-#define _MINIX             1   /* tell headers to include MINIX stuff */
-
-#define VERBOSE                   0    /* display diagnostics */
-
-#ifdef __NBSD_LIBC
-#include <sys/ioc_net.h>
-#else
-#include <net/ioctl.h>
-#endif
-
-#include <minix/ansi.h>
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/stat.h>
-#include <limits.h>
-#include <errno.h>
-#include <signal.h>
-#include <unistd.h>
-
-#include <minix/callnr.h>
-#include <minix/config.h>
-#include <minix/dmap.h>
-#include <minix/type.h>
-#include <minix/const.h>
-#include <minix/com.h>
-#include <minix/syslib.h>
-#include <minix/sysutil.h>
-#include <minix/keymap.h>
-#include <minix/bitmap.h>
-
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <signal.h>
-
-#include "proto.h"
diff --git a/servers/apfs/inode.c b/servers/apfs/inode.c
deleted file mode 100644 (file)
index 98be692..0000000
+++ /dev/null
@@ -1,338 +0,0 @@
-/* This file manages the inode table.  There are procedures to allocate and
- * deallocate inodes, acquire, erase, and release them, and read and write
- * them from the disk.
- *
- * The entry points into this file are
- *   get_inode:           search inode table for a given inode; if not there,
- *                 read it
- *   put_inode:           indicate that an inode is no longer needed in memory
- *   alloc_inode:  allocate a new, unused inode
- *   wipe_inode:   erase some fields of a newly allocated inode
- *   free_inode:   mark an inode as available for a new file
- *   update_times: update atime, ctime, and mtime
- *   find_inode:   retrieve pointer to inode in inode cache
- *
- */
-
-#include "fs.h"
-#include "buf.h"
-#include "inode.h"
-#include <minix/vfsif.h>
-
-FORWARD _PROTOTYPE( void addhash_inode, (struct inode * const node)            );
-FORWARD _PROTOTYPE( void unhash_inode, (struct inode * const node)             );
-
-
-/*===========================================================================*
- *                             fs_putnode                                   *
- *===========================================================================*/
-PUBLIC int fs_putnode(message *fs_m_in, message *fs_m_out)
-{
-/* Find the inode specified by the request message and decrease its counter.*/
-
-  struct inode *rip;
-  int count;
-  dev_t dev;
-  ino_t inum;
-
-  rip = find_inode( (ino_t) fs_m_in->REQ_INODE_NR);
-
-  if(!rip) {
-         printf("%s:%d put_inode: inode #%ld dev: %d not found\n", __FILE__,
-                __LINE__, fs_m_in->REQ_INODE_NR, (dev_t) fs_m_in->REQ_DEV);
-         panic("fs_putnode failed");
-  }
-
-  count = fs_m_in->REQ_COUNT;
-  if (count <= 0) {
-       printf("%s:%d put_inode: bad value for count: %d\n", __FILE__,
-              __LINE__, count);
-       panic("fs_putnode failed");
-  } else if(count > rip->i_count) {
-       printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__,
-              __LINE__, count, rip->i_count);
-       panic("fs_putnode failed");
-  }
-
-  /* Decrease reference counter, but keep one reference; it will be consumed by
-   * put_inode(). */
-  rip->i_count -= count - 1;
-  dev = rip->i_dev;
-  inum = rip->i_num;
-  put_inode(rip);
-  if (rip->i_count == 0) put_block(dev, inum);
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             init_inode_cache                             *
- *===========================================================================*/
-PUBLIC void init_inode_cache()
-{
-  struct inode *rip;
-  struct inodelist *rlp;
-
-  /* init free/unused list */
-  TAILQ_INIT(&unused_inodes);
-
-  /* init hash lists */
-  for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp)
-      LIST_INIT(rlp);
-
-  /* add free inodes to unused/free list */
-  for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) {
-      rip->i_num = NO_ENTRY;
-      TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
-  }
-
-  /* Reserve the first inode (bit 0) to prevent it from being allocated later*/
-  if (alloc_bit() != NO_BIT) printf("PFS could not reserve NO_BIT\n");
-  busy = 0; /* This bit does not make the server 'in use/busy'. */
-}
-
-
-/*===========================================================================*
- *                             addhash_inode                                *
- *===========================================================================*/
-PRIVATE void addhash_inode(struct inode * const node)
-{
-  int hashi = (int) (node->i_num & INODE_HASH_MASK);
-
-  /* insert into hash table */
-  LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash);
-}
-
-
-/*===========================================================================*
- *                             unhash_inode                                 *
- *===========================================================================*/
-PRIVATE void unhash_inode(struct inode * const node)
-{
-  /* remove from hash table */
-  LIST_REMOVE(node, i_hash);
-}
-
-
-/*===========================================================================*
- *                             get_inode                                    *
- *===========================================================================*/
-PUBLIC struct inode *get_inode(
-  dev_t dev,           /* device on which inode resides */
-  ino_t numb           /* inode number */
-)
-{
-/* Find the inode in the hash table. If it is not there, get a free inode
- * load it from the disk if it's necessary and put on the hash list
- */
-  register struct inode *rip;
-  int hashi;
-
-  hashi = (int) (numb & INODE_HASH_MASK);
-
-  /* Search inode in the hash table */
-  LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
-       if (rip->i_num == numb && rip->i_dev == dev) {
-               /* If unused, remove it from the unused/free list */
-               if (rip->i_count == 0) {
-                       TAILQ_REMOVE(&unused_inodes, rip, i_unused);
-               }
-               ++rip->i_count;
-
-               return(rip);
-       }
-  }
-
-  /* Inode is not on the hash, get a free one */
-  if (TAILQ_EMPTY(&unused_inodes)) {
-      err_code = ENFILE;
-      return(NULL);
-  }
-  rip = TAILQ_FIRST(&unused_inodes);
-
-  /* If not free unhash it */
-  if (rip->i_num != NO_ENTRY) unhash_inode(rip);
-
-  /* Inode is not unused any more */
-  TAILQ_REMOVE(&unused_inodes, rip, i_unused);
-
-  /* Load the inode. */
-  rip->i_dev = dev;
-  rip->i_num = numb;
-  rip->i_count = 1;
-  rip->i_update = 0;           /* all the times are initially up-to-date */
-
-  /* Add to hash */
-  addhash_inode(rip);
-
-
-  return(rip);
-}
-
-
-/*===========================================================================*
- *                             find_inode                                   *
- *===========================================================================*/
-PUBLIC struct inode *find_inode(numb)
-ino_t numb;            /* inode number */
-{
-/* Find the inode specified by the inode and device number.
- */
-  struct inode *rip;
-  int hashi;
-
-  hashi = (int) (numb & INODE_HASH_MASK);
-
-  /* Search inode in the hash table */
-  LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
-      if (rip->i_count > 0 && rip->i_num == numb) {
-          return(rip);
-      }
-  }
-
-  return(NULL);
-}
-
-
-/*===========================================================================*
- *                             put_inode                                    *
- *===========================================================================*/
-PUBLIC void put_inode(rip)
-struct inode *rip;     /* pointer to inode to be released */
-{
-/* The caller is no longer using this inode.  If no one else is using it either
- * write it back to the disk immediately.  If it has no links, truncate it and
- * return it to the pool of available inodes.
- */
-
-  if (rip == NULL) return;     /* checking here is easier than in caller */
-
-  if (rip->i_count < 1)
-       panic("put_inode: i_count already below 1: %d", rip->i_count);
-
-  if (--rip->i_count == 0) {   /* i_count == 0 means no one is using it now */
-       if (rip->i_nlinks == NO_LINK) { /* Are there links to this file? */
-               /* no links, free the inode. */
-               truncate_inode(rip, 0); /* return all the disk blocks */
-               rip->i_mode = I_NOT_ALLOC;      /* clear I_TYPE field */
-               free_inode(rip);
-       } else {
-               truncate_inode(rip, (off_t) 0);
-       }
-
-       if (rip->i_nlinks == NO_LINK) {
-               /* free, put at the front of the LRU list */
-               unhash_inode(rip);
-               rip->i_num = NO_ENTRY;
-               rip->i_dev = NO_DEV;
-               rip->i_rdev = NO_DEV;
-               TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
-       } else {
-               /* unused, put at the back of the LRU (cache it) */
-               TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused);
-       }
-  }
-}
-
-
-/*===========================================================================*
- *                             alloc_inode                                  *
- *===========================================================================*/
-PUBLIC struct inode *alloc_inode(dev_t dev, mode_t bits)
-{
-/* Allocate a free inode on 'dev', and return a pointer to it. */
-
-  register struct inode *rip;
-  bit_t b;
-  ino_t i_num;
-  int print_oos_msg = 1;
-
-  b = alloc_bit();
-  if (b == NO_BIT) {
-       err_code = ENOSPC;
-       if (print_oos_msg)
-               printf("PipeFS is out of inodes\n");
-       print_oos_msg = 0;      /* Don't repeat message */
-       return(NULL);
-  }
-  i_num = (ino_t) b;
-  print_oos_msg = 1;
-
-
-  /* Try to acquire a slot in the inode table. */
-  if ((rip = get_inode(dev, i_num)) == NULL) {
-       /* No inode table slots available.  Free the inode if just allocated.*/
-       if (dev == NO_DEV) free_bit(b);
-  } else {
-       /* An inode slot is available. */
-
-       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 */
-
-       /* Fields not cleared already are cleared in wipe_inode().  They have
-        * been put there because truncate() needs to clear the same fields if
-        * the file happens to be open while being truncated.  It saves space
-        * not to repeat the code twice.
-        */
-       wipe_inode(rip);
-  }
-
-  return(rip);
-}
-
-
-/*===========================================================================*
- *                             wipe_inode                                   *
- *===========================================================================*/
-PUBLIC void wipe_inode(rip)
-struct inode *rip;     /* the inode to be erased */
-{
-/* Erase some fields in the inode.  This function is called from alloc_inode()
- * when a new inode is to be allocated, and from truncate(), when an existing
- * inode is to be truncated.
- */
-
-  rip->i_size = 0;
-  rip->i_update = ATIME | CTIME | MTIME;       /* update all times later */
-}
-
-
-/*===========================================================================*
- *                             free_inode                                   *
- *===========================================================================*/
-PUBLIC void free_inode(rip)
-struct inode *rip;
-{
-/* Return an inode to the pool of unallocated inodes. */
-
-  bit_t b;
-
-  if (rip->i_num <= (ino_t) 0 || rip->i_num >= (ino_t) NR_INODES) return;
-  b = (bit_t) rip->i_num;
-  free_bit(b);
-}
-
-
-/*===========================================================================*
- *                             update_times                                 *
- *===========================================================================*/
-PUBLIC void update_times(rip)
-struct inode *rip;     /* pointer to inode to be read/written */
-{
-/* Various system calls are required by the standard to update atime, ctime,
- * or mtime.  Since updating a time requires sending a message to the clock
- * task--an expensive business--the times are marked for update by setting
- * bits in i_update.  When a stat, fstat, or sync is done, or an inode is
- * released, update_times() may be called to actually fill in the times.
- */
-
-  time_t cur_time;
-
-  cur_time = clock_time();
-  if (rip->i_update & ATIME) rip->i_atime = cur_time;
-  if (rip->i_update & CTIME) rip->i_ctime = cur_time;
-  if (rip->i_update & MTIME) rip->i_mtime = cur_time;
-  rip->i_update = 0;           /* they are all up-to-date now */
-}
diff --git a/servers/apfs/inode.h b/servers/apfs/inode.h
deleted file mode 100644 (file)
index 19e5825..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef __PFS_INODE_H__
-#define __PFS_INODE_H__
-
-/* Inode table.  This table holds inodes that are currently in use.
- */
-
-#include <sys/queue.h>
-
-EXTERN struct inode {
-  mode_t i_mode;               /* file type, protection, etc. */
-  nlink_t i_nlinks;            /* how many links to this file */
-  uid_t i_uid;                 /* user id of the file's owner */
-  gid_t i_gid;                 /* group number */
-  off_t i_size;                        /* current file size in bytes */
-  time_t i_atime;              /* time of last access (V2 only) */
-  time_t i_mtime;              /* when was file data last changed */
-  time_t i_ctime;              /* when was inode itself changed (V2 only)*/
-
-  /* The following items are not present on the disk. */
-  dev_t i_dev;                 /* which device is the inode on */
-  dev_t i_rdev;                        /* which special device is the inode on */
-  ino_t i_num;                 /* inode number on its (minor) device */
-  int i_count;                 /* # times inode used; 0 means slot is free */
-  char i_update;               /* the ATIME, CTIME, and MTIME bits are here */
-
-  LIST_ENTRY(inode) i_hash;     /* hash list */
-  TAILQ_ENTRY(inode) i_unused;  /* free and unused list */
-
-
-} inode[NR_INODES];
-
-/* list of unused/free inodes */
-EXTERN TAILQ_HEAD(unused_inodes_t, inode)  unused_inodes;
-
-/* inode hashtable */
-EXTERN LIST_HEAD(inodelist, inode)         hash_inodes[INODE_HASH_SIZE];
-
-
-#endif
diff --git a/servers/apfs/link.c b/servers/apfs/link.c
deleted file mode 100644 (file)
index 4ec064e..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#include "fs.h"
-#include "buf.h"
-#include "inode.h"
-#include <minix/vfsif.h>
-
-/*===========================================================================*
- *                             fs_ftrunc                                    *
- *===========================================================================*/
-PUBLIC int fs_ftrunc(message *fs_m_in, message *fs_m_out)
-{
-  struct inode *rip;
-  off_t start, end;
-  ino_t inumb;
-
-  inumb = (ino_t) fs_m_in->REQ_INODE_NR;
-
-  if( (rip = find_inode(inumb)) == NULL) return(EINVAL);
-
-  start = fs_m_in->REQ_TRC_START_LO;
-  end = fs_m_in->REQ_TRC_END_LO;
-
-  return truncate_inode(rip, start);
-}
-
-
-/*===========================================================================*
- *                             truncate_inode                               *
- *===========================================================================*/
-PUBLIC int truncate_inode(rip, newsize)
-register struct inode *rip;    /* pointer to inode to be truncated */
-off_t newsize;                 /* inode must become this size */
-{
-/* Set inode to a certain size, freeing any zones no longer referenced
- * and updating the size in the inode. If the inode is extended, the
- * extra space is a hole that reads as zeroes.
- *
- * Nothing special has to happen to file pointers if inode is opened in
- * O_APPEND mode, as this is different per fd and is checked when
- * writing is done.
- */
-
-  /* Pipes can shrink, so adjust size to make sure all zones are removed. */
-  if(newsize != 0) return(EINVAL);     /* Only truncate pipes to 0. */
-  rip->i_size = newsize;
-
-  /* Next correct the inode size. */
-  wipe_inode(rip);     /* Pipes can only be truncated to 0. */
-
-  return(OK);
-}
diff --git a/servers/apfs/main.c b/servers/apfs/main.c
deleted file mode 100644 (file)
index f4f20f8..0000000
+++ /dev/null
@@ -1,197 +0,0 @@
-#include "fs.h"
-#include <assert.h>
-#include <signal.h>
-#include <minix/dmap.h>
-#include <minix/driver.h>
-#include <minix/endpoint.h>
-#include <minix/rs.h>
-#include <minix/vfsif.h>
-#include <sys/types.h>
-#include <pwd.h>
-#include "buf.h"
-#include "inode.h"
-#include "uds.h"
-
-FORWARD _PROTOTYPE(void get_work, (message *m_in)                      );
-
-/* SEF functions and variables. */
-FORWARD _PROTOTYPE( void sef_local_startup, (void) );
-FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
-
-/*===========================================================================*
- *                             main                                         *
- *===========================================================================*/
-PUBLIC int main(int argc, char *argv[])
-{
-/* This is the main routine of this service. The main loop consists of
- * 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;
-  message pfs_m_in;
-  message pfs_m_out;
-
-  /* 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);
-
-       transid = TRNS_GET_ID(pfs_m_in.m_type);
-       pfs_m_in.m_type = TRNS_DEL_ID(pfs_m_in.m_type);
-       if (pfs_m_in.m_type == 0) {
-               assert(!IS_VFS_FS_TRANSID(transid));
-               pfs_m_in.m_type = transid;
-               transid = 0;
-       } else
-               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)) {
-               ind = req_nr - VFS_BASE;
-               if (ind < 0 || ind >= FS_CALL_VEC_SIZE) {
-                       printf("pfs: bad FS request %d\n", req_nr);
-                       pfs_m_out.m_type = EINVAL;
-               } else {
-                       pfs_m_out.m_type =
-                               (*fs_call_vec[ind])(&pfs_m_in, &pfs_m_out);
-               }
-       } else {
-               printf("pfs: bad request %d\n", req_nr);
-               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);
-       }
-  }
-  return(OK);
-}
-
-/*===========================================================================*
- *                            sef_local_startup                             *
- *===========================================================================*/
-PRIVATE void sef_local_startup()
-{
-  /* Register init callbacks. */
-  sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fail);
-
-  /* No live update support for now. */
-
-  /* Register signal callbacks. */
-  sef_setcb_signal_handler(sef_cb_signal_handler);
-
-  /* Let SEF perform startup. */
-  sef_startup();
-}
-
-/*===========================================================================*
- *                         sef_cb_init_fresh                                *
- *===========================================================================*/
-PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
-{
-/* Initialize the pipe file server. */
-  int i;
-  struct passwd *pw;
-
-  /* Initialize main loop parameters. */
-  exitsignaled = 0;    /* No exit request seen yet. */
-  busy = 0;            /* Server is not 'busy' (i.e., inodes in use). */
-
-  /* Init inode table */
-  for (i = 0; i < NR_INODES; ++i) {
-       inode[i].i_count = 0;
-  }
-
-  init_inode_cache();
-  uds_init();
-  buf_pool();
-
-
-  /* Drop root privileges */
-  if ((pw = getpwnam(SERVICE_LOGIN)) == NULL) {
-       printf("PFS: unable to retrieve uid of SERVICE_LOGIN, "
-               "still running as root");
-  } else if (setuid(pw->pw_uid) != 0) {
-       panic("unable to drop privileges");
-  }
-
-  SELF_E = getprocnr();
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                        sef_cb_signal_handler                             *
- *===========================================================================*/
-PRIVATE void sef_cb_signal_handler(int signo)
-{
-  /* Only check for termination signal, ignore anything else. */
-  if (signo != SIGTERM) return;
-
-
-  exitsignaled = 1;
-}
-
-/*===========================================================================*
- *                             get_work                                     *
- *===========================================================================*/
-PRIVATE void get_work(m_in)
-message *m_in;                         /* pointer to message */
-{
-  int r, srcok = 0, status;
-  endpoint_t src;
-
-  do {
-       /* wait for a message */
-       if ((r = sef_receive_status(ANY, m_in, &status)) != OK)
-               panic("sef_receive_status failed: %d", r);
-       src = m_in->m_source;
-
-       if(src == VFS_PROC_NR) {
-               srcok = 1;              /* Normal FS request. */
-       } else
-               printf("PFS: unexpected source %d\n", src);
-  } while(!srcok);
-}
-
-
-/*===========================================================================*
- *                             reply                                        *
- *===========================================================================*/
-PUBLIC 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);
-}
diff --git a/servers/apfs/misc.c b/servers/apfs/misc.c
deleted file mode 100644 (file)
index 2f8e301..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#include "fs.h"
-
-
-/*===========================================================================*
- *                             fs_sync                                      *
- *===========================================================================*/
-PUBLIC int fs_sync(message *fs_m_in, message *fs_m_out)
-{
-/* Perform the sync() system call.  No-op on this FS. */
-
-  return(OK);          /* sync() can't fail */
-}
diff --git a/servers/apfs/open.c b/servers/apfs/open.c
deleted file mode 100644 (file)
index a7e2757..0000000
+++ /dev/null
@@ -1,52 +0,0 @@
-#include "fs.h"
-#include <sys/stat.h>
-#include "buf.h"
-#include "inode.h"
-#include <minix/vfsif.h>
-
-
-/*===========================================================================*
- *                             fs_newnode                                   *
- *===========================================================================*/
-PUBLIC int fs_newnode(message *fs_m_in, message *fs_m_out)
-{
-  register int r = OK;
-  mode_t bits;
-  struct inode *rip;
-  dev_t dev;
-
-  caller_uid = (uid_t) fs_m_in->REQ_UID;
-  caller_gid = (gid_t) fs_m_in->REQ_GID;
-  bits = (mode_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);
-
-  switch (bits & S_IFMT) {
-       case S_IFBLK:
-       case S_IFCHR:
-               rip->i_rdev = dev;              /* Major/minor dev numbers */
-               break;
-       case S_IFIFO:
-               if ((get_block(dev, rip->i_num)) == NULL)
-                       r = EIO;
-               break;
-       default:
-               r = EIO; /* Unsupported file type */
-  }
-
-  if (r != OK) {
-       free_inode(rip);
-  } else {
-       /* Fill in the fields of the response message */
-       fs_m_out->RES_INODE_NR = rip->i_num;
-       fs_m_out->RES_MODE = rip->i_mode;
-       fs_m_out->RES_FILE_SIZE_LO = rip->i_size;
-       fs_m_out->RES_UID = rip->i_uid;
-       fs_m_out->RES_GID = rip->i_gid;
-       fs_m_out->RES_DEV = dev;
-  }
-
-  return(r);
-}
diff --git a/servers/apfs/proto.h b/servers/apfs/proto.h
deleted file mode 100644 (file)
index 210e9d1..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-#ifndef __PFS_PROTO_H__
-#define __PFS_PROTO_H__
-
-/* Function prototypes. */
-
-/* Structs used in prototypes must be declared as such first. */
-struct buf;
-struct inode;
-struct sockaddr_un;
-struct ancillary;
-
-/* buffer.c */
-_PROTOTYPE( struct buf *get_block, (dev_t dev, ino_t inum)             );
-_PROTOTYPE( void put_block, (dev_t dev, ino_t inum)                    );
-
-/* cache.c */
-_PROTOTYPE( void buf_pool, (void)                                      );
-
-/* inode.c */
-_PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t mode)                );
-_PROTOTYPE( void dup_inode, (struct inode *ip)                         );
-_PROTOTYPE( struct inode *find_inode, (ino_t numb)                     );
-_PROTOTYPE( void free_inode, (struct inode *rip)                       );
-_PROTOTYPE( int fs_putnode, (message *fs_m_in, message *fs_m_out)      );
-_PROTOTYPE( void init_inode_cache, (void)                              );
-_PROTOTYPE( struct inode *get_inode, (dev_t dev, ino_t numb)           );
-_PROTOTYPE( void put_inode, (struct inode *rip)                                );
-_PROTOTYPE( void update_times, (struct inode *rip)                     );
-_PROTOTYPE( void wipe_inode, (struct inode *rip)                       );
-
-/* link.c */
-_PROTOTYPE( int fs_ftrunc, (message *fs_m_in, message *fs_m_out)       );
-_PROTOTYPE( int truncate_inode, (struct inode *rip, off_t newsize)     );
-
-
-/* main.c */
-_PROTOTYPE( void reply, (endpoint_t who, message *m_out)               );
-
-/* misc.c */
-_PROTOTYPE( int fs_sync, (message *fs_m_in, message *fs_m_out)         );
-
-/* mount.c */
-_PROTOTYPE( int fs_unmount, (message *fs_m_in, message *fs_m_out)      );
-
-/* open.c */
-_PROTOTYPE( int fs_newnode, (message *fs_m_in, message *fs_m_out)      );
-
-/* read.c */
-_PROTOTYPE( int fs_readwrite, (message *fs_m_in, message *fs_m_out)    );
-
-/* utility.c */
-_PROTOTYPE( time_t clock_time, (void)                                  );
-_PROTOTYPE( int no_sys, (message *pfs_m_in, message *pfs_m_out)                );
-
-/* stadir.c */
-_PROTOTYPE( int fs_stat, (message *fs_m_in, message *fs_m_out)         );
-
-/* super.c */
-_PROTOTYPE( bit_t alloc_bit, (void)                                    );
-_PROTOTYPE( void free_bit, (bit_t bit_returned)                                );
-
-/* dev_uds.c */
-_PROTOTYPE( int uds_open, (message *dev_m_in, message *dev_m_out)      );
-_PROTOTYPE( int uds_close, (message *dev_m_in, message *dev_m_out)     );
-_PROTOTYPE( int uds_read, (message *dev_m_in, message *dev_m_out)      );
-_PROTOTYPE( int uds_write, (message *dev_m_in, message *dev_m_out)     );
-_PROTOTYPE( int uds_ioctl, (message *dev_m_in, message *dev_m_out)     );
-_PROTOTYPE( int uds_select, (message *dev_m_in, message *dev_m_out)    );
-_PROTOTYPE( int uds_unsuspend, (endpoint_t m_source, int minor)                );
-_PROTOTYPE( int uds_cancel, (message *dev_m_in, message *dev_m_out)    );
-
-/* uds.c */
-_PROTOTYPE( void uds_init, (void)                                      );
-_PROTOTYPE( int do_accept, (message *dev_m_in, message *dev_m_out)     );
-_PROTOTYPE( int do_connect, (message *dev_m_in, message *dev_m_out)    );
-_PROTOTYPE( int do_listen, (message *dev_m_in, message *dev_m_out)     );
-_PROTOTYPE( int do_socket, (message *dev_m_in, message *dev_m_out)     );
-_PROTOTYPE( int do_bind, (message *dev_m_in, message *dev_m_out)       );
-_PROTOTYPE( int do_getsockname, (message *dev_m_in, message *dev_m_out)        );
-_PROTOTYPE( int do_getpeername, (message *dev_m_in, message *dev_m_out)        );
-_PROTOTYPE( int do_shutdown, (message *dev_m_in, message *dev_m_out)   );
-_PROTOTYPE( int do_socketpair, (message *dev_m_in, message *dev_m_out) );
-_PROTOTYPE( int do_socketpair_old, (message *dev_m_in, message *dev_m_out)     );
-_PROTOTYPE( int do_getsockopt_sotype,
-                               (message *dev_m_in, message *dev_m_out) );
-_PROTOTYPE( int do_getsockopt_peercred,
-                               (message *dev_m_in, message *dev_m_out) );
-_PROTOTYPE( int do_getsockopt_peercred_old,
-                               (message *dev_m_in, message *dev_m_out) );
-_PROTOTYPE( int do_getsockopt_sndbuf,
-                               (message *dev_m_in, message *dev_m_out) );
-_PROTOTYPE( int do_setsockopt_sndbuf,
-                               (message *dev_m_in, message *dev_m_out) );
-_PROTOTYPE( int do_getsockopt_rcvbuf,
-                               (message *dev_m_in, message *dev_m_out) );
-_PROTOTYPE( int do_setsockopt_rcvbuf,
-                               (message *dev_m_in, message *dev_m_out) );
-_PROTOTYPE( int do_sendto, (message *dev_m_in, message *dev_m_out)     );
-_PROTOTYPE( int do_recvfrom, (message *dev_m_in, message *dev_m_out)   );
-_PROTOTYPE( int do_sendmsg, (message *dev_m_in, message *dev_m_out)    );
-_PROTOTYPE( int do_recvmsg, (message *dev_m_in, message *dev_m_out)    );
-_PROTOTYPE( int perform_connection,
-                               (message *dev_m_in, message *dev_m_out,
-                               struct sockaddr_un *addr, int minorx,
-                               int minory)                             );
-_PROTOTYPE( int clear_fds, (int minor, struct ancillary *data)         );
-#endif
diff --git a/servers/apfs/read.c b/servers/apfs/read.c
deleted file mode 100644 (file)
index b4f06b8..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-#include "fs.h"
-#include "buf.h"
-#include <minix/com.h>
-#include "inode.h"
-
-
-/*===========================================================================*
- *                             fs_readwrite                                 *
- *===========================================================================*/
-PUBLIC int fs_readwrite(message *fs_m_in, message *fs_m_out)
-{
-  int r, rw_flag;
-  struct buf *bp;
-  cp_grant_id_t gid;
-  off_t position, f_size;
-  unsigned int nrbytes, cum_io;
-  mode_t mode_word;
-  struct inode *rip;
-  ino_t inumb;
-
-  r = OK;
-  cum_io = 0;
-  inumb = (ino_t) fs_m_in->REQ_INODE_NR;
-
-  /* Find the inode referred */
-  if ((rip = find_inode(inumb)) == NULL) return(EINVAL);
-
-  mode_word = rip->i_mode & I_TYPE;
-  if (mode_word != I_NAMED_PIPE) return(EIO);
-  f_size = rip->i_size;
-
-  /* Get the values from the request message */
-  rw_flag = (fs_m_in->m_type == REQ_READ ? READING : WRITING);
-  gid = (cp_grant_id_t) fs_m_in->REQ_GRANT;
-  position = fs_m_in->REQ_SEEK_POS_LO;
-  nrbytes = (unsigned) fs_m_in->REQ_NBYTES;
-
-  /* We can't read beyond the max file position */
-  if (nrbytes > MAX_FILE_POS) return(EFBIG);
-
-  if (rw_flag == WRITING) {
-         /* Check in advance to see if file will grow too big. */
-         /* Casting nrbytes to signed is safe, because it's guaranteed not to
-            be beyond max signed value (i.e., MAX_FILE_POS). */
-         if (position > PIPE_BUF - (signed) nrbytes) return(EFBIG);
-  }
-
-  /* Mark inode in use */
-  if ((get_inode(rip->i_dev, rip->i_num)) == NULL) return(err_code);
-  if ((bp = get_block(rip->i_dev, rip->i_num)) == NULL) return(err_code);
-
-  if (rw_flag == READING) {
-       /* Copy a chunk from the block buffer to user space. */
-       r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
-               (vir_bytes) (bp->b_data+position), (size_t) nrbytes, D);
-  } else {
-       /* Copy a chunk from user space to the block buffer. */
-       r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) 0,
-               (vir_bytes) (bp->b_data+position), (size_t) nrbytes, D);
-  }
-
-  if (r == OK) {
-       position += (signed) nrbytes; /* Update position */
-       cum_io += nrbytes;
-  }
-
-  fs_m_out->RES_SEEK_POS_LO = position; /* It might change later and the VFS
-                                          has to know this value */
-
-  /* On write, update file size and access time. */
-  if (rw_flag == WRITING) {
-         if (position > f_size) rip->i_size = position;
-  } else {
-       if(position >= rip->i_size) {
-               /* All data in the pipe is read, so reset pipe pointers */
-               rip->i_size = 0;        /* no data left */
-               position = 0;           /* reset reader(s) */
-       }
-  }
-
-  bp->b_bytes = position;
-  if (rw_flag == READING) rip->i_update |= ATIME;
-  if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
-  fs_m_out->RES_NBYTES = (size_t) cum_io;
-  put_inode(rip);
-  put_block(rip->i_dev, rip->i_num);
-
-  return(r);
-}
diff --git a/servers/apfs/stadir.c b/servers/apfs/stadir.c
deleted file mode 100644 (file)
index 7a49caf..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-#include "fs.h"
-#include "inode.h"
-#include <string.h>
-#include <sys/stat.h>
-
-
-/*===========================================================================*
- *                             stat_inode                                   *
- *===========================================================================*/
-PRIVATE int stat_inode(
-  register struct inode *rip,  /* pointer to inode to stat */
-  endpoint_t who_e,            /* Caller endpoint */
-  cp_grant_id_t gid            /* grant for the stat buf */
-)
-{
-/* Common code for stat and fstat system calls. */
-  mode_t type;
-  struct stat statbuf;
-  u32_t blocks; /* The unit of this is 512 */
-  int r, s;
-
-  type = rip->i_mode & I_TYPE;
-  s = (type == I_CHAR_SPECIAL || type == I_BLOCK_SPECIAL);
-
-  /* Update the atime, ctime, and mtime fields in the inode, if need be. */
-  if (rip->i_update) update_times(rip);
-
-  blocks = rip->i_size / S_BLKSIZE;
-  if (rip->i_size % S_BLKSIZE != 0)
-       blocks += 1;
-
-  memset(&statbuf, 0, sizeof(struct stat));
-
-  statbuf.st_dev = rip->i_dev;
-  statbuf.st_ino = rip->i_num;
-  statbuf.st_mode = rip->i_mode;
-  statbuf.st_nlink = rip->i_nlinks;
-  statbuf.st_uid = rip->i_uid;
-  statbuf.st_gid = (short int) rip->i_gid;
-  statbuf.st_rdev = (dev_t) (s ? rip->i_rdev : NO_DEV);
-  statbuf.st_size = rip->i_size;
-  if (!s)  statbuf.st_mode &= ~I_REGULAR;/* wipe out I_REGULAR bit for pipes */
-  statbuf.st_atime = rip->i_atime;
-  statbuf.st_mtime = rip->i_mtime;
-  statbuf.st_ctime = rip->i_ctime;
-  statbuf.st_blksize = PIPE_BUF;
-  statbuf.st_blocks = blocks;
-
-  /* Copy the struct to user space. */
-  r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf,
-               (size_t) sizeof(statbuf), D);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             fs_stat                                      *
- *===========================================================================*/
-PUBLIC int fs_stat(message *fs_m_in, message *fs_m_out)
-{
-  register int r;              /* return value */
-  register struct inode *rip;  /* target inode */
-
-  if( (rip = find_inode(fs_m_in->REQ_INODE_NR)) == NULL) return(EINVAL);
-  get_inode(rip->i_dev, rip->i_num);   /* mark inode in use */
-  r = stat_inode(rip, fs_m_in->m_source, (cp_grant_id_t) fs_m_in->REQ_GRANT);
-  put_inode(rip);                      /* release the inode */
-  return(r);
-}
diff --git a/servers/apfs/super.c b/servers/apfs/super.c
deleted file mode 100644 (file)
index 50f4e0b..0000000
+++ /dev/null
@@ -1,75 +0,0 @@
-/* This file manages the super block table and the related data structures,
- * namely, the bit maps that keep track of which zones and which inodes are
- * allocated and which are free.  When a new inode or zone is needed, the
- * appropriate bit map is searched for a free entry.
- *
- * The entry points into this file are
- *   alloc_bit:       somebody wants to allocate a zone or inode; find one
- *   free_bit:        indicate that a zone or inode is available for allocation
- */
-
-#include "fs.h"
-#include "buf.h"
-#include "inode.h"
-#include "const.h"
-
-
-/*===========================================================================*
- *                             alloc_bit                                    *
- *===========================================================================*/
-PUBLIC bit_t alloc_bit(void)
-{
-/* Allocate a bit from a bit map and return its bit number. */
-  bitchunk_t *wptr, *wlim;
-  bit_t b;
-  unsigned int i, bcount;
-
-  bcount = FS_BITMAP_CHUNKS(NR_INODES); /* Inode map has this many chunks. */
-  wlim = &inodemap[bcount]; /* Point to last chunk in inodemap. */
-
-  for (wptr = &inodemap[0]; wptr < wlim; wptr++) {
-       /* Does this word contain a free bit? */
-       if (*wptr == (bitchunk_t) ~0) continue; /* No. Go to next word */
-
-       /* Find and allocate the free bit. */
-       for (i = 0; (*wptr & (1 << i)) != 0; ++i) {}
-
-       /* Get inode number */
-       b = (bit_t) ((wptr - &inodemap[0]) * FS_BITCHUNK_BITS + i);
-
-       /* Don't allocate bits beyond end of map. */
-       if (b >= NR_INODES) break;
-
-       /* Allocate and return bit number. */
-       *wptr |= 1 << i;
-
-       /* Mark server 'busy' */
-       busy++;
-       return(b);
-  }
-
-  return(NO_BIT);                      /* no bit could be allocated */
-}
-
-
-/*===========================================================================*
- *                             free_bit                                     *
- *===========================================================================*/
-PUBLIC void free_bit(bit_returned)
-bit_t bit_returned;            /* number of bit to insert into the inode map*/
-{
-  bitchunk_t *k, mask;
-  bit_t bit;
-  unsigned word;
-
-  /* Get word offset and bit within offset */
-  word = (unsigned) (bit_returned / (bit_t) FS_BITCHUNK_BITS);
-  bit = bit_returned % (bit_t) FS_BITCHUNK_BITS;
-
-  /* Unset bit */
-  k = &inodemap[word];
-  mask = (unsigned) 1 << bit;
-  *k &= ~mask;
-
-  busy--; /* One inode less in use. */
-}
diff --git a/servers/apfs/table.c b/servers/apfs/table.c
deleted file mode 100644 (file)
index 760e5b2..0000000
+++ /dev/null
@@ -1,82 +0,0 @@
-
-/* This file contains the table used to map system call numbers onto the
- * routines that perform them.
- */
-
-#define _TABLE
-
-#include "fs.h"
-#include "inode.h"
-#include "buf.h"
-#include "uds.h"
-
-/* File System Handlers (pfs) */
-PUBLIC _PROTOTYPE (int (*fs_call_vec[]),
-                               (message *fs_m_in, message *fs_m_out) ) = {
-
-        no_sys,             /* 0   not used */
-        no_sys,             /* 1   */
-        fs_putnode,         /* 2   */
-        no_sys,             /* 3   */
-        fs_ftrunc,          /* 4   */
-        no_sys,             /* 5   */
-       no_sys,             /* 6   */
-        no_sys,             /* 7   */
-        fs_stat,            /* 8   */
-        no_sys,             /* 9   */
-        no_sys,             /* 10  */
-        no_sys,             /* 11  */
-        no_sys,             /* 12  */
-        no_sys,                    /* 13  */
-        no_sys,             /* 14  */
-        fs_unmount,         /* 15  */
-       fs_sync,            /* 16  */
-        no_sys,             /* 17  */
-        no_sys,                    /* 18  */
-        fs_readwrite,      /* 19  */
-        fs_readwrite,      /* 20  */
-        no_sys,             /* 21  */
-        no_sys,             /* 22  */
-        no_sys,             /* 23  */
-        no_sys,             /* 24  */
-        no_sys,             /* 25  */
-        no_sys,             /* 26  */
-        no_sys,             /* 27  */
-        no_sys,                    /* 28  */
-        fs_newnode,        /* 29  */
-        no_sys,                    /* 30  */
-        no_sys,                    /* 31  */
-       no_sys,             /* 32 */
-};
-
-/* Device Handlers (/dev/uds) */
-PUBLIC _PROTOTYPE (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 TTY_SETPGRP */
-        no_sys,             /* 11 TTY_EXIT */
-        uds_select,         /* 12 DEV_SELECT */
-        no_sys,             /* 13 DEV_STATUS */
-        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 */
-};
diff --git a/servers/apfs/uds.c b/servers/apfs/uds.c
deleted file mode 100644 (file)
index 18c70e1..0000000
+++ /dev/null
@@ -1,1623 +0,0 @@
-/*
- * Unix Domain Sockets Implementation (PF_UNIX, PF_LOCAL)
- * This code handles ioctl(2) commands to implement the socket API.
- * Some helper functions are also present.
- *
- * 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.
- *
- * Also see...
- *
- *   table.c, dev_uds.c, uds.h
- */
-
-#define DEBUG 0
-
-#include "inc.h"
-#include "const.h"
-#include "glo.h"
-#include "uds.h"
-
-/* File Descriptor Table */
-uds_fd_t uds_fd_table[NR_FDS];
-
-/* initialize the descriptor table */
-PUBLIC void uds_init(void)
-{
-       /*
-        * Setting everything to NULL implicitly sets the
-        * state to UDS_FREE.
-        */
-       memset(uds_fd_table, '\0', sizeof(uds_fd_t) * NR_FDS);
-}
-
-/* check the permissions of a socket file */
-PRIVATE int check_perms(int minor, struct sockaddr_un *addr)
-{
-       int rc;
-       message vfs_m;
-       cp_grant_id_t grant_id;
-
-       grant_id = cpf_grant_direct(VFS_PROC_NR, (vir_bytes) addr->sun_path,
-                                       UNIX_PATH_MAX, CPF_READ | CPF_WRITE);
-
-       /* ask the VFS to verify the permissions */
-       memset(&vfs_m, '\0', sizeof(message));
-
-       vfs_m.m_type = PFS_REQ_CHECK_PERMS;
-       vfs_m.USER_ENDPT = uds_fd_table[minor].owner;
-       vfs_m.IO_GRANT = (char *) grant_id;
-       vfs_m.COUNT = UNIX_PATH_MAX;
-
-       rc = sendrec(VFS_PROC_NR, &vfs_m);
-       cpf_revoke(grant_id);
-       if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",
-                       vfs_m.m_type, rc);
-
-               return EIO;
-       }
-
-#if DEBUG == 1
-       printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-       printf("(uds) Canonical Path => %s\n", addr->sun_path);
-#endif
-
-       return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
-}
-
-PRIVATE filp_id_t verify_fd(endpoint_t ep, int fd)
-{
-       int rc;
-       message vfs_m;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) verify_fd(%d,%d) call_count=%d\n", ep, fd,
-                                                       ++call_count);
-#endif
-
-       memset(&vfs_m, '\0', sizeof(message));
-
-       vfs_m.m_type = PFS_REQ_VERIFY_FD;
-       vfs_m.USER_ENDPT = ep;
-       vfs_m.COUNT = fd;
-
-       rc = sendrec(VFS_PROC_NR, &vfs_m);
-       if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",
-                       vfs_m.m_type, rc);
-               return NULL;
-       }
-
-#if DEBUG == 1
-       printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
-
-       return vfs_m.ADDRESS;
-}
-
-PRIVATE int set_filp(filp_id_t sfilp)
-{
-       int rc;
-       message vfs_m;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) set_filp(0x%x) call_count=%d\n", sfilp, ++call_count);
-#endif
-
-       memset(&vfs_m, '\0', sizeof(message));
-
-       vfs_m.m_type = PFS_REQ_SET_FILP;
-       vfs_m.ADDRESS = sfilp;
-
-       rc = sendrec(VFS_PROC_NR, &vfs_m);
-       if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",
-                       vfs_m.m_type, rc);
-               return EIO;
-       }
-
-#if DEBUG == 1
-       printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
-       return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
-}
-
-PRIVATE int copy_filp(endpoint_t to_ep, filp_id_t cfilp)
-{
-       int rc;
-       message vfs_m;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) copy_filp(%d, 0x%x) call_count=%d\n",to_ep, cfilp,
-                                                       ++call_count);
-#endif
-
-       memset(&vfs_m, '\0', sizeof(message));
-
-       vfs_m.m_type = PFS_REQ_COPY_FILP;
-       vfs_m.USER_ENDPT = to_ep;
-       vfs_m.ADDRESS = cfilp;
-
-       rc = sendrec(VFS_PROC_NR, &vfs_m);
-       if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",
-                       vfs_m.m_type, rc);
-               return EIO;
-       }
-
-#if DEBUG == 1
-       printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
-       return vfs_m.m_type;
-}
-
-PRIVATE int put_filp(filp_id_t pfilp)
-{
-       int rc;
-       message vfs_m;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) put_filp(0x%x) call_count=%d\n", pfilp, ++call_count);
-#endif
-
-       memset(&vfs_m, '\0', sizeof(message));
-
-       vfs_m.m_type = PFS_REQ_PUT_FILP;
-       vfs_m.ADDRESS = pfilp;
-
-       rc = sendrec(VFS_PROC_NR, &vfs_m);
-       if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",
-                       vfs_m.m_type, rc);
-               return EIO;
-       }
-
-#if DEBUG == 1
-       printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
-       return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
-}
-
-PRIVATE int cancel_fd(endpoint_t ep, int fd)
-{
-       int rc;
-       message vfs_m;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) cancel_fd(%d,%d) call_count=%d\n", ep, fd, ++call_count);
-#endif
-
-       memset(&vfs_m, '\0', sizeof(message));
-
-       vfs_m.m_type = PFS_REQ_CANCEL_FD;
-       vfs_m.USER_ENDPT = ep;
-       vfs_m.COUNT = fd;
-
-       rc = sendrec(VFS_PROC_NR, &vfs_m);
-       if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",
-                       vfs_m.m_type, rc);
-               return EIO;
-       }
-
-#if DEBUG == 1
-       printf("(uds) VFS reply => %d\n", vfs_m.m_type);
-#endif
-       return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
-}
-
-PUBLIC int perform_connection(message *dev_m_in, message *dev_m_out,
-                       struct sockaddr_un *addr, int minorx, int minory)
-{
-       /* there are several places were a connection is established. */
-       /* accept(2), connect(2), uds_status(2), socketpair(2)        */
-       /* This is a helper function to make sure it is done in the   */
-       /* same way in each place with the same validation checks.    */
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] perform_connection() call_count=%d\n",
-                                       uds_minor(dev_m_in), ++call_count);
-#endif
-
-       /* only connection oriented types are acceptable and only like
-        * types can connect to each other
-        */
-       if ((uds_fd_table[minorx].type != SOCK_SEQPACKET &&
-               uds_fd_table[minorx].type != SOCK_STREAM) ||
-               uds_fd_table[minorx].type != uds_fd_table[minory].type) {
-
-               /* sockets are not in a valid state */
-               return EINVAL;
-       }
-
-       /* connect the pair of sockets */
-       uds_fd_table[minorx].peer = minory;
-       uds_fd_table[minory].peer = minorx;
-
-       /* Set the address of both sockets */
-       memcpy(&(uds_fd_table[minorx].addr), addr, sizeof(struct sockaddr_un));
-       memcpy(&(uds_fd_table[minory].addr), addr, sizeof(struct sockaddr_un));
-
-       return OK;
-}
-
-
-PUBLIC int do_accept(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       int minorparent; /* minor number of parent (server) */
-       int 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);
-#endif
-
-       /* Somewhat weird logic is used in this function, so here's an
-        * overview... The minor number is the server's client socket
-        * (the socket to be returned by accept()). The data waiting
-        * for us in the IO Grant is the address that the server is
-        * listening on. This function uses the address to find the
-        * server's descriptor. From there we can perform the
-        * 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),
-               D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       /* locate server socket */
-       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,
-                               UNIX_PATH_MAX) &&
-                               uds_fd_table[i].listening == 1) {
-
-                       rc = 0;
-                       break;
-               }
-       }
-
-       if (rc == -1) {
-               /* there is no server listening on addr. Maybe someone
-                * screwed up the ioctl()?
-                */
-               return EINVAL;
-       }
-
-       minorparent = i; /* parent */
-
-       /* we are the parent's child */
-       uds_fd_table[minorparent].child = minor;
-
-       /* the peer has the same type as the parent. we need to be that
-        * type too.
-        */
-       uds_fd_table[minor].type = uds_fd_table[minorparent].type;
-
-       /* locate peer to accept in the parent's backlog */
-       minorpeer = -1; /* to trap error */
-       for (i = 0; i < uds_fd_table[minorparent].backlog_size; i++) {
-               if (uds_fd_table[minorparent].backlog[i] != -1) {
-                       minorpeer = uds_fd_table[minorparent].backlog[i];
-                       uds_fd_table[minorparent].backlog[i] = -1;
-                       rc = 0;
-                       break;
-               }
-       }
-
-       if (minorpeer == -1) {
-
-#if DEBUG == 1
-               printf("(uds) [%d] {do_accept} suspend\n", minor);
-#endif
-
-               /* there are no peers in the backlog, suspend and wait
-                * for some to show up
-                */
-               uds_fd_table[minor].suspended = UDS_SUSPENDED_ACCEPT;
-
-               return SUSPEND;
-       }
-
-#if DEBUG == 1
-       printf("(uds) [%d] connecting to %d -- parent is %d\n", minor,
-                                               minorpeer, minorparent);
-#endif
-
-       rc = perform_connection(dev_m_in, dev_m_out, &addr, minor, minorpeer);
-       if (rc != OK) {
-#if DEBUG == 1
-               printf("(uds) [%d] {do_accept} connection not performed\n",
-                                                               minor);
-#endif
-               return rc;
-       }
-
-       uds_fd_table[minorparent].child = -1;
-
-       /* if peer is blocked on connect() revive peer */
-       if (uds_fd_table[minorpeer].suspended) {
-#if DEBUG == 1
-               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);
-       }
-
-       return OK;
-}
-
-PUBLIC int do_connect(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       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);
-#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) {
-               return EINVAL;
-       }
-
-       if (uds_fd_table[minor].peer != -1) {
-               /* socket is already connected */
-               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), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       rc = check_perms(minor, &addr);
-       if (rc != OK) {
-               /* permission denied, socket file doesn't exist, etc. */
-               return rc;
-       }
-
-       /* look for a socket of the same type that is listening on the
-        * 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 &&
-                       !strncmp(addr.sun_path, uds_fd_table[i].addr.sun_path,
-                       UNIX_PATH_MAX)) {
-
-                       if (uds_fd_table[i].child != -1) {
-
-                               /* the server is blocked on accept(2) --
-                                * perform connection to the child
-                                */
-
-                               rc = perform_connection(dev_m_in, dev_m_out,
-                                       &addr, minor, uds_fd_table[i].child);
-
-                               if (rc == OK) {
-
-                                       uds_fd_table[i].child = -1;
-
-#if DEBUG == 1
-                       printf("(uds) [%d] {do_connect} revive %d\n", minor, i);
-#endif
-
-                                       /* wake the parent (server) */
-                                       uds_fd_table[i].ready_to_revive = 1;
-                                       uds_unsuspend(dev_m_in->m_source, i);
-                               }
-
-                               return rc;
-
-                       } else {
-
-#if DEBUG == 1
-                               printf("(uds) [%d] adding to %d's backlog\n",
-                                                               minor, i);
-#endif
-
-                               /* tell the server were waiting to be served */
-
-                               /* look for a free slot in the backlog */
-                               rc = -1; /* to trap error */
-                               for (j = 0; j < uds_fd_table[i].backlog_size;
-                                       j++) {
-
-                                       if (uds_fd_table[i].backlog[j] == -1) {
-
-                                               uds_fd_table[i].backlog[j] =
-                                                       minor;
-
-                                               rc = 0;
-                                               break;
-                                       }
-                               }
-
-                               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_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);
-                                       }
-                               }
-
-                               /* we found our server */
-                               uds_fd_table[minor].peer = i;
-
-                               /* set the address */
-                               memcpy(&(uds_fd_table[minor].addr), &addr,
-                                       sizeof(struct sockaddr_un));
-
-                               break;
-                       }
-               }
-       }
-
-       if (uds_fd_table[minor].peer == -1) {
-               /* could not find another open socket listening on the
-                * specified address with room in the backlog
-                */
-               return ECONNREFUSED;
-       }
-
-#if DEBUG == 1
-       printf("(uds) [%d] {do_connect} suspend\n", minor);
-#endif
-
-       /* suspend until the server side completes the connection with accept()
-        */
-
-       uds_fd_table[minor].suspended = UDS_SUSPENDED_CONNECT;
-
-       return SUSPEND;
-}
-
-PUBLIC int do_listen(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#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) {
-
-               /* probably trying to call listen() before bind() */
-               return EINVAL;
-       }
-
-       /* the two supported types for listen(2) are SOCK_STREAM and
-        * SOCK_SEQPACKET
-        */
-       if (uds_fd_table[minor].type != SOCK_STREAM &&
-                       uds_fd_table[minor].type != SOCK_SEQPACKET) {
-
-               /* probably trying to call listen() with a SOCK_DGRAM */
-               return EOPNOTSUPP;
-       }
-
-       /* The POSIX standard doesn't say what to do if listen() has
-        * already been called. Well, there isn't an errno. we silently
-        * 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), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       if (uds_fd_table[minor].listening == 0) {
-
-               /* See if backlog_size is between 0 and UDS_SOMAXCONN */
-               if (backlog_size >= 0 && backlog_size < UDS_SOMAXCONN) {
-
-                       /* use the user provided backlog_size */
-                       uds_fd_table[minor].backlog_size = backlog_size;
-
-               } else {
-
-                       /* the user gave an invalid size, use
-                        * UDS_SOMAXCONN instead
-                        */
-                       uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;
-               }
-       } else {
-
-               /* See if the user is trying to expand the backlog_size */
-               if (backlog_size > uds_fd_table[minor].backlog_size &&
-                       backlog_size < UDS_SOMAXCONN) {
-
-                       /* expand backlog_size */
-                       uds_fd_table[minor].backlog_size = backlog_size;
-               }
-
-               /* Don't let the user shrink the backlog_size (we might
-                * have clients waiting in those slots
-                */
-       }
-
-       /* perform listen(2) */
-       uds_fd_table[minor].listening = 1;
-
-       return OK;
-}
-
-PUBLIC int do_socket(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#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 */
-               return EINVAL;
-       }
-
-       /* 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), D);
-
-       if (rc != OK) {
-
-               /* something went wrong and we couldn't get the type */
-               return EIO;
-       }
-
-       /* validate the type */
-       switch (uds_fd_table[minor].type) {
-               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.
-                        */
-
-                       /* set the type back to '-1' (no type set) */
-                       uds_fd_table[minor].type = -1;
-
-                       return EINVAL;
-       }
-}
-
-PUBLIC int do_bind(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#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)) {
-
-               /* the type hasn't been set by do_socket() yet OR attempting
-                * to re-bind() a non-SOCK_DGRAM socket
-                */
-               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),
-               D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       /* 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;
-       }
-
-       rc = check_perms(minor, &addr);
-       if (rc != OK) {
-               /* permission denied, socket file doesn't exist, etc. */
-               return rc;
-       }
-
-       /* make sure the address isn't already in use by another socket. */
-       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, UNIX_PATH_MAX)) {
-
-                       /* another socket is bound to this sun_path */
-                       return EADDRINUSE;
-               }
-       }
-
-       /* looks good, perform the bind() */
-       memcpy(&(uds_fd_table[minor].addr), &addr, sizeof(struct sockaddr_un));
-
-       return OK;
-}
-
-PUBLIC int do_getsockname(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#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),
-               sizeof(struct sockaddr_un), D);
-
-       return rc ? EIO : OK;
-}
-
-PUBLIC int do_getpeername(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#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;
-
-               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),
-                       sizeof(struct sockaddr_un), D);
-
-               return rc ? EIO : OK;
-       } else {
-               if (uds_fd_table[minor].err == ECONNRESET) {
-                       uds_fd_table[minor].err = 0;
-
-                       return ECONNRESET;
-               } else {
-                       return ENOTCONN;
-               }
-       }
-}
-
-PUBLIC int do_shutdown(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       if (uds_fd_table[minor].type != SOCK_STREAM &&
-                       uds_fd_table[minor].type != SOCK_SEQPACKET) {
-
-               /* socket must be a connection oriented socket */
-               return EINVAL;
-       }
-
-       if (uds_fd_table[minor].peer == -1) {
-               /* shutdown(2) is only valid for connected sockets */
-               if (uds_fd_table[minor].err == ECONNRESET) {
-                       return ECONNRESET;
-               } else {
-                       return ENOTCONN;
-               }
-       }
-
-       /* 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), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       switch (how) {
-               case SHUT_RD:
-                       /* take away read permission */
-                       uds_fd_table[minor].mode =
-                               uds_fd_table[minor].mode ^ S_IRUSR;
-                       break;
-
-               case SHUT_WR:
-                       /* take away write permission */
-                       uds_fd_table[minor].mode =
-                               uds_fd_table[minor].mode ^ S_IWUSR;
-                       break;
-
-               case SHUT_RDWR:
-                       /* completely shutdown */
-                       uds_fd_table[minor].mode = 0;
-                       break;
-
-               default:
-                       /* the 'how' parameter is invalid */
-                       return EINVAL;
-       }
-
-       return OK;
-}
-
-PUBLIC int do_socketpair_old(message *dev_m_in, message *dev_m_out)
-{
-       int rc;
-       short minorin;
-       int minorx, 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);
-#endif
-
-       /* first ioctl param is the first socket */
-       minorx = uds_minor_old(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(short), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       minory = minor(minorin);
-
-#if DEBUG == 1
-       printf("socketpair() %d - %d\n", minorx, minory);
-#endif
-
-       /* 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
-                */
-               return EPERM;
-       }
-
-       addr.sun_family = AF_UNIX;
-       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);
-}
-
-PUBLIC int do_socketpair(message *dev_m_in, message *dev_m_out)
-{
-       int rc;
-       dev_t minorin;
-       int minorx, 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);
-#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), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       minory = minor(minorin);
-
-#if DEBUG == 1
-       printf("socketpair() %d - %d\n", minorx, minory);
-#endif
-
-       /* 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
-                */
-               return EPERM;
-       }
-
-       addr.sun_family = AF_UNIX;
-       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);
-}
-
-PUBLIC int do_getsockopt_sotype(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#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), D);
-
-       return rc ? EIO : OK;
-}
-
-PUBLIC int do_getsockopt_peercred(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       int peer_minor;
-       int rc;
-       struct ucred 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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       if (uds_fd_table[minor].peer == -1) {
-
-               if (uds_fd_table[minor].err == ECONNRESET) {
-                       uds_fd_table[minor].err = 0;
-
-                       return ECONNRESET;
-               } else {
-                       return ENOTCONN;
-               }
-       }
-
-       peer_minor = uds_fd_table[minor].peer;
-
-       /* obtain the peer's credentials */
-       rc = getnucred(uds_fd_table[peer_minor].owner, &cred);
-       if (rc == -1) {
-               /* likely error: invalid endpoint / proc doesn't exist */
-               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 ucred), D);
-
-       return rc ? EIO : OK;
-}
-
-PUBLIC int do_getsockopt_peercred_old(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       int peer_minor;
-       int rc;
-       struct ucred cred;
-       struct ucred_old cred_old;
-
-#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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-       if (uds_fd_table[minor].peer == -1) {
-
-               if (uds_fd_table[minor].err == ECONNRESET) {
-                       uds_fd_table[minor].err = 0;
-
-                       return ECONNRESET;
-               } else {
-                       return ENOTCONN;
-               }
-       }
-
-       peer_minor = uds_fd_table[minor].peer;
-
-       /* obtain the peer's credentials */
-       rc = getnucred(uds_fd_table[peer_minor].owner, &cred);
-       if (rc == -1) {
-               /* likely error: invalid endpoint / proc doesn't exist */
-               return errno;
-       }
-
-       /* copy to old structure */
-       cred_old.pid = cred.pid;
-       cred_old.uid = (short) cred.uid;
-       cred_old.gid = (char) cred.gid;
-
-       rc = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-               (vir_bytes) 0, (vir_bytes) &cred_old, sizeof(struct ucred_old),
-               D);
-
-       return rc ? EIO : OK;
-}
-
-int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       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);
-#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) &(sndbuf),
-               sizeof(size_t), D);
-
-       return rc ? EIO : OK;
-}
-
-int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                               (vir_bytes) 0, (vir_bytes) &sndbuf,
-                               sizeof(size_t), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       if (sndbuf > PIPE_BUF) {
-               /* The send buffer is limited to 32K at the moment. */
-               return ENOSYS;
-       }
-
-       /* There is no way to reduce the send buffer, do we have to
-        * let this call fail for smaller buffers?
-        */
-       return OK;
-}
-
-int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       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);
-#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) &(rcvbuf),
-               sizeof(size_t), D);
-
-       return rc ? EIO : OK;
-}
-
-int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       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);
-#endif
-
-       minor = uds_minor(dev_m_in);
-
-
-       rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                               (vir_bytes) 0, (vir_bytes) &rcvbuf,
-                               sizeof(size_t), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       if (rcvbuf > PIPE_BUF) {
-               /* The send buffer is limited to 32K at the moment. */
-               return ENOSYS;
-       }
-
-       /* There is no way to reduce the send buffer, do we have to
-        * let this call fail for smaller buffers?
-        */
-       return OK;
-}
-
-
-PUBLIC int do_sendto(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#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),
-               D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       /* do some basic sanity checks on the address */
-       if (addr.sun_family != AF_UNIX || addr.sun_path[0] == '\0') {
-               /* bad address */
-               return EINVAL;
-       }
-
-       rc = check_perms(minor, &addr);
-       if (rc != OK) {
-               return rc;
-       }
-
-       memcpy(&(uds_fd_table[minor].target), &addr,
-                                       sizeof(struct sockaddr_un));
-
-       return OK;
-}
-
-PUBLIC int do_recvfrom(message *dev_m_in, message *dev_m_out)
-{
-       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);
-#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),
-               sizeof(struct sockaddr_un), D);
-
-       return rc ? EIO : OK;
-}
-
-int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
-                                                       int minor)
-{
-       int rc;
-       struct msghdr msghdr;
-       struct cmsghdr *cmsg = NULL;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] msg_control_read() call_count=%d\n", minor,
-                                                       ++call_count);
-#endif
-
-       data->nfiledes = 0;
-
-       memset(&msghdr, '\0', sizeof(struct msghdr));
-       msghdr.msg_control = msg_ctrl->msg_control;
-       msghdr.msg_controllen = msg_ctrl->msg_controllen;
-
-       for(cmsg = CMSG_FIRSTHDR(&msghdr); cmsg != NULL;
-                                       cmsg = CMSG_NXTHDR(&msghdr, cmsg)) {
-
-               if (cmsg->cmsg_level == SOL_SOCKET &&
-                                       cmsg->cmsg_type == SCM_RIGHTS) {
-
-                       int i;
-                       int nfds =
-                               MIN((cmsg->cmsg_len-CMSG_LEN(0))/sizeof(int),
-                                                               OPEN_MAX);
-
-                       for (i = 0; i < nfds; i++) {
-                               if (data->nfiledes == OPEN_MAX) {
-                                       return EOVERFLOW;
-                               }
-
-                               data->fds[data->nfiledes] =
-                                       ((int *) CMSG_DATA(cmsg))[i];
-#if DEBUG == 1
-                               printf("(uds) [%d] fd[%d]=%d\n", minor,
-                               data->nfiledes, data->fds[data->nfiledes]);
-#endif
-                               data->nfiledes++;
-                       }
-               }
-       }
-
-       /* obtain this socket's credentials */
-       rc = getnucred(uds_fd_table[minor].owner, &(data->cred));
-       if (rc == -1) {
-               return errno;
-       }
-#if DEBUG == 1
-       printf("(uds) [%d] cred={%d,%d,%d}\n", minor,
-               data->cred.pid, data->cred.uid,
-               data->cred.gid);
-#endif
-       return OK;
-}
-
-PRIVATE int send_fds(int minor, struct ancillary *data)
-{
-       int rc, i, j;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] send_fds() call_count=%d\n", minor, ++call_count);
-#endif
-
-       /* verify the file descriptors and get their filps. */
-       for (i = 0; i < data->nfiledes; i++) {
-               data->filps[i] = verify_fd(uds_fd_table[minor].owner,
-                                               data->fds[i]);
-
-               if (data->filps[i] == NULL) {
-                       return EINVAL;
-               }
-       }
-
-       /* set them as in-flight */
-       for (i = 0; i < data->nfiledes; i++) {
-               rc = set_filp(data->filps[i]);
-               if (rc != OK) {
-                       /* revert set_filp() calls */
-                       for (j = i; j >= 0; j--) {
-                               put_filp(data->filps[j]);
-                       }
-                       return rc;
-               }
-       }
-
-       return OK;
-}
-
-PUBLIC int clear_fds(int 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
- * exists references to file descriptors that haven't been received
- * with recvmsg().
- */
-       int i;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] recv_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]);
-#endif
-               data->fds[i] = -1;
-               data->filps[i] = NULL;
-       }
-
-       data->nfiledes = 0;
-
-       return OK;
-}
-
-PRIVATE int recv_fds(int minor, struct ancillary *data,
-                                       struct msg_control *msg_ctrl)
-{
-       int rc, i, j;
-       struct msghdr msghdr;
-       struct cmsghdr *cmsg;
-       endpoint_t to_ep;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] recv_fds() call_count=%d\n", minor,
-                                                       ++call_count);
-#endif
-
-       msghdr.msg_control = msg_ctrl->msg_control;
-       msghdr.msg_controllen = msg_ctrl->msg_controllen;
-
-       cmsg = CMSG_FIRSTHDR(&msghdr);
-       cmsg->cmsg_len = CMSG_LEN(sizeof(int) * data->nfiledes);
-       cmsg->cmsg_level = SOL_SOCKET;
-       cmsg->cmsg_type = SCM_RIGHTS;
-
-       to_ep = uds_fd_table[minor].owner;
-
-       /* copy to the target endpoint */
-       for (i = 0; i < data->nfiledes; i++) {
-               rc = copy_filp(to_ep, data->filps[i]);
-               if (rc < 0) {
-                       /* revert set_filp() calls */
-                       for (j = 0; j < data->nfiledes; j++) {
-                               put_filp(data->filps[j]);
-                       }
-                       /* revert copy_filp() calls */
-                       for (j = i; j >= 0; j--) {
-                               cancel_fd(to_ep, data->fds[j]);
-                       }
-                       return rc;
-               }
-               data->fds[i] = rc; /* data->fds[i] now has the new FD */
-       }
-
-       for (i = 0; i < data->nfiledes; i++) {
-               put_filp(data->filps[i]);
-#if DEBUG == 1
-               printf("(uds) recv_fds() => %d\n", data->fds[i]);
-#endif
-               ((int *)CMSG_DATA(cmsg))[i] = data->fds[i];
-               data->fds[i] = -1;
-               data->filps[i] = NULL;
-       }
-
-       data->nfiledes = 0;
-
-       return OK;
-}
-
-PRIVATE int recv_cred(int minor, struct ancillary *data,
-                                       struct msg_control *msg_ctrl)
-{
-       struct msghdr msghdr;
-       struct cmsghdr *cmsg;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] recv_cred() call_count=%d\n", minor,
-                                                       ++call_count);
-#endif
-
-       msghdr.msg_control = msg_ctrl->msg_control;
-       msghdr.msg_controllen = msg_ctrl->msg_controllen;
-
-       cmsg = CMSG_FIRSTHDR(&msghdr);
-       if (cmsg->cmsg_len > 0) {
-               cmsg = CMSG_NXTHDR(&msghdr, cmsg);
-       }
-
-       cmsg->cmsg_len = CMSG_LEN(sizeof(struct ucred));
-       cmsg->cmsg_level = SOL_SOCKET;
-       cmsg->cmsg_type = SCM_CREDENTIALS;
-       memcpy(CMSG_DATA(cmsg), &(data->cred), sizeof(struct ucred));
-
-       return OK;
-}
-
-PUBLIC int do_sendmsg(message *dev_m_in, message *dev_m_out)
-{
-       int minor, 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);
-#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), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       /* locate peer */
-       peer = -1;
-       if (uds_fd_table[minor].type == SOCK_DGRAM) {
-               if (uds_fd_table[minor].target.sun_path[0] == '\0' ||
-                       uds_fd_table[minor].target.sun_family != AF_UNIX) {
-
-                       return EDESTADDRREQ;
-               }
-
-               for (i = 0; i < NR_FDS; i++) {
-
-                       /* look for a SOCK_DGRAM socket that is bound on
-                        * the target address
-                        */
-                       if (uds_fd_table[i].type == SOCK_DGRAM &&
-                               uds_fd_table[i].addr.sun_family == AF_UNIX &&
-                               !strncmp(uds_fd_table[minor].target.sun_path,
-                               uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)){
-
-                               peer = i;
-                               break;
-                       }
-               }
-
-               if (peer == -1) {
-                       return ENOENT;
-               }
-       } else {
-               peer = uds_fd_table[minor].peer;
-               if (peer == -1) {
-                       return ENOTCONN;
-               }
-       }
-
-#if DEBUG == 1
-       printf("(uds) [%d] sendmsg() -- peer=%d\n", minor, peer);
-#endif
-       /* note: it's possible that there is already some file
-        * descriptors in ancillary_data if the peer didn't call
-        * recvmsg() yet. That's okay. The receiver will
-        * get the current file descriptors plus the new ones.
-        */
-       rc = msg_control_read(&msg_ctrl, &uds_fd_table[peer].ancillary_data,
-                                                               minor);
-       if (rc != OK) {
-               return rc;
-       }
-
-       return send_fds(minor, &uds_fd_table[peer].ancillary_data);
-}
-
-PUBLIC int do_recvmsg(message *dev_m_in, message *dev_m_out)
-{
-       int minor;
-       int rc;
-       struct msg_control msg_ctrl;
-       socklen_t controllen_avail = 0;
-       socklen_t controllen_needed = 0;
-       socklen_t controllen_desired = 0;
-
-#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] 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,
-                               uds_fd_table[minor].ancillary_data.cred.gid);
-#endif
-
-       memset(&msg_ctrl, '\0', sizeof(struct msg_control));
-
-       /* 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), D);
-
-       if (rc != OK) {
-               return EIO;
-       }
-
-       controllen_avail = MIN(msg_ctrl.msg_controllen, MSG_CONTROL_MAX);
-
-       if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
-               controllen_needed = CMSG_LEN(sizeof(int) *
-                               (uds_fd_table[minor].ancillary_data.nfiledes));
-       }
-
-       /* if there is room we also include credentials */
-       controllen_desired = controllen_needed +
-                               CMSG_LEN(sizeof(struct ucred));
-
-       if (controllen_needed > controllen_avail) {
-               return EOVERFLOW;
-       }
-
-       rc = recv_fds(minor, &uds_fd_table[minor].ancillary_data, &msg_ctrl);
-       if (rc != OK) {
-               return rc;
-       }
-
-       if (controllen_desired <= controllen_avail) {
-               rc = recv_cred(minor, &uds_fd_table[minor].ancillary_data,
-                                                               &msg_ctrl);
-               if (rc != OK) {
-                       return rc;
-               }
-       }
-
-       /* 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,
-               sizeof(struct msg_control), D);
-
-       return rc ? EIO : OK;
-}
diff --git a/servers/apfs/uds.h b/servers/apfs/uds.h
deleted file mode 100644 (file)
index efcb9c1..0000000
+++ /dev/null
@@ -1,251 +0,0 @@
-#ifndef __PFS_UDS_H__
-#define __PFS_UDS_H__
-
-/*
- * Unix Domain Sockets Implementation (PF_UNIX, PF_LOCAL)
- *
- * Also See...
- *
- *   dev_uds.c, table.c, uds.c
- */
-
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/ucred.h>
-#include <sys/un.h>
-
-#include <minix/endpoint.h>
-
-/* max connection backlog for incoming connections */
-#define UDS_SOMAXCONN 64
-
-typedef void* filp_id_t;
-
-/* ancillary data to be sent */
-struct ancillary {
-       filp_id_t filps[OPEN_MAX];
-       int fds[OPEN_MAX];
-       int nfiledes;
-       struct ucred cred;
-};
-
-/*
- * Internal State Information for a socket descriptor.
- */
-struct uds_fd {
-
-/* Flags */
-
-       enum UDS_STATE {
-               /* This file descriptor is UDS_FREE and can be allocated. */
-               UDS_FREE  = 0,
-
-               /* OR it is UDS_INUSE and can't be allocated. */
-               UDS_INUSE = 1
-
-       /* state is set to UDS_INUSE in uds_open(). state is Set to
-        * UDS_FREE in uds_init() and uds_close(). state should be
-        * checked prior to all operations.
-        */
-       } state;
-
-/* Owner Info */
-
-       /* Socket Owner */
-       endpoint_t owner;
-
-       /* endpoint for suspend/resume */
-       endpoint_t endpoint;
-
-/* Pipe Housekeeping */
-
-       /* inode number on PFS -- each descriptor is backed by 1
-        * PIPE which is allocated in uds_open() and freed in
-        * uds_close(). Data is sent/written to a peer's PIPE.
-        * Data is recv/read from this PIPE.
-        */
-       ino_t inode_nr;
-
-
-       /* position in the PIPE where the data starts */
-       off_t pos;
-
-       /* size of data in the PIPE */
-       size_t size;
-
-       /* control read/write, set by uds_open() and shutdown(2).
-        * Can be set to S_IRUSR|S_IWUSR, S_IRUSR, S_IWUSR, or 0
-        * for read and write, read only, write only, or neither.
-        * default is S_IRUSR|S_IWUSR.
-        */
-       mode_t mode;
-
-/* 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
-        * uds_ioctl(NWIOSUDSTYPE) and uds_close() will result in
-        * an error.
-        */
-       int type;
-
-       /* queue of pending connections for server sockets.
-        * connect(2) inserts and accept(2) removes from the queue
-        */
-       int backlog[UDS_SOMAXCONN];
-
-       /* requested connection backlog size. Set by listen(2)
-        * Bounds (0 <= backlog_size <= UDS_SOMAXCONN)
-        * Defaults to UDS_SOMAXCONN which is defined above.
-        */
-       unsigned char backlog_size;
-
-       /* index of peer in uds_fd_table for connected sockets.
-        * -1 is used to mean no peer. Assumptions: peer != -1 means
-        * connected.
-        */
-       int peer;
-
-       /* index of child (client sd returned by accept(2))
-        * -1 is used to mean no child.
-        */
-       int child;
-
-       /* address -- the address the socket is bound to.
-        * Assumptions: addr.sun_family == AF_UNIX means its bound.
-        */
-       struct sockaddr_un addr;
-
-       /* target -- where DGRAMs are sent to on the next uds_write(). */
-       struct sockaddr_un target;
-
-       /* source -- address where DGRAMs are from. used to fill in the
-        * from address in recvfrom(2) and recvmsg(2).
-        */
-       struct sockaddr_un source;
-
-       /* Flag (1 or 0) - listening for incoming connections.
-        * Default to 0. Set to 1 by do_listen()
-        */
-       int listening;
-
-       /* stores file pointers and credentials being sent between
-        * processes with sendmsg(2) and recvmsg(2).
-        */
-       struct ancillary ancillary_data;
-
-       /* Holds an errno. This is set when a connected socket is
-        * closed and we need to pass ECONNRESET on to a suspended
-        * peer.
-        */
-       int err;
-
-/* Suspend/Revive Housekeeping */
-
-
-       /* SUSPEND State Flags */
-       enum UDS_SUSPENDED {
-
-               /* Socket isn't blocked. */
-               UDS_NOT_SUSPENDED     = 0,
-
-               /* Socket is blocked on read(2) waiting for data to read. */
-               UDS_SUSPENDED_READ    = 1,
-
-               /* Socket is blocked on write(2) for space to write data. */
-               UDS_SUSPENDED_WRITE   = 2,
-
-               /* Socket is blocked on connect(2) waiting for the server. */
-               UDS_SUSPENDED_CONNECT = 4,
-
-               /* Socket is blocked on accept(2) waiting for clients. */
-               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;
-
-       /* 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;
-
-       /* Save the IOCTL so uds_cancel() knows what got cancelled. */
-       int ioctl;
-
-       /* 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;
-
-/* 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;
-
-       /* 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;
-};
-
-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))
-#define uds_minor_old(m)       (minor((short) 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
diff --git a/servers/apfs/utility.c b/servers/apfs/utility.c
deleted file mode 100644 (file)
index fac9ec6..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-#include "fs.h"
-
-
-/*===========================================================================*
- *                             no_sys                                       *
- *===========================================================================*/
-PUBLIC 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);
-  return(EINVAL);
-}
-
-
-/*===========================================================================*
- *                             clock_time                                   *
- *===========================================================================*/
-PUBLIC time_t clock_time()
-{
-/* This routine returns the time in seconds since 1.1.1970.  MINIX is an
- * astrophysically naive system that assumes the earth rotates at a constant
- * rate and that such things as leap seconds do not exist.
- */
-
-  int r;
-  clock_t uptime;      /* Uptime in ticks */
-  time_t boottime;
-
-  if ((r = getuptime2(&uptime, &boottime)) != OK)
-               panic("clock_time: getuptme2 failed: %d", r);
-
-  return( (time_t) (boottime + (uptime/sys_hz())));
-}
diff --git a/servers/avfs/Makefile b/servers/avfs/Makefile
deleted file mode 100644 (file)
index ec0553f..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# Makefile for Virtual File System (VFS)
-.include <bsd.own.mk>
-
-PROG=  vfs
-SRCS=  main.c open.c read.c write.c pipe.c dmap.c \
-       path.c device.c mount.c link.c exec.c \
-       filedes.c stadir.c protect.c time.c \
-       lock.c misc.c utility.c select.c table.c \
-       vnode.c vmnt.c request.c fscall.c \
-       tll.c comm.c worker.c coredump.c
-
-.if ${MKCOVERAGE} != "no"
-SRCS+=  gcov.c
-CPPFLAGS+= -DUSE_COVERAGE
-.endif
-
-DPADD+=        ${LIBSYS} ${LIBTIMERS} ${LIBEXEC}
-LDADD+=        -lsys -ltimers -lexec -lmthread
-
-.if ${COMPILER_TYPE} == "gnu"
-LDADD+=        -lc
-.endif
-
-MAN=
-
-BINDIR?= /usr/sbin
-INSTALLFLAGS+= -S 16k
-
-.include <minix.bootprog.mk>
diff --git a/servers/avfs/const.h b/servers/avfs/const.h
deleted file mode 100644 (file)
index 44a339d..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifndef __VFS_CONST_H__
-#define __VFS_CONST_H__
-
-/* Tables sizes */
-#define NR_FILPS         512   /* # slots in filp table */
-#define NR_LOCKS           8   /* # slots in the file locking table */
-#define NR_MNTS           16   /* # slots in mount table */
-#define NR_VNODES        512   /* # slots in vnode table */
-#define NR_WTHREADS       8    /* # slots in worker thread table */
-
-#define NR_NONEDEVS    NR_MNTS /* # slots in nonedev bitmap */
-
-/* Miscellaneous constants */
-#define SU_UID          ((uid_t) 0)    /* super_user's uid_t */
-#define SYS_UID  ((uid_t) 0)   /* uid_t for system processes and INIT */
-#define SYS_GID  ((gid_t) 0)   /* gid_t for system processes and INIT */
-
-#define FP_BLOCKED_ON_NONE     0 /* not blocked */
-#define FP_BLOCKED_ON_PIPE     1 /* susp'd on pipe */
-#define FP_BLOCKED_ON_LOCK     2 /* susp'd on lock */
-#define FP_BLOCKED_ON_POPEN    3 /* susp'd on pipe open */
-#define FP_BLOCKED_ON_SELECT   4 /* susp'd on select */
-#define FP_BLOCKED_ON_DOPEN    5 /* susp'd on device open */
-#define FP_BLOCKED_ON_OTHER    6 /* blocked on other process, check
-                                    fp_task to find out */
-
-/* test if the process is blocked on something */
-#define fp_is_blocked(fp)      ((fp)->fp_blocked_on != FP_BLOCKED_ON_NONE)
-
-#define DUP_MASK        0100   /* mask to distinguish dup2 from dup */
-
-#define LOOK_UP            0 /* tells search_dir to lookup string */
-#define ENTER              1 /* tells search_dir to make dir entry */
-#define DELETE             2 /* tells search_dir to delete entry */
-#define IS_EMPTY           3 /* tells search_dir to ret. OK or ENOTEMPTY */
-
-#define SYMLOOP                16
-
-#define LABEL_MAX      16      /* maximum label size (including '\0'). Should
-                                * not be smaller than 16 or bigger than
-                                * M3_LONG_STRING.
-                                */
-
-/* Args to dev_io */
-#define VFS_DEV_READ   2001
-#define        VFS_DEV_WRITE   2002
-#define VFS_DEV_IOCTL  2005
-#define VFS_DEV_SELECT 2006
-
-#endif
diff --git a/servers/avfs/device.c b/servers/avfs/device.c
deleted file mode 100644 (file)
index 926cf32..0000000
+++ /dev/null
@@ -1,1193 +0,0 @@
-/* When a needed block is not in the cache, it must be fetched from the disk.
- * Special character files also require I/O.  The routines for these are here.
- *
- * The entry points in this file are:
- *   dev_open:   open a character device
- *   dev_reopen: reopen a character device after a driver crash
- *   dev_close:  close a character device
- *   bdev_open:  open a block device
- *   bdev_close: close a block device
- *   dev_io:    FS does a read or write on a device
- *   dev_status: FS processes callback request alert
- *   gen_opcl:   generic call to a task to perform an open/close
- *   gen_io:     generic call to a task to perform an I/O operation
- *   no_dev:     open/close processing for devices that don't exist
- *   no_dev_io:  i/o processing for devices that don't exist
- *   tty_opcl:   perform tty-specific processing for open/close
- *   ctty_opcl:  perform controlling-tty-specific processing for open/close
- *   ctty_io:    perform controlling-tty-specific processing for I/O
- *   pm_setsid:         perform VFS's side of setsid system call
- *   do_ioctl:  perform the IOCTL system call
- */
-
-#include "fs.h"
-#include <string.h>
-#include <fcntl.h>
-#include <assert.h>
-#include <sys/stat.h>
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include <minix/endpoint.h>
-#include <minix/ioctl.h>
-#include <minix/u64.h>
-#include "file.h"
-#include "fproc.h"
-#include "scratchpad.h"
-#include "dmap.h"
-#include <minix/vfsif.h>
-#include "vnode.h"
-#include "vmnt.h"
-#include "param.h"
-
-FORWARD _PROTOTYPE( void restart_reopen, (int major)                   );
-FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, cp_grant_id_t *,
-                                            int *,
-                                            endpoint_t *, void **,
-                                            size_t, u32_t *)   );
-
-PRIVATE int dummyproc;
-
-
-/*===========================================================================*
- *                             dev_open                                     *
- *===========================================================================*/
-PUBLIC int dev_open(
-  dev_t dev,                   /* device to open */
-  endpoint_t proc_e,           /* process to open for */
-  int flags                    /* mode bits and flags */
-)
-{
-/* Open a character device. */
-  int major, r;
-
-  /* Determine the major device number so as to call the device class specific
-   * open/close routine.  (This is the only routine that must check the
-   * device number for being in range.  All others can trust this check.)
-   */
-  major = major(dev);
-  if (major < 0 || major >= NR_DEVICES) major = 0;
-  if (dmap[major].dmap_driver == NONE) return(ENXIO);
-  r = (*dmap[major].dmap_opcl)(DEV_OPEN, dev, proc_e, flags);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             dev_reopen                                   *
- *===========================================================================*/
-PUBLIC int dev_reopen(
-  dev_t dev,                   /* device to open */
-  int filp_no,                 /* filp to reopen for */
-  int flags                    /* mode bits and flags */
-)
-{
-/* Reopen a character device after a failing device driver. */
-
-  int major, r;
-  struct dmap *dp;
-
-  /* Determine the major device number and call the device class specific
-   * open/close routine.  (This is the only routine that must check the device
-   * number for being in range.  All others can trust this check.)
-   */
-
-  major = major(dev);
-  if (major < 0 || major >= NR_DEVICES) major = 0;
-  dp = &dmap[major];
-  if (dp->dmap_driver == NONE) return(ENXIO);
-  r = (*dp->dmap_opcl)(DEV_REOPEN, dev, filp_no, flags);
-  if (r == SUSPEND) r = OK;
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             dev_close                                    *
- *===========================================================================*/
-PUBLIC int dev_close(
-  dev_t dev,                   /* device to close */
-  int filp_no
-)
-{
-/* Close a character device. */
-  int r, major;
-
-  /* See if driver is roughly valid. */
-  major = major(dev);
-  if (major < 0 || major >= NR_DEVICES) return(ENXIO);
-  if (dmap[major].dmap_driver == NONE) return(ENXIO);
-  r = (*dmap[major].dmap_opcl)(DEV_CLOSE, dev, filp_no, 0);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             dev_open                                     *
- *===========================================================================*/
-PUBLIC int bdev_open(dev_t dev, int access)
-{
-/* Open a block device. */
-  int major;
-
-  major = major(dev);
-  if (major < 0 || major >= NR_DEVICES) return(ENXIO);
-  if (dmap[major].dmap_driver == NONE) return(ENXIO);
-
-  return (*dmap[major].dmap_opcl)(BDEV_OPEN, dev, 0, access);
-}
-
-
-/*===========================================================================*
- *                             bdev_close                                   *
- *===========================================================================*/
-PUBLIC int bdev_close(dev_t dev)
-{
-/* Close a block device. */
-  int major;
-
-  major = major(dev);
-  if (major < 0 || major >= NR_DEVICES) return(ENXIO);
-  if (dmap[major].dmap_driver == NONE) return(ENXIO);
-
-  return (*dmap[major].dmap_opcl)(BDEV_CLOSE, dev, 0, 0);
-}
-
-
-/*===========================================================================*
- *                             bdev_ioctl                                   *
- *===========================================================================*/
-PRIVATE int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
-{
-/* Perform an I/O control operation on a block device. */
-  struct dmap *dp;
-  u32_t dummy;
-  cp_grant_id_t gid;
-  message dev_mess;
-  int op, major_dev, minor_dev;
-
-  major_dev = major(dev);
-  minor_dev = minor(dev);
-
-  /* Determine task dmap. */
-  dp = &dmap[major_dev];
-  if (dp->dmap_driver == NONE) {
-       printf("VFS: dev_io: no driver for major %d\n", major_dev);
-       return(ENXIO);
-  }
-
-  /* Set up a grant if necessary. */
-  op = VFS_DEV_IOCTL;
-  (void) safe_io_conversion(dp->dmap_driver, &gid, &op, &proc_e, &buf, 0,
-       &dummy);
-
-  /* Set up the message passed to the task. */
-  memset(&dev_mess, 0, sizeof(dev_mess));
-
-  dev_mess.m_type = BDEV_IOCTL;
-  dev_mess.BDEV_MINOR = minor_dev;
-  dev_mess.BDEV_REQUEST = req;
-  dev_mess.BDEV_GRANT = gid;
-  dev_mess.BDEV_ID = 0;
-
-  /* Call the task. */
-  (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
-
-  /* Clean up. */
-  if (GRANT_VALID(gid)) cpf_revoke(gid);
-
-  if (dp->dmap_driver == NONE) {
-       printf("VFS: block driver gone!?\n");
-       return(EIO);
-  }
-
-  /* Return the result. */
-  return(dev_mess.BDEV_STATUS);
-}
-
-
-/*===========================================================================*
- *                             find_suspended_ep                            *
- *===========================================================================*/
-endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g)
-{
-/* A process is suspended on a driver for which VFS issued a grant. Find out
- * which process it was.
- */
-  struct fproc *rfp;
-  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       if(rfp->fp_pid == PID_FREE)
-               continue;
-
-       if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
-          rfp->fp_task == driver && rfp->fp_grant == g)
-               return(rfp->fp_endpoint);
-  }
-
-  return(NONE);
-}
-
-
-/*===========================================================================*
- *                             dev_status                                   *
- *===========================================================================*/
-PUBLIC void dev_status(message *m)
-{
-/* A device sent us a notification it has something for us. Retrieve it. */
-
-  message st;
-  int major, get_more = 1;
-  endpoint_t endpt;
-
-  for (major = 0; major < NR_DEVICES; major++)
-       if (dmap_driver_match(m->m_source, major))
-               break; /* 'major' is the device that sent the message */
-
-  if (major >= NR_DEVICES)     /* Device endpoint not found; nothing to do */
-       return;
-
-  if (dmap[major].dmap_style == STYLE_DEVA ||
-      dmap[major].dmap_style == STYLE_CLONE_A) {
-       printf("VFS: not doing dev_status for async driver %d\n", m->m_source);
-       return;
-  }
-
-  /* Continuously send DEV_STATUS messages until the device has nothing to
-   * say to us anymore. */
-  do {
-       int r;
-       st.m_type = DEV_STATUS;
-       r = sendrec(m->m_source, &st);
-       if (r == OK && st.REP_STATUS == ERESTART) r = EDEADEPT;
-       if (r != OK) {
-               printf("VFS: DEV_STATUS failed to %d: %d\n", m->m_source, r);
-               if (r == EDEADSRCDST || r == EDEADEPT) return;
-               panic("VFS: couldn't sendrec for DEV_STATUS: %d", r);
-       }
-
-       switch(st.m_type) {
-         case DEV_REVIVE:
-               /* We've got results for a read/write/ioctl call to a
-                * synchronous character driver */
-               endpt = st.REP_ENDPT;
-               if (endpt == VFS_PROC_NR) {
-                       endpt = find_suspended_ep(m->m_source,st.REP_IO_GRANT);
-                       if(endpt == NONE) {
-                         printf("VFS: proc with grant %d from %d not found\n",
-                                st.REP_IO_GRANT, st.m_source);
-                         continue;
-                       }
-               }
-               revive(endpt, st.REP_STATUS);
-               break;
-         case DEV_IO_READY:
-               /* Reply to a select request: driver is ready for I/O */
-               select_reply2(st.m_source, st.DEV_MINOR, st.DEV_SEL_OPS);
-               break;
-         default:
-               printf("VFS: unrecognized reply %d to DEV_STATUS\n",st.m_type);
-               /* Fall through. */
-         case DEV_NO_STATUS:
-               get_more = 0;
-               break;
-       }
-  } while(get_more);
-}
-
-/*===========================================================================*
- *                             safe_io_conversion                           *
- *===========================================================================*/
-PRIVATE int safe_io_conversion(driver, gid, op, io_ept, buf, bytes, pos_lo)
-endpoint_t driver;
-cp_grant_id_t *gid;
-int *op;
-endpoint_t *io_ept;
-void **buf;
-size_t bytes;
-u32_t *pos_lo;
-{
-/* Convert operation to the 'safe' variant (i.e., grant based) if applicable.
- * If no copying of data is involved, there is also no need to convert. */
-
-  int access = 0;
-  size_t size;
-
-  *gid = GRANT_INVALID;                /* Grant to buffer */
-
-  switch(*op) {
-    case VFS_DEV_READ:
-    case VFS_DEV_WRITE:
-       /* Change to safe op. */
-       *op = (*op == VFS_DEV_READ) ? DEV_READ_S : DEV_WRITE_S;
-       *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, bytes,
-                              *op == DEV_READ_S ? CPF_WRITE : CPF_READ);
-       if (*gid < 0)
-               panic("VFS: cpf_grant_magic of READ/WRITE buffer failed");
-       break;
-    case VFS_DEV_IOCTL:
-       *pos_lo = *io_ept; /* Old endpoint in POSITION field. */
-       *op = DEV_IOCTL_S;
-       if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE;
-       if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ;
-       if(_MINIX_IOCTL_BIG(m_in.REQUEST))
-               size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST);
-       else
-               size = _MINIX_IOCTL_SIZE(m_in.REQUEST);
-
-       /* Grant access to the buffer even if no I/O happens with the ioctl, in
-        * order to disambiguate requests with DEV_IOCTL_S.
-        */
-       *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, size, access);
-       if (*gid < 0)
-               panic("VFS: cpf_grant_magic IOCTL buffer failed");
-
-       break;
-    case VFS_DEV_SELECT:
-       *op = DEV_SELECT;
-       break;
-    default:
-       panic("VFS: unknown operation %d for safe I/O conversion", *op);
-  }
-
-  /* If we have converted to a safe operation, I/O endpoint becomes VFS if it
-   * wasn't already.
-   */
-  if(GRANT_VALID(*gid)) {
-       *io_ept = VFS_PROC_NR;
-       return(1);
-  }
-
-  /* Not converted to a safe operation (because there is no copying involved in
-   * this operation).
-   */
-  return(0);
-}
-
-/*===========================================================================*
- *                             dev_io                                       *
- *===========================================================================*/
-PUBLIC int dev_io(
-  int op,                      /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
-  dev_t dev,                   /* major-minor device number */
-  int proc_e,                  /* in whose address space is buf? */
-  void *buf,                   /* virtual address of the buffer */
-  u64_t pos,                   /* byte position */
-  size_t bytes,                        /* how many bytes to transfer */
-  int flags,                   /* special flags, like O_NONBLOCK */
-  int suspend_reopen           /* Just suspend the process */
-)
-{
-/* Read from or write to a device.  The parameter 'dev' tells which one. */
-  struct dmap *dp;
-  u32_t pos_lo, pos_high;
-  message dev_mess;
-  cp_grant_id_t gid = GRANT_INVALID;
-  int safe, minor_dev, major_dev;
-  void *buf_used;
-  endpoint_t ioproc;
-
-  pos_lo = ex64lo(pos);
-  pos_high = ex64hi(pos);
-  major_dev = major(dev);
-  minor_dev = minor(dev);
-
-  /* Determine task dmap. */
-  dp = &dmap[major_dev];
-
-  /* See if driver is roughly valid. */
-  if (dp->dmap_driver == NONE) {
-       printf("VFS: dev_io: no driver for major %d\n", major_dev);
-       return(ENXIO);
-  }
-
-  if (suspend_reopen) {
-       /* Suspend user. */
-       fp->fp_grant = GRANT_INVALID;
-       fp->fp_ioproc = NONE;
-       wait_for(dp->dmap_driver);
-       fp->fp_flags |= FP_SUSP_REOPEN;
-       return(SUSPEND);
-  }
-
-  if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
-       printf("VFS: dev_io: old driver for major %x (%d)\n", major_dev,
-               dp->dmap_driver);
-       return(ENXIO);
-  }
-
-  /* By default, these are right. */
-  dev_mess.USER_ENDPT = proc_e;
-  dev_mess.ADDRESS  = buf;
-
-  /* Convert DEV_* to DEV_*_S variants. */
-  buf_used = buf;
-  safe = safe_io_conversion(dp->dmap_driver, &gid, &op,
-                           (endpoint_t *) &dev_mess.USER_ENDPT, &buf_used,
-                           bytes, &pos_lo);
-
-  /* If the safe conversion was done, set the IO_GRANT to
-   * the grant id.
-   */
-  if(safe) dev_mess.IO_GRANT = (char *) gid;
-
-  /* Set up the rest of the message passed to task. */
-  dev_mess.m_type   = op;
-  dev_mess.DEVICE   = minor_dev;
-  dev_mess.POSITION = pos_lo;
-  dev_mess.COUNT    = bytes;
-  dev_mess.HIGHPOS  = pos_high;
-
-  /* This will be used if the i/o is suspended. */
-  ioproc = dev_mess.USER_ENDPT;
-
-  /* Call the task. */
-  (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
-
-  if(dp->dmap_driver == NONE) {
-       /* Driver has vanished. */
-       printf("VFS: driver gone?!\n");
-       if(safe) cpf_revoke(gid);
-       return(EIO);
-  }
-
-  /* Task has completed.  See if call completed. */
-  if (dev_mess.REP_STATUS == SUSPEND) {
-       if ((flags & O_NONBLOCK) && !(dp->dmap_style == STYLE_DEVA ||
-                                     dp->dmap_style == STYLE_CLONE_A)) {
-               /* Not supposed to block. */
-               dev_mess.m_type = CANCEL;
-               dev_mess.USER_ENDPT = ioproc;
-               dev_mess.IO_GRANT = (char *) gid;
-
-               /* This R_BIT/W_BIT check taken from suspend()/unpause()
-                * logic. Mode is expected in the COUNT field.
-                */
-               dev_mess.COUNT = 0;
-               if (call_nr == READ)            dev_mess.COUNT = R_BIT;
-               else if (call_nr == WRITE)      dev_mess.COUNT = W_BIT;
-               dev_mess.DEVICE = minor_dev;
-               (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
-               if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN;
-       } else {
-               /* select() will do suspending itself. */
-               if(op != DEV_SELECT) {
-                       /* Suspend user. */
-                       wait_for(dp->dmap_driver);
-               }
-               assert(!GRANT_VALID(fp->fp_grant));
-               fp->fp_grant = gid;     /* revoke this when unsuspended. */
-               fp->fp_ioproc = ioproc;
-
-               if (flags & O_NONBLOCK) {
-                       /* Not supposed to block, send cancel message */
-                       dev_mess.m_type = CANCEL;
-                       dev_mess.USER_ENDPT = ioproc;
-                       dev_mess.IO_GRANT = (char *) gid;
-
-                       /* This R_BIT/W_BIT check taken from suspend()/unpause()
-                        * logic. Mode is expected in the COUNT field.
-                        */
-                       dev_mess.COUNT = 0;
-                       if(call_nr == READ)             dev_mess.COUNT = R_BIT;
-                       else if(call_nr == WRITE)       dev_mess.COUNT = W_BIT;
-                       dev_mess.DEVICE = minor_dev;
-                       (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
-
-                       /* Should do something about EINTR -> EAGAIN mapping */
-               }
-               return(SUSPEND);
-       }
-  }
-
-  /* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */
-  if(safe) cpf_revoke(gid);
-
-  return(dev_mess.REP_STATUS);
-}
-
-/*===========================================================================*
- *                             gen_opcl                                     *
- *===========================================================================*/
-PUBLIC int gen_opcl(
-  int op,                      /* operation, (B)DEV_OPEN or (B)DEV_CLOSE */
-  dev_t dev,                   /* device to open or close */
-  endpoint_t proc_e,           /* process to open/close for */
-  int flags                    /* mode bits and flags */
-)
-{
-/* Called from the dmap struct on opens & closes of special files.*/
-  int r, minor_dev, major_dev, is_bdev;
-  struct dmap *dp;
-  message dev_mess;
-
-  /* Determine task dmap. */
-  major_dev = major(dev);
-  minor_dev = minor(dev);
-  assert(major_dev >= 0 && major_dev < NR_DEVICES);
-  dp = &dmap[major_dev];
-  assert(dp->dmap_driver != NONE);
-
-  is_bdev = IS_BDEV_RQ(op);
-
-  if (is_bdev) {
-       memset(&dev_mess, 0, sizeof(dev_mess));
-       dev_mess.m_type = op;
-       dev_mess.BDEV_MINOR = minor_dev;
-       dev_mess.BDEV_ACCESS = flags;
-       dev_mess.BDEV_ID = 0;
-  } else {
-       dev_mess.m_type = op;
-       dev_mess.DEVICE = minor_dev;
-       dev_mess.USER_ENDPT = proc_e;
-       dev_mess.COUNT = flags;
-  }
-
-  /* Call the task. */
-  r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
-  if (r != OK) return(r);
-
-  if (op == DEV_OPEN && dp->dmap_style == STYLE_DEVA) {
-       fp->fp_task = dp->dmap_driver;
-       worker_wait();
-  }
-
-  if (is_bdev)
-       return(dev_mess.BDEV_STATUS);
-  else
-       return(dev_mess.REP_STATUS);
-}
-
-/*===========================================================================*
- *                             tty_opcl                                     *
- *===========================================================================*/
-PUBLIC int tty_opcl(
-  int op,                      /* operation, DEV_OPEN or DEV_CLOSE */
-  dev_t dev,                   /* device to open or close */
-  endpoint_t proc_e,           /* process to open/close for */
-  int flags                    /* mode bits and flags */
-)
-{
-/* This procedure is called from the dmap struct on tty open/close. */
-
-  int r;
-  register struct fproc *rfp;
-
-  assert(!IS_BDEV_RQ(op));
-
-  /* Add O_NOCTTY to the flags if this process is not a session leader, or
-   * if it already has a controlling tty, or if it is someone elses
-   * controlling tty.
-   */
-  if (!(fp->fp_flags & FP_SESLDR) || fp->fp_tty != 0) {
-       flags |= O_NOCTTY;
-  } else {
-       for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-               if(rfp->fp_pid == PID_FREE) continue;
-               if (rfp->fp_tty == dev) flags |= O_NOCTTY;
-       }
-  }
-
-  r = gen_opcl(op, dev, proc_e, flags);
-
-  /* Did this call make the tty the controlling tty? */
-  if (r == 1) {
-       fp->fp_tty = dev;
-       r = OK;
-  }
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             ctty_opcl                                    *
- *===========================================================================*/
-PUBLIC int ctty_opcl(
-  int op,                      /* operation, DEV_OPEN or DEV_CLOSE */
-  dev_t UNUSED(dev),           /* device to open or close */
-  endpoint_t UNUSED(proc_e),   /* process to open/close for */
-  int UNUSED(flags)            /* mode bits and flags */
-)
-{
-/* This procedure is called from the dmap struct on opening or closing
- * /dev/tty, the magic device that translates to the controlling tty.
- */
-
-  assert(!IS_BDEV_RQ(op));
-
-  return(fp->fp_tty == 0 ? ENXIO : OK);
-}
-
-
-/*===========================================================================*
- *                             pm_setsid                                    *
- *===========================================================================*/
-PUBLIC void pm_setsid(proc_e)
-int proc_e;
-{
-/* Perform the VFS side of the SETSID call, i.e. get rid of the controlling
- * terminal of a process, and make the process a session leader.
- */
-  register struct fproc *rfp;
-  int slot;
-
-  /* Make the process a session leader with no controlling tty. */
-  okendpt(proc_e, &slot);
-  rfp = &fproc[slot];
-  rfp->fp_flags |= FP_SESLDR;
-  rfp->fp_tty = 0;
-}
-
-
-/*===========================================================================*
- *                             do_ioctl                                     *
- *===========================================================================*/
-PUBLIC int do_ioctl()
-{
-/* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
-
-  int r = OK, suspend_reopen;
-  struct filp *f;
-  register struct vnode *vp;
-  dev_t dev;
-
-  scratch(fp).file.fd_nr = m_in.ls_fd;
-
-  if ((f = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
-       return(err_code);
-  vp = f->filp_vno;            /* get vnode pointer */
-  if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL &&
-      (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) {
-       r = ENOTTY;
-  }
-
-  if (r == OK) {
-       suspend_reopen = (f->filp_state != FS_NORMAL);
-       dev = (dev_t) vp->v_sdev;
-
-       if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL)
-               r = bdev_ioctl(dev, who_e, m_in.REQUEST, m_in.ADDRESS);
-       else
-               r = dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
-                  m_in.REQUEST, f->filp_flags, suspend_reopen);
-  }
-
-  unlock_filp(f);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             gen_io                                       *
- *===========================================================================*/
-PUBLIC int gen_io(driver_e, mess_ptr)
-endpoint_t driver_e;           /* which endpoint to call */
-message *mess_ptr;             /* pointer to message for task */
-{
-/* All file system I/O ultimately comes down to I/O on major/minor device
- * pairs.  These lead to calls on the following routines via the dmap table.
- */
-  int r, status, proc_e = NONE, is_bdev;
-
-  is_bdev = IS_BDEV_RQ(mess_ptr->m_type);
-
-  if (!is_bdev) proc_e = mess_ptr->USER_ENDPT;
-
-  r = sendrec(driver_e, mess_ptr);
-  if (r == OK) {
-       if (is_bdev)
-               status = mess_ptr->BDEV_STATUS;
-       else
-               status = mess_ptr->REP_STATUS;
-       if (status == ERESTART)
-               r = EDEADEPT;
-  }
-  if (r != OK) {
-       if (r == EDEADSRCDST || r == EDEADEPT) {
-               printf("VFS: dead driver %d\n", driver_e);
-               dmap_unmap_by_endpt(driver_e);
-               return(r);
-       } else if (r == ELOCKED) {
-               printf("VFS: ELOCKED talking to %d\n", driver_e);
-               return(r);
-       }
-       panic("call_task: can't send/receive: %d", r);
-  }
-
-  /* Did the process we did the sendrec() for get a result? */
-  if (!is_bdev && mess_ptr->REP_ENDPT != proc_e) {
-       printf("VFS: strange device reply from %d, type = %d, "
-               "proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
-               mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
-
-       return(EIO);
-  }
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             asyn_io                                      *
- *===========================================================================*/
-PUBLIC int asyn_io(task_nr, mess_ptr)
-int task_nr;                   /* which task to call */
-message *mess_ptr;             /* pointer to message for task */
-{
-/* All file system I/O ultimately comes down to I/O on major/minor device
- * pairs. These lead to calls on the following routines via the dmap table.
- */
-
-  int r;
-
-  assert(!IS_BDEV_RQ(mess_ptr->m_type));
-
-  fp->fp_sendrec = mess_ptr;   /* Remember where result should be stored */
-  r = asynsend3(task_nr, mess_ptr, AMF_NOREPLY);
-
-  if (r != OK) panic("VFS: asynsend in asyn_io failed: %d", r);
-
-  /* Fake a SUSPEND */
-  mess_ptr->REP_STATUS = SUSPEND;
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             ctty_io                                      *
- *===========================================================================*/
-PUBLIC int ctty_io(
-  endpoint_t UNUSED(task_nr),  /* not used - for compatibility with dmap_t */
-  message *mess_ptr            /* pointer to message for task */
-)
-{
-/* This routine is only called for one device, namely /dev/tty.  Its job
- * is to change the message to use the controlling terminal, instead of the
- * major/minor pair for /dev/tty itself.
- */
-
-  struct dmap *dp;
-
-  if (fp->fp_tty == 0) {
-       /* No controlling tty present anymore, return an I/O error. */
-       mess_ptr->REP_STATUS = EIO;
-  } else {
-       /* Substitute the controlling terminal device. */
-       dp = &dmap[major(fp->fp_tty)];
-       mess_ptr->DEVICE = minor(fp->fp_tty);
-
-       if (dp->dmap_driver == NONE) {
-               printf("FS: ctty_io: no driver for dev\n");
-               return(EIO);
-       }
-
-       if (isokendpt(dp->dmap_driver, &dummyproc) != OK) {
-               printf("VFS: ctty_io: old driver %d\n", dp->dmap_driver);
-               return(EIO);
-       }
-
-       (*dp->dmap_io)(dp->dmap_driver, mess_ptr);
-  }
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             no_dev                                       *
- *===========================================================================*/
-PUBLIC int no_dev(
-  int UNUSED(op),              /* operation, DEV_OPEN or DEV_CLOSE */
-  dev_t UNUSED(dev),           /* device to open or close */
-  int UNUSED(proc),            /* process to open/close for */
-  int UNUSED(flags)            /* mode bits and flags */
-)
-{
-/* Called when opening a nonexistent device. */
-  return(ENODEV);
-}
-
-/*===========================================================================*
- *                             no_dev_io                                    *
- *===========================================================================*/
-PUBLIC int no_dev_io(endpoint_t UNUSED(proc), message *UNUSED(m))
-{
-/* Called when doing i/o on a nonexistent device. */
-  printf("VFS: I/O on unmapped device number\n");
-  return(EIO);
-}
-
-
-/*===========================================================================*
- *                             clone_opcl                                   *
- *===========================================================================*/
-PUBLIC int clone_opcl(
-  int op,                      /* operation, DEV_OPEN or DEV_CLOSE */
-  dev_t dev,                   /* device to open or close */
-  int proc_e,                  /* process to open/close for */
-  int flags                    /* mode bits and flags */
-)
-{
-/* Some devices need special processing upon open.  Such a device is "cloned",
- * i.e. on a succesful open it is replaced by a new device with a new unique
- * minor device number.  This new device number identifies a new object (such
- * as a new network connection) that has been allocated within a task.
- */
-  struct dmap *dp;
-  int r, minor_dev, major_dev;
-  message dev_mess;
-
-  assert(!IS_BDEV_RQ(op));
-
-  /* Determine task dmap. */
-  minor_dev = minor(dev);
-  major_dev = major(dev);
-  assert(major_dev >= 0 && major_dev < NR_DEVICES);
-  dp = &dmap[major_dev];
-  assert(dp->dmap_driver != NONE);
-
-  dev_mess.m_type   = op;
-  dev_mess.DEVICE   = minor_dev;
-  dev_mess.USER_ENDPT = proc_e;
-  dev_mess.COUNT    = flags;
-
-  if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
-       printf("VFS clone_opcl: bad driver endpoint for major %d (%d)\n",
-              major_dev, dp->dmap_driver);
-       return(ENXIO);
-  }
-
-  /* Call the task. */
-  r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
-  if (r != OK) return(r);
-
-  if (op == DEV_OPEN && dp->dmap_style == STYLE_CLONE_A) {
-       /* Wait for reply when driver is asynchronous */
-       fp->fp_task = dp->dmap_driver;
-       worker_wait();
-  }
-
-  if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) {
-       if (dev_mess.REP_STATUS != minor_dev) {
-                struct vnode *vp;
-                struct node_details res;
-
-               /* A new minor device number has been returned.
-                 * Request PFS to create a temporary device file to hold it.
-                 */
-
-                /* Device number of the new device. */
-               dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
-
-                /* Issue request */
-               r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid,
-                       ALL_MODES | I_CHAR_SPECIAL, dev, &res);
-                if (r != OK) {
-                       (void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
-                       return r;
-                }
-
-                /* Drop old node and use the new values */
-                assert(FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse));
-                vp = fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno;
-
-               unlock_vnode(vp);
-                put_vnode(vp);
-               if ((vp = get_free_vnode()) == NULL)
-                       return(err_code);
-
-               lock_vnode(vp, VNODE_OPCL);
-
-                vp->v_fs_e = res.fs_e;
-                vp->v_vmnt = NULL;
-                vp->v_dev = NO_DEV;
-               vp->v_fs_e = res.fs_e;
-                vp->v_inode_nr = res.inode_nr;
-                vp->v_mode = res.fmode;
-                vp->v_sdev = dev;
-                vp->v_fs_count = 1;
-                vp->v_ref_count = 1;
-               fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno = vp;
-       }
-       dev_mess.REP_STATUS = OK;
-  }
-  return(dev_mess.REP_STATUS);
-}
-
-
-/*===========================================================================*
- *                             bdev_up                                      *
- *===========================================================================*/
-PUBLIC void bdev_up(int maj)
-{
-  /* A new block device driver has been mapped in. This may affect both mounted
-   * file systems and open block-special files.
-   */
-  int r, found, bits;
-  struct filp *rfilp;
-  struct vmnt *vmp;
-  struct vnode *vp;
-  char *label;
-
-  if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major");
-  label = dmap[maj].dmap_label;
-
-  /* Tell each affected mounted file system about the new endpoint. This code
-   * is currently useless, as driver endpoints do not change across restarts.
-   */
-  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
-       if (major(vmp->m_dev) != maj) continue;
-
-       /* Send the driver label to the mounted file system. */
-       if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, label))
-               printf("VFS dev_up: error sending new driver label to %d\n",
-                      vmp->m_fs_e);
-  }
-
-  /* For each block-special file that was previously opened on the affected
-   * device, we need to reopen it on the new driver.
-   */
-  found = 0;
-  for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
-       if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
-       if (major(vp->v_sdev) != maj) continue;
-       if (!S_ISBLK(vp->v_mode)) continue;
-
-       /* Reopen the device on the driver, once per filp. */
-       bits = mode_map[rfilp->filp_mode & O_ACCMODE];
-       if ((r = bdev_open(vp->v_sdev, bits)) != OK)
-               printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
-                       maj, minor(vp->v_sdev), r);
-
-       found = 1;
-  }
-
-  /* If any block-special file was open for this major at all, also inform the
-   * root file system about the new driver. We do this even if the
-   * block-special file is linked to another mounted file system, merely
-   * because it is more work to check for that case.
-   */
-  if (found) {
-       if (OK != req_newdriver(ROOT_FS_E, makedev(maj, 0), label))
-               printf("VFSdev_up: error sending new driver label to %d\n",
-                       ROOT_FS_E);
-  }
-}
-
-
-/*===========================================================================*
- *                             cdev_up                                      *
- *===========================================================================*/
-PUBLIC void cdev_up(int maj)
-{
-  /* A new character device driver has been mapped in.
-  */
-  int needs_reopen, fd_nr;
-  struct filp *rfilp;
-  struct fproc *rfp;
-  struct vnode *vp;
-
-  /* Look for processes that are suspened in an OPEN call. Set FP_SUSP_REOPEN
-   * to indicate that this process was suspended before the call to dev_up.
-   */
-  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       if(rfp->fp_pid == PID_FREE) continue;
-       if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN) continue;
-
-       fd_nr = scratch(rfp).file.fd_nr;
-       printf("VFS: dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
-               fd_nr);
-       rfilp = rfp->fp_filp[fd_nr];
-       vp = rfilp->filp_vno;
-       if (!vp) panic("VFS: cdev_up: no vp");
-       if ((vp->v_mode &  I_TYPE) != I_CHAR_SPECIAL) continue;
-       if (major(vp->v_sdev) != maj) continue;
-
-       rfp->fp_flags |= FP_SUSP_REOPEN;
-  }
-
-  needs_reopen= FALSE;
-  for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
-       if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
-       if (major(vp->v_sdev) != maj) continue;
-       if (!S_ISCHR(vp->v_mode)) continue;
-
-       rfilp->filp_state = FS_NEEDS_REOPEN;
-       needs_reopen = TRUE;
-  }
-
-  if (needs_reopen)
-       restart_reopen(maj);
-}
-
-/*===========================================================================*
- *                             open_reply                                   *
- *===========================================================================*/
-PUBLIC void open_reply(void)
-{
-  struct fproc *rfp;
-  endpoint_t proc_e;
-  int slot;
-
-  proc_e = m_in.REP_ENDPT;
-  if (isokendpt(proc_e, &slot) != OK) return;
-  rfp = &fproc[slot];
-  *rfp->fp_sendrec = m_in;
-  worker_signal(worker_get(rfp->fp_wtid));     /* Continue open */
-}
-
-/*===========================================================================*
- *                             restart_reopen                               *
- *===========================================================================*/
-PRIVATE void restart_reopen(maj)
-int maj;
-{
-  int n, r, minor_dev, major_dev, fd_nr;
-  endpoint_t driver_e;
-  struct vnode *vp;
-  struct filp *rfilp;
-  struct fproc *rfp;
-
-  if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major");
-  for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
-       if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
-       if (rfilp->filp_state != FS_NEEDS_REOPEN) continue;
-       if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
-
-       major_dev = major(vp->v_sdev);
-       minor_dev = minor(vp->v_sdev);
-       if (major_dev != maj) continue;
-
-       if (!(rfilp->filp_flags & O_REOPEN)) {
-               /* File descriptor is to be closed when driver restarts. */
-               n = invalidate_filp(rfilp);
-               if (n != rfilp->filp_count) {
-                       printf("VFS: warning: invalidate/count "
-                              "discrepancy (%d, %d)\n", n, rfilp->filp_count);
-               }
-               rfilp->filp_count = 0;
-               continue;
-       }
-
-       r = dev_reopen(vp->v_sdev, rfilp-filp, vp->v_mode & (R_BIT|W_BIT));
-       if (r == OK) return;
-
-       /* Device could not be reopened. Invalidate all filps on that device.*/
-       n = invalidate_filp(rfilp);
-       if (n != rfilp->filp_count) {
-               printf("VFS: warning: invalidate/count "
-                       "discrepancy (%d, %d)\n", n, rfilp->filp_count);
-       }
-       rfilp->filp_count = 0;
-       printf("VFS: file on dev %d/%d re-open failed: %d; "
-               "invalidated %d fd's.\n", major_dev, minor_dev, r, n);
-  }
-
-  /* Nothing more to re-open. Restart suspended processes */
-  driver_e = dmap[maj].dmap_driver;
-
-  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       if(rfp->fp_pid == PID_FREE) continue;
-       if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
-          rfp->fp_task == driver_e && (rfp->fp_flags & FP_SUSP_REOPEN)) {
-               rfp->fp_flags &= ~FP_SUSP_REOPEN;
-               rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-               reply(rfp->fp_endpoint, ERESTART);
-       }
-  }
-
-  /* Look for processes that are suspened in an OPEN call */
-  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       if (rfp->fp_pid == PID_FREE) continue;
-       if (rfp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
-           !(rfp->fp_flags & FP_SUSP_REOPEN)) continue;
-
-       fd_nr = scratch(rfp).file.fd_nr;
-       printf("VFS: restart_reopen: process in FP_BLOCKED_ON_DOPEN fd=%d\n",
-               fd_nr);
-       rfilp = rfp->fp_filp[fd_nr];
-
-       if (!rfilp) {
-               /* Open failed, and automatic reopen was not requested */
-               rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-               FD_CLR(fd_nr, &rfp->fp_filp_inuse);
-               reply(rfp->fp_endpoint, EIO);
-               continue;
-       }
-
-       vp = rfilp->filp_vno;
-       if (!vp) panic("VFS: restart_reopen: no vp");
-       if ((vp->v_mode &  I_TYPE) != I_CHAR_SPECIAL) continue;
-       if (major(vp->v_sdev) != maj) continue;
-
-       rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-       reply(rfp->fp_endpoint, fd_nr);
-  }
-}
-
-
-/*===========================================================================*
- *                             reopen_reply                                 *
- *===========================================================================*/
-PUBLIC void reopen_reply()
-{
-  endpoint_t driver_e;
-  int filp_no, status, maj;
-  struct filp *rfilp;
-  struct vnode *vp;
-  struct dmap *dp;
-
-  driver_e = m_in.m_source;
-  filp_no = m_in.REP_ENDPT;
-  status = m_in.REP_STATUS;
-
-  if (filp_no < 0 || filp_no >= NR_FILPS) {
-       printf("VFS: reopen_reply: bad filp number %d from driver %d\n",
-               filp_no, driver_e);
-       return;
-  }
-
-  rfilp = &filp[filp_no];
-  if (rfilp->filp_count < 1) {
-       printf("VFS: reopen_reply: filp number %d not inuse (from driver %d)\n",
-              filp_no, driver_e);
-       return;
-  }
-
-  vp = rfilp->filp_vno;
-  if (!vp) {
-       printf("VFS: reopen_reply: no vnode for filp number %d (from driver "
-               "%d)\n", filp_no, driver_e);
-       return;
-  }
-
-  if (rfilp->filp_state != FS_NEEDS_REOPEN) {
-       printf("VFS: reopen_reply: bad state %d for filp number %d"
-              " (from driver %d)\n", rfilp->filp_state, filp_no, driver_e);
-       return;
-  }
-
-  if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) {
-       printf("VFS: reopen_reply: bad mode 0%o for filp number %d"
-              " (from driver %d)\n", vp->v_mode, filp_no, driver_e);
-       return;
-  }
-
-  maj = major(vp->v_sdev);
-  dp = &dmap[maj];
-  if (dp->dmap_driver != driver_e) {
-       printf("VFS: reopen_reply: bad major %d for filp number %d "
-               "(from driver %d, current driver is %d)\n", maj, filp_no,
-               driver_e, dp->dmap_driver);
-       return;
-  }
-
-  if (status == OK) {
-       rfilp->filp_state= FS_NORMAL;
-  } else {
-       printf("VFS: reopen_reply: should handle error status\n");
-       return;
-  }
-
-  restart_reopen(maj);
-}
diff --git a/servers/avfs/dmap.c b/servers/avfs/dmap.c
deleted file mode 100644 (file)
index eb5d13b..0000000
+++ /dev/null
@@ -1,266 +0,0 @@
-/* This file contains the table with device <-> driver mappings. It also
- * contains some routines to dynamically add and/ or remove device drivers
- * or change mappings.
- */
-
-#include "fs.h"
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-#include <unistd.h>
-#include <minix/com.h>
-#include <minix/ds.h>
-#include "fproc.h"
-#include "dmap.h"
-#include "param.h"
-
-/* The order of the entries in the table determines the mapping between major
- * device numbers and device drivers. Character and block devices
- * can be intermixed at random.  The ordering determines the device numbers in
- * /dev. Note that the major device numbers used in /dev are NOT the same as
- * the process numbers of the device drivers. See <minix/dmap.h> for mappings.
- */
-
-struct dmap dmap[NR_DEVICES];
-
-#define DT_EMPTY { no_dev, no_dev_io, NONE, "", 0, STYLE_NDEV, NULL }
-
-/*===========================================================================*
- *                             do_mapdriver                                 *
- *===========================================================================*/
-PUBLIC int do_mapdriver()
-{
-/* Create a device->driver mapping. RS will tell us which major is driven by
- * this driver, what type of device it is (regular, TTY, asynchronous, clone,
- * etc), and its label. This label is registered with DS, and allows us to
- * retrieve the driver's endpoint.
- */
-  int r, flags, major;
-  endpoint_t endpoint;
-  vir_bytes label_vir;
-  size_t label_len;
-  char label[LABEL_MAX];
-
-  /* Only RS can map drivers. */
-  if (who_e != RS_PROC_NR) return(EPERM);
-
-  /* Get the label */
-  label_vir = (vir_bytes) m_in.md_label;
-  label_len = (size_t) m_in.md_label_len;
-
-  if (label_len+1 > sizeof(label)) { /* Can we store this label? */
-       printf("VFS: do_mapdriver: label too long\n");
-       return(EINVAL);
-  }
-  r = sys_vircopy(who_e, D, label_vir, SELF, D, (vir_bytes) label, label_len);
-  if (r != OK) {
-       printf("VFS: do_mapdriver: sys_vircopy failed: %d\n", r);
-       return(EINVAL);
-  }
-  label[label_len] = '\0';     /* Terminate label */
-
-  /* Now we know how the driver is called, fetch its endpoint */
-  r = ds_retrieve_label_endpt(label, &endpoint);
-  if (r != OK) {
-       printf("VFS: do_mapdriver: label '%s' unknown\n", label);
-       return(EINVAL);
-  }
-
-  /* Try to update device mapping. */
-  major = m_in.md_major;
-  flags = m_in.md_flags;
-
-  return map_driver(label, major, endpoint, m_in.md_style, flags);
-}
-
-/*===========================================================================*
- *                             map_driver                                   *
- *===========================================================================*/
-PUBLIC int map_driver(label, major, proc_nr_e, style, flags)
-const char *label;             /* name of the driver */
-int major;                     /* major number of the device */
-endpoint_t proc_nr_e;          /* process number of the driver */
-int style;                     /* style of the device */
-int flags;                     /* device flags */
-{
-/* Add a new device driver mapping in the dmap table. If the proc_nr is set to
- * NONE, we're supposed to unmap it.
- */
-
-  int slot;
-  size_t len;
-  struct dmap *dp;
-
-  /* Get pointer to device entry in the dmap table. */
-  if (major < 0 || major >= NR_DEVICES) return(ENODEV);
-  dp = &dmap[major];
-
-  /* Check if we're supposed to unmap it. */
- if (proc_nr_e == NONE) {
-       dp->dmap_opcl = no_dev;
-       dp->dmap_io = no_dev_io;
-       dp->dmap_driver = NONE;
-       dp->dmap_flags = flags;
-       return(OK);
-  }
-
-  /* Check process number of new driver if it was alive before mapping */
-  if (! (flags & DRV_FORCED)) {
-       struct fproc *rfp;
-
-       if (isokendpt(proc_nr_e, &slot) != OK)
-               return(EINVAL);
-
-       rfp = &fproc[slot];
-       rfp->fp_flags |= FP_SYS_PROC;   /* Process is a driver */
-  }
-
-  if (label != NULL) {
-       len = strlen(label);
-       if (len+1 > sizeof(dp->dmap_label))
-               panic("VFS: map_driver: label too long: %d", len);
-       strcpy(dp->dmap_label, label);
-  }
-
-  /* Store driver I/O routines based on type of device */
-  switch (style) {
-    case STYLE_DEV:
-       dp->dmap_opcl = gen_opcl;
-       dp->dmap_io = gen_io;
-       break;
-    case STYLE_DEVA:
-       dp->dmap_opcl = gen_opcl;
-       dp->dmap_io = asyn_io;
-       break;
-    case STYLE_TTY:
-       dp->dmap_opcl = tty_opcl;
-       dp->dmap_io = gen_io;
-       break;
-    case STYLE_CTTY:
-       dp->dmap_opcl = ctty_opcl;
-       dp->dmap_io = ctty_io;
-       break;
-    case STYLE_CLONE:
-       dp->dmap_opcl = clone_opcl;
-       dp->dmap_io = gen_io;
-       break;
-    case STYLE_CLONE_A:
-       dp->dmap_opcl = clone_opcl;
-       dp->dmap_io = asyn_io;
-       break;
-    default:
-       return(EINVAL);
-  }
-
-  dp->dmap_driver = proc_nr_e;
-  dp->dmap_flags = flags;
-  dp->dmap_style = style;
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                             dmap_unmap_by_endpt                          *
- *===========================================================================*/
-PUBLIC void dmap_unmap_by_endpt(endpoint_t proc_e)
-{
-/* Lookup driver in dmap table by endpoint and unmap it */
-  int major, r;
-
-  for (major = 0; major < NR_DEVICES; major++) {
-       if (dmap_driver_match(proc_e, major)) {
-               /* Found driver; overwrite it with a NULL entry */
-               if ((r = map_driver(NULL, major, NONE, 0, 0)) != OK) {
-                       printf("VFS: unmapping driver %d for major %d failed:"
-                               " %d\n", proc_e, major, r);
-               }
-       }
-  }
-}
-
-/*===========================================================================*
- *                            map_service                                   *
- *===========================================================================*/
-PUBLIC int map_service(struct rprocpub *rpub)
-{
-/* Map a new service by storing its device driver properties. */
-  int r;
-
-  /* Not a driver, nothing more to do. */
-  if(rpub->dev_nr == NO_DEV) return(OK);
-
-  /* Map driver. */
-  r = map_driver(rpub->label, rpub->dev_nr, rpub->endpoint, rpub->dev_style,
-                rpub->dev_flags);
-  if(r != OK) return(r);
-
-  /* If driver has two major numbers associated, also map the other one. */
-  if(rpub->dev_style2 != STYLE_NDEV) {
-       r = map_driver(rpub->label, rpub->dev_nr+1, rpub->endpoint,
-                      rpub->dev_style2, rpub->dev_flags);
-       if(r != OK) return(r);
-  }
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                             init_dmap                                    *
- *===========================================================================*/
-PUBLIC void init_dmap()
-{
-/* Initialize the table with empty device <-> driver mappings. */
-  int i;
-  struct dmap dmap_default = DT_EMPTY;
-
-  for (i = 0; i < NR_DEVICES; i++)
-       dmap[i] = dmap_default;
-}
-
-/*===========================================================================*
- *                             dmap_driver_match                            *
- *===========================================================================*/
-PUBLIC int dmap_driver_match(endpoint_t proc, int major)
-{
-  if (major < 0 || major >= NR_DEVICES) return(0);
-  if (dmap[major].dmap_driver != NONE && dmap[major].dmap_driver == proc)
-       return(1);
-
-  return(0);
-}
-
-/*===========================================================================*
- *                             dmap_endpt_up                                *
- *===========================================================================*/
-PUBLIC void dmap_endpt_up(endpoint_t proc_e, int is_blk)
-{
-/* A device driver with endpoint proc_e has been restarted. Go tell everyone
- * that might be blocking on it that this device is 'up'.
- */
-
-  int major;
-  for (major = 0; major < NR_DEVICES; major++) {
-       if (dmap_driver_match(proc_e, major)) {
-               if (is_blk)
-                       bdev_up(major);
-               else
-                       cdev_up(major);
-       }
-  }
-}
-
-/*===========================================================================*
- *                             get_dmap                                     *
- *===========================================================================*/
-PUBLIC struct dmap *get_dmap(endpoint_t proc_e)
-{
-/* See if 'proc_e' endpoint belongs to a valid dmap entry. If so, return a
- * pointer */
-
-  int major;
-  for (major = 0; major < NR_DEVICES; major++)
-       if (dmap_driver_match(proc_e, major))
-               return(&dmap[major]);
-
-  return(NULL);
-}
diff --git a/servers/avfs/dmap.h b/servers/avfs/dmap.h
deleted file mode 100644 (file)
index 6a83bf5..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-#ifndef __VFS_DMAP_H__
-#define __VFS_DMAP_H__
-
-/*
-dmap.h
-*/
-
-/*===========================================================================*
- *                      Device <-> Driver Table                             *
- *===========================================================================*/
-
-/* Device table.  This table is indexed by major device number.  It provides
- * the link between major device numbers and the routines that process them.
- * The table can be update dynamically. The field 'dmap_flags' describe an
- * entry's current status and determines what control options are possible.
- */
-
-extern struct dmap {
-  int _PROTOTYPE ((*dmap_opcl), (int, dev_t, int, int) );
-  int _PROTOTYPE ((*dmap_io), (int, message *) );
-  endpoint_t dmap_driver;
-  char dmap_label[LABEL_MAX];
-  int dmap_flags;
-  int dmap_style;
-  struct filp *dmap_sel_filp;
-} dmap[];
-
-#endif
diff --git a/servers/avfs/exec.c b/servers/avfs/exec.c
deleted file mode 100644 (file)
index 3f6e4a7..0000000
+++ /dev/null
@@ -1,721 +0,0 @@
-/* This file handles the EXEC system call.  It performs the work as follows:
- *    - see if the permissions allow the file to be executed
- *    - read the header and extract the sizes
- *    - fetch the initial args and environment from the user space
- *    - allocate the memory for the new process
- *    - copy the initial stack from PM to the process
- *    - read in the text and data segments and copy to the process
- *    - take care of setuid and setgid bits
- *    - fix up 'mproc' table
- *    - tell kernel about EXEC
- *    - save offset to initial argc (for ps)
- *
- * The entry points into this file are:
- *   pm_exec:   perform the EXEC system call
- */
-
-#include "fs.h"
-#include <sys/stat.h>
-#include <minix/callnr.h>
-#include <minix/endpoint.h>
-#include <minix/com.h>
-#include <minix/u64.h>
-#include <a.out.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <dirent.h>
-#include <sys/param.h>
-#include "fproc.h"
-#include "path.h"
-#include "param.h"
-#include "vnode.h"
-#include <minix/vfsif.h>
-#include <assert.h>
-#include <libexec.h>
-#include "exec.h"
-
-FORWARD _PROTOTYPE( void lock_exec, (void)                             );
-FORWARD _PROTOTYPE( void unlock_exec, (void)                           );
-FORWARD _PROTOTYPE( int exec_newmem, (int proc_e, vir_bytes text_addr, vir_bytes text_bytes,
-                      vir_bytes data_addr, vir_bytes data_bytes,
-                      vir_bytes tot_bytes, vir_bytes frame_len, int sep_id,
-                      int is_elf, dev_t st_dev, ino_t st_ino, time_t ctime,
-                      char *progname, int new_uid, int new_gid,
-                      vir_bytes *stack_topp, int *load_textp,
-                      int *setugidp)                                   );
-FORWARD _PROTOTYPE( int is_script, (const char *exec_hdr, size_t exec_len));
-FORWARD _PROTOTYPE( int patch_stack, (struct vnode *vp, char stack[ARG_MAX],
-                      vir_bytes *stk_bytes, char path[PATH_MAX])       );
-FORWARD _PROTOTYPE( int insert_arg, (char stack[ARG_MAX], vir_bytes *stk_bytes,
-                                       char *arg, int replace)         );
-FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX], vir_bytes base));
-FORWARD _PROTOTYPE( void clo_exec, (struct fproc *rfp)                 );
-FORWARD _PROTOTYPE( int read_seg, (struct vnode *vp, off_t off, int proc_e,
-                                       int seg, vir_bytes seg_addr,
-                                       phys_bytes seg_bytes)           );
-FORWARD _PROTOTYPE( int load_aout, (struct exec_info *execi)           );
-FORWARD _PROTOTYPE( int load_elf, (struct exec_info *execi)            );
-FORWARD _PROTOTYPE( int map_header, (char **exec_hdr,
-                                       const struct vnode *vp)         );
-
-#define PTRSIZE        sizeof(char *) /* Size of pointers in argv[] and envp[]. */
-
-/* Array of loaders for different object file formats */
-struct exec_loaders {
-       int (*load_object)(struct exec_info *);
-};
-
-PRIVATE const struct exec_loaders exec_loaders[] = {
-       { load_aout },
-       { load_elf },
-       { NULL }
-};
-
-PRIVATE char hdr[PAGE_SIZE]; /* Assume that header is not larger than a page */
-
-/*===========================================================================*
- *                             lock_exec                                    *
- *===========================================================================*/
-PRIVATE void lock_exec(void)
-{
-  message org_m_in;
-  struct fproc *org_fp;
-  struct worker_thread *org_self;
-
-  /* First try to get it right off the bat */
-  if (mutex_trylock(&exec_lock) == 0)
-       return;
-
-  org_m_in = m_in;
-  org_fp = fp;
-  org_self = self;
-
-  if (mutex_lock(&exec_lock) != 0)
-       panic("Could not obtain lock on exec");
-
-  m_in = org_m_in;
-  fp = org_fp;
-  self = org_self;
-}
-
-/*===========================================================================*
- *                             unlock_exec                                  *
- *===========================================================================*/
-PRIVATE void unlock_exec(void)
-{
-  if (mutex_unlock(&exec_lock) != 0)
-       panic("Could not release lock on exec");
-}
-
-/*===========================================================================*
- *                             pm_exec                                      *
- *===========================================================================*/
-PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame,
-                  vir_bytes frame_len, vir_bytes *pc)
-{
-/* Perform the execve(name, argv, envp) call.  The user library builds a
- * complete stack image, including pointers, args, environ, etc.  The stack
- * is copied to a buffer inside VFS, and then to the new core image.
- */
-  int r, r1, round, slot;
-  vir_bytes vsp;
-  struct fproc *rfp;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char *cp;
-  static char mbuf[ARG_MAX];   /* buffer for stack and zeroes */
-  struct exec_info execi;
-  int i;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lock_exec();
-
-  okendpt(proc_e, &slot);
-  rfp = fp = &fproc[slot];
-  vp = NULL;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* Get the exec file name. */
-  if ((r = fetch_name(path, path_len, 0, fullpath)) != OK)
-       goto pm_execfinal;
-
-  /* Fetch the stack from the user before destroying the old core image. */
-  if (frame_len > ARG_MAX) {
-               r = ENOMEM; /* stack too big */
-               goto pm_execfinal;
-  }
-  r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
-                  (phys_bytes) frame_len);
-  if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
-        printf("VFS: pm_exec: sys_datacopy failed\n");
-        goto pm_execfinal;
-  }
-
-  /* The default is to keep the original user and group IDs */
-  execi.new_uid = rfp->fp_effuid;
-  execi.new_gid = rfp->fp_effgid;
-
-  for (round = 0; round < 2; round++) {
-       /* round = 0 (first attempt), or 1 (interpreted script) */
-       /* Save the name of the program */
-       (cp = strrchr(fullpath, '/')) ? cp++ : (cp = fullpath);
-
-       strncpy(execi.progname, cp, PROC_NAME_LEN-1);
-       execi.progname[PROC_NAME_LEN-1] = '\0';
-       execi.setugid = 0;
-
-       /* Open executable */
-       if ((vp = eat_path(&resolve, fp)) == NULL) {
-               r = err_code;
-               goto pm_execfinal;
-       }
-       execi.vp = vp;
-       unlock_vmnt(vmp);
-
-       if ((vp->v_mode & I_TYPE) != I_REGULAR)
-               r = ENOEXEC;
-       else if ((r1 = forbidden(fp, vp, X_BIT)) != OK)
-               r = r1;
-       else
-               r = req_stat(vp->v_fs_e, vp->v_inode_nr, VFS_PROC_NR,
-                            (char *) &(execi.sb), 0, 0);
-       if (r != OK) goto pm_execfinal;
-
-        if (round == 0) {
-               /* Deal with setuid/setgid executables */
-               if (vp->v_mode & I_SET_UID_BIT) {
-                       execi.new_uid = vp->v_uid;
-                       execi.setugid = 1;
-               }
-               if (vp->v_mode & I_SET_GID_BIT) {
-                       execi.new_gid = vp->v_gid;
-                       execi.setugid = 1;
-               }
-        }
-
-       r = map_header(&execi.hdr, execi.vp);
-       if (r != OK) goto pm_execfinal;
-
-       if (!is_script(execi.hdr, execi.vp->v_size) || round != 0)
-               break;
-
-       /* Get fresh copy of the file name. */
-       if ((r = fetch_name(path, path_len, 0, fullpath)) != OK)
-               printf("VFS pm_exec: 2nd fetch_name failed\n");
-       else
-               r = patch_stack(vp, mbuf, &frame_len, fullpath);
-
-       unlock_vnode(vp);
-       put_vnode(vp);
-       vp = NULL;
-       if (r != OK) goto pm_execfinal;
-  }
-
-  execi.proc_e = proc_e;
-  execi.frame_len = frame_len;
-
-  for (i = 0; exec_loaders[i].load_object != NULL; i++) {
-      r = (*exec_loaders[i].load_object)(&execi);
-      /* Loaded successfully, so no need to try other loaders */
-      if (r == OK) break;
-  }
-
-  if (r != OK) {   /* No exec loader could load the object */
-       r = ENOEXEC;
-       goto pm_execfinal;
-  }
-
-  /* Save off PC */
-  *pc = execi.pc;
-
-  /* Patch up stack and copy it from VFS to new core image. */
-  vsp = execi.stack_top;
-  vsp -= frame_len;
-  patch_ptr(mbuf, vsp);
-  if ((r = sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
-                  (phys_bytes)frame_len)) != OK) {
-       printf("VFS: datacopy failed (%d) trying to copy to %lu\n", r, vsp);
-       goto pm_execfinal;
-  }
-
-  if (r != OK) goto pm_execfinal;
-  clo_exec(rfp);
-
-  if (execi.setugid) {
-       /* If after loading the image we're still allowed to run with
-        * setuid or setgid, change credentials now */
-       rfp->fp_effuid = execi.new_uid;
-       rfp->fp_effgid = execi.new_gid;
-  }
-
-pm_execfinal:
-  if (vp != NULL) {
-       unlock_vnode(vp);
-       put_vnode(vp);
-  }
-  unlock_exec();
-  return(r);
-}
-
-/*===========================================================================*
- *                             load_aout                                    *
- *===========================================================================*/
-PRIVATE int load_aout(struct exec_info *execi)
-{
-  int r;
-  struct vnode *vp;
-  int proc_e;
-  off_t off;
-  int hdrlen;
-  int sep_id;
-  vir_bytes text_bytes, data_bytes, bss_bytes;
-  phys_bytes tot_bytes;                /* total space for program, including gap */
-
-  assert(execi != NULL);
-  assert(execi->hdr != NULL);
-  assert(execi->vp != NULL);
-
-  proc_e = execi->proc_e;
-  vp = execi->vp;
-
-  /* Read the file header and extract the segment sizes. */
-  r = read_header_aout(execi->hdr, execi->vp->v_size, &sep_id,
-                      &text_bytes, &data_bytes, &bss_bytes,
-                      &tot_bytes, &execi->pc, &hdrlen);
-  if (r != OK) return(r);
-
-  r = exec_newmem(proc_e, 0 /* text_addr */, text_bytes,
-                 0 /* data_addr */, data_bytes + bss_bytes, tot_bytes,
-                 execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, vp->v_inode_nr,
-                 execi->sb.st_ctime,
-                 execi->progname, execi->new_uid, execi->new_gid,
-                 &execi->stack_top, &execi->load_text, &execi->setugid);
-
-  if (r != OK) {
-        printf("VFS: load_aout: exec_newmem failed: %d\n", r);
-        return(r);
-  }
-
-  off = hdrlen;
-
-  /* Read in text and data segments. */
-  if (execi->load_text)
-       r = read_seg(vp, off, proc_e, T, 0, text_bytes);
-  off += text_bytes;
-  if (r == OK)
-       r = read_seg(vp, off, proc_e, D, 0, data_bytes);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             load_elf                                     *
- *===========================================================================*/
-PRIVATE int load_elf(struct exec_info *execi)
-{
-  int r;
-  struct vnode *vp;
-  int proc_e;
-  phys_bytes tot_bytes;                /* total space for program, including gap */
-  vir_bytes text_vaddr, text_paddr, text_filebytes, text_membytes;
-  vir_bytes data_vaddr, data_paddr, data_filebytes, data_membytes;
-  off_t text_offset, data_offset;
-  int sep_id, is_elf;
-
-  assert(execi != NULL);
-  assert(execi->hdr != NULL);
-  assert(execi->vp != NULL);
-
-  proc_e = execi->proc_e;
-  vp = execi->vp;
-
-  /* Read the file header and extract the segment sizes. */
-  r = read_header_elf(execi->hdr, &text_vaddr, &text_paddr,
-                     &text_filebytes, &text_membytes,
-                     &data_vaddr, &data_paddr,
-                     &data_filebytes, &data_membytes,
-                     &execi->pc, &text_offset, &data_offset);
-  if (r != OK) return(r);
-
-  sep_id = 0;
-  is_elf = 1;
-  tot_bytes = 0; /* Use default stack size */
-  r = exec_newmem(proc_e,
-                 trunc_page(text_vaddr), text_membytes,
-                 trunc_page(data_vaddr), data_membytes,
-                 tot_bytes, execi->frame_len, sep_id, is_elf,
-                 vp->v_dev, vp->v_inode_nr, execi->sb.st_ctime,
-                 execi->progname, execi->new_uid, execi->new_gid,
-                 &execi->stack_top, &execi->load_text, &execi->setugid);
-
-  if (r != OK) {
-        printf("VFS: load_elf: exec_newmem failed: %d\n", r);
-        return(r);
-  }
-
-  /* Read in text and data segments. */
-  if (execi->load_text)
-      r = read_seg(vp, text_offset, proc_e, T, text_vaddr, text_filebytes);
-
-  if (r == OK)
-      r = read_seg(vp, data_offset, proc_e, D, data_vaddr, data_filebytes);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             exec_newmem                                  *
- *===========================================================================*/
-PRIVATE int exec_newmem(
-  int proc_e,
-  vir_bytes text_addr,
-  vir_bytes text_bytes,
-  vir_bytes data_addr,
-  vir_bytes data_bytes,
-  vir_bytes tot_bytes,
-  vir_bytes frame_len,
-  int sep_id,
-  int is_elf,
-  dev_t st_dev,
-  ino_t st_ino,
-  time_t ctime,
-  char *progname,
-  int new_uid,
-  int new_gid,
-  vir_bytes *stack_topp,
-  int *load_textp,
-  int *setugidp
-)
-{
-/* Allocate a new memory map for a process that tries to exec */
-  int r;
-  struct exec_newmem e;
-  message m;
-
-  assert(setugidp != NULL);
-
-  e.text_addr = text_addr;
-  e.text_bytes = text_bytes;
-  e.data_addr = data_addr;
-  e.data_bytes = data_bytes;
-  e.tot_bytes  = tot_bytes;
-  e.args_bytes = frame_len;
-  e.sep_id     = sep_id;
-  e.is_elf     = is_elf;
-  e.st_dev     = st_dev;
-  e.st_ino     = st_ino;
-  e.enst_ctime = ctime;
-  e.new_uid    = new_uid;
-  e.new_gid    = new_gid;
-  e.setugid    = *setugidp;
-  strncpy(e.progname, progname, sizeof(e.progname)-1);
-  e.progname[sizeof(e.progname)-1] = '\0';
-
-  m.m_type = EXEC_NEWMEM;
-  m.EXC_NM_PROC = proc_e;
-  m.EXC_NM_PTR = (char *)&e;
-  if ((r = sendrec(PM_PROC_NR, &m)) != OK) return(r);
-
-  *stack_topp = m.m1_i1;
-  *load_textp = !!(m.m1_i2 & EXC_NM_RF_LOAD_TEXT);
-  *setugidp = !!(m.m1_i2 & EXC_NM_RF_ALLOW_SETUID);
-
-  return(m.m_type);
-}
-
-/*===========================================================================*
- *                             is_script                                    *
- *===========================================================================*/
-PRIVATE int is_script(const char *exec_hdr, size_t exec_len)
-{
-/* Is Interpreted script? */
-  assert(exec_hdr != NULL);
-
-  return(exec_hdr[0] == '#' && exec_hdr[1] == '!' && exec_len >= 2);
-}
-
-/*===========================================================================*
- *                             patch_stack                                  *
- *===========================================================================*/
-PRIVATE int patch_stack(vp, stack, stk_bytes, path)
-struct vnode *vp;              /* pointer for open script file */
-char stack[ARG_MAX];           /* pointer to stack image within VFS */
-vir_bytes *stk_bytes;          /* size of initial stack */
-char path[PATH_MAX];           /* path to script file */
-{
-/* Patch the argument vector to include the path name of the script to be
- * interpreted, and all strings on the #! line.  Returns the path name of
- * the interpreter.
- */
-  enum { INSERT=FALSE, REPLACE=TRUE };
-  int n, r;
-  off_t pos;
-  char *sp, *interp = NULL;
-  u64_t new_pos;
-  unsigned int cum_io;
-  char buf[_MAX_BLOCK_SIZE];
-
-  /* Make 'path' the new argv[0]. */
-  if (!insert_arg(stack, stk_bytes, path, REPLACE)) return(ENOMEM);
-
-  pos = 0;     /* Read from the start of the file */
-
-  /* Issue request */
-  r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING,
-                   VFS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io);
-  if (r != OK) return(r);
-
-  n = vp->v_size;
-  if (n > _MAX_BLOCK_SIZE)
-       n = _MAX_BLOCK_SIZE;
-  if (n < 2) return ENOEXEC;
-
-  sp = &(buf[2]);                              /* just behind the #! */
-  n -= 2;
-  if (n > PATH_MAX) n = PATH_MAX;
-
-  /* Use the 'path' variable for temporary storage */
-  memcpy(path, sp, n);
-
-  if ((sp = memchr(path, '\n', n)) == NULL) /* must be a proper line */
-       return(ENOEXEC);
-
-  /* Move sp backwards through script[], prepending each string to stack. */
-  for (;;) {
-       /* skip spaces behind argument. */
-       while (sp > path && (*--sp == ' ' || *sp == '\t')) {}
-       if (sp == path) break;
-
-       sp[1] = 0;
-       /* Move to the start of the argument. */
-       while (sp > path && sp[-1] != ' ' && sp[-1] != '\t') --sp;
-
-       interp = sp;
-       if (!insert_arg(stack, stk_bytes, sp, INSERT)) {
-               printf("VFS: patch_stack: insert_arg failed\n");
-               return(ENOMEM);
-       }
-  }
-
-  if(!interp)
-       return ENOEXEC;
-
-  /* Round *stk_bytes up to the size of a pointer for alignment contraints. */
-  *stk_bytes= ((*stk_bytes + PTRSIZE - 1) / PTRSIZE) * PTRSIZE;
-
-  if (interp != path)
-       memmove(path, interp, strlen(interp)+1);
-  return(OK);
-}
-
-/*===========================================================================*
- *                             insert_arg                                   *
- *===========================================================================*/
-PRIVATE int insert_arg(
-char stack[ARG_MAX],           /* pointer to stack image within PM */
-vir_bytes *stk_bytes,          /* size of initial stack */
-char *arg,                     /* argument to prepend/replace as new argv[0] */
-int replace
-)
-{
-/* Patch the stack so that arg will become argv[0].  Be careful, the stack may
- * be filled with garbage, although it normally looks like this:
- *     nargs argv[0] ... argv[nargs-1] NULL envp[0] ... NULL
- * followed by the strings "pointed" to by the argv[i] and the envp[i].  The
- * pointers are really offsets from the start of stack.
- * Return true iff the operation succeeded.
- */
-  int offset, a0, a1, old_bytes = *stk_bytes;
-
-  /* Prepending arg adds at least one string and a zero byte. */
-  offset = strlen(arg) + 1;
-
-  a0 = (int) ((char **) stack)[1];     /* argv[0] */
-  if (a0 < 4 * PTRSIZE || a0 >= old_bytes) return(FALSE);
-
-  a1 = a0;                     /* a1 will point to the strings to be moved */
-  if (replace) {
-       /* Move a1 to the end of argv[0][] (argv[1] if nargs > 1). */
-       do {
-               if (a1 == old_bytes) return(FALSE);
-               --offset;
-       } while (stack[a1++] != 0);
-  } else {
-       offset += PTRSIZE;      /* new argv[0] needs new pointer in argv[] */
-       a0 += PTRSIZE;          /* location of new argv[0][]. */
-  }
-
-  /* stack will grow by offset bytes (or shrink by -offset bytes) */
-  if ((*stk_bytes += offset) > ARG_MAX) return(FALSE);
-
-  /* Reposition the strings by offset bytes */
-  memmove(stack + a1 + offset, stack + a1, old_bytes - a1);
-
-  strcpy(stack + a0, arg);     /* Put arg in the new space. */
-
-  if (!replace) {
-       /* Make space for a new argv[0]. */
-       memmove(stack + 2 * PTRSIZE, stack + 1 * PTRSIZE, a0 - 2 * PTRSIZE);
-
-       ((char **) stack)[0]++; /* nargs++; */
-  }
-  /* Now patch up argv[] and envp[] by offset. */
-  patch_ptr(stack, (vir_bytes) offset);
-  ((char **) stack)[1] = (char *) a0;  /* set argv[0] correctly */
-  return(TRUE);
-}
-
-
-/*===========================================================================*
- *                             patch_ptr                                    *
- *===========================================================================*/
-PRIVATE void patch_ptr(
-char stack[ARG_MAX],           /* pointer to stack image within PM */
-vir_bytes base                 /* virtual address of stack base inside user */
-)
-{
-/* When doing an exec(name, argv, envp) call, the user builds up a stack
- * image with arg and env pointers relative to the start of the stack.  Now
- * these pointers must be relocated, since the stack is not positioned at
- * address 0 in the user's address space.
- */
-
-  char **ap, flag;
-  vir_bytes v;
-
-  flag = 0;                    /* counts number of 0-pointers seen */
-  ap = (char **) stack;                /* points initially to 'nargs' */
-  ap++;                                /* now points to argv[0] */
-  while (flag < 2) {
-       if (ap >= (char **) &stack[ARG_MAX]) return;    /* too bad */
-       if (*ap != NULL) {
-               v = (vir_bytes) *ap;    /* v is relative pointer */
-               v += base;              /* relocate it */
-               *ap = (char *) v;       /* put it back */
-       } else {
-               flag++;
-       }
-       ap++;
-  }
-}
-
-/*===========================================================================*
- *                             read_seg                                     *
- *===========================================================================*/
-PRIVATE int read_seg(
-struct vnode *vp,              /* inode descriptor to read from */
-off_t off,                     /* offset in file */
-int proc_e,                    /* process number (endpoint) */
-int seg,                       /* T, D, or S */
-vir_bytes seg_addr,            /* address to load segment */
-phys_bytes seg_bytes           /* how much is to be transferred? */
-)
-{
-/*
- * The byte count on read is usually smaller than the segment count, because
- * a segment is padded out to a click multiple, and the data segment is only
- * partially initialized.
- */
-  int r;
-  unsigned n, o;
-  u64_t new_pos;
-  unsigned int cum_io;
-  static char buf[128 * 1024];
-
-  assert((seg == T)||(seg == D));
-
-  /* Make sure that the file is big enough */
-  if (vp->v_size < off+seg_bytes) return(EIO);
-
-  if (seg == T) {
-       /* We have to use a copy loop until safecopies support segments */
-       o = 0;
-       while (o < seg_bytes) {
-               n = seg_bytes - o;
-               if (n > sizeof(buf))
-                       n = sizeof(buf);
-
-               if ((r = req_readwrite(vp->v_fs_e,vp->v_inode_nr,cvul64(off+o),
-                                      READING, VFS_PROC_NR, buf,
-                                      n, &new_pos, &cum_io)) != OK) {
-                       printf("VFS: read_seg: req_readwrite failed (text)\n");
-                       return(r);
-               }
-
-               if (cum_io != n) {
-                       printf(
-               "VFSread_seg segment has not been read properly by exec() \n");
-                       return(EIO);
-               }
-
-               if ((r = sys_vircopy(VFS_PROC_NR, D, (vir_bytes)buf, proc_e,
-                                    seg, seg_addr + o, n)) != OK) {
-                       printf("VFS: read_seg: copy failed (text)\n");
-                       return(r);
-               }
-
-               o += n;
-       }
-       return(OK);
-  } else if (seg == D) {
-
-       if ((r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(off), READING,
-                        proc_e, (char*)seg_addr, seg_bytes,
-                        &new_pos, &cum_io)) != OK) {
-           printf("VFS: read_seg: req_readwrite failed (data)\n");
-           return(r);
-       }
-
-       if (r == OK && cum_io != seg_bytes)
-           printf("VFS: read_seg segment has not been read properly by exec()\n");
-
-       return(r);
-  }
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             clo_exec                                     *
- *===========================================================================*/
-PRIVATE void clo_exec(struct fproc *rfp)
-{
-/* Files can be marked with the FD_CLOEXEC bit (in fp->fp_cloexec).
- */
-  int i;
-
-  /* Check the file desriptors one by one for presence of FD_CLOEXEC. */
-  for (i = 0; i < OPEN_MAX; i++)
-       if ( FD_ISSET(i, &rfp->fp_cloexec_set))
-               (void) close_fd(rfp, i);
-}
-
-/*===========================================================================*
- *                             map_header                                   *
- *===========================================================================*/
-PRIVATE int map_header(char **exec_hdr, const struct vnode *vp)
-{
-  int r;
-  u64_t new_pos;
-  unsigned int cum_io;
-  off_t pos;
-
-  pos = 0;     /* Read from the start of the file */
-
-  r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING,
-                   VFS_PROC_NR, hdr, MIN(vp->v_size, PAGE_SIZE),
-                   &new_pos, &cum_io);
-  if (r != OK) {
-       printf("VFS: exec: map_header: req_readwrite failed\n");
-       return(r);
-  }
-
-  *exec_hdr = hdr;
-  return(OK);
-}
diff --git a/servers/avfs/exec.h b/servers/avfs/exec.h
deleted file mode 100644 (file)
index ddf6e5a..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-#ifndef _VFS_EXEC_H_
-#define _VFS_EXEC_H_ 1
-
-struct exec_info {
-    int  proc_e;                       /* Process endpoint */
-    char *hdr;                         /* Exec file's header */
-    vir_bytes pc;                      /* Entry point of exec file */
-    vir_bytes stack_top;               /* Top of the stack */
-    vir_bytes frame_len;               /* Stack size */
-    uid_t new_uid;                     /* Process UID after exec */
-    gid_t new_gid;                     /* Process GID after exec */
-    int load_text;                     /* Load text section? */
-    int setugid;                       /* Allow set{u,g}id execution? */
-    struct vnode *vp;                  /* Exec file's vnode */
-    struct stat sb;                    /* Exec file's stat structure */
-    char progname[PROC_NAME_LEN];      /* Program name */
-};
-
-#endif /* !_VFS_EXEC_H_ */
diff --git a/servers/avfs/file.h b/servers/avfs/file.h
deleted file mode 100644 (file)
index 52a5773..0000000
+++ /dev/null
@@ -1,48 +0,0 @@
-#ifndef __VFS_FILE_H__
-#define __VFS_FILE_H__
-
-/* This is the filp table.  It is an intermediary between file descriptors and
- * inodes.  A slot is free if filp_count == 0.
- */
-
-EXTERN struct filp {
-  mode_t filp_mode;            /* RW bits, telling how file is opened */
-  int filp_flags;              /* flags from open and fcntl */
-  int filp_state;              /* state for crash recovery */
-  int filp_count;              /* how many file descriptors share this slot?*/
-  struct vnode *filp_vno;      /* vnode belonging to this file */
-  u64_t filp_pos;              /* file position */
-  mutex_t filp_lock;           /* lock to gain exclusive access */
-  struct fproc *filp_softlock; /* if not NULL; this filp didn't lock the
-                                * vnode. Another filp already holds a lock
-                                * for this thread */
-
-  /* the following fields are for select() and are owned by the generic
-   * select() code (i.e., fd-type-specific select() code can't touch these).
-   */
-  int filp_selectors;          /* select()ing processes blocking on this fd */
-  int filp_select_ops;         /* interested in these SEL_* operations */
-  int filp_select_flags;       /* Select flags for the filp */
-
-  /* following are for fd-type-specific select() */
-  int filp_pipe_select_ops;
-} filp[NR_FILPS];
-
-#define FILP_CLOSED    0       /* filp_mode: associated device closed */
-
-#define FS_NORMAL      0       /* file descriptor can be used normally */
-#define FS_NEEDS_REOPEN        1       /* file descriptor needs to be re-opened */
-
-#define FSF_UPDATE     001     /* The driver should be informed about new
-                                * state.
-                                */
-#define FSF_BUSY       002     /* Select operation sent to driver but no
-                                * reply yet.
-                                */
-#define FSF_RD_BLOCK   010     /* Read request is blocking, the driver should
-                                * keep state.
-                                */
-#define FSF_WR_BLOCK   020     /* Write request is blocking */
-#define FSF_ERR_BLOCK  040     /* Exception request is blocking */
-#define FSF_BLOCKED    070
-#endif
diff --git a/servers/avfs/filedes.c b/servers/avfs/filedes.c
deleted file mode 100644 (file)
index 1d3cbc0..0000000
+++ /dev/null
@@ -1,578 +0,0 @@
-/* This file contains the procedures that manipulate file descriptors.
- *
- * The entry points into this file are
- *   get_fd:       look for free file descriptor and free filp slots
- *   get_filp:     look up the filp entry for a given file descriptor
- *   find_filp:            find a filp slot that points to a given vnode
- *   inval_filp:    invalidate a filp and associated fd's, only let close()
- *                  happen on it
- *   do_verify_fd:  verify whether the given file descriptor is valid for
- *                  the given endpoint.
- *   do_set_filp:   marks a filp as in-flight.
- *   do_copy_filp:  copies a filp to another endpoint.
- *   do_put_filp:   marks a filp as not in-flight anymore.
- *   do_cancel_fd:  cancel the transaction when something goes wrong for
- *                  the receiver.
- */
-
-#include <sys/select.h>
-#include <minix/callnr.h>
-#include <minix/u64.h>
-#include <assert.h>
-#include "fs.h"
-#include "file.h"
-#include "fproc.h"
-#include "vnode.h"
-
-
-FORWARD _PROTOTYPE( filp_id_t verify_fd, (endpoint_t ep, int fd)       );
-
-#if LOCK_DEBUG
-/*===========================================================================*
- *                             check_filp_locks                             *
- *===========================================================================*/
-PUBLIC void check_filp_locks_by_me(void)
-{
-/* Check whether this thread still has filp locks held */
-  struct filp *f;
-  int r;
-
-  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-       r = mutex_trylock(&f->filp_lock);
-       if (r == -EDEADLK)
-               panic("Thread %d still holds filp lock on filp %p call_nr=%d\n",
-                     mthread_self(), f, call_nr);
-       else if (r == 0) {
-               /* We just obtained the lock, release it */
-               mutex_unlock(&f->filp_lock);
-       }
-  }
-}
-#endif
-
-/*===========================================================================*
- *                             check_filp_locks                             *
- *===========================================================================*/
-PUBLIC void check_filp_locks(void)
-{
-  struct filp *f;
-  int r, count = 0;
-
-  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-       r = mutex_trylock(&f->filp_lock);
-       if (r == -EBUSY) {
-               /* Mutex is still locked */
-               count++;
-       } else if (r == 0) {
-               /* We just obtained a lock, don't want it */
-               mutex_unlock(&f->filp_lock);
-       } else
-               panic("filp_lock weird state");
-  }
-  if (count) panic("locked filps");
-#if 0
-  else printf("check_filp_locks OK\n");
-#endif
-}
-
-/*===========================================================================*
- *                             init_filps                                           *
- *===========================================================================*/
-PUBLIC void init_filps(void)
-{
-/* Initialize filps */
-  struct filp *f;
-
-  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-       mutex_init(&f->filp_lock, NULL);
-  }
-
-}
-
-/*===========================================================================*
- *                             get_fd                                       *
- *===========================================================================*/
-PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
-{
-/* Look for a free file descriptor and a free filp slot.  Fill in the mode word
- * in the latter, but don't claim either one yet, since the open() or creat()
- * may yet fail.
- */
-
-  register struct filp *f;
-  register int i;
-
-  /* Search the fproc fp_filp table for a free file descriptor. */
-  for (i = start; i < OPEN_MAX; i++) {
-       if (fp->fp_filp[i] == NULL && !FD_ISSET(i, &fp->fp_filp_inuse)) {
-               /* A file descriptor has been located. */
-               *k = i;
-               break;
-       }
-  }
-
-  /* Check to see if a file descriptor has been found. */
-  if (i >= OPEN_MAX) return(EMFILE);
-
-  /* If we don't care about a filp, return now */
-  if (fpt == NULL) return(OK);
-
-  /* Now that a file descriptor has been found, look for a free filp slot. */
-  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-       assert(f->filp_count >= 0);
-       if (f->filp_count == 0 && mutex_trylock(&f->filp_lock) == 0) {
-               f->filp_mode = bits;
-               f->filp_pos = cvu64(0);
-               f->filp_selectors = 0;
-               f->filp_select_ops = 0;
-               f->filp_pipe_select_ops = 0;
-               f->filp_flags = 0;
-               f->filp_state = FS_NORMAL;
-               f->filp_select_flags = 0;
-               f->filp_softlock = NULL;
-               *fpt = f;
-               return(OK);
-       }
-  }
-
-  /* If control passes here, the filp table must be full.  Report that back. */
-  return(ENFILE);
-}
-
-
-/*===========================================================================*
- *                             get_filp                                     *
- *===========================================================================*/
-PUBLIC struct filp *get_filp(fild, locktype)
-int fild;                      /* file descriptor */
-tll_access_t locktype;
-{
-/* See if 'fild' refers to a valid file descr.  If so, return its filp ptr. */
-
-  return get_filp2(fp, fild, locktype);
-}
-
-
-/*===========================================================================*
- *                             get_filp2                                    *
- *===========================================================================*/
-PUBLIC struct filp *get_filp2(rfp, fild, locktype)
-register struct fproc *rfp;
-int fild;                      /* file descriptor */
-tll_access_t locktype;
-{
-/* See if 'fild' refers to a valid file descr.  If so, return its filp ptr. */
-  struct filp *filp;
-
-  err_code = EBADF;
-  if (fild < 0 || fild >= OPEN_MAX ) return(NULL);
-  if (rfp->fp_filp[fild] == NULL && FD_ISSET(fild, &rfp->fp_filp_inuse))
-       err_code = EIO; /* The filedes is not there, but is not closed either.
-                        */
-  if ((filp = rfp->fp_filp[fild]) != NULL) lock_filp(filp, locktype);
-
-  return(filp);        /* may also be NULL */
-}
-
-
-/*===========================================================================*
- *                             find_filp                                    *
- *===========================================================================*/
-PUBLIC struct filp *find_filp(struct vnode *vp, mode_t bits)
-{
-/* Find a filp slot that refers to the vnode 'vp' in a way as described
- * by the mode bit 'bits'. Used for determining whether somebody is still
- * interested in either end of a pipe.  Also used when opening a FIFO to
- * find partners to share a filp field with (to shared the file position).
- * Like 'get_fd' it performs its job by linear search through the filp table.
- */
-
-  struct filp *f;
-
-  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-       if (f->filp_count != 0 && f->filp_vno == vp && (f->filp_mode & bits)) {
-               return(f);
-       }
-  }
-
-  /* If control passes here, the filp wasn't there.  Report that back. */
-  return(NULL);
-}
-
-/*===========================================================================*
- *                             invalidate_filp                              *
- *===========================================================================*/
-PUBLIC int invalidate_filp(struct filp *rfilp)
-{
-/* Invalidate filp. fp_filp_inuse is not cleared, so filp can't be reused
-   until it is closed first. */
-
-  int f, fd, n = 0;
-  for (f = 0; f < NR_PROCS; f++) {
-       if (fproc[f].fp_pid == PID_FREE) continue;
-       for (fd = 0; fd < OPEN_MAX; fd++) {
-               if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == rfilp) {
-                       fproc[f].fp_filp[fd] = NULL;
-                       n++;
-               }
-       }
-  }
-
-  return(n);   /* Report back how often this filp has been invalidated. */
-}
-
-/*===========================================================================*
- *                     invalidate_filp_by_endpt                             *
- *===========================================================================*/
-PUBLIC void invalidate_filp_by_endpt(endpoint_t proc_e)
-{
-  struct filp *f;
-
-  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-       if (f->filp_count != 0 && f->filp_vno != NULL) {
-               if (f->filp_vno->v_fs_e == proc_e)
-                       (void) invalidate_filp(f);
-       }
-  }
-}
-
-/*===========================================================================*
- *                             lock_filp                                    *
- *===========================================================================*/
-PUBLIC void lock_filp(filp, locktype)
-struct filp *filp;
-tll_access_t locktype;
-{
-  message org_m_in;
-  struct fproc *org_fp;
-  struct worker_thread *org_self;
-  struct vnode *vp;
-
-  assert(filp->filp_count > 0);
-  vp = filp->filp_vno;
-  assert(vp != NULL);
-
-  /* Lock vnode only if we haven't already locked it. If already locked by us,
-   * we're allowed to have one additional 'soft' lock. */
-  if (tll_locked_by_me(&vp->v_lock)) {
-       assert(filp->filp_softlock == NULL);
-       filp->filp_softlock = fp;
-  } else {
-       lock_vnode(vp, locktype);
-  }
-
-  assert(vp->v_ref_count > 0); /* vnode still in use? */
-  assert(filp->filp_vno == vp);        /* vnode still what we think it is? */
-  assert(filp->filp_count > 0); /* filp still in use? */
-
-  /* First try to get filp lock right off the bat */
-  if (mutex_trylock(&filp->filp_lock) != 0) {
-
-       /* Already in use, let's wait for our turn */
-       org_m_in = m_in;
-       org_fp = fp;
-       org_self = self;
-
-       if (mutex_lock(&filp->filp_lock) != 0)
-               panic("unable to obtain lock on filp");
-
-       m_in = org_m_in;
-       fp = org_fp;
-       self = org_self;
-  }
-
-  assert(filp->filp_count > 0);        /* Yet again; filp still in use? */
-}
-
-/*===========================================================================*
- *                             unlock_filp                                  *
- *===========================================================================*/
-PUBLIC void unlock_filp(filp)
-struct filp *filp;
-{
-  /* If this filp holds a soft lock on the vnode, we must be the owner */
-  if (filp->filp_softlock != NULL)
-       assert(filp->filp_softlock == fp);
-
-  if (filp->filp_count > 0) {
-       /* Only unlock vnode if filp is still in use */
-
-       /* and if we don't hold a soft lock */
-       if (filp->filp_softlock == NULL) {
-               assert(tll_islocked(&(filp->filp_vno->v_lock)));
-               unlock_vnode(filp->filp_vno);
-       }
-  }
-
-  filp->filp_softlock = NULL;
-  if (mutex_unlock(&filp->filp_lock) != 0)
-       panic("unable to release lock on filp");
-}
-
-/*===========================================================================*
- *                             unlock_filps                                 *
- *===========================================================================*/
-PUBLIC void unlock_filps(filp1, filp2)
-struct filp *filp1;
-struct filp *filp2;
-{
-/* Unlock two filps that are tied to the same vnode. As a thread can lock a
- * vnode only once, unlocking the vnode twice would result in an error. */
-
-  /* No NULL pointers and not equal */
-  assert(filp1);
-  assert(filp2);
-  assert(filp1 != filp2);
-
-  /* Must be tied to the same vnode and not NULL */
-  assert(filp1->filp_vno == filp2->filp_vno);
-  assert(filp1->filp_vno != NULL);
-
-  if (filp1->filp_count > 0 && filp2->filp_count > 0) {
-       /* Only unlock vnode if filps are still in use */
-       unlock_vnode(filp1->filp_vno);
-  }
-
-  filp1->filp_softlock = NULL;
-  filp2->filp_softlock = NULL;
-  if (mutex_unlock(&filp2->filp_lock) != 0)
-       panic("unable to release filp lock on filp2");
-  if (mutex_unlock(&filp1->filp_lock) != 0)
-       panic("unable to release filp lock on filp1");
-}
-
-/*===========================================================================*
- *                             verify_fd                                    *
- *===========================================================================*/
-PRIVATE filp_id_t verify_fd(ep, fd)
-endpoint_t ep;
-int fd;
-{
-/* Verify whether the file descriptor 'fd' is valid for the endpoint 'ep'. When
- * the file descriptor is valid, verify_fd returns a pointer to that filp, else
- * it returns NULL.
- */
-  int slot;
-  struct filp *rfilp;
-
-  if (isokendpt(ep, &slot) != OK)
-       return(NULL);
-
-  rfilp = get_filp2(&fproc[slot], fd, VNODE_READ);
-
-  return(rfilp);
-}
-
-/*===========================================================================*
- *                              do_verify_fd                                 *
- *===========================================================================*/
-PUBLIC int do_verify_fd(void)
-{
-  struct filp *rfilp;
-  rfilp = (struct filp *) verify_fd(m_in.USER_ENDPT, m_in.COUNT);
-  m_out.ADDRESS = (void *) rfilp;
-  if (rfilp != NULL) unlock_filp(rfilp);
-  return (rfilp != NULL) ? OK : EINVAL;
-}
-
-/*===========================================================================*
- *                              set_filp                                     *
- *===========================================================================*/
-PUBLIC int set_filp(sfilp)
-filp_id_t sfilp;
-{
-  if (sfilp == NULL) return(EINVAL);
-
-  lock_filp(sfilp, VNODE_READ);
-  sfilp->filp_count++;
-  unlock_filp(sfilp);
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                              do_set_filp                                  *
- *===========================================================================*/
-PUBLIC int do_set_filp(void)
-{
-  return set_filp((filp_id_t) m_in.ADDRESS);
-}
-
-/*===========================================================================*
- *                              copy_filp                                    *
- *===========================================================================*/
-PUBLIC int copy_filp(to_ep, cfilp)
-endpoint_t to_ep;
-filp_id_t cfilp;
-{
-  int fd;
-  int slot;
-  struct fproc *rfp;
-
-  if (isokendpt(to_ep, &slot) != OK) return(EINVAL);
-  rfp = &fproc[slot];
-
-  /* Find an open slot in fp_filp */
-  for (fd = 0; fd < OPEN_MAX; fd++) {
-       if (rfp->fp_filp[fd] == NULL &&
-           !FD_ISSET(fd, &rfp->fp_filp_inuse)) {
-
-               /* Found a free slot, add descriptor */
-               FD_SET(fd, &rfp->fp_filp_inuse);
-               rfp->fp_filp[fd] = cfilp;
-               rfp->fp_filp[fd]->filp_count++;
-               return(fd);
-       }
-  }
-
-  /* File descriptor table is full */
-  return(EMFILE);
-}
-
-/*===========================================================================*
- *                              do_copy_filp                                 *
- *===========================================================================*/
-PUBLIC int do_copy_filp(void)
-{
-  return copy_filp(m_in.USER_ENDPT, (filp_id_t) m_in.ADDRESS);
-}
-
-/*===========================================================================*
- *                              put_filp                                     *
- *===========================================================================*/
-PUBLIC int put_filp(pfilp)
-filp_id_t pfilp;
-{
-  if (pfilp == NULL) {
-       return EINVAL;
-  } else {
-       lock_filp(pfilp, VNODE_OPCL);
-       close_filp(pfilp);
-       return(OK);
-  }
-}
-
-/*===========================================================================*
- *                              do_put_filp                                  *
- *===========================================================================*/
-PUBLIC int do_put_filp(void)
-{
-  return put_filp((filp_id_t) m_in.ADDRESS);
-}
-
-/*===========================================================================*
- *                             cancel_fd                                    *
- *===========================================================================*/
-PUBLIC int cancel_fd(ep, fd)
-endpoint_t ep;
-int fd;
-{
-  int slot;
-  struct fproc *rfp;
-  struct filp *rfilp;
-
-  if (isokendpt(ep, &slot) != OK) return(EINVAL);
-  rfp = &fproc[slot];
-
-  /* Check that the input 'fd' is valid */
-  rfilp = (struct filp *) verify_fd(ep, fd);
-  if (rfilp != NULL) {
-       /* Found a valid descriptor, remove it */
-       FD_CLR(fd, &rfp->fp_filp_inuse);
-       if (rfp->fp_filp[fd]->filp_count == 0) {
-               unlock_filp(rfilp);
-               printf("VFS: filp_count for slot %d fd %d already zero", slot,
-                     fd);
-               return(EINVAL);
-       }
-       rfp->fp_filp[fd]->filp_count--;
-       rfp->fp_filp[fd] = NULL;
-       unlock_filp(rfilp);
-       return(fd);
-  }
-
-  /* File descriptor is not valid for the endpoint. */
-  return(EINVAL);
-}
-
-/*===========================================================================*
- *                              do_cancel_fd                                 *
- *===========================================================================*/
-PUBLIC int do_cancel_fd(void)
-{
-  return cancel_fd(m_in.USER_ENDPT, m_in.COUNT);
-}
-
-/*===========================================================================*
- *                             close_filp                                   *
- *===========================================================================*/
-PUBLIC void close_filp(f)
-struct filp *f;
-{
-/* Close a file. Will also unlock filp when done */
-
-  int mode_word, rw;
-  dev_t dev;
-  struct vnode *vp;
-
-  /* Must be locked */
-  assert(mutex_trylock(&f->filp_lock) == -EDEADLK);
-  assert(tll_islocked(&f->filp_vno->v_lock));
-
-  vp = f->filp_vno;
-
-  if (f->filp_count - 1 == 0 && f->filp_mode != FILP_CLOSED) {
-       /* Check to see if the file is special. */
-       mode_word = vp->v_mode & I_TYPE;
-       if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
-               dev = (dev_t) vp->v_sdev;
-               if (mode_word == I_BLOCK_SPECIAL)  {
-                       lock_bsf();
-                       if (vp->v_bfs_e == ROOT_FS_E) {
-                               /* Invalidate the cache unless the special is
-                                * mounted. Assume that the root filesystem's
-                                * is open only for fsck.
-                                */
-                               req_flush(vp->v_bfs_e, dev);
-                       }
-                       unlock_bsf();
-               }
-
-               /* Do any special processing on device close.
-                * Ignore any errors, even SUSPEND.
-                 */
-               if (mode_word == I_BLOCK_SPECIAL)
-                       (void) bdev_close(dev);
-               else
-                       (void) dev_close(dev, f-filp);
-
-               f->filp_mode = FILP_CLOSED;
-       }
-  }
-
-  /* If the inode being closed is a pipe, release everyone hanging on it. */
-  if (vp->v_pipe == I_PIPE) {
-       rw = (f->filp_mode & R_BIT ? WRITE : READ);
-       release(vp, rw, NR_PROCS);
-  }
-
-  /* If a write has been done, the inode is already marked as DIRTY. */
-  if (--f->filp_count == 0) {
-       if (vp->v_pipe == I_PIPE) {
-               /* Last reader or writer is going. Tell PFS about latest
-                * pipe size.
-                */
-               truncate_vnode(vp, vp->v_size);
-       }
-
-       unlock_vnode(f->filp_vno);
-       put_vnode(f->filp_vno);
-  } else if (f->filp_count < 0) {
-       panic("VFS: invalid filp count: %d ino %d/%d", f->filp_count,
-             vp->v_dev, vp->v_inode_nr);
-  } else {
-       unlock_vnode(f->filp_vno);
-  }
-
-  mutex_unlock(&f->filp_lock);
-}
diff --git a/servers/avfs/fproc.h b/servers/avfs/fproc.h
deleted file mode 100644 (file)
index 79ede32..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-#ifndef __VFS_FPROC_H__
-#define __VFS_FPROC_H__
-
-#include "threads.h"
-
-#include <sys/select.h>
-#include <minix/safecopies.h>
-
-/* This is the per-process information.  A slot is reserved for each potential
- * process. Thus NR_PROCS must be the same as in the kernel. It is not
- * possible or even necessary to tell when a slot is free here.
- */
-#define LOCK_DEBUG 0
-EXTERN struct fproc {
-  unsigned fp_flags;
-
-  pid_t fp_pid;                        /* process id */
-  endpoint_t fp_endpoint;      /* kernel endpoint number of this process */
-
-  struct vnode *fp_wd;         /* working directory; NULL during reboot */
-  struct vnode *fp_rd;         /* root directory; NULL during reboot */
-
-  struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
-  fd_set fp_filp_inuse;                /* which fd's are in use? */
-  fd_set fp_cloexec_set;       /* bit map for POSIX Table 6-2 FD_CLOEXEC */
-
-  dev_t fp_tty;                        /* major/minor of controlling tty */
-
-  int fp_blocked_on;           /* what is it blocked on */
-  int fp_block_callnr;         /* blocked call if rd/wr can't finish */
-  int  fp_cum_io_partial;      /* partial byte count if rd/wr can't finish */
-  endpoint_t fp_task;          /* which task is proc suspended on */
-  endpoint_t fp_ioproc;                /* proc no. in suspended-on i/o message */
-
-  cp_grant_id_t fp_grant;      /* revoke this grant on unsuspend if > -1 */
-
-  uid_t fp_realuid;            /* real user id */
-  uid_t fp_effuid;             /* effective user id */
-  gid_t fp_realgid;            /* real group id */
-  gid_t fp_effgid;             /* effective group id */
-  int fp_ngroups;              /* number of supplemental groups */
-  gid_t fp_sgroups[NGROUPS_MAX];/* supplemental groups */
-  mode_t fp_umask;             /* mask set by umask system call */
-
-  message *fp_sendrec;         /* request/reply to/from FS/driver */
-  mutex_t fp_lock;             /* mutex to lock fproc object */
-  struct job fp_job;           /* pending job */
-  thread_t fp_wtid;            /* Thread ID of worker */
-#if LOCK_DEBUG
-  int fp_vp_rdlocks;           /* number of read-only locks on vnodes */
-  int fp_vmnt_rdlocks;         /* number of read-only locks on vmnts */
-#endif
-} fproc[NR_PROCS];
-
-/* fp_flags */
-#define FP_NOFLAGS     00
-#define FP_SUSP_REOPEN 01      /* Process is suspended until the reopens are
-                                * completed (after the restart of a driver).
-                                */
-#define FP_REVIVED      0002   /* Indicates process is being revived */
-#define FP_SESLDR       0004   /* Set if process is session leader */
-#define FP_PENDING      0010   /* Set if process has pending work */
-#define FP_EXITING      0020   /* Set if process is exiting */
-#define FP_PM_PENDING   0040   /* Set if process has pending PM request */
-#define FP_SYS_PROC     0100   /* Set if process is a driver or FS */
-#define FP_DROP_WORK    0200   /* Set if process won't accept new work */
-
-/* Field values. */
-#define NOT_REVIVING       0xC0FFEEE   /* process is not being revived */
-#define REVIVING           0xDEEAD     /* process is being revived from suspension */
-#define PID_FREE          0    /* process slot free */
-
-#endif /* __VFS_FPROC_H__ */
diff --git a/servers/avfs/fs.h b/servers/avfs/fs.h
deleted file mode 100644 (file)
index 9531c22..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef __VFS_FS_H__
-#define __VFS_FS_H__
-
-/* This is the master header for fs.  It includes some other files
- * and defines the principal constants.
- */
-#define _POSIX_SOURCE      1   /* tell headers to include POSIX stuff */
-#define _MINIX             1   /* tell headers to include MINIX stuff */
-#define _SYSTEM            1   /* tell headers that this is the kernel */
-
-#define DO_SANITYCHECKS           0
-
-#if DO_SANITYCHECKS
-#define SANITYCHECK do {                       \
-       if(!check_vrefs() || !check_pipe()) {                           \
-          printf("VFS:%s:%d: call_nr %d who_e %d\n", \
-                       __FILE__, __LINE__, call_nr, who_e);    \
-          panic("sanity check failed");        \
-       }                                                       \
-} while(0)
-#else
-#define SANITYCHECK
-#endif
-
-/* The following are so basic, all the *.c files get them automatically. */
-#include <minix/config.h>      /* MUST be first */
-#include <minix/ansi.h>                /* MUST be second */
-#include <sys/types.h>
-#include <minix/const.h>
-#include <minix/type.h>
-#include <minix/dmap.h>
-#include <minix/ds.h>
-#include <minix/rs.h>
-
-#include <limits.h>
-#include <errno.h>
-#include <unistd.h>
-
-#include <minix/syslib.h>
-#include <minix/sysutil.h>
-#include <minix/timers.h>
-
-#include "const.h"
-#include "dmap.h"
-#include "proto.h"
-#include "threads.h"
-#include "glo.h"
-#include "comm.h"
-#include "vmnt.h"
-
-#endif
diff --git a/servers/avfs/fscall.c b/servers/avfs/fscall.c
deleted file mode 100644 (file)
index 257afb3..0000000
+++ /dev/null
@@ -1,132 +0,0 @@
-/* This file handles nested counter-request calls to VFS sent by file system
- * (FS) servers in response to VFS requests.
- *
- * The entry points into this file are
- *   nested_fs_call    perform a nested call from a file system server
- *   nested_dev_call   perform a nested call from a device driver server
- *
- */
-
-#include "fs.h"
-#include "fproc.h"
-#include <string.h>
-#include <assert.h>
-#include <minix/callnr.h>
-#include <minix/endpoint.h>
-#include <minix/vfsif.h>
-
-/* maximum nested call stack depth */
-#define MAX_DEPTH 1
-
-/* global variables stack */
-PRIVATE struct {
-  struct fproc *g_fp;                  /* pointer to caller process */
-  message g_m_in;                      /* request message */
-  message g_m_out;                     /* reply message */
-  int g_who_e;                         /* endpoint of caller process */
-  int g_who_p;                         /* slot number of caller process */
-  int g_call_nr;                       /* call number */
-  int g_super_user;                    /* is the caller root? */
-  char g_user_fullpath[PATH_MAX];      /* path to look up */
-} globals[MAX_DEPTH];
-
-PRIVATE int depth = 0;                 /* current globals stack level */
-
-FORWARD _PROTOTYPE( int push_globals, (void)                           );
-FORWARD _PROTOTYPE( void pop_globals, (void)                           );
-FORWARD _PROTOTYPE( void set_globals, (message *m)                     );
-
-/*===========================================================================*
- *                             push_globals                                 *
- *===========================================================================*/
-PRIVATE int push_globals()
-{
-/* Save the global variables of the current call onto the globals stack.
- */
-
-  if (depth == MAX_DEPTH)
-       return(EPERM);
-
-  globals[depth].g_fp = fp;
-  globals[depth].g_m_in = m_in;
-  globals[depth].g_m_out = m_out;
-  globals[depth].g_super_user = super_user;
-
-  /* err_code is not used across blocking calls */
-  depth++;
-  return(OK);
-}
-
-/*===========================================================================*
- *                             pop_globals                                  *
- *===========================================================================*/
-PRIVATE void pop_globals()
-{
-/* Restore the global variables of a call from the globals stack.
- */
-
-  if (depth == 0)
-       panic("Popping from empty globals stack!");
-
-  depth--;
-
-  fp = globals[depth].g_fp;
-  m_in = globals[depth].g_m_in;
-  m_out = globals[depth].g_m_out;
-
-}
-
-/*===========================================================================*
- *                             set_globals                                  *
- *===========================================================================*/
-PRIVATE void set_globals(m)
-message *m;                            /* request message */
-{
-/* Initialize global variables based on a request message.
- */
-  int proc_p;
-
-  m_in = *m;
-
-  proc_p = _ENDPOINT_P(m_in.m_source);
-  fp = &fproc[proc_p];
-
-  /* the rest need not be initialized */
-}
-
-/*===========================================================================*
- *                             nested_fs_call                               *
- *===========================================================================*/
-PUBLIC void nested_fs_call(m)
-message *m;                            /* request/reply message pointer */
-{
-/* Handle a nested call from a file system server.
- */
-  int r;
-
-  /* Save global variables of the current call */
-  if ((r = push_globals()) != OK) {
-       printf("VFS: error saving global variables in call %d from FS %d\n",
-               m->m_type, m->m_source);
-  } else {
-       /* Initialize global variables for the nested call */
-       set_globals(m);
-
-       /* Perform the nested call - only getsysinfo() is allowed right now */
-       if (call_nr == COMMON_GETSYSINFO) {
-               r = do_getsysinfo();
-       } else {
-               printf("VFS: invalid nested call %d from FS %d\n", call_nr,
-                       who_e);
-
-               r = ENOSYS;
-       }
-
-       /* Store the result, and restore original global variables */
-       *m = m_out;
-
-       pop_globals();
-  }
-
-  m->m_type = r;
-}
diff --git a/servers/avfs/gcov.c b/servers/avfs/gcov.c
deleted file mode 100644 (file)
index 50bed64..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-
-#include "fs.h"
-#include "file.h"
-#include "fproc.h"
-
-_PROTOTYPE( int gcov_flush, (cp_grant_id_t grantid, size_t size ));
-
-/*===========================================================================*
- *                             do_gcov_flush                           *
- *===========================================================================*/
-PUBLIC int do_gcov_flush()
-{
-/* A userland tool has requested the gcov data from another
- * process (possibly vfs itself). Grant the target process
- * access to the supplied buffer, and perform the call that
- * makes the target copy its buffer to the caller (incl vfs
- * itself).
- */
-  struct fproc *rfp;
-  ssize_t size;
-  cp_grant_id_t grantid;
-  int r, n;
-  pid_t target;
-  message m;
-
-  size = m_in.GCOV_BUFF_SZ;
-  target = m_in.GCOV_PID;
-
-  /* If the wrong process is sent to, the system hangs; so make this root-only.
-   */
-
-  if (!super_user) return(EPERM);
-
-  /* Find target gcov process. */
-  for(n = 0; n < NR_PROCS; n++) {
-       if(fproc[n].fp_endpoint != NONE && fproc[n].fp_pid == target)
-                break;
-  }
-  if(n >= NR_PROCS) {
-       printf("VFS: gcov process %d not found\n", target);
-       return(ESRCH);
-  }
-  rfp = &fproc[n];
-
-  /* Grant target process to requestor's buffer. */
-  if ((grantid = cpf_grant_magic(rfp->fp_endpoint, who_e,
-                                (vir_bytes) m_in.GCOV_BUFF_P, size,
-                                CPF_WRITE)) < 0) {
-       printf("VFS: gcov_flush: grant failed\n");
-       return(ENOMEM);
-  }
-
-  if(rfp->fp_endpoint == VFS_PROC_NR) {
-       /* Request is for VFS itself. */
-       r = gcov_flush(grantid, size);
-  } else {
-       /* Perform generic GCOV request. */
-       m.GCOV_GRANT = grantid;
-       m.GCOV_BUFF_SZ = size;
-       r = _taskcall(rfp->fp_endpoint, COMMON_REQ_GCOV_DATA, &m);
-  }
-
-  cpf_revoke(grantid);
-
-  return(r);
-}
diff --git a/servers/avfs/glo.h b/servers/avfs/glo.h
deleted file mode 100644 (file)
index c07220a..0000000
+++ /dev/null
@@ -1,57 +0,0 @@
-#ifndef __VFS_GLO_H__
-#define __VFS_GLO_H__
-
-/* EXTERN should be extern except for the table file */
-#ifdef _TABLE
-#undef EXTERN
-#define EXTERN
-#endif
-
-/* File System global variables */
-EXTERN struct fproc *fp;       /* pointer to caller's fproc struct */
-EXTERN int susp_count;         /* number of procs suspended on pipe */
-EXTERN int nr_locks;           /* number of locks currently in place */
-EXTERN int reviving;           /* number of pipe processes to be revived */
-EXTERN int pending;
-EXTERN int sending;
-
-EXTERN dev_t ROOT_DEV;         /* device number of the root device */
-EXTERN int ROOT_FS_E;           /* kernel endpoint of the root FS proc */
-EXTERN u32_t system_hz;                /* system clock frequency. */
-
-/* The parameters of the call are kept here. */
-EXTERN message m_in;           /* the input message itself */
-EXTERN message m_out;          /* the output message used for reply */
-# define who_p         ((int) (fp - fproc))
-# define isokslot(p)   (p >= 0 && \
-                        p < (int)(sizeof(fproc) / sizeof(struct fproc)))
-#if 0
-# define who_e         (isokslot(who_p) ? fp->fp_endpoint : m_in.m_source)
-#else
-# define who_e         (isokslot(who_p) && fp->fp_endpoint != NONE ? \
-                                       fp->fp_endpoint : m_in.m_source)
-#endif
-# define call_nr       (m_in.m_type)
-# define super_user    (fp->fp_effuid == SU_UID ? 1 : 0)
-# define scratch(p)            (scratchpad[((int) ((p) - fproc))])
-EXTERN struct worker_thread *self;
-EXTERN int force_sync;         /* toggle forced synchronous communication */
-EXTERN int deadlock_resolving;
-EXTERN mutex_t exec_lock;
-EXTERN mutex_t bsf_lock;/* Global lock for access to block special files */
-EXTERN struct worker_thread workers[NR_WTHREADS];
-EXTERN struct worker_thread sys_worker;
-EXTERN struct worker_thread dl_worker;
-EXTERN char mount_label[LABEL_MAX];    /* label of file system to mount */
-
-/* The following variables are used for returning results to the caller. */
-EXTERN int err_code;           /* temporary storage for error number */
-
-/* Data initialized elsewhere. */
-extern _PROTOTYPE (int (*call_vec[]), (void) ); /* sys call table */
-extern _PROTOTYPE (int (*pfs_call_vec[]), (void) ); /* pfs callback table */
-extern char dot1[2];   /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
-extern char dot2[3];   /* meaning to search_dir: no access permission check. */
-extern char mode_map[];        /* mapping from O_ACCMODE mask to R_BIT/W_BIT flags */
-
-#endif
diff --git a/servers/avfs/link.c b/servers/avfs/link.c
deleted file mode 100644 (file)
index 1c0b4af..0000000
+++ /dev/null
@@ -1,455 +0,0 @@
-/* This file handles the LINK and UNLINK system calls.  It also deals with
- * deallocating the storage used by a file when the last UNLINK is done to a
- * file and the blocks must be returned to the free block pool.
- *
- * The entry points into this file are
- *   do_link:         perform the LINK system call
- *   do_unlink:              perform the UNLINK and RMDIR system calls
- *   do_rename:              perform the RENAME system call
- *   do_truncate:     perform the TRUNCATE system call
- *   do_ftruncate:    perform the FTRUNCATE system call
- *   do_rdlink:       perform the RDLNK system call
- */
-
-#include "fs.h"
-#include <sys/stat.h>
-#include <string.h>
-#include <minix/com.h>
-#include <minix/callnr.h>
-#include <minix/vfsif.h>
-#include <dirent.h>
-#include <assert.h>
-#include "file.h"
-#include "fproc.h"
-#include "path.h"
-#include "vnode.h"
-#include "param.h"
-
-/*===========================================================================*
- *                             do_link                                      *
- *===========================================================================*/
-PUBLIC int do_link()
-{
-/* Perform the link(name1, name2) system call. */
-  int r = OK;
-  struct vnode *vp = NULL, *dirp = NULL;
-  struct vmnt *vmp1 = NULL, *vmp2 = NULL;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp1, &vp);
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* See if 'name1' (file to be linked to) exists. */
-  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-       return(err_code);
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-
-  /* Does the final directory of 'name2' exist? */
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp2, &dirp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
-       r = err_code;
-  else if ((dirp = last_dir(&resolve, fp)) == NULL)
-       r = err_code;
-
-  if (r != OK) {
-       unlock_vnode(vp);
-       unlock_vmnt(vmp1);
-       put_vnode(vp);
-       return(r);
-  }
-
-  /* Check for links across devices. */
-  if (vp->v_fs_e != dirp->v_fs_e)
-       r = EXDEV;
-  else
-       r = forbidden(fp, dirp, W_BIT | X_BIT);
-
-  if (r == OK)
-       r = req_link(vp->v_fs_e, dirp->v_inode_nr, fullpath,
-                    vp->v_inode_nr);
-
-  unlock_vnode(vp);
-  unlock_vnode(dirp);
-  if (vmp2 != NULL) unlock_vmnt(vmp2);
-  unlock_vmnt(vmp1);
-  put_vnode(vp);
-  put_vnode(dirp);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             do_unlink                                    *
- *===========================================================================*/
-PUBLIC int do_unlink()
-{
-/* Perform the unlink(name) or rmdir(name) system call. The code for these two
- * is almost the same.  They differ only in some condition testing.  Unlink()
- * may be used by the superuser to do dangerous things; rmdir() may not.
- */
-  struct vnode *dirp, *vp;
-  struct vmnt *vmp, *vmp2;
-  int r;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &dirp);
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* Get the last directory in the path. */
-  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
-       return(err_code);
-
-  if ((dirp = last_dir(&resolve, fp)) == NULL) return(err_code);
-  assert(vmp != NULL);
-
-  /* Make sure that the object is a directory */
-  if ((dirp->v_mode & I_TYPE) != I_DIRECTORY) {
-       unlock_vnode(dirp);
-       unlock_vmnt(vmp);
-       put_vnode(dirp);
-       return(ENOTDIR);
-  }
-
-  /* The caller must have both search and execute permission */
-  if ((r = forbidden(fp, dirp, X_BIT | W_BIT)) != OK) {
-       unlock_vnode(dirp);
-       unlock_vmnt(vmp);
-       put_vnode(dirp);
-       return(r);
-  }
-
-  /* Also, if the sticky bit is set, only the owner of the file or a privileged
-     user is allowed to unlink */
-  if ((dirp->v_mode & S_ISVTX) == S_ISVTX) {
-       /* Look up inode of file to unlink to retrieve owner */
-       resolve.l_flags = PATH_RET_SYMLINK;
-       resolve.l_vmp = &vmp2;  /* Shouldn't actually get locked */
-       resolve.l_vmnt_lock = VMNT_READ;
-       resolve.l_vnode = &vp;
-       resolve.l_vnode_lock = VNODE_READ;
-       vp = advance(dirp, &resolve, fp);
-       assert(vmp2 == NULL);
-       if (vp != NULL) {
-               if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
-                       r = EPERM;
-               unlock_vnode(vp);
-               put_vnode(vp);
-       } else
-               r = err_code;
-       if (r != OK) {
-               unlock_vnode(dirp);
-               unlock_vmnt(vmp);
-               put_vnode(dirp);
-               return(r);
-       }
-  }
-
-  assert(vmp != NULL);
-  tll_upgrade(&vmp->m_lock);
-
-  if (call_nr == UNLINK)
-         r = req_unlink(dirp->v_fs_e, dirp->v_inode_nr, fullpath);
-  else
-         r = req_rmdir(dirp->v_fs_e, dirp->v_inode_nr, fullpath);
-  unlock_vnode(dirp);
-  unlock_vmnt(vmp);
-  put_vnode(dirp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_rename                                    *
- *===========================================================================*/
-PUBLIC int do_rename()
-{
-/* Perform the rename(name1, name2) system call. */
-  int r = OK, r1;
-  struct vnode *old_dirp, *new_dirp = NULL, *vp;
-  struct vmnt *oldvmp, *newvmp, *vmp2;
-  char old_name[PATH_MAX];
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &oldvmp, &old_dirp);
-  /* Do not yet request exclusive lock on vmnt to prevent deadlocks later on */
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
-  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-       return(err_code);
-  if ((old_dirp = last_dir(&resolve, fp)) == NULL)
-       return(err_code);
-
-  /* If the sticky bit is set, only the owner of the file or a privileged
-     user is allowed to rename */
-  if ((old_dirp->v_mode & S_ISVTX) == S_ISVTX) {
-       /* Look up inode of file to unlink to retrieve owner */
-       lookup_init(&resolve, resolve.l_path, PATH_RET_SYMLINK, &vmp2, &vp);
-       resolve.l_vmnt_lock = VMNT_READ;
-       resolve.l_vnode_lock = VNODE_READ;
-       vp = advance(old_dirp, &resolve, fp);
-       assert(vmp2 == NULL);
-       if (vp != NULL) {
-               if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
-                       r = EPERM;
-               unlock_vnode(vp);
-               put_vnode(vp);
-       } else
-               r = err_code;
-       if (r != OK) {
-               unlock_vnode(old_dirp);
-               unlock_vmnt(oldvmp);
-               put_vnode(old_dirp);
-               return(r);
-       }
-  }
-
-  /* Save the last component of the old name */
-  if(strlen(fullpath) >= sizeof(old_name)) {
-       unlock_vnode(old_dirp);
-       unlock_vmnt(oldvmp);
-       put_vnode(old_dirp);
-       return(ENAMETOOLONG);
-  }
-  strcpy(old_name, fullpath);
-
-  /* See if 'name2' (new name) exists.  Get dir inode */
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &newvmp, &new_dirp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
-       r = err_code;
-  else if ((new_dirp = last_dir(&resolve, fp)) == NULL)
-       r = err_code;
-
-  if (r != OK) {
-       unlock_vnode(old_dirp);
-       unlock_vmnt(oldvmp);
-       put_vnode(old_dirp);
-       return(r);
-  }
-
-  /* Both parent directories must be on the same device. */
-  if (old_dirp->v_fs_e != new_dirp->v_fs_e) r = EXDEV;
-
-  /* Parent dirs must be writable, searchable and on a writable device */
-  if ((r1 = forbidden(fp, old_dirp, W_BIT|X_BIT)) != OK ||
-      (r1 = forbidden(fp, new_dirp, W_BIT|X_BIT)) != OK) r = r1;
-
-  if (r == OK) {
-       tll_upgrade(&oldvmp->m_lock); /* Upgrade to exclusive access */
-       r = req_rename(old_dirp->v_fs_e, old_dirp->v_inode_nr, old_name,
-                      new_dirp->v_inode_nr, fullpath);
-  }
-  unlock_vnode(old_dirp);
-  unlock_vnode(new_dirp);
-  unlock_vmnt(oldvmp);
-  if (newvmp) unlock_vmnt(newvmp);
-
-  put_vnode(old_dirp);
-  put_vnode(new_dirp);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_truncate                                  *
- *===========================================================================*/
-PUBLIC int do_truncate()
-{
-/* truncate_vnode() does the actual work of do_truncate() and do_ftruncate().
- * do_truncate() and do_ftruncate() have to get hold of the inode, either
- * by name or fd, do checks on it, and call truncate_inode() to do the
- * work.
- */
-  struct vnode *vp;
-  struct vmnt *vmp;
-  int r;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_EXCL;
-  resolve.l_vnode_lock = VNODE_WRITE;
-
-  if ((off_t) m_in.flength < 0) return(EINVAL);
-
-  /* Temporarily open file */
-  if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1, fullpath) != OK) return(err_code);
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-
-  /* Ask FS to truncate the file */
-  if ((r = forbidden(fp, vp, W_BIT)) == OK)
-       r = truncate_vnode(vp, m_in.flength);
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-  put_vnode(vp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_ftruncate                                 *
- *===========================================================================*/
-PUBLIC int do_ftruncate()
-{
-/* As with do_truncate(), truncate_vnode() does the actual work. */
-  struct filp *rfilp;
-  int r;
-
-  if ((off_t) m_in.flength < 0) return(EINVAL);
-
-  /* File is already opened; get a vnode pointer from filp */
-  if ((rfilp = get_filp(m_in.m2_i1, VNODE_WRITE)) == NULL) return(err_code);
-
-  if (!(rfilp->filp_mode & W_BIT))
-       r = EBADF;
-  else
-       r = truncate_vnode(rfilp->filp_vno, m_in.flength);
-
-  unlock_filp(rfilp);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             truncate_vnode                               *
- *===========================================================================*/
-PUBLIC int truncate_vnode(vp, newsize)
-struct vnode *vp;
-off_t newsize;
-{
-/* Truncate a regular file or a pipe */
-  int r, file_type;
-
-  assert(tll_locked_by_me(&vp->v_lock));
-  file_type = vp->v_mode & I_TYPE;
-  if (file_type != I_REGULAR && file_type != I_NAMED_PIPE) return(EINVAL);
-  if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) == OK)
-       vp->v_size = newsize;
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             do_slink                                             *
- *===========================================================================*/
-PUBLIC int do_slink()
-{
-/* Perform the symlink(name1, name2) system call. */
-  int r;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  if (m_in.name1_length <= 1) return(ENOENT);
-  if (m_in.name1_length >= SYMLINK_MAX) return(ENAMETOOLONG);
-
-  /* Get dir inode of 'name2' */
-  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
-       return(err_code);
-
-  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
-
-  if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
-       r = req_slink(vp->v_fs_e, vp->v_inode_nr, fullpath, who_e,
-                     m_in.name1, m_in.name1_length - 1, fp->fp_effuid,
-                     fp->fp_effgid);
-  }
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-  put_vnode(vp);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                              rdlink_direct                                *
- *===========================================================================*/
-PUBLIC int rdlink_direct(orig_path, link_path, rfp)
-char *orig_path;
-char link_path[PATH_MAX]; /* should have length PATH_MAX */
-struct fproc *rfp;
-{
-/* Perform a readlink()-like call from within the VFS */
-  int r;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  struct lookup resolve;
-
-  lookup_init(&resolve, link_path, PATH_RET_SYMLINK, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* Temporarily open the file containing the symbolic link. Use link_path
-   * for temporary storage to keep orig_path untouched. */
-  strncpy(link_path, orig_path, PATH_MAX);     /* PATH_MAX includes '\0' */
-  link_path[PATH_MAX - 1] = '\0';
-  if ((vp = eat_path(&resolve, rfp)) == NULL) return(err_code);
-
-  /* Make sure this is a symbolic link */
-  if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
-       r = EINVAL;
-  else
-       r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, NONE, link_path,
-                      PATH_MAX - 1, 1);
-
-  if (r > 0) link_path[r] = '\0';      /* Terminate string when succesful */
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-  put_vnode(vp);
-
-  return r;
-}
-
-/*===========================================================================*
- *                             do_rdlink                                    *
- *===========================================================================*/
-PUBLIC int do_rdlink()
-{
-/* Perform the readlink(name, buf, bufsize) system call. */
-  int r, copylen;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  copylen = m_in.nbytes;
-  if (copylen < 0) return(EINVAL);
-
-  /* Temporarily open the file containing the symbolic link */
-  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-       return(err_code);
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-
-  /* Make sure this is a symbolic link */
-  if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
-       r = EINVAL;
-  else
-       r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2,
-                      copylen, 0);
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-  put_vnode(vp);
-
-  return(r);
-}
diff --git a/servers/avfs/lock.c b/servers/avfs/lock.c
deleted file mode 100644 (file)
index 36ab593..0000000
+++ /dev/null
@@ -1,191 +0,0 @@
-/* This file handles advisory file locking as required by POSIX.
- *
- * The entry points into this file are
- *   lock_op:  perform locking operations for FCNTL system call
- *   lock_revive: revive processes when a lock is released
- */
-
-#include "fs.h"
-#include <minix/com.h>
-#include <minix/u64.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include "file.h"
-#include "fproc.h"
-#include "scratchpad.h"
-#include "lock.h"
-#include "vnode.h"
-#include "param.h"
-
-/*===========================================================================*
- *                             lock_op                                      *
- *===========================================================================*/
-PUBLIC int lock_op(f, req)
-struct filp *f;
-int req;                       /* either F_SETLK or F_SETLKW */
-{
-/* Perform the advisory locking required by POSIX. */
-
-  int r, ltype, i, conflict = 0, unlocking = 0;
-  mode_t mo;
-  off_t first, last;
-  struct flock flock;
-  struct file_lock *flp, *flp2, *empty;
-
-  /* Fetch the flock structure from user space. */
-  r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, VFS_PROC_NR,
-                  (vir_bytes) &flock, sizeof(flock));
-  if (r != OK) return(EINVAL);
-
-  /* Make some error checks. */
-  ltype = flock.l_type;
-  mo = f->filp_mode;
-  if (ltype != F_UNLCK && ltype != F_RDLCK && ltype != F_WRLCK) return(EINVAL);
-  if (req == F_GETLK && ltype == F_UNLCK) return(EINVAL);
-  if ( (f->filp_vno->v_mode & I_TYPE) != I_REGULAR &&
-       (f->filp_vno->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(EINVAL);
-  if (req != F_GETLK && ltype == F_RDLCK && (mo & R_BIT) == 0) return(EBADF);
-  if (req != F_GETLK && ltype == F_WRLCK && (mo & W_BIT) == 0) return(EBADF);
-
-  /* Compute the first and last bytes in the lock region. */
-  switch (flock.l_whence) {
-    case SEEK_SET:     first = 0; break;
-    case SEEK_CUR:
-       if (ex64hi(f->filp_pos) != 0)
-               panic("lock_op: position in file too high");
-       first = ex64lo(f->filp_pos);
-       break;
-    case SEEK_END:     first = f->filp_vno->v_size; break;
-    default:   return(EINVAL);
-  }
-
-  /* Check for overflow. */
-  if (((long) flock.l_start > 0) && ((first + flock.l_start) < first))
-       return(EINVAL);
-  if (((long) flock.l_start < 0) && ((first + flock.l_start) > first))
-       return(EINVAL);
-  first = first + flock.l_start;
-  last = first + flock.l_len - 1;
-  if (flock.l_len == 0) last = MAX_FILE_POS;
-  if (last < first) return(EINVAL);
-
-  /* Check if this region conflicts with any existing lock. */
-  empty = NULL;
-  for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
-       if (flp->lock_type == 0) {
-               if (empty == NULL) empty = flp;
-               continue;       /* 0 means unused slot */
-       }
-       if (flp->lock_vnode != f->filp_vno) continue;   /* different file */
-       if (last < flp->lock_first) continue;   /* new one is in front */
-       if (first > flp->lock_last) continue;   /* new one is afterwards */
-       if (ltype == F_RDLCK && flp->lock_type == F_RDLCK) continue;
-       if (ltype != F_UNLCK && flp->lock_pid == fp->fp_pid) continue;
-
-       /* There might be a conflict.  Process it. */
-       conflict = 1;
-       if (req == F_GETLK) break;
-
-       /* If we are trying to set a lock, it just failed. */
-       if (ltype == F_RDLCK || ltype == F_WRLCK) {
-               if (req == F_SETLK) {
-                       /* For F_SETLK, just report back failure. */
-                       return(EAGAIN);
-               } else {
-                       /* For F_SETLKW, suspend the process. */
-                       suspend(FP_BLOCKED_ON_LOCK);
-                       return(SUSPEND);
-               }
-       }
-
-       /* We are clearing a lock and we found something that overlaps. */
-       unlocking = 1;
-       if (first <= flp->lock_first && last >= flp->lock_last) {
-               flp->lock_type = 0;     /* mark slot as unused */
-               nr_locks--;             /* number of locks is now 1 less */
-               continue;
-       }
-
-       /* Part of a locked region has been unlocked. */
-       if (first <= flp->lock_first) {
-               flp->lock_first = last + 1;
-               continue;
-       }
-
-       if (last >= flp->lock_last) {
-               flp->lock_last = first - 1;
-               continue;
-       }
-
-       /* Bad luck. A lock has been split in two by unlocking the middle. */
-       if (nr_locks == NR_LOCKS) return(ENOLCK);
-       for (i = 0; i < NR_LOCKS; i++)
-               if (file_lock[i].lock_type == 0) break;
-       flp2 = &file_lock[i];
-       flp2->lock_type = flp->lock_type;
-       flp2->lock_pid = flp->lock_pid;
-       flp2->lock_vnode = flp->lock_vnode;
-       flp2->lock_first = last + 1;
-       flp2->lock_last = flp->lock_last;
-       flp->lock_last = first - 1;
-       nr_locks++;
-  }
-  if (unlocking) lock_revive();
-
-  if (req == F_GETLK) {
-       if (conflict) {
-               /* GETLK and conflict. Report on the conflicting lock. */
-               flock.l_type = flp->lock_type;
-               flock.l_whence = SEEK_SET;
-               flock.l_start = flp->lock_first;
-               flock.l_len = flp->lock_last - flp->lock_first + 1;
-               flock.l_pid = flp->lock_pid;
-
-       } else {
-               /* It is GETLK and there is no conflict. */
-               flock.l_type = F_UNLCK;
-       }
-
-       /* Copy the flock structure back to the caller. */
-       r = sys_datacopy(VFS_PROC_NR, (vir_bytes) &flock,
-               who_e, (vir_bytes) scratch(fp).io.io_buffer, sizeof(flock));
-       return(r);
-  }
-
-  if (ltype == F_UNLCK) return(OK);    /* unlocked a region with no locks */
-
-  /* There is no conflict.  If space exists, store new lock in the table. */
-  if (empty == NULL) return(ENOLCK);   /* table full */
-  empty->lock_type = ltype;
-  empty->lock_pid = fp->fp_pid;
-  empty->lock_vnode = f->filp_vno;
-  empty->lock_first = first;
-  empty->lock_last = last;
-  nr_locks++;
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             lock_revive                                  *
- *===========================================================================*/
-PUBLIC void lock_revive()
-{
-/* Go find all the processes that are waiting for any kind of lock and
- * revive them all.  The ones that are still blocked will block again when
- * they run.  The others will complete.  This strategy is a space-time
- * tradeoff.  Figuring out exactly which ones to unblock now would take
- * extra code, and the only thing it would win would be some performance in
- * extremely rare circumstances (namely, that somebody actually used
- * locking).
- */
-
-  struct fproc *fptr;
-
-  for (fptr = &fproc[0]; fptr < &fproc[NR_PROCS]; fptr++){
-       if (fptr->fp_pid == PID_FREE) continue;
-       if (fptr->fp_blocked_on == FP_BLOCKED_ON_LOCK) {
-               revive(fptr->fp_endpoint, 0);
-       }
-  }
-}
diff --git a/servers/avfs/lock.h b/servers/avfs/lock.h
deleted file mode 100644 (file)
index c2baa65..0000000
+++ /dev/null
@@ -1,15 +0,0 @@
-#ifndef __VFS_LOCK_H__
-#define __VFS_LOCK_H__
-
-/* This is the file locking table.  Like the filp table, it points to the
- * inode table, however, in this case to achieve advisory locking.
- */
-EXTERN struct file_lock {
-  short lock_type;             /* F_RDLOCK or F_WRLOCK; 0 means unused slot */
-  pid_t lock_pid;              /* pid of the process holding the lock */
-  struct vnode *lock_vnode;
-  off_t lock_first;            /* offset of first byte locked */
-  off_t lock_last;             /* offset of last byte locked */
-} file_lock[NR_LOCKS];
-
-#endif
diff --git a/servers/avfs/main.c b/servers/avfs/main.c
deleted file mode 100644 (file)
index 337cc83..0000000
+++ /dev/null
@@ -1,990 +0,0 @@
-/*
- * a loop that gets messages requesting work, carries out the work, and sends
- * replies.
- *
- * The entry points into this file are:
- *   main:     main program of the Virtual File System
- *   reply:    send a reply to a process after the requested work is done
- *
- */
-
-#include "fs.h"
-#include <fcntl.h>
-#include <string.h>
-#include <stdio.h>
-#include <signal.h>
-#include <assert.h>
-#include <stdlib.h>
-#include <sys/ioc_memory.h>
-#include <sys/svrctl.h>
-#include <sys/select.h>
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include <minix/keymap.h>
-#include <minix/const.h>
-#include <minix/endpoint.h>
-#include <minix/safecopies.h>
-#include <minix/debug.h>
-#include <minix/vfsif.h>
-#include "file.h"
-#include "dmap.h"
-#include "fproc.h"
-#include "scratchpad.h"
-#include "vmnt.h"
-#include "vnode.h"
-#include "job.h"
-#include "param.h"
-
-#if ENABLE_SYSCALL_STATS
-EXTERN unsigned long calls_stats[NCALLS];
-#endif
-
-/* Thread related prototypes */
-FORWARD _PROTOTYPE( void thread_cleanup_f, (struct fproc *rfp, char *f,
-                                           int l)                      );
-#define thread_cleanup(x) thread_cleanup_f(x, __FILE__, __LINE__)
-FORWARD _PROTOTYPE( void *do_async_dev_result, (void *arg)             );
-FORWARD _PROTOTYPE( void *do_control_msgs, (void *arg)                 );
-FORWARD _PROTOTYPE( void *do_fs_reply, (struct job *job)                       );
-FORWARD _PROTOTYPE( void *do_work, (void *arg)                         );
-FORWARD _PROTOTYPE( void *do_pm, (void *arg)                           );
-FORWARD _PROTOTYPE( void *do_init_root, (void *arg)                    );
-FORWARD _PROTOTYPE( void handle_work, (void *(*func)(void *arg))               );
-
-FORWARD _PROTOTYPE( void get_work, (void)                              );
-FORWARD _PROTOTYPE( void lock_pm, (void)                               );
-FORWARD _PROTOTYPE( void unlock_pm, (void)                             );
-FORWARD _PROTOTYPE( void service_pm, (void)                            );
-FORWARD _PROTOTYPE( void service_pm_postponed, (void)                          );
-FORWARD _PROTOTYPE( int unblock, (struct fproc *rfp)                   );
-
-/* SEF functions and variables. */
-FORWARD _PROTOTYPE( void sef_local_startup, (void) );
-FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
-PRIVATE mutex_t pm_lock;
-PRIVATE endpoint_t receive_from;
-
-/*===========================================================================*
- *                             main                                         *
- *===========================================================================*/
-PUBLIC int main(void)
-{
-/* This is the main program of the file system.  The main loop consists of
- * three major activities: getting new work, processing the work, and sending
- * the reply.  This loop never terminates as long as the file system runs.
- */
-  int transid, req;
-  struct job *job;
-
-  /* SEF local startup. */
-  sef_local_startup();
-
-  printf("Started AVFS: %d worker thread(s)\n", NR_WTHREADS);
-
-  /* This is the main loop that gets work, processes it, and sends replies. */
-  while (TRUE) {
-       yield_all();    /* let other threads run */
-       send_work();
-       get_work();
-
-       transid = TRNS_GET_ID(m_in.m_type);
-       req = TRNS_DEL_ID(m_in.m_type);
-       job = worker_getjob( (thread_t) transid - VFS_TRANSID);
-
-       /* Transaction encoding changes original m_type value; restore. */
-       if (job == NULL)
-               m_in.m_type = transid;
-       else
-               m_in.m_type = req;
-
-       if (job != NULL) {
-               do_fs_reply(job);
-               continue;
-       } else if (who_e == PM_PROC_NR) { /* Calls from PM */
-               /* Special control messages from PM */
-               sys_worker_start(do_pm);
-               continue;
-       } else if (is_notify(call_nr)) {
-               /* A task notify()ed us */
-               sys_worker_start(do_control_msgs);
-               continue;
-       } else if (who_p < 0) { /* i.e., message comes from a task */
-               /* We're going to ignore this message. Tasks should
-                * send notify()s only.
-                */
-                printf("VFS: ignoring message from %d (%d)\n", who_e, call_nr);
-                continue;
-       }
-
-       /* At this point we either have results from an asynchronous device
-        * or a new system call. In both cases a new worker thread has to be
-        * started and there might not be one available from the pool. This is
-        * not a problem (requests/replies are simply queued), except when
-        * they're from an FS endpoint, because these can cause a deadlock.
-        * handle_work() takes care of the details. */
-       if (IS_DEV_RS(call_nr)) {
-               /* We've got results for a device request */
-               handle_work(do_async_dev_result);
-               continue;
-       } else {
-               /* Normal syscall. */
-               handle_work(do_work);
-       }
-  }
-  return(OK);                          /* shouldn't come here */
-}
-
-/*===========================================================================*
- *                            handle_work                                   *
- *===========================================================================*/
-PRIVATE void handle_work(void *(*func)(void *arg))
-{
-/* Handle asynchronous device replies and new system calls. If the originating
- * endpoint is an FS endpoint, take extra care not to get in deadlock. */
-  struct vmnt *vmp = NULL;
-
-  if ((vmp = find_vmnt(who_e)) != NULL) {
-       /* A call back or dev result from an FS endpoint */
-
-       /* Set call back flag. We assume that an FS does only one call back
-        * at a time */
-       vmp->m_flags |= VMNT_CALLBACK;
-
-       /* When an FS point has to make a call back in order to mount, force
-        * its device to a "none device" so block reads/writes will be handled
-        * by ROOT_FS_E.
-        */
-       if (vmp->m_flags & VMNT_MOUNTING)
-               vmp->m_flags |= VMNT_FORCEROOTBSF;
-
-       if (worker_available() == 0) {
-               /* No worker threads available to handle call */
-               if (deadlock_resolving) {
-                       /* Already trying to resolve a deadlock, can't
-                        * handle more, sorry */
-                       vmp->m_flags &= ~VMNT_CALLBACK;
-                       reply(who_e, EAGAIN);
-                       return;
-               }
-               deadlock_resolving = 1;
-               dl_worker_start(func);
-               return;
-       }
-  }
-
-  worker_start(func);
-}
-
-/*===========================================================================*
- *                            do_async_dev_result                                   *
- *===========================================================================*/
-PRIVATE void *do_async_dev_result(void *arg)
-{
-  endpoint_t endpt;
-  struct job my_job;
-
-  my_job = *((struct job *) arg);
-  fp = my_job.j_fp;
-  m_in = my_job.j_m_in;
-
-  /* An asynchronous character driver has results for us */
-  if (call_nr == DEV_REVIVE) {
-       endpt = m_in.REP_ENDPT;
-       if (endpt == VFS_PROC_NR)
-               endpt = find_suspended_ep(m_in.m_source, m_in.REP_IO_GRANT);
-
-       if (endpt == NONE) {
-               printf("VFS: proc with grant %d from %d not found\n",
-                       m_in.REP_IO_GRANT, m_in.m_source);
-       } else if (m_in.REP_STATUS == SUSPEND) {
-               printf("VFS: got SUSPEND on DEV_REVIVE: not reviving proc\n");
-       } else
-               revive(endpt, m_in.REP_STATUS);
-  }
-  else if (call_nr == DEV_OPEN_REPL) open_reply();
-  else if (call_nr == DEV_REOPEN_REPL) reopen_reply();
-  else if (call_nr == DEV_CLOSE_REPL) close_reply();
-  else if (call_nr == DEV_SEL_REPL1)
-       select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
-  else if (call_nr == DEV_SEL_REPL2)
-       select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
-
-  if (deadlock_resolving) {
-       if (fp != NULL && fp->fp_wtid == dl_worker.w_tid)
-               deadlock_resolving = 0;
-  }
-
-  if (fp != NULL && (fp->fp_flags & FP_SYS_PROC)) {
-       struct vmnt *vmp;
-
-       if ((vmp = find_vmnt(fp->fp_endpoint)) != NULL)
-               vmp->m_flags &= ~VMNT_CALLBACK;
-  }
-
-  thread_cleanup(NULL);
-  return(NULL);
-}
-
-/*===========================================================================*
- *                            do_control_msgs                               *
- *===========================================================================*/
-PRIVATE void *do_control_msgs(void *arg)
-{
-  struct job my_job;
-
-  my_job = *((struct job *) arg);
-  fp = my_job.j_fp;
-  m_in = my_job.j_m_in;
-
-  /* Check for special control messages. */
-  if (who_e == CLOCK) {
-       /* Alarm timer expired. Used only for select(). Check it. */
-       expire_timers(m_in.NOTIFY_TIMESTAMP);
-  } else if (who_e == DS_PROC_NR) {
-       /* DS notifies us of an event. */
-       ds_event();
-  } else {
-       /* Device notifies us of an event. */
-       dev_status(&m_in);
-  }
-
-  thread_cleanup(NULL);
-  return(NULL);
-}
-
-/*===========================================================================*
- *                            do_fs_reply                                   *
- *===========================================================================*/
-PRIVATE void *do_fs_reply(struct job *job)
-{
-  struct vmnt *vmp;
-  struct fproc *rfp;
-
-  if ((vmp = find_vmnt(who_e)) == NULL)
-       panic("Couldn't find vmnt for endpoint %d", who_e);
-
-  rfp = job->j_fp;
-
-  if (rfp == NULL || rfp->fp_endpoint == NONE) {
-       printf("VFS: spurious reply from %d\n", who_e);
-       return(NULL);
-  }
-
-  if (rfp->fp_task != who_e)
-       printf("AVFS: expected %d to reply, not %d\n", rfp->fp_task, who_e);
-  *rfp->fp_sendrec = m_in;
-  rfp->fp_task = NONE;
-  vmp->m_comm.c_cur_reqs--;    /* We've got our reply, make room for others */
-  worker_signal(worker_get(rfp->fp_wtid));/* Continue this worker thread */
-  return(NULL);
-}
-
-/*===========================================================================*
- *                             lock_pm                                      *
- *===========================================================================*/
-PRIVATE void lock_pm(void)
-{
-  message org_m_in;
-  struct fproc *org_fp;
-  struct worker_thread *org_self;
-
-  /* First try to get it right off the bat */
-  if (mutex_trylock(&pm_lock) == 0)
-       return;
-
-  org_m_in = m_in;
-  org_fp = fp;
-  org_self = self;
-
-  if (mutex_lock(&pm_lock) != 0)
-       panic("Could not obtain lock on pm\n");
-
-  m_in = org_m_in;
-  fp = org_fp;
-  self = org_self;
-}
-
-/*===========================================================================*
- *                             unlock_pm                                    *
- *===========================================================================*/
-PRIVATE void unlock_pm(void)
-{
-  if (mutex_unlock(&pm_lock) != 0)
-       panic("Could not release lock on pm");
-}
-
-/*===========================================================================*
- *                            do_pm                                         *
- *===========================================================================*/
-PRIVATE void *do_pm(void *arg)
-{
-  struct job my_job;
-  struct fproc *rfp;
-
-  my_job = *((struct job *) arg);
-  rfp = fp = my_job.j_fp;
-  m_in = my_job.j_m_in;
-
-  lock_pm();
-  service_pm();
-  unlock_pm();
-
-  thread_cleanup(NULL);
-  return(NULL);
-}
-
-/*===========================================================================*
- *                            do_pending_pipe                                       *
- *===========================================================================*/
-PRIVATE void *do_pending_pipe(void *arg)
-{
-  int r, op;
-  struct job my_job;
-  struct filp *f;
-  tll_access_t locktype;
-
-  my_job = *((struct job *) arg);
-  fp = my_job.j_fp;
-  m_in = my_job.j_m_in;
-
-  lock_proc(fp, 1 /* force lock */);
-
-  f = scratch(fp).file.filp;
-  assert(f != NULL);
-  scratch(fp).file.filp = NULL;
-
-  locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE;
-  op = (call_nr == READ) ? READING : WRITING;
-  lock_filp(f, locktype);
-
-  r = rw_pipe(op, who_e, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes);
-
-  if (r != SUSPEND)  /* Do we have results to report? */
-       reply(who_e, r);
-
-  unlock_filp(f);
-
-  thread_cleanup(fp);
-  return(NULL);
-}
-
-/*===========================================================================*
- *                            do_dummy                                      *
- *===========================================================================*/
-PUBLIC void *do_dummy(void *arg)
-{
-  struct job my_job;
-  int r;
-
-  my_job = *((struct job *) arg);
-  fp = my_job.j_fp;
-  m_in = my_job.j_m_in;
-
-  if ((r = mutex_trylock(&fp->fp_lock)) == 0) {
-       thread_cleanup(fp);
-  } else {
-       /* Proc is busy, let that worker thread carry out the work */
-       thread_cleanup(NULL);
-  }
-  return(NULL);
-}
-
-/*===========================================================================*
- *                            do_work                                       *
- *===========================================================================*/
-PRIVATE void *do_work(void *arg)
-{
-  int error;
-  struct job my_job;
-
-  my_job = *((struct job *) arg);
-  fp = my_job.j_fp;
-  m_in = my_job.j_m_in;
-
-  lock_proc(fp, 0); /* This proc is busy */
-
-  if (call_nr == MAPDRIVER) {
-       error = do_mapdriver();
-  } else if (call_nr == COMMON_GETSYSINFO) {
-       error = do_getsysinfo();
-  } else if (IS_PFS_VFS_RQ(call_nr)) {
-       if (who_e != PFS_PROC_NR) {
-               printf("VFS: only PFS is allowed to make nested VFS calls\n");
-               error = ENOSYS;
-       } else if (call_nr <= PFS_BASE || call_nr >= PFS_BASE + PFS_NREQS) {
-               error = ENOSYS;
-       } else {
-               call_nr -= PFS_BASE;
-               error = (*pfs_call_vec[call_nr])();
-       }
-  } else {
-       /* We're dealing with a POSIX system call from a normal
-        * process. Call the internal function that does the work.
-        */
-       if (call_nr < 0 || call_nr >= NCALLS) {
-               error = ENOSYS;
-       } else if (fp->fp_pid == PID_FREE) {
-               /* Process vanished before we were able to handle request.
-                * Replying has no use. Just drop it. */
-               error = SUSPEND;
-       } else {
-#if ENABLE_SYSCALL_STATS
-               calls_stats[call_nr]++;
-#endif
-               error = (*call_vec[call_nr])();
-       }
-  }
-
-  /* Copy the results back to the user and send reply. */
-  if (error != SUSPEND) {
-
-       if ((fp->fp_flags & FP_SYS_PROC)) {
-               struct vmnt *vmp;
-
-               if ((vmp = find_vmnt(fp->fp_endpoint)) != NULL)
-                       vmp->m_flags &= ~VMNT_CALLBACK;
-       }
-
-       if (deadlock_resolving) {
-               if (fp->fp_wtid == dl_worker.w_tid)
-                       deadlock_resolving = 0;
-       }
-       reply(who_e, error);
-  }
-
-  thread_cleanup(fp);
-  return(NULL);
-}
-
-/*===========================================================================*
- *                            sef_local_startup                             *
- *===========================================================================*/
-PRIVATE void sef_local_startup()
-{
-  /* Register init callbacks. */
-  sef_setcb_init_fresh(sef_cb_init_fresh);
-  sef_setcb_init_restart(sef_cb_init_fail);
-
-  /* No live update support for now. */
-
-  /* Let SEF perform startup. */
-  sef_startup();
-}
-
-/*===========================================================================*
- *                             sef_cb_init_fresh                            *
- *===========================================================================*/
-PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
-{
-/* Initialize the virtual file server. */
-  int s, i;
-  struct fproc *rfp;
-  message mess;
-  struct rprocpub rprocpub[NR_BOOT_PROCS];
-
-  force_sync = 0;
-  receive_from = ANY;
-
-  /* Initialize proc endpoints to NONE */
-  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       rfp->fp_endpoint = NONE;
-       rfp->fp_pid = PID_FREE;
-  }
-
-  /* Initialize the process table with help of the process manager messages.
-   * Expect one message for each system process with its slot number and pid.
-   * When no more processes follow, the magic process number NONE is sent.
-   * Then, stop and synchronize with the PM.
-   */
-  do {
-       if ((s = sef_receive(PM_PROC_NR, &mess)) != OK)
-               panic("VFS: couldn't receive from PM: %d", s);
-
-       if (mess.m_type != PM_INIT)
-               panic("unexpected message from PM: %d", mess.m_type);
-
-       if (NONE == mess.PM_PROC) break;
-
-       rfp = &fproc[mess.PM_SLOT];
-       rfp->fp_flags = FP_NOFLAGS;
-       rfp->fp_pid = mess.PM_PID;
-       rfp->fp_endpoint = mess.PM_PROC;
-       rfp->fp_grant = GRANT_INVALID;
-       rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-       rfp->fp_realuid = (uid_t) SYS_UID;
-       rfp->fp_effuid = (uid_t) SYS_UID;
-       rfp->fp_realgid = (gid_t) SYS_GID;
-       rfp->fp_effgid = (gid_t) SYS_GID;
-       rfp->fp_umask = ~0;
-  } while (TRUE);                      /* continue until process NONE */
-  mess.m_type = OK;                    /* tell PM that we succeeded */
-  s = send(PM_PROC_NR, &mess);         /* send synchronization message */
-
-  /* All process table entries have been set. Continue with initialization. */
-  fp = &fproc[_ENDPOINT_P(VFS_PROC_NR)];/* During init all communication with
-                                        * FSes is on behalf of myself */
-  init_dmap();                 /* Initialize device table. */
-  system_hz = sys_hz();
-
-  /* Map all the services in the boot image. */
-  if ((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
-                           (vir_bytes) rprocpub, sizeof(rprocpub), S)) != OK){
-       panic("sys_safecopyfrom failed: %d", s);
-  }
-  for (i = 0; i < NR_BOOT_PROCS; i++) {
-       if (rprocpub[i].in_use) {
-               if ((s = map_service(&rprocpub[i])) != OK) {
-                       panic("VFS: unable to map service: %d", s);
-               }
-       }
-  }
-
-  /* Subscribe to block and character driver events. */
-  s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
-  if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);
-
-#if DO_SANITYCHECKS
-  FIXME("VFS: DO_SANITYCHECKS is on");
-#endif
-
-  /* Initialize worker threads */
-  for (i = 0; i < NR_WTHREADS; i++)  {
-       worker_init(&workers[i]);
-  }
-  worker_init(&sys_worker); /* exclusive system worker thread */
-  worker_init(&dl_worker); /* exclusive worker thread to resolve deadlocks */
-
-  /* Initialize global locks */
-  if (mthread_mutex_init(&pm_lock, NULL) != 0)
-       panic("VFS: couldn't initialize pm lock mutex");
-  if (mthread_mutex_init(&exec_lock, NULL) != 0)
-       panic("VFS: couldn't initialize exec lock");
-  if (mthread_mutex_init(&bsf_lock, NULL) != 0)
-       panic("VFS: couldn't initialize block special file lock");
-
-  /* Initialize event resources for boot procs and locks for all procs */
-  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       if (mutex_init(&rfp->fp_lock, NULL) != 0)
-               panic("unable to initialize fproc lock");
-#if LOCK_DEBUG
-       rfp->fp_vp_rdlocks = 0;
-       rfp->fp_vmnt_rdlocks = 0;
-#endif
-  }
-
-  init_vnodes();               /* init vnodes */
-  init_vmnts();                        /* init vmnt structures */
-  init_select();               /* init select() structures */
-  init_filps();                        /* Init filp structures */
-  mount_pfs();                 /* mount Pipe File Server */
-  worker_start(do_init_root);  /* mount initial ramdisk as file system root */
-  yield();                     /* force do_init_root to start */
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                            do_init_root                                  *
- *===========================================================================*/
-PRIVATE void *do_init_root(void *arg)
-{
-  struct fproc *rfp;
-  struct job my_job;
-  int r;
-  char *mount_label = "fs_imgrd"; /* FIXME: obtain this from RS */
-
-  my_job = *((struct job *) arg);
-  fp = my_job.j_fp;
-
-  lock_proc(fp, 1 /* force lock */); /* This proc is busy */
-  lock_pm();
-
-  /* Initialize process directories. mount_fs will set them to the correct
-   * values */
-  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       FD_ZERO(&(rfp->fp_filp_inuse));
-       rfp->fp_rd = NULL;
-       rfp->fp_wd = NULL;
-  }
-
-  receive_from = MFS_PROC_NR;
-  if ((r = mount_fs(DEV_IMGRD, "/", MFS_PROC_NR, 0, mount_label)) != OK)
-       panic("Failed to initialize root");
-  receive_from = ANY;
-
-  unlock_pm();
-  thread_cleanup(fp);
-  return(NULL);
-}
-
-/*===========================================================================*
- *                             lock_proc                                    *
- *===========================================================================*/
-PUBLIC void lock_proc(struct fproc *rfp, int force_lock)
-{
-  int r;
-  message org_m_in;
-  struct fproc *org_fp;
-  struct worker_thread *org_self;
-
-  r = mutex_trylock(&rfp->fp_lock);
-
-  /* Were we supposed to obtain this lock immediately? */
-  if (force_lock) {
-       assert(r == 0);
-       return;
-  }
-
-  if (r == 0) return;
-
-  org_m_in = m_in;
-  org_fp = fp;
-  org_self = self;
-  if ((r = mutex_lock(&rfp->fp_lock)) != 0)
-       panic("unable to lock fproc lock: %d", r);
-  m_in = org_m_in;
-  fp = org_fp;
-  self = org_self;
-}
-
-/*===========================================================================*
- *                             unlock_proc                                  *
- *===========================================================================*/
-PUBLIC void unlock_proc(struct fproc *rfp)
-{
-  int r;
-
-  if ((r = mutex_unlock(&rfp->fp_lock)) != 0)
-       panic("Failed to unlock: %d", r);
-}
-
-/*===========================================================================*
- *                             thread_cleanup                               *
- *===========================================================================*/
-PRIVATE void thread_cleanup_f(struct fproc *rfp, char *f, int l)
-{
-/* Clean up worker thread. Skip parts if this thread is not associated
- * with a particular process (i.e., rfp is NULL) */
-
-  assert(mthread_self() != -1);
-
-#if LOCK_DEBUG
-  if (rfp != NULL) {
-       check_filp_locks_by_me();
-       check_vnode_locks_by_me(rfp);
-       check_vmnt_locks_by_me(rfp);
-  }
-#endif
-
-  if (rfp != NULL && rfp->fp_flags & FP_PM_PENDING) {  /* Postponed PM call */
-       m_in = rfp->fp_job.j_m_in;
-       rfp->fp_flags &= ~FP_PM_PENDING;
-       service_pm_postponed();
-  }
-
-#if LOCK_DEBUG
-  if (rfp != NULL) {
-       check_filp_locks_by_me();
-       check_vnode_locks_by_me(rfp);
-       check_vmnt_locks_by_me(rfp);
-  }
-#endif
-
-  if (rfp != NULL) {
-       rfp->fp_flags &= ~FP_DROP_WORK;
-       unlock_proc(rfp);
-  }
-
-#if 0
-  mthread_exit(NULL);
-#endif
-}
-
-/*===========================================================================*
- *                             get_work                                     *
- *===========================================================================*/
-PRIVATE void get_work()
-{
-  /* Normally wait for new input.  However, if 'reviving' is
-   * nonzero, a suspended process must be awakened.
-   */
-  int r, found_one, proc_p;
-  register struct fproc *rp;
-
-  while (reviving != 0) {
-       found_one = FALSE;
-
-       /* Find a suspended process. */
-       for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++)
-               if (rp->fp_pid != PID_FREE && (rp->fp_flags & FP_REVIVED)) {
-                       found_one = TRUE; /* Found a suspended process */
-                       if (unblock(rp))
-                               return; /* So main loop can process job */
-                       send_work();
-               }
-
-       if (!found_one) /* Consistency error */
-               panic("VFS: get_work couldn't revive anyone");
-  }
-
-  for(;;) {
-       /* Normal case.  No one to revive. Get a useful request. */
-       if ((r = sef_receive(receive_from, &m_in)) != OK) {
-               panic("VFS: sef_receive error: %d", r);
-       }
-
-       proc_p = _ENDPOINT_P(m_in.m_source);
-       if (proc_p < 0) fp = NULL;
-       else fp = &fproc[proc_p];
-
-       if (m_in.m_type == EDEADSRCDST) return; /* Failed 'sendrec' */
-
-       /* Negative who_p is never used to access the fproc array. Negative
-        * numbers (kernel tasks) are treated in a special way.
-        */
-       if (who_p >= (int)(sizeof(fproc) / sizeof(struct fproc)))
-               panic("receive process out of range: %d", who_p);
-       if (who_p >= 0 && fproc[who_p].fp_endpoint == NONE) {
-               printf("VFS: ignoring request from %d, endpointless slot %d (%d)\n",
-                       m_in.m_source, who_p, m_in.m_type);
-               continue;
-       }
-
-       /* Internal consistency check; our mental image of process numbers and
-        * endpoints must match with how the rest of the system thinks of them.
-        */
-       if (who_p >= 0 && fproc[who_p].fp_endpoint != who_e) {
-               if (fproc[who_p].fp_endpoint == NONE)
-                       printf("slot unknown even\n");
-
-               printf("VFS: receive endpoint inconsistent (source %d, who_p "
-                       "%d, stored ep %d, who_e %d).\n", m_in.m_source, who_p,
-                       fproc[who_p].fp_endpoint, who_e);
-               panic("VFS: inconsistent endpoint ");
-       }
-
-       return;
-  }
-}
-
-
-/*===========================================================================*
- *                             reply                                        *
- *===========================================================================*/
-PUBLIC void reply(whom, result)
-int whom;                      /* process to reply to */
-int result;                    /* result of the call (usually OK or error #) */
-{
-/* Send a reply to a user process.  If the send fails, just ignore it. */
-  int r;
-
-  m_out.reply_type = result;
-  r = sendnb(whom, &m_out);
-  if (r != OK) {
-       printf("VFS: couldn't send reply %d to %d: %d\n", result, whom, r);
-  }
-}
-
-/*===========================================================================*
- *                             service_pm_postponed                         *
- *===========================================================================*/
-PRIVATE void service_pm_postponed(void)
-{
-  int r;
-  vir_bytes pc;
-
-  switch(call_nr) {
-    case PM_EXEC:
-       r = pm_exec(m_in.PM_PROC, m_in.PM_PATH, m_in.PM_PATH_LEN,
-                   m_in.PM_FRAME, m_in.PM_FRAME_LEN, &pc);
-
-       /* Reply status to PM */
-       m_out.m_type = PM_EXEC_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-       m_out.PM_PC = (void*)pc;
-       m_out.PM_STATUS = r;
-
-       break;
-
-    case PM_EXIT:
-       pm_exit(m_in.PM_PROC);
-
-       /* Reply dummy status to PM for synchronization */
-       m_out.m_type = PM_EXIT_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-
-       break;
-
-    case PM_DUMPCORE:
-       /* Copy parameters first. m_in gets overwritten when creating core
-        * file.
-        */
-
-       r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG,
-                       (vir_bytes) m_in.PM_PATH);
-
-       /* Reply status to PM */
-       m_out.m_type = PM_CORE_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-       m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC;
-       m_out.PM_STATUS = r;
-
-       break;
-
-    default:
-       panic("Unhandled postponed PM call %d", m_in.m_type);
-  }
-
-  r = send(PM_PROC_NR, &m_out);
-  if (r != OK)
-       panic("service_pm_postponed: send failed: %d", r);
-}
-
-/*===========================================================================*
- *                             service_pm                                   *
- *===========================================================================*/
-PRIVATE void service_pm()
-{
-  int r, slot;
-
-  switch (call_nr) {
-    case PM_SETUID:
-       pm_setuid(m_in.PM_PROC, m_in.PM_EID, m_in.PM_RID);
-
-       m_out.m_type = PM_SETUID_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-
-       break;
-
-    case PM_SETGID:
-       pm_setgid(m_in.PM_PROC, m_in.PM_EID, m_in.PM_RID);
-
-       m_out.m_type = PM_SETGID_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-
-       break;
-
-    case PM_SETSID:
-       pm_setsid(m_in.PM_PROC);
-
-       m_out.m_type = PM_SETSID_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-
-       break;
-
-    case PM_EXEC:
-    case PM_EXIT:
-    case PM_DUMPCORE:
-       okendpt(m_in.PM_PROC, &slot);
-       fp = &fproc[slot];
-
-       if (fp->fp_flags & FP_PENDING) {
-               /* This process has a request pending, but PM wants it gone.
-                * Forget about the pending request and satisfy PM's request
-                * instead. Note that a pending request AND an EXEC request
-                * are mutually exclusive. Also, PM should send only one
-                * request/process at a time.
-                */
-                assert(fp->fp_job.j_m_in.m_source != PM_PROC_NR);
-       }
-
-        /* PM requests on behalf of a proc are handled after the system call
-         * that might be in progress for that proc has finished. If the proc
-         * is not busy, we start a dummy call */
-       if (!(fp->fp_flags & FP_PENDING) && mutex_trylock(&fp->fp_lock) == 0) {
-               mutex_unlock(&fp->fp_lock);
-               worker_start(do_dummy);
-               fp->fp_flags |= FP_DROP_WORK;
-        }
-
-       fp->fp_job.j_m_in = m_in;
-       fp->fp_flags |= FP_PM_PENDING;
-
-       return;
-
-    case PM_FORK:
-    case PM_SRV_FORK:
-       pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID);
-       m_out.m_type = PM_FORK_REPLY;
-
-       if (call_nr == PM_SRV_FORK) {
-               m_out.m_type = PM_SRV_FORK_REPLY;
-               pm_setuid(m_in.PM_PROC, m_in.PM_REUID, m_in.PM_REUID);
-               pm_setgid(m_in.PM_PROC, m_in.PM_REGID, m_in.PM_REGID);
-       }
-
-       m_out.PM_PROC = m_in.PM_PROC;
-
-       break;
-    case PM_SETGROUPS:
-       pm_setgroups(m_in.PM_PROC, m_in.PM_GROUP_NO,
-                       (gid_t *) m_in.PM_GROUP_ADDR);
-
-       m_out.m_type = PM_SETGROUPS_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-
-       break;
-
-    case PM_UNPAUSE:
-       unpause(m_in.PM_PROC);
-
-       m_out.m_type = PM_UNPAUSE_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-
-       break;
-
-    case PM_REBOOT:
-       pm_reboot();
-
-       /* Reply dummy status to PM for synchronization */
-       m_out.m_type = PM_REBOOT_REPLY;
-
-       break;
-
-    default:
-       printf("VFS: don't know how to handle PM request %d\n", call_nr);
-
-       return;
-  }
-
-  r = send(PM_PROC_NR, &m_out);
-  if (r != OK)
-       panic("service_pm: send failed: %d", r);
-
-}
-
-
-/*===========================================================================*
- *                             unblock                                      *
- *===========================================================================*/
-PRIVATE int unblock(rfp)
-struct fproc *rfp;
-{
-  int blocked_on;
-
-  fp = rfp;
-  blocked_on = rfp->fp_blocked_on;
-  m_in.m_type = rfp->fp_block_callnr;
-  m_in.fd = scratch(fp).file.fd_nr;
-  m_in.buffer = scratch(fp).io.io_buffer;
-  m_in.nbytes = scratch(fp).io.io_nbytes;
-
-  rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;     /* no longer blocked */
-  rfp->fp_flags &= ~FP_REVIVED;
-  reviving--;
-  assert(reviving >= 0);
-
-  /* This should be a pipe I/O, not a device I/O. If it is, it'll 'leak'
-   * grants.
-   */
-  assert(!GRANT_VALID(rfp->fp_grant));
-
-  /* Pending pipe reads/writes can be handled directly */
-  if (blocked_on == FP_BLOCKED_ON_PIPE) {
-       worker_start(do_pending_pipe);
-       yield();        /* Give thread a chance to run */
-       return(0);      /* Retrieve more work */
-  }
-
-  return(1);   /* We've unblocked a process */
-}
diff --git a/servers/avfs/misc.c b/servers/avfs/misc.c
deleted file mode 100644 (file)
index 5497bf7..0000000
+++ /dev/null
@@ -1,663 +0,0 @@
-/* This file contains a collection of miscellaneous procedures.  Some of them
- * perform simple system calls.  Some others do a little part of system calls
- * that are mostly performed by the Memory Manager.
- *
- * The entry points into this file are
- *   do_dup:     perform the DUP system call
- *   do_fcntl:   perform the FCNTL system call
- *   do_sync:    perform the SYNC system call
- *   do_fsync:   perform the FSYNC system call
- *   pm_reboot:          sync disks and prepare for shutdown
- *   pm_fork:    adjust the tables after PM has performed a FORK system call
- *   do_exec:    handle files with FD_CLOEXEC on after PM has done an EXEC
- *   do_exit:    a process has exited; note that in the tables
- *   do_set:     set uid or gid for some process
- *   do_revive:          revive a process that was waiting for something (e.g. TTY)
- *   do_svrctl:          file system control
- *   do_getsysinfo:    request copy of FS data structure
- *   pm_dumpcore: create a core dump
- */
-
-#include "fs.h"
-#include <fcntl.h>
-#include <assert.h>
-#include <unistd.h>
-#include <string.h>
-#include <minix/callnr.h>
-#include <minix/safecopies.h>
-#include <minix/endpoint.h>
-#include <minix/com.h>
-#include <minix/sysinfo.h>
-#include <minix/u64.h>
-#include <sys/ptrace.h>
-#include <sys/svrctl.h>
-#include "file.h"
-#include "fproc.h"
-#include "scratchpad.h"
-#include "dmap.h"
-#include <minix/vfsif.h>
-#include "vnode.h"
-#include "vmnt.h"
-#include "param.h"
-
-#define CORE_NAME      "core"
-#define CORE_MODE      0777    /* mode to use on core image files */
-
-#if ENABLE_SYSCALL_STATS
-PUBLIC unsigned long calls_stats[NCALLS];
-#endif
-
-FORWARD _PROTOTYPE( void free_proc, (struct fproc *freed, int flags)   );
-/*
-FORWARD _PROTOTYPE( int dumpcore, (int proc_e, struct mem_map *seg_ptr)        );
-FORWARD _PROTOTYPE( int write_bytes, (struct inode *rip, off_t off,
-                                     char *buf, size_t bytes)          );
-FORWARD _PROTOTYPE( int write_seg, (struct inode *rip, off_t off, int proc_e,
-                       int seg, off_t seg_off, phys_bytes seg_bytes)   );
-*/
-
-/*===========================================================================*
- *                             do_getsysinfo                                *
- *===========================================================================*/
-PUBLIC int do_getsysinfo()
-{
-  vir_bytes src_addr, dst_addr;
-  size_t len;
-
-  /* Only su may call do_getsysinfo. This call may leak information (and is not
-   * stable enough to be part of the API/ABI). In the future, requests from
-   * non-system processes should be denied.
-   */
-
-  if (!super_user) return(EPERM);
-
-  switch(m_in.SI_WHAT) {
-    case SI_PROC_TAB:
-       src_addr = (vir_bytes) fproc;
-       len = sizeof(struct fproc) * NR_PROCS;
-       break;
-    case SI_DMAP_TAB:
-       src_addr = (vir_bytes) dmap;
-       len = sizeof(struct dmap) * NR_DEVICES;
-       break;
-#if ENABLE_SYSCALL_STATS
-    case SI_CALL_STATS:
-       src_addr = (vir_bytes) calls_stats;
-       len = sizeof(calls_stats);
-       break;
-#endif
-    default:
-       return(EINVAL);
-  }
-
-  if (len != m_in.SI_SIZE)
-       return(EINVAL);
-
-  dst_addr = (vir_bytes) m_in.SI_WHERE;
-  return sys_datacopy(SELF, src_addr, who_e, dst_addr, len);
-}
-
-/*===========================================================================*
- *                             do_dup                                       *
- *===========================================================================*/
-PUBLIC int do_dup()
-{
-/* Perform the dup(fd) or dup2(fd,fd2) system call. These system calls are
- * obsolete.  In fact, it is not even possible to invoke them using the
- * current library because the library routines call fcntl().  They are
- * provided to permit old binary programs to continue to run.
- */
-
-  register int rfd;
-  register struct filp *f;
-  int r = OK;
-
-  /* Is the file descriptor valid? */
-  rfd = m_in.fd & ~DUP_MASK;           /* kill off dup2 bit, if on */
-  if ((f = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
-
-  /* Distinguish between dup and dup2. */
-  if (m_in.fd == rfd) {                        /* bit not on */
-       /* dup(fd) */
-       r = get_fd(0, 0, &m_in.fd2, NULL);
-  } else {
-       /* dup2(old_fd, new_fd) */
-       if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) {
-               r = EBADF;
-       } else if (rfd == m_in.fd2) {   /* ignore the call: dup2(x, x) */
-               r = m_in.fd2;
-       } else {
-               /* All is fine, close new_fd if necessary */
-               m_in.fd = m_in.fd2;     /* prepare to close fd2 */
-               unlock_filp(f);         /* or it might deadlock on do_close */
-               (void) do_close();      /* cannot fail */
-               f = get_filp(rfd, VNODE_READ); /* lock old_fd again */
-       }
-  }
-
-  if (r == OK) {
-       /* Success. Set up new file descriptors. */
-       f->filp_count++;
-       fp->fp_filp[m_in.fd2] = f;
-       FD_SET(m_in.fd2, &fp->fp_filp_inuse);
-       r = m_in.fd2;
-  }
-
-  unlock_filp(f);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_fcntl                                     *
- *===========================================================================*/
-PUBLIC int do_fcntl()
-{
-/* Perform the fcntl(fd, request, ...) system call. */
-
-  register struct filp *f;
-  int new_fd, fl, r = OK;
-  tll_access_t locktype;
-
-  scratch(fp).file.fd_nr = m_in.fd;
-  scratch(fp).io.io_buffer = m_in.buffer;
-  scratch(fp).io.io_nbytes = m_in.nbytes;      /* a.k.a. m_in.request */
-
-  /* Is the file descriptor valid? */
-  locktype = (m_in.request == F_FREESP) ? VNODE_WRITE : VNODE_READ;
-  if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
-       return(err_code);
-
-  switch (m_in.request) {
-    case F_DUPFD:
-       /* This replaces the old dup() system call. */
-       if (m_in.addr < 0 || m_in.addr >= OPEN_MAX) r = EINVAL;
-       else if ((r = get_fd(m_in.addr, 0, &new_fd, NULL)) == OK) {
-               f->filp_count++;
-               fp->fp_filp[new_fd] = f;
-               FD_SET(new_fd, &fp->fp_filp_inuse);
-               r = new_fd;
-       }
-       break;
-
-    case F_GETFD:
-       /* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
-       r = 0;
-       if (FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set))
-               r = FD_CLOEXEC;
-       break;
-
-    case F_SETFD:
-       /* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
-       if(m_in.addr & FD_CLOEXEC)
-               FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
-       else
-               FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
-       break;
-
-    case F_GETFL:
-       /* Get file status flags (O_NONBLOCK and O_APPEND). */
-       fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
-       r = fl;
-       break;
-
-    case F_SETFL:
-       /* Set file status flags (O_NONBLOCK and O_APPEND). */
-       fl = O_NONBLOCK | O_APPEND | O_REOPEN;
-       f->filp_flags = (f->filp_flags & ~fl) | (m_in.addr & fl);
-       break;
-
-    case F_GETLK:
-    case F_SETLK:
-    case F_SETLKW:
-       /* Set or clear a file lock. */
-       r = lock_op(f, m_in.request);
-       break;
-
-    case F_FREESP:
-     {
-       /* Free a section of a file */
-       off_t start, end;
-       struct flock flock_arg;
-       signed long offset;
-
-       /* Check if it's a regular file. */
-       if ((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) r = EINVAL;
-       else if (!(f->filp_mode & W_BIT)) r = EBADF;
-       else
-               /* Copy flock data from userspace. */
-               r = sys_datacopy(who_e, (vir_bytes) m_in.name1, SELF,
-                                (vir_bytes) &flock_arg,
-                                (phys_bytes) sizeof(flock_arg));
-
-       if (r != OK) break;
-
-       /* Convert starting offset to signed. */
-       offset = (signed long) flock_arg.l_start;
-
-       /* Figure out starting position base. */
-       switch(flock_arg.l_whence) {
-         case SEEK_SET: start = 0; break;
-         case SEEK_CUR:
-               if (ex64hi(f->filp_pos) != 0)
-                       panic("do_fcntl: position in file too high");
-               start = ex64lo(f->filp_pos);
-               break;
-         case SEEK_END: start = f->filp_vno->v_size; break;
-         default: r = EINVAL;
-       }
-       if (r != OK) break;
-
-       /* Check for overflow or underflow. */
-       if (offset > 0 && start + offset < start) r = EINVAL;
-       else if (offset < 0 && start + offset > start) r = EINVAL;
-       else {
-               start += offset;
-               if (start < 0) r = EINVAL;
-       }
-       if (r != OK) break;
-
-       if (flock_arg.l_len != 0) {
-               if (start >= f->filp_vno->v_size) r = EINVAL;
-               else if ((end = start + flock_arg.l_len) <= start) r = EINVAL;
-               else if (end > f->filp_vno->v_size) end = f->filp_vno->v_size;
-       } else {
-                end = 0;
-       }
-       if (r != OK) break;
-
-       r = req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr,start,end);
-
-       if (r == OK && flock_arg.l_len == 0)
-               f->filp_vno->v_size = start;
-
-       break;
-     }
-
-    default:
-       r = EINVAL;
-  }
-
-  unlock_filp(f);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_sync                                      *
- *===========================================================================*/
-PUBLIC int do_sync()
-{
-  struct vmnt *vmp;
-  int r = OK;
-
-  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
-       if (vmp->m_dev != NO_DEV && vmp->m_fs_e != NONE &&
-                vmp->m_root_node != NULL) {
-               if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK)
-                       break;
-               req_sync(vmp->m_fs_e);
-               unlock_vmnt(vmp);
-       }
-  }
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_fsync                                     *
- *===========================================================================*/
-PUBLIC int do_fsync()
-{
-/* Perform the fsync() system call. */
-  struct filp *rfilp;
-  struct vmnt *vmp;
-  dev_t dev;
-  int r = OK;
-
-  if ((rfilp = get_filp(m_in.m1_i1, VNODE_READ)) == NULL) return(err_code);
-  dev = rfilp->filp_vno->v_dev;
-  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
-       if (vmp->m_dev != NO_DEV && vmp->m_dev == dev &&
-               vmp->m_fs_e != NONE && vmp->m_root_node != NULL) {
-
-               if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK)
-                       break;
-               req_sync(vmp->m_fs_e);
-               unlock_vmnt(vmp);
-       }
-  }
-
-  unlock_filp(rfilp);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             pm_reboot                                    *
- *===========================================================================*/
-PUBLIC void pm_reboot()
-{
-  /* Perform the VFS side of the reboot call. */
-  int i;
-  struct fproc *rfp;
-
-  do_sync();
-
-  /* Do exit processing for all leftover processes and servers,
-   * but don't actually exit them (if they were really gone, PM
-   * will tell us about it).
-   */
-  for (i = 0; i < NR_PROCS; i++) {
-       rfp = &fproc[i];
-       if (rfp->fp_endpoint == NONE) continue;
-
-       /* Don't just free the proc right away, but let it finish what it was
-        * doing first */
-       lock_proc(rfp, 0);
-       free_proc(rfp, 0);
-       unlock_proc(rfp);
-  }
-
-  do_sync();
-  unmount_all();
-}
-
-/*===========================================================================*
- *                             pm_fork                                      *
- *===========================================================================*/
-PUBLIC void pm_fork(pproc, cproc, cpid)
-int pproc;     /* Parent process */
-int cproc;     /* Child process */
-int cpid;      /* Child process id */
-{
-/* Perform those aspects of the fork() system call that relate to files.
- * In particular, let the child inherit its parent's file descriptors.
- * The parent and child parameters tell who forked off whom. The file
- * system uses the same slot numbers as the kernel.  Only PM makes this call.
- */
-
-  register struct fproc *cp, *pp;
-  int i, parentno, childno;
-  mutex_t c_fp_lock;
-
-  /* Check up-to-dateness of fproc. */
-  okendpt(pproc, &parentno);
-
-  /* PM gives child endpoint, which implies process slot information.
-   * Don't call isokendpt, because that will verify if the endpoint
-   * number is correct in fproc, which it won't be.
-   */
-  childno = _ENDPOINT_P(cproc);
-  if (childno < 0 || childno >= NR_PROCS)
-       panic("VFS: bogus child for forking: %d", m_in.child_endpt);
-  if (fproc[childno].fp_pid != PID_FREE)
-       panic("VFS: forking on top of in-use child: %d", childno);
-
-  /* Copy the parent's fproc struct to the child. */
-  /* However, the mutex variables belong to a slot and must stay the same. */
-  c_fp_lock = fproc[childno].fp_lock;
-  fproc[childno] = fproc[parentno];
-  fproc[childno].fp_lock = c_fp_lock;
-
-  /* Increase the counters in the 'filp' table. */
-  cp = &fproc[childno];
-  pp = &fproc[parentno];
-
-  for (i = 0; i < OPEN_MAX; i++)
-       if (cp->fp_filp[i] != NULL) cp->fp_filp[i]->filp_count++;
-
-  /* Fill in new process and endpoint id. */
-  cp->fp_pid = cpid;
-  cp->fp_endpoint = cproc;
-
-  /* A forking process never has an outstanding grant, as it isn't blocking on
-   * I/O. */
-  if(GRANT_VALID(pp->fp_grant)) {
-       panic("VFS: fork: pp (endpoint %d) has grant %d\n", pp->fp_endpoint,
-              pp->fp_grant);
-  }
-  if(GRANT_VALID(cp->fp_grant)) {
-       panic("VFS: fork: cp (endpoint %d) has grant %d\n", cp->fp_endpoint,
-              cp->fp_grant);
-  }
-
-  /* A child is not a process leader, not being revived, etc. */
-  cp->fp_flags = FP_NOFLAGS;
-
-  /* Record the fact that both root and working dir have another user. */
-  if (cp->fp_rd) dup_vnode(cp->fp_rd);
-  if (cp->fp_wd) dup_vnode(cp->fp_wd);
-}
-
-/*===========================================================================*
- *                             free_proc                                    *
- *===========================================================================*/
-PRIVATE void free_proc(struct fproc *exiter, int flags)
-{
-  int i;
-  register struct fproc *rfp;
-  register struct filp *rfilp;
-  register struct vnode *vp;
-  dev_t dev;
-
-  if (exiter->fp_endpoint == NONE)
-       panic("free_proc: already free");
-
-  if (fp_is_blocked(exiter))
-       unpause(exiter->fp_endpoint);
-
-  /* Loop on file descriptors, closing any that are open. */
-  for (i = 0; i < OPEN_MAX; i++) {
-       (void) close_fd(exiter, i);
-  }
-
-  /* Release root and working directories. */
-  if (exiter->fp_rd) { put_vnode(exiter->fp_rd); exiter->fp_rd = NULL; }
-  if (exiter->fp_wd) { put_vnode(exiter->fp_wd); exiter->fp_wd = NULL; }
-
-  /* The rest of these actions is only done when processes actually exit. */
-  if (!(flags & FP_EXITING)) return;
-
-  exiter->fp_flags |= FP_EXITING;
-
-  /* Check if any process is SUSPENDed on this driver.
-   * If a driver exits, unmap its entries in the dmap table.
-   * (unmapping has to be done after the first step, because the
-   * dmap table is used in the first step.)
-   */
-  unsuspend_by_endpt(exiter->fp_endpoint);
-  dmap_unmap_by_endpt(exiter->fp_endpoint);
-
-  worker_stop_by_endpt(exiter->fp_endpoint); /* Unblock waiting threads */
-  vmnt_unmap_by_endpt(exiter->fp_endpoint); /* Invalidate open files if this
-                                            * was an active FS */
-
-  /* Invalidate endpoint number for error and sanity checks. */
-  exiter->fp_endpoint = NONE;
-
-  /* If a session leader exits and it has a controlling tty, then revoke
-   * access to its controlling tty from all other processes using it.
-   */
-  if ((exiter->fp_flags & FP_SESLDR) && exiter->fp_tty != 0) {
-      dev = exiter->fp_tty;
-      for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-         if(rfp->fp_pid == PID_FREE) continue;
-          if (rfp->fp_tty == dev) rfp->fp_tty = 0;
-
-          for (i = 0; i < OPEN_MAX; i++) {
-               if ((rfilp = rfp->fp_filp[i]) == NULL) continue;
-               if (rfilp->filp_mode == FILP_CLOSED) continue;
-               vp = rfilp->filp_vno;
-               if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
-               if ((dev_t) vp->v_sdev != dev) continue;
-               lock_filp(rfilp, VNODE_READ);
-               (void) dev_close(dev, rfilp-filp); /* Ignore any errors, even
-                                                   * SUSPEND. */
-
-               rfilp->filp_mode = FILP_CLOSED;
-               unlock_filp(rfilp);
-          }
-      }
-  }
-
-  /* Exit done. Mark slot as free. */
-  exiter->fp_pid = PID_FREE;
-  if (exiter->fp_flags & FP_PENDING)
-       pending--;      /* No longer pending job, not going to do it */
-  exiter->fp_flags = FP_NOFLAGS;
-}
-
-/*===========================================================================*
- *                             pm_exit                                      *
- *===========================================================================*/
-PUBLIC void pm_exit(proc)
-int proc;
-{
-/* Perform the file system portion of the exit(status) system call. */
-  int exitee_p;
-
-  /* Nevertheless, pretend that the call came from the user. */
-  okendpt(proc, &exitee_p);
-  fp = &fproc[exitee_p];
-  free_proc(fp, FP_EXITING);
-}
-
-/*===========================================================================*
- *                             pm_setgid                                    *
- *===========================================================================*/
-PUBLIC void pm_setgid(proc_e, egid, rgid)
-int proc_e;
-int egid;
-int rgid;
-{
-  register struct fproc *tfp;
-  int slot;
-
-  okendpt(proc_e, &slot);
-  tfp = &fproc[slot];
-
-  tfp->fp_effgid =  egid;
-  tfp->fp_realgid = rgid;
-}
-
-
-/*===========================================================================*
- *                             pm_setgroups                                 *
- *===========================================================================*/
-PUBLIC void pm_setgroups(proc_e, ngroups, groups)
-int proc_e;
-int ngroups;
-gid_t *groups;
-{
-  struct fproc *rfp;
-  int slot;
-
-  okendpt(proc_e, &slot);
-  rfp = &fproc[slot];
-  if (ngroups * sizeof(gid_t) > sizeof(rfp->fp_sgroups))
-       panic("VFS: pm_setgroups: too much data to copy");
-  if (sys_datacopy(who_e, (vir_bytes) groups, SELF, (vir_bytes) rfp->fp_sgroups,
-                  ngroups * sizeof(gid_t)) == OK) {
-       rfp->fp_ngroups = ngroups;
-  } else
-       panic("VFS: pm_setgroups: datacopy failed");
-}
-
-
-/*===========================================================================*
- *                             pm_setuid                                    *
- *===========================================================================*/
-PUBLIC void pm_setuid(proc_e, euid, ruid)
-int proc_e;
-int euid;
-int ruid;
-{
-  struct fproc *tfp;
-  int slot;
-
-  okendpt(proc_e, &slot);
-  tfp = &fproc[slot];
-
-  tfp->fp_effuid =  euid;
-  tfp->fp_realuid = ruid;
-}
-
-/*===========================================================================*
- *                             do_svrctl                                    *
- *===========================================================================*/
-PUBLIC int do_svrctl()
-{
-  switch (m_in.svrctl_req) {
-  /* No control request implemented yet. */
-    default:
-       return(EINVAL);
-  }
-}
-
-/*===========================================================================*
- *                             pm_dumpcore                                  *
- *===========================================================================*/
-PUBLIC int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name)
-{
-  int slot, r, core_fd;
-  struct filp *f;
-  char core_path[PATH_MAX];
-  char proc_name[PROC_NAME_LEN];
-
-  okendpt(proc_e, &slot);
-  fp = &fproc[slot];
-
-  /* open core file */
-  snprintf(core_path, PATH_MAX, "%s.%d", CORE_NAME, fp->fp_pid);
-  core_fd = common_open(core_path, O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE);
-  if (core_fd < 0) return(core_fd);
-
-  /* get process' name */
-  r = sys_datacopy(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name,
-                       PROC_NAME_LEN);
-  if (r != OK) return(r);
-  proc_name[PROC_NAME_LEN - 1] = '\0';
-
-  if ((f = get_filp(core_fd, VNODE_WRITE)) == NULL) return(EBADF);
-  write_elf_core_file(f, csig, proc_name);
-  unlock_filp(f);
-  (void) close_fd(fp, core_fd);        /* ignore failure, we're exiting anyway */
-
-  free_proc(fp, FP_EXITING);
-  return(OK);
-}
-
-/*===========================================================================*
- *                              ds_event                                    *
- *===========================================================================*/
-PUBLIC void ds_event(void)
-{
-  char key[DS_MAX_KEYLEN];
-  char *blkdrv_prefix = "drv.blk.";
-  char *chrdrv_prefix = "drv.chr.";
-  u32_t value;
-  int type, r, is_blk;
-  endpoint_t owner_endpoint;
-
-  /* Get the event and the owner from DS. */
-  while ((r = ds_check(key, &type, &owner_endpoint)) == OK) {
-       /* Only check for block and character driver up events. */
-       if (!strncmp(key, blkdrv_prefix, strlen(blkdrv_prefix))) {
-               is_blk = TRUE;
-       } else if (!strncmp(key, chrdrv_prefix, strlen(chrdrv_prefix))) {
-               is_blk = FALSE;
-       } else {
-               continue;
-       }
-
-       if ((r = ds_retrieve_u32(key, &value)) != OK) {
-               printf("VFS: ds_event: ds_retrieve_u32 failed\n");
-               return;
-       }
-       if (value != DS_DRIVER_UP) continue;
-
-       /* Perform up. */
-       dmap_endpt_up(owner_endpoint, is_blk);
-  }
-
-  if (r != ENOENT) printf("VFS: ds_event: ds_check failed: %d\n", r);
-}
diff --git a/servers/avfs/mount.c b/servers/avfs/mount.c
deleted file mode 100644 (file)
index 4e4666d..0000000
+++ /dev/null
@@ -1,614 +0,0 @@
-/* This file performs the MOUNT and UMOUNT system calls.
- *
- * The entry points into this file are
- *   do_fsready:       perform the FS_READY system call
- *   do_mount:         perform the MOUNT system call
- *   do_umount:                perform the UMOUNT system call
- *   unmount:          unmount a file system
- */
-
-#include "fs.h"
-#include <fcntl.h>
-#include <string.h>
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include <minix/keymap.h>
-#include <minix/const.h>
-#include <minix/endpoint.h>
-#include <minix/syslib.h>
-#include <minix/bitmap.h>
-#include <minix/ds.h>
-#include <unistd.h>
-#include <sys/stat.h>
-#include <sys/mount.h>
-#include <dirent.h>
-#include <assert.h>
-#include "file.h"
-#include "fproc.h"
-#include "dmap.h"
-#include <minix/vfsif.h>
-#include "vnode.h"
-#include "vmnt.h"
-#include "path.h"
-#include "param.h"
-
-/* Allow the root to be replaced before the first 'real' mount. */
-PRIVATE int have_root = 0;
-
-/* Bitmap of in-use "none" pseudo devices. */
-PRIVATE bitchunk_t nonedev[BITMAP_CHUNKS(NR_NONEDEVS)] = { 0 };
-
-#define alloc_nonedev(dev) SET_BIT(nonedev, minor(dev) - 1)
-#define free_nonedev(dev) UNSET_BIT(nonedev, minor(dev) - 1)
-
-FORWARD _PROTOTYPE( dev_t name_to_dev, (int allow_mountpt,
-                                       char path[PATH_MAX])            );
-FORWARD _PROTOTYPE( dev_t find_free_nonedev, (void)                    );
-FORWARD _PROTOTYPE( void update_bspec, (dev_t dev, endpoint_t fs_e,
-                                     int send_drv_e)                   );
-
-/*===========================================================================*
- *                             update_bspec                                 *
- *===========================================================================*/
-PRIVATE void update_bspec(dev_t dev, endpoint_t fs_e, int send_drv_e)
-{
-/* Update all block special files for a certain device, to use a new FS endpt
- * to route raw block I/O requests through.
- */
-  struct vnode *vp;
-  struct dmap *dp;
-  int r, major;
-
-  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
-       if (vp->v_ref_count > 0 && S_ISBLK(vp->v_mode) && vp->v_sdev == dev) {
-               vp->v_bfs_e = fs_e;
-               if (send_drv_e) {
-                       major = major(dev);
-                       if (major < 0 || major >= NR_DEVICES) {
-                               /* Can't update for out-of-range major */
-                               continue;
-                       }
-                       dp = &dmap[major(dev)];
-                       if (dp->dmap_driver == NONE) {
-                               /* Can't update for vanished driver */
-                               printf("VFS: can't send new driver label\n");
-                               continue;
-                       }
-
-                       if ((r = req_newdriver(fs_e, vp->v_sdev,
-                                       dp->dmap_label)) != OK) {
-                               printf("VFS: Failed to send new driver label"
-                                      " for moved block special file to %d\n",
-                                      fs_e);
-                       }
-               }
-       }
-}
-
-/*===========================================================================*
- *                              do_fsready                                   *
- *===========================================================================*/
-PUBLIC int do_fsready()
-{
-  /* deprecated */
-  return(SUSPEND);
-}
-
-/*===========================================================================*
- *                              do_mount                                     *
- *===========================================================================*/
-PUBLIC int do_mount()
-{
-/* Perform the mount(name, mfile, mount_flags) system call. */
-  endpoint_t fs_e;
-  int r, slot, rdonly, nodev;
-  char fullpath[PATH_MAX];
-  char mount_label[LABEL_MAX];
-  dev_t dev;
-
-  /* Only the super-user may do MOUNT. */
-  if (!super_user) return(EPERM);
-
-  /* FS process' endpoint number */
-  if (m_in.mount_flags & MS_LABEL16) {
-       /* Get the label from the caller, and ask DS for the endpoint. */
-       r = sys_datacopy(who_e, (vir_bytes) m_in.fs_label, SELF,
-               (vir_bytes) mount_label, (phys_bytes) sizeof(mount_label));
-       if (r != OK) return(r);
-
-       mount_label[sizeof(mount_label)-1] = 0;
-
-       r = ds_retrieve_label_endpt(mount_label, &fs_e);
-       if (r != OK) return(r);
-  } else {
-       /* Legacy support: get the endpoint from the request itself. */
-       fs_e = (endpoint_t) m_in.fs_label;
-       mount_label[0] = 0;
-  }
-
-  /* Sanity check on process number. */
-  if (isokendpt(fs_e, &slot) != OK) return(EINVAL);
-
-  /* Should the file system be mounted read-only? */
-  rdonly = (m_in.mount_flags & MS_RDONLY);
-
-  /* A null string for block special device means don't use a device at all. */
-  nodev = (m_in.name1_length == 0);
-  if (!nodev) {
-       /* If 'name' is not for a block special file, return error. */
-       if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-               return(err_code);
-       if ((dev = name_to_dev(FALSE /*allow_mountpt*/, fullpath)) == NO_DEV)
-               return(err_code);
-  } else {
-       /* Find a free pseudo-device as substitute for an actual device. */
-       if ((dev = find_free_nonedev()) == NO_DEV)
-               return(err_code);
-  }
-
-  /* Fetch the name of the mountpoint */
-  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
-       return(err_code);
-
-  /* Do the actual job */
-  return mount_fs(dev, fullpath, fs_e, rdonly, mount_label);
-}
-
-
-/*===========================================================================*
- *                              mount_fs                                    *
- *===========================================================================*/
-PUBLIC int mount_fs(
-dev_t dev,
-char mountpoint[PATH_MAX],
-endpoint_t fs_e,
-int rdonly,
-char mount_label[LABEL_MAX] )
-{
-  int rdir, mdir;               /* TRUE iff {root|mount} file is dir */
-  int i, r = OK, found, isroot, mount_root, con_reqs, slot;
-  struct fproc *tfp, *rfp;
-  struct dmap *dp;
-  struct vnode *root_node, *vp = NULL;
-  struct vmnt *new_vmp, *parent_vmp;
-  char *label;
-  struct node_details res;
-  struct lookup resolve;
-
-  /* Look up block device driver label when dev is not a pseudo-device */
-  label = "";
-  if (!is_nonedev(dev)) {
-       /* Get driver process' endpoint */
-       dp = &dmap[major(dev)];
-       if (dp->dmap_driver == NONE) {
-               printf("VFS: no driver for dev %d\n", dev);
-               return(EINVAL);
-       }
-
-       label = dp->dmap_label;
-       assert(strlen(label) > 0);
-  }
-
-  /* Scan vmnt table to see if dev already mounted. If not, find a free slot.*/
-  found = FALSE;
-  for (i = 0; i < NR_MNTS; ++i) {
-       if (vmnt[i].m_dev == dev) found = TRUE;
-  }
-  if (found) {
-       return(EBUSY);
-  } else if ((new_vmp = get_free_vmnt()) == NULL) {
-       return(ENOMEM);
-  }
-
-  if ((r = lock_vmnt(new_vmp, VMNT_EXCL)) != OK) return(r);
-
-  isroot = (strcmp(mountpoint, "/") == 0);
-  mount_root = (isroot && have_root < 2); /* Root can be mounted twice:
-                                          * 1: ramdisk
-                                          * 2: boot disk (e.g., harddisk)
-                                          */
-
-  if (!mount_root) {
-       /* Get vnode of mountpoint */
-       lookup_init(&resolve, mountpoint, PATH_NOFLAGS, &parent_vmp, &vp);
-       resolve.l_vmnt_lock = VMNT_EXCL;
-       resolve.l_vnode_lock = VNODE_WRITE;
-       if ((vp = eat_path(&resolve, fp)) == NULL)
-               r = err_code;
-       else if (vp->v_ref_count == 1) {
-               /*Tell FS on which vnode it is mounted (glue into mount tree)*/
-               r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr);
-       } else
-               r = EBUSY;
-
-       if (vp != NULL) {
-               /* Quickly unlock to allow back calls (from e.g. FUSE) to
-                * relock */
-               unlock_vmnt(parent_vmp);
-       }
-
-       if (r != OK) {
-               if (vp != NULL) {
-                       unlock_vnode(vp);
-                       put_vnode(vp);
-               }
-               unlock_vmnt(new_vmp);
-               return(r);
-       }
-  }
-
-  /* We'll need a vnode for the root inode */
-  if ((root_node = get_free_vnode()) == NULL) {
-       if (vp != NULL) {
-               unlock_vnode(vp);
-               put_vnode(vp);
-       }
-       unlock_vmnt(new_vmp);
-       return(err_code);
-  }
-  lock_vnode(root_node, VNODE_OPCL);
-
-  /* Record process as a system process */
-  if (isokendpt(fs_e, &slot) != OK) {
-       if (vp != NULL) {
-               unlock_vnode(vp);
-               put_vnode(vp);
-       }
-       unlock_vnode(root_node);
-       unlock_vmnt(new_vmp);
-       return(EINVAL);
-  }
-  rfp = &fproc[slot];
-  rfp->fp_flags |= FP_SYS_PROC;        /* Process is an FS */
-
-  /* Store some essential vmnt data first */
-  new_vmp->m_fs_e = fs_e;
-  new_vmp->m_dev = dev;
-  if (rdonly) new_vmp->m_flags |= VMNT_READONLY;
-  else new_vmp->m_flags &= ~VMNT_READONLY;
-
-  /* Tell FS which device to mount */
-  new_vmp->m_flags |= VMNT_MOUNTING;
-  r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res, &con_reqs);
-  new_vmp->m_flags &= ~VMNT_MOUNTING;
-
-  if (r != OK) {
-       new_vmp->m_fs_e = NONE;
-       new_vmp->m_dev = NO_DEV;
-       unlock_vnode(root_node);
-       if (vp != NULL) {
-               unlock_vnode(vp);
-               put_vnode(vp);
-       }
-       unlock_vmnt(new_vmp);
-       return(r);
-  }
-
-  lock_bsf();
-
-  /* Fill in root node's fields */
-  root_node->v_fs_e = res.fs_e;
-  root_node->v_inode_nr = res.inode_nr;
-  root_node->v_mode = res.fmode;
-  root_node->v_uid = res.uid;
-  root_node->v_gid = res.gid;
-  root_node->v_size = res.fsize;
-  root_node->v_sdev = NO_DEV;
-  root_node->v_fs_count = 1;
-  root_node->v_ref_count = 1;
-
-  /* Root node is indeed on the partition */
-  root_node->v_vmnt = new_vmp;
-  root_node->v_dev = new_vmp->m_dev;
-  if (con_reqs == 0)
-       new_vmp->m_comm.c_max_reqs = 1; /* Default if FS doesn't tell us */
-  else
-       new_vmp->m_comm.c_max_reqs = con_reqs;
-  new_vmp->m_comm.c_cur_reqs = 0;
-
-  if (mount_root) {
-       /* Superblock and root node already read.
-        * Nothing else can go wrong. Perform the mount. */
-       new_vmp->m_root_node = root_node;
-       new_vmp->m_mounted_on = NULL;
-       strcpy(new_vmp->m_label, mount_label);
-       if (is_nonedev(dev)) alloc_nonedev(dev);
-       update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */);
-
-       ROOT_DEV = dev;
-       ROOT_FS_E = fs_e;
-
-       /* Replace all root and working directories */
-       for (i = 0, tfp = fproc; i < NR_PROCS; i++, tfp++) {
-               if (tfp->fp_pid == PID_FREE)
-                       continue;
-
-#define                MAKEROOT(what) {                        \
-                       if (what) put_vnode(what);      \
-                       dup_vnode(root_node);           \
-                       what = root_node;               \
-               }
-
-               MAKEROOT(tfp->fp_rd);
-               MAKEROOT(tfp->fp_wd);
-       }
-
-       unlock_vnode(root_node);
-       unlock_vmnt(new_vmp);
-       have_root++; /* We have a (new) root */
-       unlock_bsf();
-       return(OK);
-  }
-
-  /* File types may not conflict. */
-  mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY); /*TRUE iff dir*/
-  rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
-  if (!mdir && rdir) r = EISDIR;
-
-  /* If error, return the super block and both inodes; release the vmnt. */
-  if (r != OK) {
-       unlock_vnode(vp);
-       unlock_vnode(root_node);
-       unlock_vmnt(new_vmp);
-       put_vnode(vp);
-       put_vnode(root_node);
-       new_vmp->m_dev = NO_DEV;
-       new_vmp->m_flags = 0;
-       unlock_bsf();
-       return(r);
-  }
-
-  /* Nothing else can go wrong.  Perform the mount. */
-  new_vmp->m_mounted_on = vp;
-  new_vmp->m_root_node = root_node;
-  strcpy(new_vmp->m_label, mount_label);
-
-  /* Allocate the pseudo device that was found, if not using a real device. */
-  if (is_nonedev(dev)) alloc_nonedev(dev);
-
-  /* The new FS will handle block I/O requests for its device now. */
-  if (!(new_vmp->m_flags & VMNT_FORCEROOTBSF))
-       update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */);
-
-  unlock_vnode(vp);
-  unlock_vnode(root_node);
-  unlock_vmnt(new_vmp);
-  unlock_bsf();
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             mount_pfs                                    *
- *===========================================================================*/
-PUBLIC void mount_pfs(void)
-{
-/* Mount the Pipe File Server. It's not really mounted onto the file system,
-   but it's necessary it has a vmnt entry to make locking easier */
-
-  dev_t dev;
-  struct vmnt *vmp;
-  struct fproc *rfp;
-
-  if ((dev = find_free_nonedev()) == NO_DEV)
-       panic("VFS: no nonedev to initialize PFS");
-
-  if ((vmp = get_free_vmnt()) == NULL)
-       panic("VFS: no vmnt to initialize PFS");
-
-  alloc_nonedev(dev);
-
-  vmp->m_dev = dev;
-  vmp->m_fs_e = PFS_PROC_NR;
-  strcpy(vmp->m_label, "pfs");
-
-  rfp = &fproc[_ENDPOINT_P(PFS_PROC_NR)];
-  rfp->fp_flags |= FP_SYS_PROC;        /* PFS is a driver and an FS */
-}
-
-/*===========================================================================*
- *                              do_umount                                    *
- *===========================================================================*/
-PUBLIC int do_umount(void)
-{
-/* Perform the umount(name) system call. */
-  char label[LABEL_MAX];
-  dev_t dev;
-  int r;
-  char fullpath[PATH_MAX];
-
-  /* Only the super-user may do umount. */
-  if (!super_user) return(EPERM);
-
-  /* If 'name' is not for a block special file or mountpoint, return error. */
-  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
-       return(err_code);
-  if ((dev = name_to_dev(TRUE /*allow_mountpt*/, fullpath)) == NO_DEV)
-       return(err_code);
-
-  if ((r = unmount(dev, label)) != OK) return(r);
-
-  /* Return the label of the mounted file system, so that the caller
-   * can shut down the corresponding server process.
-   */
-  if (strlen(label) >= M3_LONG_STRING) /* should never evaluate to true */
-       label[M3_LONG_STRING-1] = 0;
-  strcpy(m_out.umount_label, label);
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                              unmount                                      *
- *===========================================================================*/
-PUBLIC int unmount(
-  dev_t dev,                   /* block-special device */
-  char *label                  /* buffer to retrieve label, or NULL */
-)
-{
-  struct vnode *vp;
-  struct vmnt *vmp_i = NULL, *vmp = NULL;
-  int count, locks, r;
-
-  /* Find vmnt that is to be unmounted */
-  for (vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) {
-         if (vmp_i->m_dev == dev) {
-                 if(vmp) panic("device mounted more than once: %d", dev);
-                 vmp = vmp_i;
-         }
-  }
-
-  /* Did we find the vmnt (i.e., was dev a mounted device)? */
-  if(!vmp) return(EINVAL);
-
-  if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK) return(r);
-
-  /* See if the mounted device is busy.  Only 1 vnode using it should be
-   * open -- the root vnode -- and that inode only 1 time. */
-  locks = count = 0;
-  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++)
-         if (vp->v_ref_count > 0 && vp->v_dev == dev) {
-               count += vp->v_ref_count;
-               if (is_vnode_locked(vp)) locks++;
-         }
-
-  if (count > 1 || locks > 1 || tll_haspendinglock(&vmp->m_lock)) {
-       unlock_vmnt(vmp);
-       return(EBUSY);    /* can't umount a busy file system */
-  }
-
-  /* Tell FS to drop all inode references for root inode except 1. */
-  vnode_clean_refs(vmp->m_root_node);
-
-  if (vmp->m_mounted_on) {
-       put_vnode(vmp->m_mounted_on);
-       vmp->m_mounted_on = NULL;
-  }
-
-  vmp->m_comm.c_max_reqs = 1;  /* Force max concurrent reqs to just one, so
-                                * we won't send any messages after the
-                                * unmount request */
-
-  /* Tell FS to unmount */
-  if ((r = req_unmount(vmp->m_fs_e)) != OK)              /* Not recoverable. */
-       printf("VFS: ignoring failed umount attempt FS endpoint: %d (%d)\n",
-              vmp->m_fs_e, r);
-
-  if (is_nonedev(vmp->m_dev)) free_nonedev(vmp->m_dev);
-
-  if (label != NULL) strcpy(label, vmp->m_label);
-
-  if (vmp->m_root_node) {      /* PFS lacks a root node */
-       vmp->m_root_node->v_ref_count = 0;
-       vmp->m_root_node->v_fs_count = 0;
-       vmp->m_root_node->v_sdev = NO_DEV;
-       vmp->m_root_node = NULL;
-  }
-  vmp->m_dev = NO_DEV;
-  vmp->m_fs_e = NONE;
-
-  unlock_vmnt(vmp);
-
-  /* The root FS will handle block I/O requests for this device now. */
-  lock_bsf();
-  update_bspec(dev, ROOT_FS_E, 1 /* send new driver endpoint */);
-  unlock_bsf();
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             unmount_all                                  *
- *===========================================================================*/
-PUBLIC void unmount_all(void)
-{
-/* Unmount all filesystems.  File systems are mounted on other file systems,
- * so you have to pull off the loose bits repeatedly to get it all undone.
- */
-
-  int i;
-  struct vmnt *vmp;
-
-  /* Now unmount the rest */
-  for (i = 0; i < NR_MNTS; i++) {
-       /* Unmount at least one. */
-       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
-               if (vmp->m_dev != NO_DEV)
-                       unmount(vmp->m_dev, NULL);
-       }
-  }
-  check_vnode_locks();
-  check_vmnt_locks();
-  check_filp_locks();
-  check_bsf_lock();
-}
-
-/*===========================================================================*
- *                              name_to_dev                                  *
- *===========================================================================*/
-PRIVATE dev_t name_to_dev(int allow_mountpt, char path[PATH_MAX])
-{
-/* Convert the block special file in 'user_fullpath' to a device number.
- * If the given path is not a block special file, but 'allow_mountpt' is set
- * and the path is the root node of a mounted file system, return that device
- * number. In all other cases, return NO_DEV and an error code in 'err_code'.
- */
-  dev_t dev;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  struct lookup resolve;
-
-  lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* Request lookup */
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(NO_DEV);
-
-  if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL) {
-       dev = vp->v_sdev;
-  } else if (allow_mountpt && vp->v_vmnt->m_root_node == vp) {
-       dev = vp->v_dev;
-  } else {
-       err_code = ENOTBLK;
-       dev = NO_DEV;
-  }
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-  put_vnode(vp);
-  return(dev);
-}
-
-
-/*===========================================================================*
- *                              is_nonedev                                  *
- *===========================================================================*/
-PUBLIC int is_nonedev(dev_t dev)
-{
-/* Return whether the given device is a "none" pseudo device.
- */
-
-  return (major(dev) == NONE_MAJOR &&
-       minor(dev) > 0 && minor(dev) <= NR_NONEDEVS);
-}
-
-
-/*===========================================================================*
- *                              find_free_nonedev                           *
- *===========================================================================*/
-PRIVATE dev_t find_free_nonedev(void)
-{
-/* Find a free "none" pseudo device. Do not allocate it yet.
- */
-  int i;
-
-  for (i = 0; i < NR_NONEDEVS; i++)
-       if (!GET_BIT(nonedev, i))
-               return makedev(NONE_MAJOR, i + 1);
-
-  err_code = EMFILE;
-  return NO_DEV;
-}
diff --git a/servers/avfs/open.c b/servers/avfs/open.c
deleted file mode 100644 (file)
index a3fd9dc..0000000
+++ /dev/null
@@ -1,744 +0,0 @@
-/* This file contains the procedures for creating, opening, closing, and
- * seeking on files.
- *
- * The entry points into this file are
- *   do_creat: perform the CREAT system call
- *   do_open:  perform the OPEN system call
- *   do_mknod: perform the MKNOD system call
- *   do_mkdir: perform the MKDIR system call
- *   do_close: perform the CLOSE system call
- *   do_lseek:  perform the LSEEK system call
- *   do_llseek: perform the LLSEEK system call
- */
-
-#include "fs.h"
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include <minix/u64.h>
-#include "file.h"
-#include "fproc.h"
-#include "scratchpad.h"
-#include "dmap.h"
-#include "lock.h"
-#include "param.h"
-#include <dirent.h>
-#include <assert.h>
-#include <minix/vfsif.h>
-#include "vnode.h"
-#include "vmnt.h"
-#include "path.h"
-
-PUBLIC char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
-
-FORWARD _PROTOTYPE( struct vnode *new_node, (struct lookup *resolve,
-                                            int oflags, mode_t bits)   );
-FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp, mode_t bits,
-                                   int oflags)                         );
-
-
-/*===========================================================================*
- *                             do_creat                                     *
- *===========================================================================*/
-PUBLIC int do_creat()
-{
-/* Perform the creat(name, mode) system call. */
-  int r;
-  char fullpath[PATH_MAX];
-
-  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
-       return(err_code);
-  r = common_open(fullpath, O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             do_open                                      *
- *===========================================================================*/
-PUBLIC int do_open()
-{
-/* Perform the open(name, flags,...) system call. */
-  int create_mode = 0;         /* is really mode_t but this gives problems */
-  int r;
-  char fullpath[PATH_MAX];
-
-  /* If O_CREAT is set, open has three parameters, otherwise two. */
-  if (m_in.mode & O_CREAT) {
-       create_mode = m_in.c_mode;
-       r = fetch_name(m_in.c_name, m_in.name1_length, M1, fullpath);
-  } else {
-       r = fetch_name(m_in.name, m_in.name_length, M3, fullpath);
-  }
-
-  if (r != OK) return(err_code); /* name was bad */
-  r = common_open(fullpath, m_in.mode, create_mode);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             common_open                                  *
- *===========================================================================*/
-PUBLIC int common_open(char path[PATH_MAX], int oflags, mode_t omode)
-{
-/* Common code from do_creat and do_open. */
-  int b, r, exist = TRUE, major_dev;
-  dev_t dev;
-  mode_t bits;
-  struct filp *filp, *filp2;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  struct dmap *dp;
-  struct lookup resolve;
-
-  /* Remap the bottom two bits of oflags. */
-  bits = (mode_t) mode_map[oflags & O_ACCMODE];
-  if (!bits) return(EINVAL);
-
-  /* See if file descriptor and filp slots are available. */
-  if ((r = get_fd(0, bits, &(scratch(fp).file.fd_nr), &filp)) != OK) return(r);
-
-  lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp);
-
-  /* If O_CREATE is set, try to make the file. */
-  if (oflags & O_CREAT) {
-        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
-       vp = new_node(&resolve, oflags, omode);
-       r = err_code;
-       if (r == OK) exist = FALSE;     /* We just created the file */
-       else if (r != EEXIST) {         /* other error */
-               if (vp) unlock_vnode(vp);
-               unlock_filp(filp);
-               return(r);
-       }
-       else exist = !(oflags & O_EXCL);/* file exists, if the O_EXCL
-                                          flag is set this is an error */
-  } else {
-       /* Scan path name */
-       resolve.l_vmnt_lock = VMNT_READ;
-       resolve.l_vnode_lock = VNODE_OPCL;
-       if ((vp = eat_path(&resolve, fp)) == NULL) {
-               unlock_filp(filp);
-               return(err_code);
-       }
-
-       if (vmp != NULL) unlock_vmnt(vmp);
-  }
-
-  /* Claim the file descriptor and filp slot and fill them in. */
-  fp->fp_filp[scratch(fp).file.fd_nr] = filp;
-  FD_SET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse);
-  filp->filp_count = 1;
-  filp->filp_vno = vp;
-  filp->filp_flags = oflags;
-
-  /* Only do the normal open code if we didn't just create the file. */
-  if (exist) {
-       /* Check protections. */
-       if ((r = forbidden(fp, vp, bits)) == OK) {
-               /* Opening reg. files, directories, and special files differ */
-               switch (vp->v_mode & I_TYPE) {
-                  case I_REGULAR:
-                       /* Truncate regular file if O_TRUNC. */
-                       if (oflags & O_TRUNC) {
-                               if ((r = forbidden(fp, vp, W_BIT)) != OK)
-                                       break;
-                               truncate_vnode(vp, 0);
-                       }
-                       break;
-                  case I_DIRECTORY:
-                       /* Directories may be read but not written. */
-                       r = (bits & W_BIT ? EISDIR : OK);
-                       break;
-                  case I_CHAR_SPECIAL:
-                       /* Invoke the driver for special processing. */
-                       dev = (dev_t) vp->v_sdev;
-                       /* TTY needs to know about the O_NOCTTY flag. */
-                       r = dev_open(dev, who_e, bits | (oflags & O_NOCTTY));
-                       if (r == SUSPEND) suspend(FP_BLOCKED_ON_DOPEN);
-                       else vp = filp->filp_vno; /* Might be updated by
-                                                  * dev_open/clone_opcl */
-                       break;
-                  case I_BLOCK_SPECIAL:
-
-                       lock_bsf();
-
-                       /* Invoke the driver for special processing. */
-                       dev = (dev_t) vp->v_sdev;
-                       r = bdev_open(dev, bits);
-                       if (r != OK) {
-                               unlock_bsf();
-                               break;
-                       }
-
-                       major_dev = major(vp->v_sdev);
-                       dp = &dmap[major_dev];
-                       if (dp->dmap_driver == NONE) {
-                               printf("VFS: block driver disappeared!\n");
-                               unlock_bsf();
-                               r = ENXIO;
-                               break;
-                       }
-
-                       /* Check whether the device is mounted or not. If so,
-                        * then that FS is responsible for this device.
-                        * Otherwise we default to ROOT_FS.
-                        */
-                       vp->v_bfs_e = ROOT_FS_E; /* By default */
-                       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
-                               if (vmp->m_dev == vp->v_sdev &&
-                                   !(vmp->m_flags & VMNT_FORCEROOTBSF)) {
-                                       vp->v_bfs_e = vmp->m_fs_e;
-                               }
-
-                       /* Send the driver label to the file system that will
-                        * handle the block I/O requests (even when its label
-                        * and endpoint are known already), but only when it is
-                        * the root file system. Other file systems will
-                        * already have it anyway.
-                        */
-                       if (vp->v_bfs_e != ROOT_FS_E) {
-                               unlock_bsf();
-                               break;
-                       }
-
-                       if (req_newdriver(vp->v_bfs_e, vp->v_sdev,
-                                       dp->dmap_label) != OK) {
-                               printf("VFS: error sending driver label\n");
-                               bdev_close(dev);
-                               r = ENXIO;
-                       }
-                       unlock_bsf();
-                       break;
-
-                  case I_NAMED_PIPE:
-                       /* Create a mapped inode on PFS which handles reads
-                          and writes to this named pipe. */
-                       tll_upgrade(&vp->v_lock);
-                       r = map_vnode(vp, PFS_PROC_NR);
-                       if (r == OK) {
-                               vp->v_pipe = I_PIPE;
-                               if (vp->v_ref_count == 1) {
-                                       vp->v_pipe_rd_pos = 0;
-                                       vp->v_pipe_wr_pos = 0;
-                                       if (vp->v_size != 0)
-                                               r = truncate_vnode(vp, 0);
-                               }
-                               oflags |= O_APPEND;     /* force append mode */
-                               filp->filp_flags = oflags;
-                       }
-                       if (r == OK) {
-                               r = pipe_open(vp, bits, oflags);
-                       }
-                       if (r != ENXIO) {
-                               /* See if someone else is doing a rd or wt on
-                                * the FIFO.  If so, use its filp entry so the
-                                * file position will be automatically shared.
-                                */
-                               b = (bits & R_BIT ? R_BIT : W_BIT);
-                               filp->filp_count = 0; /* don't find self */
-                               if ((filp2 = find_filp(vp, b)) != NULL) {
-                                       /* Co-reader or writer found. Use it.*/
-                                       fp->fp_filp[scratch(fp).file.fd_nr] = filp2;
-                                       filp2->filp_count++;
-                                       filp2->filp_vno = vp;
-                                       filp2->filp_flags = oflags;
-
-                                       /* v_count was incremented after the
-                                        * vnode has been found. i_count was
-                                        * incremented incorrectly in FS, not
-                                        * knowing that we were going to use an
-                                        * existing filp entry.  Correct this
-                                        * error.
-                                        */
-                                       unlock_vnode(vp);
-                                       put_vnode(vp);
-                               } else {
-                                       /* Nobody else found. Restore filp. */
-                                       filp->filp_count = 1;
-                               }
-                       }
-                       break;
-               }
-       }
-  }
-
-  unlock_filp(filp);
-
-  /* If error, release inode. */
-  if (r != OK) {
-       if (r != SUSPEND) {
-               fp->fp_filp[scratch(fp).file.fd_nr] = NULL;
-               FD_CLR(scratch(fp).file.fd_nr, &fp->fp_filp_inuse);
-               filp->filp_count = 0;
-               filp->filp_vno = NULL;
-               put_vnode(vp);
-       }
-  } else {
-       r = scratch(fp).file.fd_nr;
-  }
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             new_node                                     *
- *===========================================================================*/
-PRIVATE struct vnode *new_node(struct lookup *resolve, int oflags, mode_t bits)
-{
-/* Try to create a new inode and return a pointer to it. If the inode already
-   exists, return a pointer to it as well, but set err_code accordingly.
-   NULL is returned if the path cannot be resolved up to the last
-   directory, or when the inode cannot be created due to permissions or
-   otherwise. */
-  struct vnode *dirp, *vp;
-  struct vmnt *dir_vmp, *vp_vmp;
-  int r;
-  struct node_details res;
-  struct lookup findnode;
-  char *path;
-
-  path = resolve->l_path;      /* For easy access */
-
-  lookup_init(&findnode, path, resolve->l_flags, &dir_vmp, &dirp);
-  findnode.l_vmnt_lock = VMNT_WRITE;
-  findnode.l_vnode_lock = VNODE_WRITE; /* dir node */
-
-  /* When O_CREAT and O_EXCL flags are set, the path may not be named by a
-   * symbolic link. */
-  if (oflags & O_EXCL) findnode.l_flags |= PATH_RET_SYMLINK;
-
-  /* See if the path can be opened down to the last directory. */
-  if ((dirp = last_dir(&findnode, fp)) == NULL) return(NULL);
-
-  /* The final directory is accessible. Get final component of the path. */
-  lookup_init(&findnode, findnode.l_path, findnode.l_flags, &vp_vmp, &vp);
-  findnode.l_vmnt_lock = VMNT_WRITE;
-  findnode.l_vnode_lock = (oflags & O_TRUNC) ? VNODE_WRITE : VNODE_OPCL;
-  vp = advance(dirp, &findnode, fp);
-  assert(vp_vmp == NULL);      /* Lookup to last dir should have yielded lock
-                                * on vmp or final component does not exist.
-                                * Either way, vp_vmp ought to be not set.
-                                */
-
-  /* The combination of a symlink with absolute path followed by a danglink
-   * symlink results in a new path that needs to be re-resolved entirely. */
-  if (path[0] == '/') {
-       unlock_vnode(dirp);
-       unlock_vmnt(dir_vmp);
-       put_vnode(dirp);
-       if (vp != NULL) {
-               unlock_vnode(vp);
-               put_vnode(vp);
-       }
-       return new_node(resolve, oflags, bits);
-  }
-
-  if (vp == NULL && err_code == ENOENT) {
-       /* Last path component does not exist. Make a new directory entry. */
-       if ((vp = get_free_vnode()) == NULL) {
-               /* Can't create new entry: out of vnodes. */
-               unlock_vnode(dirp);
-               unlock_vmnt(dir_vmp);
-               put_vnode(dirp);
-               return(NULL);
-       }
-
-       lock_vnode(vp, VNODE_OPCL);
-
-       if ((r = forbidden(fp, dirp, W_BIT|X_BIT)) != OK ||
-           (r = req_create(dirp->v_fs_e, dirp->v_inode_nr,bits, fp->fp_effuid,
-                           fp->fp_effgid, path, &res)) != OK ) {
-               /* Can't create inode either due to permissions or some other
-                * problem. In case r is EEXIST, we might be dealing with a
-                * dangling symlink.*/
-               if (r == EEXIST) {
-                       struct vnode *slp, *old_wd;
-
-                       /* Resolve path up to symlink */
-                       findnode.l_flags = PATH_RET_SYMLINK;
-                       findnode.l_vnode_lock = VNODE_READ;
-                       findnode.l_vnode = &slp;
-                       slp = advance(dirp, &findnode, fp);
-                       if (slp != NULL) {
-                               if (S_ISLNK(slp->v_mode)) {
-                                       /* Get contents of link */
-
-                                       r = req_rdlink(slp->v_fs_e,
-                                                      slp->v_inode_nr,
-                                                      VFS_PROC_NR,
-                                                      path,
-                                                      PATH_MAX - 1, 0);
-                                       if (r < 0) {
-                                               /* Failed to read link */
-                                               unlock_vnode(slp);
-                                               unlock_vnode(dirp);
-                                               unlock_vmnt(dir_vmp);
-                                               put_vnode(slp);
-                                               put_vnode(dirp);
-                                               err_code = r;
-                                               return(NULL);
-                                       }
-                                       path[r] = '\0'; /* Terminate path */
-                               }
-                               unlock_vnode(slp);
-                               put_vnode(slp);
-                       }
-
-                       /* Try to create the inode the dangling symlink was
-                        * pointing to. We have to use dirp as starting point
-                        * as there might be multiple successive symlinks
-                        * crossing multiple mountpoints.
-                        * Unlock vnodes and vmnts as we're going to recurse.
-                        */
-                       unlock_vnode(dirp);
-                       unlock_vnode(vp);
-                       unlock_vmnt(dir_vmp);
-
-                       old_wd = fp->fp_wd; /* Save orig. working dirp */
-                       fp->fp_wd = dirp;
-                       vp = new_node(resolve, oflags, bits);
-                       fp->fp_wd = old_wd; /* Restore */
-
-                       if (vp != NULL) {
-                               put_vnode(dirp);
-                               *(resolve->l_vnode) = vp;
-                               return(vp);
-                       }
-                       r = err_code;
-               }
-
-               if (r == EEXIST)
-                       err_code = EIO; /* Impossible, we have verified that
-                                        * the last component doesn't exist and
-                                        * is not a dangling symlink. */
-               else
-                       err_code = r;
-
-               unlock_vnode(dirp);
-               unlock_vnode(vp);
-               unlock_vmnt(dir_vmp);
-               put_vnode(dirp);
-               return(NULL);
-       }
-
-       /* Store results and mark vnode in use */
-
-       vp->v_fs_e = res.fs_e;
-       vp->v_inode_nr = res.inode_nr;
-       vp->v_mode = res.fmode;
-       vp->v_size = res.fsize;
-       vp->v_uid = res.uid;
-       vp->v_gid = res.gid;
-       vp->v_sdev = res.dev;
-       vp->v_vmnt = dirp->v_vmnt;
-       vp->v_dev = vp->v_vmnt->m_dev;
-       vp->v_fs_count = 1;
-       vp->v_ref_count = 1;
-  } else {
-       /* Either last component exists, or there is some other problem. */
-       if (vp != NULL) {
-               r = EEXIST;     /* File exists or a symlink names a file while
-                                * O_EXCL is set. */
-       } else
-               r = err_code;   /* Other problem. */
-  }
-
-  err_code = r;
-  /* When dirp equals vp, we shouldn't release the lock as a vp is locked only
-   * once. Releasing the lock would cause the resulting vp not be locked and
-   * cause mayhem later on. */
-  if (dirp != vp) {
-       unlock_vnode(dirp);
-  }
-  unlock_vmnt(dir_vmp);
-  put_vnode(dirp);
-
-  *(resolve->l_vnode) = vp;
-  return(vp);
-}
-
-
-/*===========================================================================*
- *                             pipe_open                                    *
- *===========================================================================*/
-PRIVATE int pipe_open(struct vnode *vp, mode_t bits, int oflags)
-{
-/*  This function is called from common_open. It checks if
- *  there is at least one reader/writer pair for the pipe, if not
- *  it suspends the caller, otherwise it revives all other blocked
- *  processes hanging on the pipe.
- */
-
-  vp->v_pipe = I_PIPE;
-
-  if ((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO);
-
-  /* Find the reader/writer at the other end of the pipe */
-  if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NULL) {
-       /* Not found */
-       if (oflags & O_NONBLOCK) {
-               if (bits & W_BIT) return(ENXIO);
-       } else {
-               /* Let's wait for the other side to show up */
-               suspend(FP_BLOCKED_ON_POPEN);
-               return(SUSPEND);
-       }
-  } else if (susp_count > 0) { /* revive blocked processes */
-       release(vp, OPEN, susp_count);
-       release(vp, CREAT, susp_count);
-  }
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             do_mknod                                     *
- *===========================================================================*/
-PUBLIC int do_mknod()
-{
-/* Perform the mknod(name, mode, addr) system call. */
-  register mode_t bits, mode_bits;
-  int r;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* Only the super_user may make nodes other than fifos. */
-  mode_bits = (mode_t) m_in.mk_mode;           /* mode of the inode */
-  if (!super_user && (((mode_bits & I_TYPE) != I_NAMED_PIPE) &&
-      ((mode_bits & I_TYPE) != I_UNIX_SOCKET))) {
-       return(EPERM);
-  }
-  bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
-
-  /* Open directory that's going to hold the new node. */
-  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-       return(err_code);
-  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
-
-  /* Make sure that the object is a directory */
-  if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
-       r = ENOTDIR;
-  } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
-       r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
-                     fp->fp_effgid, bits, m_in.mk_z0);
-  }
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-  put_vnode(vp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_mkdir                                     *
- *===========================================================================*/
-PUBLIC int do_mkdir()
-{
-/* Perform the mkdir(name, mode) system call. */
-  mode_t bits;                 /* mode bits for the new inode */
-  int r;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-       return(err_code);
-  bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
-  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
-
-  /* Make sure that the object is a directory */
-  if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
-       r = ENOTDIR;
-  } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
-       r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
-                     fp->fp_effgid, bits);
-  }
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-  put_vnode(vp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_lseek                                     *
- *===========================================================================*/
-PUBLIC int do_lseek()
-{
-/* Perform the lseek(ls_fd, offset, whence) system call. */
-  register struct filp *rfilp;
-  int r = OK;
-  long offset;
-  u64_t pos, newpos;
-
-  /* Check to see if the file descriptor is valid. */
-  if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code);
-
-  /* No lseek on pipes. */
-  if (rfilp->filp_vno->v_pipe == I_PIPE) {
-       unlock_filp(rfilp);
-       return(ESPIPE);
-  }
-
-  /* The value of 'whence' determines the start position to use. */
-  switch(m_in.whence) {
-    case SEEK_SET: pos = cvu64(0);     break;
-    case SEEK_CUR: pos = rfilp->filp_pos;      break;
-    case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size);      break;
-    default: unlock_filp(rfilp); return(EINVAL);
-  }
-
-  offset = m_in.offset_lo;
-  if (offset >= 0)
-       newpos = add64ul(pos, offset);
-  else
-       newpos = sub64ul(pos, -offset);
-
-  /* Check for overflow. */
-  if (ex64hi(newpos) != 0) {
-       r = EOVERFLOW;
-  } else if ((off_t) ex64lo(newpos) < 0) { /* no negative file size */
-       r = EOVERFLOW;
-  } else {
-       rfilp->filp_pos = newpos;
-
-       /* insert the new position into the output message */
-       m_out.reply_l1 = ex64lo(newpos);
-
-       if (cmp64(newpos, rfilp->filp_pos) != 0) {
-               /* Inhibit read ahead request */
-               r = req_inhibread(rfilp->filp_vno->v_fs_e,
-                                 rfilp->filp_vno->v_inode_nr);
-       }
-  }
-
-  unlock_filp(rfilp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_llseek                                    *
- *===========================================================================*/
-PUBLIC int do_llseek()
-{
-/* Perform the llseek(ls_fd, offset, whence) system call. */
-  register struct filp *rfilp;
-  u64_t pos, newpos;
-  int r = OK;
-
-  /* Check to see if the file descriptor is valid. */
-  if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code);
-
-  /* No lseek on pipes. */
-  if (rfilp->filp_vno->v_pipe == I_PIPE) {
-       unlock_filp(rfilp);
-       return(ESPIPE);
-  }
-
-  /* The value of 'whence' determines the start position to use. */
-  switch(m_in.whence) {
-    case SEEK_SET: pos = cvu64(0);     break;
-    case SEEK_CUR: pos = rfilp->filp_pos;      break;
-    case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size);      break;
-    default: unlock_filp(rfilp); return(EINVAL);
-  }
-
-  newpos = add64(pos, make64(m_in.offset_lo, m_in.offset_high));
-
-  /* Check for overflow. */
-  if (( (long) m_in.offset_high > 0) && cmp64(newpos, pos) < 0)
-      r = EINVAL;
-  else if (( (long) m_in.offset_high < 0) && cmp64(newpos, pos) > 0)
-      r = EINVAL;
-  else {
-       rfilp->filp_pos = newpos;
-
-       /* insert the new position into the output message */
-       m_out.reply_l1 = ex64lo(newpos);
-       m_out.reply_l2 = ex64hi(newpos);
-
-       if (cmp64(newpos, rfilp->filp_pos) != 0) {
-               /* Inhibit read ahead request */
-               r = req_inhibread(rfilp->filp_vno->v_fs_e,
-                                 rfilp->filp_vno->v_inode_nr);
-       }
-  }
-
-  unlock_filp(rfilp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_close                                     *
- *===========================================================================*/
-PUBLIC int do_close()
-{
-/* Perform the close(fd) system call. */
-
-  return close_fd(fp, m_in.fd);
-}
-
-
-/*===========================================================================*
- *                             close_fd                                     *
- *===========================================================================*/
-PUBLIC int close_fd(rfp, fd_nr)
-struct fproc *rfp;
-int fd_nr;
-{
-/* Perform the close(fd) system call. */
-  register struct filp *rfilp;
-  register struct vnode *vp;
-  struct file_lock *flp;
-  int lock_count;
-
-  /* First locate the vnode that belongs to the file descriptor. */
-  if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_OPCL)) == NULL) return(err_code);
-  vp = rfilp->filp_vno;
-
-  close_filp(rfilp);
-  rfp->fp_filp[fd_nr] = NULL;
-  FD_CLR(fd_nr, &rfp->fp_cloexec_set);
-  FD_CLR(fd_nr, &rfp->fp_filp_inuse);
-
-  /* Check to see if the file is locked.  If so, release all locks. */
-  if (nr_locks > 0) {
-       lock_count = nr_locks;  /* save count of locks */
-       for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
-               if (flp->lock_type == 0) continue;      /* slot not in use */
-               if (flp->lock_vnode == vp && flp->lock_pid == rfp->fp_pid) {
-                       flp->lock_type = 0;
-                       nr_locks--;
-               }
-       }
-       if (nr_locks < lock_count)
-               lock_revive();  /* one or more locks released */
-  }
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                             close_reply                                  *
- *===========================================================================*/
-PUBLIC void close_reply()
-{
-       /* No need to do anything */
-}
diff --git a/servers/avfs/param.h b/servers/avfs/param.h
deleted file mode 100644 (file)
index ea05621..0000000
+++ /dev/null
@@ -1,61 +0,0 @@
-#ifndef __VFS_PARAM_H__
-#define __VFS_PARAM_H__
-
-/* The following names are synonyms for the variables in the input message. */
-#define addr         m1_i3
-#define buffer       m1_p1
-#define child_endpt      m1_i2
-#define co_mode              m1_i1
-#define fd           m1_i1
-#define fd2          m1_i2
-#define group        m1_i3
-#define ls_fd        m2_i1
-#define mk_mode              m1_i2
-#define mk_z0        m1_i3
-#define mode         m3_i2
-#define c_mode        m1_i3
-#define c_name        m1_p1
-#define name         m3_p1
-#define flength       m2_l1
-#define name1        m1_p1
-#define name2        m1_p2
-#define        name_length   m3_i1
-#define name1_length  m1_i1
-#define name2_length  m1_i2
-#define nbytes        m1_i2
-#define owner        m1_i2
-#define pathname      m3_ca1
-#define pid          m1_i3
-#define ENDPT        m1_i1
-#define offset_lo     m2_l1
-#define offset_high   m2_l2
-#define ctl_req       m4_l1
-#define mount_flags   m1_i3
-#define request       m1_i2
-#define sig          m1_i2
-#define endpt1       m1_i1
-#define fs_label      m1_p3
-#define umount_label  m3_ca1
-#define tp           m2_l1
-#define utime_actime  m2_l1
-#define utime_modtime m2_l2
-#define utime_file    m2_p1
-#define utime_length  m2_i1
-#define utime_strlen  m2_i2
-#define whence       m2_i2
-#define svrctl_req    m2_i1
-#define svrctl_argp   m2_p1
-#define md_label       m2_p1
-#define md_label_len   m2_l1
-#define md_major       m2_i1
-#define md_style       m2_i2
-#define md_flags       m2_i3
-
-/* The following names are synonyms for the variables in the output message. */
-#define reply_type    m_type
-#define reply_l1      m2_l1
-#define reply_l2      m2_l2
-#define reply_i1      m1_i1
-#define reply_i2      m1_i2
-
-#endif
diff --git a/servers/avfs/path.c b/servers/avfs/path.c
deleted file mode 100644 (file)
index a694545..0000000
+++ /dev/null
@@ -1,814 +0,0 @@
-/* lookup() is the main routine that controls the path name lookup. It
- * handles mountpoints and symbolic links. The actual lookup requests
- * are sent through the req_lookup wrapper function.
- */
-
-#include "fs.h"
-#include <string.h>
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include <minix/keymap.h>
-#include <minix/const.h>
-#include <minix/endpoint.h>
-#include <unistd.h>
-#include <assert.h>
-#include <minix/vfsif.h>
-#include <sys/stat.h>
-#include <sys/un.h>
-#include <dirent.h>
-#include "threads.h"
-#include "vmnt.h"
-#include "vnode.h"
-#include "path.h"
-#include "fproc.h"
-#include "param.h"
-
-/* Set to following define to 1 if you really want to use the POSIX definition
- * (IEEE Std 1003.1, 2004) of pathname resolution. POSIX requires pathnames
- * with a traling slash (and that do not entirely consist of slash characters)
- * to be treated as if a single dot is appended. This means that for example
- * mkdir("dir/", ...) and rmdir("dir/") will fail because the call tries to
- * create or remove the directory '.'. Historically, Unix systems just ignore
- * trailing slashes.
- */
-#define DO_POSIX_PATHNAME_RES  0
-
-FORWARD _PROTOTYPE( int lookup, (struct vnode *dirp, struct lookup *resolve,
-                                node_details_t *node, struct fproc *rfp));
-FORWARD _PROTOTYPE( int check_perms, (endpoint_t ep, cp_grant_id_t io_gr,
-                                     size_t pathlen)                   );
-
-/*===========================================================================*
- *                             advance                                      *
- *===========================================================================*/
-PUBLIC struct vnode *advance(dirp, resolve, rfp)
-struct vnode *dirp;
-struct lookup *resolve;
-struct fproc *rfp;
-{
-/* Resolve a path name starting at dirp to a vnode. */
-  int r;
-  int do_downgrade = 1;
-  struct vnode *new_vp, *vp;
-  struct vmnt *vmp;
-  struct node_details res = {0,0,0,0,0,0,0};
-  tll_access_t initial_locktype;
-
-  assert(dirp);
-  assert(resolve->l_vnode_lock != TLL_NONE);
-  assert(resolve->l_vmnt_lock != TLL_NONE);
-
-  if (resolve->l_vnode_lock == VNODE_READ)
-       initial_locktype = VNODE_OPCL;
-  else
-       initial_locktype = resolve->l_vnode_lock;
-
-  /* Get a free vnode and lock it */
-  if ((new_vp = get_free_vnode()) == NULL) return(NULL);
-  lock_vnode(new_vp, initial_locktype);
-
-  /* Lookup vnode belonging to the file. */
-  if ((r = lookup(dirp, resolve, &res, rfp)) != OK) {
-       err_code = r;
-       unlock_vnode(new_vp);
-       return(NULL);
-  }
-
-  /* Check whether we already have a vnode for that file */
-  if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NULL) {
-       unlock_vnode(new_vp);   /* Don't need this anymore */
-       do_downgrade = (lock_vnode(vp, initial_locktype) != EBUSY);
-
-       /* Unfortunately, by the time we get the lock, another thread might've
-        * rid of the vnode (e.g., find_vnode found the vnode while a
-        * req_putnode was being processed). */
-       if (vp->v_ref_count == 0) { /* vnode vanished! */
-               /* As the lookup before increased the usage counters in the FS,
-                * we can simply set the usage counters to 1 and proceed as
-                * normal, because the putnode resulted in a use count of 1 in
-                * the FS. Other data is still valid, because the vnode was
-                * marked as pending lock, so get_free_vnode hasn't
-                * reinitialized the vnode yet. */
-               vp->v_fs_count = 1;
-               if (vp->v_mapfs_e != NONE) vp->v_mapfs_count = 1;
-       } else {
-               vp->v_fs_count++;       /* We got a reference from the FS */
-       }
-
-  } else {
-       /* Vnode not found, fill in the free vnode's fields */
-
-       new_vp->v_fs_e = res.fs_e;
-       new_vp->v_inode_nr = res.inode_nr;
-       new_vp->v_mode = res.fmode;
-       new_vp->v_size = res.fsize;
-       new_vp->v_uid = res.uid;
-       new_vp->v_gid = res.gid;
-       new_vp->v_sdev = res.dev;
-
-       if( (vmp = find_vmnt(new_vp->v_fs_e)) == NULL)
-                 panic("advance: vmnt not found");
-
-       new_vp->v_vmnt = vmp;
-       new_vp->v_dev = vmp->m_dev;
-       new_vp->v_fs_count = 1;
-
-       vp = new_vp;
-  }
-
-  dup_vnode(vp);
-  if (do_downgrade) {
-       /* Only downgrade a lock if we managed to lock it in the first place */
-       *(resolve->l_vnode) = vp;
-
-       if (initial_locktype != resolve->l_vnode_lock)
-               tll_downgrade(&vp->v_lock);
-
-#if LOCK_DEBUG
-       if (resolve->l_vnode_lock == VNODE_READ)
-               fp->fp_vp_rdlocks++;
-#endif
-  }
-
-  return(vp);
-}
-
-/*===========================================================================*
- *                             eat_path                                     *
- *===========================================================================*/
-PUBLIC struct vnode *eat_path(resolve, rfp)
-struct lookup *resolve;
-struct fproc *rfp;
-{
-/* Resolve path to a vnode. advance does the actual work. */
-  struct vnode *start_dir;
-
-  start_dir = (resolve->l_path[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
-  return advance(start_dir, resolve, rfp);
-}
-
-/*===========================================================================*
- *                             last_dir                                     *
- *===========================================================================*/
-PUBLIC struct vnode *last_dir(resolve, rfp)
-struct lookup *resolve;
-struct fproc *rfp;
-{
-/* Parse a path, as far as the last directory, fetch the vnode
- * for the last directory into the vnode table, and return a pointer to the
- * vnode. In addition, return the final component of the path in 'string'. If
- * the last directory can't be opened, return NULL and the reason for
- * failure in 'err_code'. We can't parse component by component as that would
- * be too expensive. Alternatively, we cut off the last component of the path,
- * and parse the path up to the penultimate component.
- */
-
-  size_t len;
-  char *cp;
-  char dir_entry[NAME_MAX+1];
-  struct vnode *start_dir, *res_vp, *sym_vp, *loop_start;
-  struct vmnt *sym_vmp = NULL;
-  int r, symloop = 0, ret_on_symlink = 0;
-  struct lookup symlink;
-
-  *resolve->l_vnode = NULL;
-  *resolve->l_vmp = NULL;
-  loop_start = NULL;
-  sym_vp = NULL;
-
-  ret_on_symlink = !!(resolve->l_flags & PATH_RET_SYMLINK);
-
-  do {
-       /* Is the path absolute or relative? Initialize 'start_dir'
-        * accordingly. Use loop_start in case we're looping.
-        */
-       if (loop_start != NULL)
-               start_dir = loop_start;
-       else
-               start_dir = (resolve->l_path[0] == '/' ? rfp->fp_rd:rfp->fp_wd);
-
-       len = strlen(resolve->l_path);
-
-       /* If path is empty, return ENOENT. */
-       if (len == 0)   {
-               err_code = ENOENT;
-               res_vp = NULL;
-               break;
-       }
-
-#if !DO_POSIX_PATHNAME_RES
-       /* Remove trailing slashes */
-       while (len > 1 && resolve->l_path[len-1] == '/') {
-               len--;
-               resolve->l_path[len]= '\0';
-       }
-#endif
-
-       cp = strrchr(resolve->l_path, '/');
-       if (cp == NULL) {
-               /* Just an entry in the current working directory */
-               struct vmnt *vmp;
-
-               vmp = find_vmnt(start_dir->v_fs_e);
-               if (vmp == NULL) {
-                       r = EIO;
-                       res_vp = NULL;
-                       break;
-               }
-               r = lock_vmnt(vmp, resolve->l_vmnt_lock);
-               if (r == EDEADLK) {
-                       res_vp = NULL;
-                       break;
-               } else if (r == OK)
-                       *resolve->l_vmp = vmp;
-
-               lock_vnode(start_dir, resolve->l_vnode_lock);
-               *resolve->l_vnode = start_dir;
-               dup_vnode(start_dir);
-               if (loop_start != NULL) {
-                       unlock_vnode(loop_start);
-                       put_vnode(loop_start);
-               }
-               return(start_dir);
-       } else if (cp[1] == '\0') {
-               /* Path ends in a slash. The directory entry is '.' */
-               strcpy(dir_entry, ".");
-       } else {
-               /* A path name for the directory and a directory entry */
-               strncpy(dir_entry, cp+1, NAME_MAX);
-               cp[1] = '\0';
-               dir_entry[NAME_MAX] = '\0';
-       }
-
-       /* Remove trailing slashes */
-       while (cp > resolve->l_path && cp[0] == '/') {
-               cp[0]= '\0';
-               cp--;
-       }
-
-       /* Resolve up to and including the last directory of the path. Turn off
-        * PATH_RET_SYMLINK, because we do want to follow the symlink in this
-        * case. That is, the flag is meant for the actual filename of the path,
-        * not the last directory.
-        */
-       resolve->l_flags &= ~PATH_RET_SYMLINK;
-       if ((res_vp = advance(start_dir, resolve, rfp)) == NULL) {
-               break;
-       }
-
-       /* If the directory entry is not a symlink we're done now. If it is a
-        * symlink, then we're not at the last directory, yet. */
-
-       /* Copy the directory entry back to user_fullpath */
-       strncpy(resolve->l_path, dir_entry, NAME_MAX + 1);
-
-       /* Look up the directory entry, but do not follow the symlink when it
-        * is one.
-        */
-       lookup_init(&symlink, resolve->l_path,
-                   resolve->l_flags|PATH_RET_SYMLINK, &sym_vmp, &sym_vp);
-       symlink.l_vnode_lock = VNODE_READ;
-       symlink.l_vmnt_lock = VMNT_READ;
-       sym_vp = advance(res_vp, &symlink, rfp);
-
-       /* Advance caused us to either switch to a different vmnt or we're
-        * still at the same vmnt. The former might've yielded a new vmnt lock,
-        * the latter should not have. Verify. */
-       if (sym_vmp != NULL) {
-               /* We got a vmnt lock, so the endpoints of the vnodes must
-                * differ.
-                */
-               assert(sym_vp->v_fs_e != res_vp->v_fs_e);
-       }
-
-       if (sym_vp != NULL && S_ISLNK(sym_vp->v_mode)) {
-               /* Last component is a symlink, but if we've been asked to not
-                * resolve it, return now.
-                */
-               if (ret_on_symlink) {
-                       break;
-               }
-
-               r = req_rdlink(sym_vp->v_fs_e, sym_vp->v_inode_nr, NONE,
-                               resolve->l_path, PATH_MAX - 1, 1);
-
-               if (r < 0) {
-                       /* Failed to read link */
-                       err_code = r;
-                       unlock_vnode(res_vp);
-                       unlock_vmnt(*resolve->l_vmp);
-                       put_vnode(res_vp);
-                       *resolve->l_vmp = NULL;
-                       *resolve->l_vnode = NULL;
-                       res_vp = NULL;
-                       break;
-               }
-               resolve->l_path[r] = '\0';
-
-               if (strrchr(resolve->l_path, '/') != NULL) {
-                       unlock_vnode(sym_vp);
-                       unlock_vmnt(*resolve->l_vmp);
-                       if (sym_vmp != NULL)
-                               unlock_vmnt(sym_vmp);
-                       *resolve->l_vmp = NULL;
-                       put_vnode(sym_vp);
-                       sym_vp = NULL;
-
-                       symloop++;
-
-                       /* Relative symlinks are relative to res_vp, not cwd */
-                       if (resolve->l_path[0] != '/') {
-                               loop_start = res_vp;
-                       } else {
-                               /* Absolute symlink, forget about res_vp */
-                               unlock_vnode(res_vp);
-                               put_vnode(res_vp);
-                       }
-
-                       continue;
-               }
-       }
-       break;
-  } while (symloop < SYMLOOP_MAX);
-
-  if (symloop >= SYMLOOP_MAX) {
-       err_code = ELOOP;
-       res_vp = NULL;
-  }
-
-  if (sym_vp != NULL) {
-       unlock_vnode(sym_vp);
-       if (sym_vmp != NULL) {
-               unlock_vmnt(sym_vmp);
-       }
-       put_vnode(sym_vp);
-  }
-
-  if (loop_start != NULL) {
-       unlock_vnode(loop_start);
-       put_vnode(loop_start);
-  }
-
-  /* Copy the directory entry back to user_fullpath */
-  strncpy(resolve->l_path, dir_entry, NAME_MAX + 1);
-  return(res_vp);
-}
-
-/*===========================================================================*
- *                             lookup                                       *
- *===========================================================================*/
-PRIVATE int lookup(start_node, resolve, result_node, rfp)
-struct vnode *start_node;
-struct lookup *resolve;
-node_details_t *result_node;
-struct fproc *rfp;
-{
-/* Resolve a path name relative to start_node. */
-
-  int r, symloop;
-  endpoint_t fs_e;
-  size_t path_off, path_left_len;
-  ino_t dir_ino, root_ino;
-  uid_t uid;
-  gid_t gid;
-  struct vnode *dir_vp;
-  struct vmnt *vmp, *vmpres;
-  struct lookup_res res;
-
-  assert(resolve->l_vmp);
-  assert(resolve->l_vnode);
-
-  *(resolve->l_vmp) = vmpres = NULL; /* No vmnt found nor locked yet */
-
-  /* Empty (start) path? */
-  if (resolve->l_path[0] == '\0') {
-       result_node->inode_nr = 0;
-       return(ENOENT);
-  }
-
-  if (!rfp->fp_rd || !rfp->fp_wd) {
-       printf("VFS: lookup %d: no rd/wd\n", rfp->fp_endpoint);
-       return(ENOENT);
-  }
-
-  fs_e = start_node->v_fs_e;
-  dir_ino = start_node->v_inode_nr;
-  vmpres = find_vmnt(fs_e);
-
-  if (vmpres == NULL) return(EIO);     /* mountpoint vanished? */
-
-  /* Is the process' root directory on the same partition?,
-   * if so, set the chroot directory too. */
-  if (rfp->fp_rd->v_dev == rfp->fp_wd->v_dev)
-       root_ino = rfp->fp_rd->v_inode_nr;
-  else
-       root_ino = 0;
-
-  /* Set user and group ids according to the system call */
-  uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid);
-  gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid);
-
-  symloop = 0; /* Number of symlinks seen so far */
-
-  /* Lock vmnt */
-  if ((r = lock_vmnt(vmpres, resolve->l_vmnt_lock)) != OK) {
-       if (r == EBUSY) /* vmnt already locked */
-               vmpres = NULL;
-       else
-               return(r);
-  }
-  *(resolve->l_vmp) = vmpres;
-
-  /* Issue the request */
-  r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, resolve, &res, rfp);
-
-  if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK) {
-       if (vmpres) unlock_vmnt(vmpres);
-       *(resolve->l_vmp) = NULL;
-       return(r); /* i.e., an error occured */
-  }
-
-  /* While the response is related to mount control set the
-   * new requests respectively */
-  while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
-       /* Update user_fullpath to reflect what's left to be parsed. */
-       path_off = res.char_processed;
-       path_left_len = strlen(&resolve->l_path[path_off]);
-       memmove(resolve->l_path, &resolve->l_path[path_off], path_left_len);
-       resolve->l_path[path_left_len] = '\0'; /* terminate string */
-
-       /* Update the current value of the symloop counter */
-       symloop += res.symloop;
-       if (symloop > SYMLOOP_MAX) {
-               if (vmpres) unlock_vmnt(vmpres);
-               *(resolve->l_vmp) = NULL;
-               return(ELOOP);
-       }
-
-       /* Symlink encountered with absolute path */
-       if (r == ESYMLINK) {
-               dir_vp = rfp->fp_rd;
-               vmp = NULL;
-       } else if (r == EENTERMOUNT) {
-               /* Entering a new partition */
-               dir_vp = NULL;
-               /* Start node is now the mounted partition's root node */
-               for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
-                       if (vmp->m_dev != NO_DEV && vmp->m_mounted_on) {
-                          if (vmp->m_mounted_on->v_inode_nr == res.inode_nr &&
-                              vmp->m_mounted_on->v_fs_e == res.fs_e) {
-                               dir_vp = vmp->m_root_node;
-                               break;
-                          }
-                       }
-               }
-               if (dir_vp == NULL) {
-                       printf("VFS: path lookup error; root node not found\n");
-                       if (vmpres) unlock_vmnt(vmpres);
-                       *(resolve->l_vmp) = NULL;
-                       return(EIO);
-               }
-       } else {
-               /* Climbing up mount */
-               /* Find the vmnt that represents the partition on
-                * which we "climb up". */
-               if ((vmp = find_vmnt(res.fs_e)) == NULL) {
-                       panic("VFS lookup: can't find parent vmnt");
-               }
-
-               /* Make sure that the child FS does not feed a bogus path
-                * to the parent FS. That is, when we climb up the tree, we
-                * must've encountered ".." in the path, and that is exactly
-                * what we're going to feed to the parent */
-               if(strncmp(resolve->l_path, "..", 2) != 0 ||
-                  (resolve->l_path[2] != '\0' && resolve->l_path[2] != '/')) {
-                       printf("VFS: bogus path: %s\n", resolve->l_path);
-                       if (vmpres) unlock_vmnt(vmpres);
-                       *(resolve->l_vmp) = NULL;
-                       return(ENOENT);
-               }
-
-               /* Start node is the vnode on which the partition is
-                * mounted */
-               dir_vp = vmp->m_mounted_on;
-       }
-
-       /* Set the starting directories inode number and FS endpoint */
-       fs_e = dir_vp->v_fs_e;
-       dir_ino = dir_vp->v_inode_nr;
-
-       /* Is the process' root directory on the same partition?,
-        * if so, set the chroot directory too. */
-       if (dir_vp->v_dev == rfp->fp_rd->v_dev)
-               root_ino = rfp->fp_rd->v_inode_nr;
-       else
-               root_ino = 0;
-
-       /* Unlock a previously locked vmnt if locked and lock new vmnt */
-       if (vmpres) unlock_vmnt(vmpres);
-       vmpres = find_vmnt(fs_e);
-       if (vmpres == NULL) return(EIO);        /* mount point vanished? */
-       if ((r = lock_vmnt(vmpres, resolve->l_vmnt_lock)) != OK) {
-               if (r == EBUSY)
-                       vmpres = NULL;  /* Already locked */
-               else
-                       return(r);
-       }
-       *(resolve->l_vmp) = vmpres;
-
-       r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, resolve, &res, rfp);
-
-       if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK) {
-               if (vmpres) unlock_vmnt(vmpres);
-               *(resolve->l_vmp) = NULL;
-               return(r);
-       }
-  }
-
-  /* Fill in response fields */
-  result_node->inode_nr = res.inode_nr;
-  result_node->fmode = res.fmode;
-  result_node->fsize = res.fsize;
-  result_node->dev = res.dev;
-  result_node->fs_e = res.fs_e;
-  result_node->uid = res.uid;
-  result_node->gid = res.gid;
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             lookup_init                                  *
- *===========================================================================*/
-PUBLIC void lookup_init(resolve, path, flags, vmp, vp)
-struct lookup *resolve;
-char *path;
-int flags;
-struct vmnt **vmp;
-struct vnode **vp;
-{
-  assert(vmp != NULL);
-  assert(vp != NULL);
-
-  resolve->l_path = path;
-  resolve->l_flags = flags;
-  resolve->l_vmp = vmp;
-  resolve->l_vnode = vp;
-  resolve->l_vmnt_lock = TLL_NONE;
-  resolve->l_vnode_lock = TLL_NONE;
-  *vmp = NULL; /* Initialize lookup result to NULL */
-  *vp = NULL;
-}
-
-/*===========================================================================*
- *                             get_name                                     *
- *===========================================================================*/
-PUBLIC int get_name(dirp, entry, ename)
-struct vnode *dirp;
-struct vnode *entry;
-char ename[NAME_MAX + 1];
-{
-  u64_t pos, new_pos;
-  int r, consumed, totalbytes;
-  char buf[(sizeof(struct dirent) + NAME_MAX) * 8];
-  struct dirent *cur;
-
-  pos = make64(0, 0);
-
-  if ((dirp->v_mode & I_TYPE) != I_DIRECTORY) {
-       return(EBADF);
-  }
-
-  do {
-       r = req_getdents(dirp->v_fs_e, dirp->v_inode_nr, pos, buf, sizeof(buf),
-                        &new_pos, 1);
-
-       if (r == 0) {
-               return(ENOENT); /* end of entries -- matching inode !found */
-       } else if (r < 0) {
-               return(r); /* error */
-       }
-
-       consumed = 0; /* bytes consumed */
-       totalbytes = r; /* number of bytes to consume */
-
-       do {
-               cur = (struct dirent *) (buf + consumed);
-               if (entry->v_inode_nr == cur->d_ino) {
-                       /* found the entry we were looking for */
-                       strncpy(ename, cur->d_name, NAME_MAX);
-                       ename[NAME_MAX] = '\0';
-                       return(OK);
-               }
-
-               /* not a match -- move on to the next dirent */
-               consumed += cur->d_reclen;
-       } while (consumed < totalbytes);
-
-       pos = new_pos;
-  } while (1);
-}
-
-/*===========================================================================*
- *                             canonical_path                               *
- *===========================================================================*/
-PUBLIC int canonical_path(orig_path, rfp)
-char orig_path[PATH_MAX];
-struct fproc *rfp;
-{
-/* Find canonical path of a given path */
-  int len = 0;
-  int r, symloop = 0;
-  struct vnode *dir_vp, *parent_dir;
-  struct vmnt *dir_vmp, *parent_vmp;
-  char component[NAME_MAX+1];  /* NAME_MAX does /not/ include '\0' */
-  char temp_path[PATH_MAX];
-  struct lookup resolve;
-
-  dir_vp = NULL;
-  strncpy(temp_path, orig_path, PATH_MAX);
-  temp_path[PATH_MAX - 1] = '\0';
-
-  /* First resolve path to the last directory holding the file */
-  do {
-       if (dir_vp) {
-               unlock_vnode(dir_vp);
-               unlock_vmnt(dir_vmp);
-               put_vnode(dir_vp);
-       }
-
-       lookup_init(&resolve, temp_path, PATH_NOFLAGS, &dir_vmp, &dir_vp);
-       resolve.l_vmnt_lock = VMNT_READ;
-       resolve.l_vnode_lock = VNODE_READ;
-       if ((dir_vp = last_dir(&resolve, rfp)) == NULL) return(err_code);
-
-       /* dir_vp points to dir and resolve path now contains only the
-        * filename.
-        */
-       strncpy(orig_path, temp_path, NAME_MAX);        /* Store file name */
-
-       /* check if the file is a symlink, if so resolve it */
-       r = rdlink_direct(orig_path, temp_path, rfp);
-
-       if (r <= 0)
-               break;
-
-       /* encountered a symlink -- loop again */
-       strncpy(orig_path, temp_path, PATH_MAX - 1);
-       symloop++;
-  } while (symloop < SYMLOOP_MAX);
-
-  if (symloop >= SYMLOOP_MAX) {
-       if (dir_vp) {
-               unlock_vnode(dir_vp);
-               unlock_vmnt(dir_vmp);
-               put_vnode(dir_vp);
-       }
-       return(ELOOP);
-  }
-
-  /* We've got the filename and the actual directory holding the file. From
-   * here we start building up the canonical path by climbing up the tree */
-  while (dir_vp != rfp->fp_rd) {
-
-       strcpy(temp_path, "..");
-
-       /* check if we're at the root node of the file system */
-       if (dir_vp->v_vmnt->m_root_node == dir_vp) {
-               unlock_vnode(dir_vp);
-               unlock_vmnt(dir_vmp);
-               put_vnode(dir_vp);
-               dir_vp = dir_vp->v_vmnt->m_mounted_on;
-               dir_vmp = dir_vp->v_vmnt;
-               if (lock_vmnt(dir_vmp, VMNT_READ) != OK)
-                       panic("failed to lock vmnt");
-               if (lock_vnode(dir_vp, VNODE_READ) != OK)
-                       panic("failed to lock vnode");
-               dup_vnode(dir_vp);
-       }
-
-       lookup_init(&resolve, temp_path, PATH_NOFLAGS, &parent_vmp,
-                   &parent_dir);
-       resolve.l_vmnt_lock = VMNT_READ;
-       resolve.l_vnode_lock = VNODE_READ;
-
-       if ((parent_dir = advance(dir_vp, &resolve, rfp)) == NULL) {
-               unlock_vnode(dir_vp);
-               unlock_vmnt(dir_vmp);
-               put_vnode(dir_vp);
-               return(err_code);
-       }
-
-       /* now we have to retrieve the name of the parent directory */
-       if (get_name(parent_dir, dir_vp, component) != OK) {
-               unlock_vnode(parent_dir);
-               unlock_vmnt(parent_vmp);
-               unlock_vnode(dir_vp);
-               unlock_vmnt(dir_vmp);
-               put_vnode(parent_dir);
-               put_vnode(dir_vp);
-               return(ENOENT);
-       }
-
-       len += strlen(component) + 1;
-       if (len >= PATH_MAX) {
-               /* adding the component to orig_path would exceed PATH_MAX */
-               unlock_vnode(parent_dir);
-               unlock_vmnt(parent_vmp);
-               unlock_vnode(dir_vp);
-               unlock_vmnt(dir_vmp);
-               put_vnode(parent_dir);
-               put_vnode(dir_vp);
-               return(ENOMEM);
-       }
-
-       /* Store result of component in orig_path. First make space by moving
-        * the contents of orig_path to the right. Move strlen + 1 bytes to
-        * include the terminating '\0'. Move to strlen + 1 bytes to reserve
-        * space for the slash.
-        */
-       memmove(orig_path+strlen(component)+1, orig_path, strlen(orig_path)+1);
-       /* Copy component into canon_path */
-       memmove(orig_path, component, strlen(component));
-       /* Put slash into place */
-       orig_path[strlen(component)] = '/';
-
-       /* Store parent_dir result, and continue the loop once more */
-       unlock_vnode(dir_vp);
-       unlock_vmnt(dir_vmp);
-       put_vnode(dir_vp);
-       dir_vp = parent_dir;
-  }
-
-  unlock_vnode(dir_vp);
-  unlock_vmnt(parent_vmp);
-
-  put_vnode(dir_vp);
-
-  /* add the leading slash */
-  if (strlen(orig_path) >= PATH_MAX) return(ENAMETOOLONG);
-  memmove(orig_path+1, orig_path, strlen(orig_path));
-  orig_path[0] = '/';
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                             check_perms                                  *
- *===========================================================================*/
-PRIVATE int check_perms(ep, io_gr, pathlen)
-endpoint_t ep;
-cp_grant_id_t io_gr;
-size_t pathlen;
-{
-  int r, slot;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  struct fproc *rfp;
-  char canon_path[PATH_MAX];
-  struct lookup resolve;
-
-  if (isokendpt(ep, &slot) != OK) return(EINVAL);
-  if (pathlen < UNIX_PATH_MAX || pathlen >= PATH_MAX) return(EINVAL);
-
-  rfp = &(fproc[slot]);
-  r = sys_safecopyfrom(PFS_PROC_NR, io_gr, (vir_bytes) 0,
-                               (vir_bytes) canon_path, pathlen, D);
-  if (r != OK) return(r);
-  canon_path[pathlen] = '\0';
-
-  /* Turn path into canonical path to the socket file */
-  if ((r = canonical_path(canon_path, rfp)) != OK)
-       return(r);
-
-  if (strlen(canon_path) >= pathlen) return(ENAMETOOLONG);
-
-  /* copy canon_path back to PFS */
-  r = sys_safecopyto(PFS_PROC_NR, (cp_grant_id_t) io_gr, (vir_bytes) 0,
-                               (vir_bytes) canon_path, pathlen, D);
-  if (r != OK) return(r);
-
-  /* Now do permissions checking */
-  lookup_init(&resolve, canon_path, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-  if ((vp = eat_path(&resolve, rfp)) == NULL) return(err_code);
-
-  /* check permissions */
-  r = forbidden(rfp, vp, (R_BIT | W_BIT));
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-
-  put_vnode(vp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_check_perms                               *
- *===========================================================================*/
-PUBLIC int do_check_perms(void)
-{
-  return check_perms(m_in.USER_ENDPT, (cp_grant_id_t) m_in.IO_GRANT,
-                    (size_t) m_in.COUNT);
-}
diff --git a/servers/avfs/pipe.c b/servers/avfs/pipe.c
deleted file mode 100644 (file)
index 0a6d6f4..0000000
+++ /dev/null
@@ -1,645 +0,0 @@
-/* This file deals with the suspension and revival of processes.  A process can
- * be suspended because it wants to read or write from a pipe and can't, or
- * because it wants to read or write from a special file and can't.  When a
- * process can't continue it is suspended, and revived later when it is able
- * to continue.
- *
- * The entry points into this file are
- *   do_pipe:    perform the PIPE system call
- *   pipe_check:  check to see that a read or write on a pipe is feasible now
- *   suspend:    suspend a process that cannot do a requested read or write
- *   release:    check to see if a suspended process can be released and do
- *                it
- *   revive:     mark a suspended process as able to run again
- *   unsuspend_by_endpt: revive all processes blocking on a given process
- *   do_unpause:  a signal has been sent to a process; see if it suspended
- */
-
-#include "fs.h"
-#include <fcntl.h>
-#include <signal.h>
-#include <assert.h>
-#include <minix/callnr.h>
-#include <minix/endpoint.h>
-#include <minix/com.h>
-#include <minix/u64.h>
-#include <sys/select.h>
-#include <sys/time.h>
-#include "file.h"
-#include "fproc.h"
-#include "scratchpad.h"
-#include "dmap.h"
-#include "param.h"
-#include "select.h"
-#include <minix/vfsif.h>
-#include "vnode.h"
-#include "vmnt.h"
-
-
-/*===========================================================================*
- *                             do_pipe                                      *
- *===========================================================================*/
-PUBLIC int do_pipe()
-{
-/* Perform the pipe(fil_des) system call. */
-
-  register struct fproc *rfp;
-  int r;
-  struct filp *fil_ptr0, *fil_ptr1;
-  int fil_des[2];              /* reply goes here */
-  struct vnode *vp;
-  struct vmnt *vmp;
-  struct node_details res;
-
-  /* Get a lock on PFS */
-  if ((vmp = find_vmnt(PFS_PROC_NR)) == NULL) panic("PFS gone");
-  if ((r = lock_vmnt(vmp, VMNT_WRITE)) != OK) return(r);
-
-  /* See if a free vnode is available */
-  if ((vp = get_free_vnode()) == NULL) return(err_code);
-  lock_vnode(vp, VNODE_OPCL);
-
-  /* Acquire two file descriptors. */
-  rfp = fp;
-  if ((r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) {
-       unlock_vnode(vp);
-       unlock_vmnt(vmp);
-       return(r);
-  }
-  rfp->fp_filp[fil_des[0]] = fil_ptr0;
-  FD_SET(fil_des[0], &rfp->fp_filp_inuse);
-  fil_ptr0->filp_count = 1;            /* mark filp in use */
-  if ((r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
-       rfp->fp_filp[fil_des[0]] = NULL;
-       FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
-       fil_ptr0->filp_count = 0;       /* mark filp free */
-       unlock_filp(fil_ptr0);
-       unlock_vnode(vp);
-       unlock_vmnt(vmp);
-       return(r);
-  }
-  rfp->fp_filp[fil_des[1]] = fil_ptr1;
-  FD_SET(fil_des[1], &rfp->fp_filp_inuse);
-  fil_ptr1->filp_count = 1;
-
-  /* Create a named pipe inode on PipeFS */
-  r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE,
-                 NO_DEV, &res);
-
-  if (r != OK) {
-       rfp->fp_filp[fil_des[0]] = NULL;
-       FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
-       fil_ptr0->filp_count = 0;
-       rfp->fp_filp[fil_des[1]] = NULL;
-       FD_CLR(fil_des[1], &rfp->fp_filp_inuse);
-       fil_ptr1->filp_count = 0;
-       unlock_filp(fil_ptr1);
-       unlock_filp(fil_ptr0);
-       unlock_vnode(vp);
-       unlock_vmnt(vmp);
-       return(r);
-  }
-
-  /* Fill in vnode */
-  vp->v_fs_e = res.fs_e;
-  vp->v_mapfs_e = res.fs_e;
-  vp->v_inode_nr = res.inode_nr;
-  vp->v_mapinode_nr = res.inode_nr;
-  vp->v_mode = res.fmode;
-  vp->v_pipe = I_PIPE;
-  vp->v_pipe_rd_pos= 0;
-  vp->v_pipe_wr_pos= 0;
-  vp->v_fs_count = 1;
-  vp->v_mapfs_count = 1;
-  vp->v_ref_count = 1;
-  vp->v_size = 0;
-  vp->v_vmnt = NULL;
-  vp->v_dev = NO_DEV;
-
-  /* Fill in filp objects */
-  fil_ptr0->filp_vno = vp;
-  dup_vnode(vp);
-  fil_ptr1->filp_vno = vp;
-  fil_ptr0->filp_flags = O_RDONLY;
-  fil_ptr1->filp_flags = O_WRONLY;
-
-  m_out.reply_i1 = fil_des[0];
-  m_out.reply_i2 = fil_des[1];
-
-  unlock_filps(fil_ptr0, fil_ptr1);
-  unlock_vmnt(vmp);
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             map_vnode                                    *
- *===========================================================================*/
-PUBLIC int map_vnode(vp, map_to_fs_e)
-struct vnode *vp;
-endpoint_t map_to_fs_e;
-{
-  int r;
-  struct vmnt *vmp;
-  struct node_details res;
-
-  if(vp->v_mapfs_e != NONE) return(OK);        /* Already mapped; nothing to do. */
-
-  if ((vmp = find_vmnt(map_to_fs_e)) == NULL)
-       panic("Can't map to unknown endpoint");
-  if ((r = lock_vmnt(vmp, VMNT_WRITE)) != OK) {
-       if (r == EBUSY)
-               vmp = NULL;     /* Already locked, do not unlock */
-       else
-               return(r);
-
-  }
-
-  /* Create a temporary mapping of this inode to another FS. Read and write
-   * operations on data will be handled by that FS. The rest by the 'original'
-   * FS that holds the inode. */
-  if ((r = req_newnode(map_to_fs_e, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE,
-                      vp->v_dev, &res)) == OK) {
-       vp->v_mapfs_e = res.fs_e;
-       vp->v_mapinode_nr = res.inode_nr;
-       vp->v_mapfs_count = 1;
-  }
-
-  if (vmp) unlock_vmnt(vmp);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             pipe_check                                   *
- *===========================================================================*/
-PUBLIC int pipe_check(vp, rw_flag, oflags, bytes, position, notouch)
-register struct vnode *vp;     /* the inode of the pipe */
-int rw_flag;                   /* READING or WRITING */
-int oflags;                    /* flags set by open or fcntl */
-register int bytes;            /* bytes to be read or written (all chunks) */
-u64_t position;                        /* current file position */
-int notouch;                   /* check only */
-{
-/* Pipes are a little different.  If a process reads from an empty pipe for
- * which a writer still exists, suspend the reader.  If the pipe is empty
- * and there is no writer, return 0 bytes.  If a process is writing to a
- * pipe and no one is reading from it, give a broken pipe error.
- */
-  off_t pos;
-  int r = OK;
-
-  if (ex64hi(position) != 0)
-       panic("pipe_check: position too large in pipe");
-  pos = ex64lo(position);
-
-  /* If reading, check for empty pipe. */
-  if (rw_flag == READING) {
-       if (pos >= vp->v_size) {
-               /* Process is reading from an empty pipe. */
-               if (find_filp(vp, W_BIT) != NULL) {
-                       /* Writer exists */
-                       if (oflags & O_NONBLOCK)
-                               r = EAGAIN;
-                       else
-                               r = SUSPEND;
-
-                       /* If need be, activate sleeping writers. */
-                       if (susp_count > 0)
-                               release(vp, WRITE, susp_count);
-               }
-               return(r);
-       }
-       return(bytes);
-  }
-
-  /* Process is writing to a pipe. */
-  if (find_filp(vp, R_BIT) == NULL) {
-       /* Process is writing, but there is no reader. Tell kernel to generate
-        * a SIGPIPE signal. */
-       if (!notouch) sys_kill(fp->fp_endpoint, SIGPIPE);
-
-       return(EPIPE);
-  }
-
-  /* Calculate how many bytes can be written. */
-  if (pos + bytes > PIPE_BUF) {
-       if (oflags & O_NONBLOCK) {
-               if (bytes <= PIPE_BUF) {
-                       /* Write has to be atomic */
-                       return(EAGAIN);
-               }
-
-               /* Compute available space */
-               bytes = PIPE_BUF - pos;
-
-               if (bytes > 0)  {
-                       /* Do a partial write. Need to wakeup reader */
-                       if (!notouch)
-                               release(vp, READ, susp_count);
-                       return(bytes);
-               } else {
-                       /* Pipe is full */
-                       return(EAGAIN);
-               }
-       }
-
-       if (bytes > PIPE_BUF) {
-               /* Compute available space */
-               bytes = PIPE_BUF - pos;
-
-               if (bytes > 0) {
-                       /* Do a partial write. Need to wakeup reader
-                        * since we'll suspend ourself in read_write()
-                        */
-                       if (!notouch)
-                               release(vp, READ, susp_count);
-                       return(bytes);
-               }
-       }
-
-       /* Pipe is full */
-       return(SUSPEND);
-  }
-
-  /* Writing to an empty pipe.  Search for suspended reader. */
-  if (pos == 0 && !notouch)
-       release(vp, READ, susp_count);
-
-  /* Requested amount fits */
-  return(bytes);
-}
-
-
-/*===========================================================================*
- *                             suspend                                      *
- *===========================================================================*/
-PUBLIC void suspend(int why)
-{
-/* Take measures to suspend the processing of the present system call.
- * Store the parameters to be used upon resuming in the process table.
- * (Actually they are not used when a process is waiting for an I/O device,
- * but they are needed for pipes, and it is not worth making the distinction.)
- * The SUSPEND pseudo error should be returned after calling suspend().
- */
-
-#if DO_SANITYCHECKS
-  if(fp_is_blocked(fp))
-       panic("suspend: called for suspended process");
-
-  if(why == FP_BLOCKED_ON_NONE)
-       panic("suspend: called for FP_BLOCKED_ON_NONE");
-#endif
-
-  if (why == FP_BLOCKED_ON_POPEN || why == FP_BLOCKED_ON_PIPE)
-       /* #procs susp'ed on pipe*/
-       susp_count++;
-
-  fp->fp_blocked_on = why;
-  assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant));
-  fp->fp_block_callnr = call_nr;
-  fp->fp_flags &= ~FP_SUSP_REOPEN;             /* Clear this flag. The caller
-                                                * can set it when needed.
-                                                */
-}
-
-/*===========================================================================*
- *                             wait_for                                     *
- *===========================================================================*/
-PUBLIC void wait_for(endpoint_t who)
-{
-  if(who == NONE || who == ANY)
-       panic("suspend on NONE or ANY");
-  suspend(FP_BLOCKED_ON_OTHER);
-  fp->fp_task = who;
-}
-
-
-/*===========================================================================*
- *                             pipe_suspend                                         *
- *===========================================================================*/
-PUBLIC void pipe_suspend(filp, buf, size)
-struct filp *filp;
-char *buf;
-size_t size;
-{
-/* Take measures to suspend the processing of the present system call.
- * Store the parameters to be used upon resuming in the process table.
- */
-#if DO_SANITYCHECKS
-  if(fp_is_blocked(fp))
-       panic("pipe_suspend: called for suspended process");
-#endif
-
-  scratch(fp).file.filp = filp;
-  scratch(fp).io.io_buffer = buf;
-  scratch(fp).io.io_nbytes = size;
-  suspend(FP_BLOCKED_ON_PIPE);
-}
-
-
-/*===========================================================================*
- *                             unsuspend_by_endpt                           *
- *===========================================================================*/
-PUBLIC void unsuspend_by_endpt(endpoint_t proc_e)
-{
-/* Revive processes waiting for drivers (SUSPENDed) that have disappeared with
- * return code EAGAIN.
- */
-  struct fproc *rp;
-
-  for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) {
-       if (rp->fp_pid == PID_FREE) continue;
-       if (rp->fp_blocked_on == FP_BLOCKED_ON_OTHER && rp->fp_task == proc_e)
-               revive(rp->fp_endpoint, EAGAIN);
-  }
-
-  /* Revive processes waiting in drivers on select()s with EAGAIN too */
-  select_unsuspend_by_endpt(proc_e);
-
-  return;
-}
-
-
-/*===========================================================================*
- *                             release                                      *
- *===========================================================================*/
-PUBLIC void release(vp, op, count)
-register struct vnode *vp;     /* inode of pipe */
-int op;                                /* READ, WRITE, OPEN or CREAT */
-int count;                     /* max number of processes to release */
-{
-/* Check to see if any process is hanging on vnode 'vp'. If one is, and it
- * was trying to perform the call indicated by 'call_nr', release it.
- */
-
-  register struct fproc *rp;
-  struct filp *f;
-  int selop;
-
-  /* Trying to perform the call also includes SELECTing on it with that
-   * operation.
-   */
-  if (op == READ || op == WRITE) {
-       if (op == READ)
-               selop = SEL_RD;
-       else
-               selop = SEL_WR;
-
-       for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-               if (f->filp_count < 1 || !(f->filp_pipe_select_ops & selop) ||
-                   f->filp_vno != vp)
-                       continue;
-               select_callback(f, selop);
-               f->filp_pipe_select_ops &= ~selop;
-       }
-  }
-
-  /* Search the proc table. */
-  for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) {
-       if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) &&
-           !(rp->fp_flags & FP_REVIVED) && rp->fp_block_callnr == op) {
-               /* Find the vnode. Depending on the reason the process was
-                * suspended, there are different ways of finding it.
-                */
-
-               if (rp->fp_blocked_on == FP_BLOCKED_ON_POPEN ||
-                   rp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
-                   rp->fp_blocked_on == FP_BLOCKED_ON_LOCK ||
-                   rp->fp_blocked_on == FP_BLOCKED_ON_OTHER) {
-                       if (!FD_ISSET(scratch(rp).file.fd_nr,
-                                                       &rp->fp_filp_inuse))
-                               continue;
-                       if (rp->fp_filp[scratch(rp).file.fd_nr]->filp_vno != vp)
-                               continue;
-               } else if (rp->fp_blocked_on == FP_BLOCKED_ON_PIPE) {
-                       if (scratch(rp).file.filp == NULL)
-                               continue;
-                       if (scratch(rp).file.filp->filp_vno != vp)
-                               continue;
-               } else
-                       continue;
-
-               /* We found the vnode. Revive process. */
-               revive(rp->fp_endpoint, 0);
-               susp_count--;   /* keep track of who is suspended */
-               if(susp_count < 0)
-                       panic("susp_count now negative: %d", susp_count);
-               if (--count == 0) return;
-       }
-  }
-}
-
-
-/*===========================================================================*
- *                             revive                                       *
- *===========================================================================*/
-PUBLIC void revive(proc_nr_e, returned)
-int proc_nr_e;                 /* process to revive */
-int returned;                  /* if hanging on task, how many bytes read */
-{
-/* Revive a previously blocked process. When a process hangs on tty, this
- * is the way it is eventually released.
- */
-  register struct fproc *rfp;
-  int blocked_on;
-  int fd_nr, slot;
-  struct filp *fil_ptr;
-
-  if (proc_nr_e == NONE || isokendpt(proc_nr_e, &slot) != OK) return;
-
-  rfp = &fproc[slot];
-  if (!fp_is_blocked(rfp) || (rfp->fp_flags & FP_REVIVED)) return;
-
-  /* The 'reviving' flag only applies to pipes.  Processes waiting for TTY get
-   * a message right away.  The revival process is different for TTY and pipes.
-   * For select and TTY revival, the work is already done, for pipes it is not:
-   * the proc must be restarted so it can try again.
-   */
-  blocked_on = rfp->fp_blocked_on;
-  fd_nr = scratch(rfp).file.fd_nr;
-  if (blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_LOCK) {
-       /* Revive a process suspended on a pipe or lock. */
-       rfp->fp_flags |= FP_REVIVED;
-       reviving++;             /* process was waiting on pipe or lock */
-  } else if (blocked_on == FP_BLOCKED_ON_DOPEN) {
-       rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-       scratch(rfp).file.fd_nr = 0;
-       if (returned < 0) {
-               fil_ptr = rfp->fp_filp[fd_nr];
-               lock_filp(fil_ptr, VNODE_OPCL);
-               rfp->fp_filp[fd_nr] = NULL;
-               FD_CLR(fd_nr, &rfp->fp_filp_inuse);
-               if (fil_ptr->filp_count != 1) {
-                       panic("VFS: revive: bad count in filp: %d",
-                               fil_ptr->filp_count);
-               }
-               fil_ptr->filp_count = 0;
-               unlock_filp(fil_ptr);
-               put_vnode(fil_ptr->filp_vno);
-               fil_ptr->filp_vno = NULL;
-               reply(proc_nr_e, returned);
-       } else {
-               reply(proc_nr_e, fd_nr);
-       }
-  } else {
-       rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-       scratch(rfp).file.fd_nr = 0;
-       if (blocked_on == FP_BLOCKED_ON_POPEN) {
-               /* process blocked in open or create */
-               reply(proc_nr_e, fd_nr);
-       } else if (blocked_on == FP_BLOCKED_ON_SELECT) {
-               reply(proc_nr_e, returned);
-       } else {
-               /* Revive a process suspended on TTY or other device.
-                * Pretend it wants only what there is.
-                */
-               scratch(rfp).io.io_nbytes = returned;
-               /* If a grant has been issued by FS for this I/O, revoke
-                * it again now that I/O is done.
-                */
-               if (GRANT_VALID(rfp->fp_grant)) {
-                       if(cpf_revoke(rfp->fp_grant)) {
-                               panic("VFS: revoke failed for grant: %d",
-                                       rfp->fp_grant);
-                       }
-                       rfp->fp_grant = GRANT_INVALID;
-               }
-               reply(proc_nr_e, returned);     /* unblock the process */
-       }
-  }
-}
-
-
-/*===========================================================================*
- *                             unpause                                      *
- *===========================================================================*/
-PUBLIC void unpause(endpoint_t proc_e)
-{
-/* A signal has been sent to a user who is paused on the file system.
- * Abort the system call with the EINTR error message.
- */
-
-  register struct fproc *rfp, *org_fp;
-  int slot, blocked_on, fild, status = EINTR, major_dev, minor_dev;
-  struct filp *f;
-  dev_t dev;
-  message mess;
-  int wasreviving = 0;
-
-  if (isokendpt(proc_e, &slot) != OK) {
-       printf("VFS: ignoring unpause for bogus endpoint %d\n", proc_e);
-       return;
-  }
-
-  rfp = &fproc[slot];
-  if (!fp_is_blocked(rfp)) return;
-  blocked_on = rfp->fp_blocked_on;
-
-  if (rfp->fp_flags & FP_REVIVED) {
-       rfp->fp_flags &= ~FP_REVIVED;
-       reviving--;
-       wasreviving = 1;
-  }
-
-  switch (blocked_on) {
-       case FP_BLOCKED_ON_PIPE:/* process trying to read or write a pipe */
-               break;
-
-       case FP_BLOCKED_ON_LOCK:/* process trying to set a lock with FCNTL */
-               break;
-
-       case FP_BLOCKED_ON_SELECT:/* process blocking on select() */
-               select_forget(proc_e);
-               break;
-
-       case FP_BLOCKED_ON_POPEN:       /* process trying to open a fifo */
-               break;
-
-       case FP_BLOCKED_ON_DOPEN:/* process trying to open a device */
-               /* Don't cancel OPEN. Just wait until the open completes. */
-               return;
-
-       case FP_BLOCKED_ON_OTHER:/* process trying to do device I/O (e.g. tty)*/
-               if (rfp->fp_flags & FP_SUSP_REOPEN) {
-                       /* Process is suspended while waiting for a reopen.
-                        * Just reply EINTR.
-                        */
-                       rfp->fp_flags &= ~FP_SUSP_REOPEN;
-                       status = EINTR;
-                       break;
-               }
-
-               fild = scratch(rfp).file.fd_nr;
-               if (fild < 0 || fild >= OPEN_MAX)
-                       panic("file descriptor out-of-range");
-               f = rfp->fp_filp[fild];
-               dev = (dev_t) f->filp_vno->v_sdev;      /* device hung on */
-               major_dev = major(dev);
-               minor_dev = minor(dev);
-               mess.TTY_LINE = minor_dev;
-               mess.USER_ENDPT = rfp->fp_ioproc;
-               mess.IO_GRANT = (char *) rfp->fp_grant;
-
-               /* Tell kernel R or W. Mode is from current call, not open. */
-               mess.COUNT = rfp->fp_block_callnr == READ ? R_BIT : W_BIT;
-               mess.m_type = CANCEL;
-
-               org_fp = fp;
-               fp = rfp;       /* hack - ctty_io uses fp */
-               (*dmap[major_dev].dmap_io)(rfp->fp_task, &mess);
-               fp = org_fp;
-               status = mess.REP_STATUS;
-               if (status == SUSPEND)
-                       return;         /* Process will be revived at a
-                                        * later time.
-                                        */
-
-               if (status == EAGAIN) status = EINTR;
-               if (GRANT_VALID(rfp->fp_grant)) {
-                       (void) cpf_revoke(rfp->fp_grant);
-                       rfp->fp_grant = GRANT_INVALID;
-               }
-               break;
-       default :
-               panic("VFS: unknown block reason: %d", blocked_on);
-  }
-
-  rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-
-  if ((blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_POPEN)&&
-       !wasreviving) {
-       susp_count--;
-  }
-
-  reply(proc_e, status);       /* signal interrupted call */
-}
-
-#if DO_SANITYCHECKS
-/*===========================================================================*
- *                             check_pipe                           *
- *===========================================================================*/
-PUBLIC int check_pipe(void)
-{
-/* Integrity check; verify that susp_count equals what the fproc table thinks
- * is suspended on a pipe */
-  struct fproc *rfp;
-  int count = 0;
-  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       if (rfp->fp_pid == PID_FREE) continue;
-       if ( !(rfp->fp_flags & FP_REVIVED) &&
-           (rfp->fp_blocked_on == FP_BLOCKED_ON_PIPE ||
-            rfp->fp_blocked_on == FP_BLOCKED_ON_POPEN)) {
-               count++;
-       }
-  }
-
-  if (count != susp_count) {
-       printf("check_pipe: count %d susp_count %d\n", count, susp_count);
-       return(0);
-  }
-
-  return(l);
-}
-#endif
diff --git a/servers/avfs/protect.c b/servers/avfs/protect.c
deleted file mode 100644 (file)
index 04325c6..0000000
+++ /dev/null
@@ -1,276 +0,0 @@
-/* This file deals with protection in the file system.  It contains the code
- * for four system calls that relate to protection.
- *
- * The entry points into this file are
- *   do_chmod: perform the CHMOD and FCHMOD system calls
- *   do_chown: perform the CHOWN and FCHOWN system calls
- *   do_umask: perform the UMASK system call
- *   do_access:        perform the ACCESS system call
- */
-
-#include "fs.h"
-#include <unistd.h>
-#include <minix/callnr.h>
-#include "file.h"
-#include "fproc.h"
-#include "path.h"
-#include "param.h"
-#include <minix/vfsif.h>
-#include "vnode.h"
-#include "vmnt.h"
-
-/*===========================================================================*
- *                             do_chmod                                     *
- *===========================================================================*/
-PUBLIC int do_chmod()
-{
-/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */
-
-  struct filp *flp;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  int r;
-  mode_t new_mode;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  flp = NULL;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_WRITE;
-
-  if (call_nr == CHMOD) {
-       /* Temporarily open the file */
-       if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
-               return(err_code);
-       if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-  } else {     /* call_nr == FCHMOD */
-       /* File is already opened; get a pointer to vnode from filp. */
-       if ((flp = get_filp(m_in.fd, VNODE_WRITE)) == NULL)
-               return(err_code);
-       vp = flp->filp_vno;
-       dup_vnode(vp);
-  }
-
-  /* Only the owner or the super_user may change the mode of a file.
-   * No one may change the mode of a file on a read-only file system.
-   */
-  if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
-       r = EPERM;
-  else
-       r = read_only(vp);
-
-  if (r == OK) {
-       /* Now make the change. Clear setgid bit if file is not in caller's
-        * group */
-       if (fp->fp_effuid != SU_UID && vp->v_gid != fp->fp_effgid)
-               m_in.mode &= ~I_SET_GID_BIT;
-
-       r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode);
-       if (r == OK)
-               vp->v_mode = new_mode;
-  }
-
-  if (call_nr == CHMOD) {
-       unlock_vnode(vp);
-       unlock_vmnt(vmp);
-  } else {     /* FCHMOD */
-       unlock_filp(flp);
-  }
-
-  put_vnode(vp);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             do_chown                                     *
- *===========================================================================*/
-PUBLIC int do_chown()
-{
-/* Perform the chown(path, owner, group) and fchmod(fd, owner, group) system
- * calls. */
-  struct filp *flp;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  int r;
-  uid_t uid;
-  gid_t gid;
-  mode_t new_mode;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  flp = NULL;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_WRITE;
-
-  if (call_nr == CHOWN) {
-       /* Temporarily open the file. */
-       if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-               return(err_code);
-       if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-  } else {     /* call_nr == FCHOWN */
-       /* File is already opened; get a pointer to the vnode from filp. */
-       if ((flp = get_filp(m_in.fd, VNODE_WRITE)) == NULL)
-               return(err_code);
-       vp = flp->filp_vno;
-       dup_vnode(vp);
-  }
-
-  r = read_only(vp);
-  if (r == OK) {
-       /* FS is R/W. Whether call is allowed depends on ownership, etc. */
-       /* The super user can do anything, so check permissions only if we're
-          a regular user. */
-       if (fp->fp_effuid != SU_UID) {
-               /* Regular users can only change groups of their own files. */
-               if (vp->v_uid != fp->fp_effuid) r = EPERM;
-               if (vp->v_uid != m_in.owner) r = EPERM; /* no giving away */
-               if (fp->fp_effgid != m_in.group) r = EPERM;
-       }
-  }
-
-  if (r == OK) {
-       /* Do not change uid/gid if new uid/gid is -1. */
-       uid = (m_in.owner == (uid_t)-1 ? vp->v_uid : m_in.owner);
-       gid = (m_in.group == (gid_t)-1 ? vp->v_gid : m_in.group);
-
-       if (uid > UID_MAX || gid > GID_MAX)
-               r = EINVAL;
-       else if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, uid, gid,
-                               &new_mode)) == OK) {
-               vp->v_uid = uid;
-               vp->v_gid = gid;
-               vp->v_mode = new_mode;
-       }
-  }
-
-  if (call_nr == CHOWN) {
-       unlock_vnode(vp);
-       unlock_vmnt(vmp);
-  } else {     /* FCHOWN */
-       unlock_filp(flp);
-  }
-
-  put_vnode(vp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_umask                                     *
- *===========================================================================*/
-PUBLIC int do_umask()
-{
-/* Perform the umask(co_mode) system call. */
-  register mode_t r;
-
-  r = ~fp->fp_umask;           /* set 'r' to complement of old mask */
-  fp->fp_umask = ~(m_in.co_mode & RWX_MODES);
-  return(r);                   /* return complement of old mask */
-}
-
-
-/*===========================================================================*
- *                             do_access                                    *
- *===========================================================================*/
-PUBLIC int do_access()
-{
-/* Perform the access(name, mode) system call. */
-  int r;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* First check to see if the mode is correct. */
-  if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
-       return(EINVAL);
-
-  /* Temporarily open the file. */
-  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
-       return(err_code);
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-
-  r = forbidden(fp, vp, m_in.mode);
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-
-  put_vnode(vp);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             forbidden                                    *
- *===========================================================================*/
-PUBLIC int forbidden(struct fproc *rfp, struct vnode *vp, mode_t access_desired)
-{
-/* Given a pointer to an vnode, 'vp', and the access desired, determine
- * if the access is allowed, and if not why not.  The routine looks up the
- * caller's uid in the 'fproc' table.  If access is allowed, OK is returned
- * if it is forbidden, EACCES is returned.
- */
-
-  register mode_t bits, perm_bits;
-  uid_t uid;
-  gid_t gid;
-  int r, shift;
-
-  if (vp->v_uid == (uid_t) -1 || vp->v_gid == (gid_t) -1) return(EACCES);
-
-  /* Isolate the relevant rwx bits from the mode. */
-  bits = vp->v_mode;
-  uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid);
-  gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid);
-
-  if (uid == SU_UID) {
-       /* Grant read and write permission.  Grant search permission for
-        * directories.  Grant execute permission (for non-directories) if
-        * and only if one of the 'X' bits is set.
-        */
-       if ( (bits & I_TYPE) == I_DIRECTORY ||
-            bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
-               perm_bits = R_BIT | W_BIT | X_BIT;
-       else
-               perm_bits = R_BIT | W_BIT;
-  } else {
-       if (uid == vp->v_uid) shift = 6;                /* owner */
-       else if (gid == vp->v_gid) shift = 3;           /* group */
-       else if (in_group(fp, vp->v_gid) == OK) shift = 3; /* suppl. groups */
-       else shift = 0;                                 /* other */
-       perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
-  }
-
-  /* If access desired is not a subset of what is allowed, it is refused. */
-  r = OK;
-  if ((perm_bits | access_desired) != perm_bits) r = EACCES;
-
-  /* Check to see if someone is trying to write on a file system that is
-   * mounted read-only.
-   */
-  if (r == OK)
-       if (access_desired & W_BIT)
-               r = read_only(vp);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             read_only                                    *
- *===========================================================================*/
-PUBLIC int read_only(vp)
-struct vnode *vp;              /* ptr to inode whose file sys is to be cked */
-{
-/* Check to see if the file system on which the inode 'ip' resides is mounted
- * read only.  If so, return EROFS, else return OK.
- */
-  return((vp->v_vmnt->m_flags & VMNT_READONLY) ? EROFS : OK);
-}
diff --git a/servers/avfs/proto.h b/servers/avfs/proto.h
deleted file mode 100644 (file)
index 432ef3a..0000000
+++ /dev/null
@@ -1,390 +0,0 @@
-#ifndef __VFS_PROTO_H__
-#define __VFS_PROTO_H__
-
-/* Function prototypes. */
-
-#include "timers.h"
-#include "request.h"
-#include "tll.h"
-#include "threads.h"
-#include <minix/rs.h>
-
-/* Structs used in prototypes must be declared as such first. */
-struct filp;
-struct fproc;
-struct vmnt;
-struct vnode;
-struct lookup;
-struct worker_thread;
-struct job;
-
-typedef struct filp * filp_id_t;
-
-/* comm.c */
-_PROTOTYPE(void fs_cancel, (struct vmnt *vmp)                          );
-_PROTOTYPE(int fs_sendrec, (endpoint_t fs_e, message *reqm)            );
-_PROTOTYPE(void fs_sendmore, (struct vmnt *vmp)                                );
-_PROTOTYPE(void send_work, (void)                                      );
-
-/* device.c */
-_PROTOTYPE( int dev_open, (dev_t dev, endpoint_t proc_e, int flags)    );
-_PROTOTYPE( int dev_reopen, (dev_t dev, int filp_no, int flags)                );
-_PROTOTYPE( int dev_close, (dev_t dev, int filp_no)                    );
-_PROTOTYPE( int bdev_open, (dev_t dev, int access)                     );
-_PROTOTYPE( int bdev_close, (dev_t dev)                                        );
-_PROTOTYPE( int dev_io, (int op, dev_t dev, endpoint_t proc_e, void *buf,
-               u64_t pos, size_t bytes, int flags, int suspend_reopen) );
-_PROTOTYPE( int gen_opcl, (int op, dev_t dev, endpoint_t task_nr, int flags));
-_PROTOTYPE( int gen_io, (endpoint_t driver_e, message *mess_ptr)               );
-_PROTOTYPE( int asyn_io, (int task_nr, message *mess_ptr)              );
-_PROTOTYPE( int no_dev, (int op, dev_t dev, int proc, int flags)       );
-_PROTOTYPE( int no_dev_io, (int, message *)                            );
-_PROTOTYPE( int tty_opcl, (int op, dev_t dev, endpoint_t proc, int flags));
-_PROTOTYPE( int ctty_opcl, (int op, dev_t dev, endpoint_t proc, int flags));
-_PROTOTYPE( int clone_opcl, (int op, dev_t dev, int proc, int flags)   );
-_PROTOTYPE( int ctty_io, (int task_nr, message *mess_ptr)              );
-_PROTOTYPE( int do_ioctl, (void)                                       );
-_PROTOTYPE( void pm_setsid, (int proc_e)                               );
-_PROTOTYPE( void dev_status, (message *)                               );
-_PROTOTYPE( void bdev_up, (int major)                                  );
-_PROTOTYPE( void cdev_up, (int major)                                  );
-_PROTOTYPE( endpoint_t find_suspended_ep, (endpoint_t driver,
-                                          cp_grant_id_t g)             );
-_PROTOTYPE( void reopen_reply, (void)                                  );
-_PROTOTYPE( void open_reply, (void)                                    );
-
-/* dmap.c */
-_PROTOTYPE( int do_mapdriver, (void)                                   );
-_PROTOTYPE( void init_dmap, (void)                                     );
-_PROTOTYPE( int dmap_driver_match, (endpoint_t proc, int major)                );
-_PROTOTYPE( void dmap_endpt_up, (int proc_nr, int is_blk)              );
-_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr)                    );
-_PROTOTYPE( struct dmap *get_dmap, (endpoint_t proc_e)                 );
-_PROTOTYPE( int do_mapdriver, (void)                                   );
-_PROTOTYPE( int map_service, (struct rprocpub *rpub)                   );
-_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr)                    );
-_PROTOTYPE( struct dmap *get_dmap, (endpoint_t proc_e)                 );
-_PROTOTYPE( int map_driver, (const char *label, int major, endpoint_t proc_nr,
-       int dev_style, int flags)                                       );
-_PROTOTYPE( int map_service, (struct rprocpub *rpub)                   );
-
-/* elf_core_dump.c */
-_PROTOTYPE( void write_elf_core_file, (struct filp *f, int csig,
-                                      char *exe_name)                  );
-
-/* exec.c */
-_PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
-                         char *frame, vir_bytes frame_len, vir_bytes *pc));
-#define check_bsf_lock() do {                                          \
-       assert(mutex_trylock(&bsf_lock) == 0);                          \
-       unlock_bsf();                                                   \
-                       } while(0)
-
-/* filedes.c */
-_PROTOTYPE( void check_filp_locks, (void)                              );
-_PROTOTYPE( void check_filp_locks_by_me, (void)                                );
-_PROTOTYPE( void init_filps, (void)                                    );
-_PROTOTYPE( struct filp *find_filp, (struct vnode *vp, mode_t bits)    );
-_PROTOTYPE( int get_fd, (int start, mode_t bits, int *k,
-            struct filp **fpt)                                         );
-_PROTOTYPE( struct filp *get_filp, (int fild, tll_access_t locktype)                           );
-_PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild,
-                                       tll_access_t locktype)          );
-_PROTOTYPE( void lock_filp, (struct filp *filp, tll_access_t locktype) );
-_PROTOTYPE( void unlock_filp, (struct filp *filp)                      );
-_PROTOTYPE( void unlock_filps, (struct filp *filp1, struct filp *filp2)        );
-_PROTOTYPE( int invalidate_filp, (struct filp *)                       );
-_PROTOTYPE( void invalidate_filp_by_endpt, (endpoint_t proc_e)         );
-_PROTOTYPE( int do_verify_fd, (void)                                   );
-_PROTOTYPE( int set_filp, (filp_id_t sfilp)                            );
-_PROTOTYPE( int do_set_filp, (void)                                    );
-_PROTOTYPE( int copy_filp, (endpoint_t to_ep, filp_id_t cfilp)         );
-_PROTOTYPE( int do_copy_filp, (void)                                   );
-_PROTOTYPE( int put_filp, (filp_id_t pfilp)                            );
-_PROTOTYPE( int do_put_filp, (void)                                    );
-_PROTOTYPE( int cancel_fd, (endpoint_t ep, int fd)                     );
-_PROTOTYPE( int do_cancel_fd, (void)                                   );
-_PROTOTYPE( void close_filp, (struct filp *fp)                         );
-
-/* fscall.c */
-_PROTOTYPE( void nested_fs_call, (message *m)                          );
-
-/* link.c */
-_PROTOTYPE( int do_link, (void)                                                );
-_PROTOTYPE( int do_unlink, (void)                                      );
-_PROTOTYPE( int do_rename, (void)                                      );
-_PROTOTYPE( int do_truncate, (void)                                    );
-_PROTOTYPE( int do_ftruncate, (void)                                   );
-_PROTOTYPE( int truncate_vnode, (struct vnode *vp, off_t newsize)      );
-_PROTOTYPE( int rdlink_direct, (char *orig_path, char *link_path,
-                                               struct fproc *rfp)      );
-
-/* lock.c */
-_PROTOTYPE( int lock_op, (struct filp *f, int req)                     );
-_PROTOTYPE( void lock_revive, (void)                                   );
-
-/* main.c */
-_PROTOTYPE( int main, (void)                                           );
-_PROTOTYPE( void reply, (int whom, int result)                         );
-_PROTOTYPE( void lock_proc, (struct fproc *rfp, int force_lock)                );
-_PROTOTYPE( void unlock_proc, (struct fproc *rfp)                      );
-_PROTOTYPE( void *do_dummy, (void *arg)                                        );
-
-/* misc.c */
-_PROTOTYPE( int do_dup, (void)                                         );
-_PROTOTYPE( void pm_exit, (int proc)                                   );
-_PROTOTYPE( int do_fcntl, (void)                                       );
-_PROTOTYPE( void pm_fork, (int pproc, int cproc, int cpid)             );
-_PROTOTYPE( void pm_setgid, (int proc_e, int egid, int rgid)           );
-_PROTOTYPE( void pm_setuid, (int proc_e, int euid, int ruid)           );
-_PROTOTYPE( void pm_setgroups, (int proc_e, int ngroups, gid_t *addr)  );
-_PROTOTYPE( int do_sync, (void)                                                );
-_PROTOTYPE( int do_fsync, (void)                                       );
-_PROTOTYPE( void pm_reboot, (void)                                     );
-_PROTOTYPE( int do_svrctl, (void)                                      );
-_PROTOTYPE( int do_getsysinfo, (void)                                  );
-_PROTOTYPE( int pm_dumpcore, (endpoint_t proc_e, int sig,
-                               vir_bytes exe_name)                     );
-_PROTOTYPE( void ds_event, (void)                                      );
-
-/* mount.c */
-_PROTOTYPE( int do_fsready, (void)                                      );
-_PROTOTYPE( int do_mount, (void)                                       );
-_PROTOTYPE( int do_umount, (void)                                      );
-_PROTOTYPE( int is_nonedev, (dev_t dev)                                        );
-_PROTOTYPE( void mount_pfs, (void)                                     );
-_PROTOTYPE( int mount_fs, (dev_t dev, char fullpath[PATH_MAX+1],
-                                  endpoint_t fs_e, int rdonly,
-                                  char mount_label[LABEL_MAX])         );
-_PROTOTYPE( int unmount, (dev_t dev, char *label)                      );
-_PROTOTYPE( void unmount_all, (void)                                   );
-
-/* open.c */
-_PROTOTYPE( int do_close, (void)                                       );
-_PROTOTYPE( int close_fd, (struct fproc *rfp, int fd_nr)               );
-_PROTOTYPE( void close_reply, (void)                                   );
-_PROTOTYPE( int common_open, (char path[PATH_MAX], int oflags,
-                               mode_t omode)                           );
-_PROTOTYPE( int do_creat, (void)                                       );
-_PROTOTYPE( int do_lseek, (void)                                       );
-_PROTOTYPE( int do_llseek, (void)                                      );
-_PROTOTYPE( int do_mknod, (void)                                       );
-_PROTOTYPE( int do_mkdir, (void)                                       );
-_PROTOTYPE( int do_open, (void)                                                );
-_PROTOTYPE( int do_slink, (void)                                        );
-_PROTOTYPE( int do_vm_open, (void)                                     );
-_PROTOTYPE( int do_vm_close, (void)                                    );
-
-/* path.c */
-_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, struct lookup *resolve,
-                                   struct fproc *rfp)                  );
-_PROTOTYPE( struct vnode *eat_path, (struct lookup *resolve,
-                                    struct fproc *rfp)                 );
-_PROTOTYPE( struct vnode *last_dir, (struct lookup *resolve,
-                                    struct fproc *rfp)                 );
-_PROTOTYPE( void lookup_init, (struct lookup *resolve, char *path, int flags,
-                              struct vmnt **vmp, struct vnode **vp)    );
-_PROTOTYPE( int get_name, (struct vnode *dirp, struct vnode *entry,
-                                                       char *_name)    );
-_PROTOTYPE( int canonical_path, (char *orig_path, struct fproc *rfp)   );
-_PROTOTYPE( int do_check_perms, (void)                                 );
-
-/* pipe.c */
-_PROTOTYPE( int do_pipe, (void)                                                );
-_PROTOTYPE( int map_vnode, (struct vnode *vp, endpoint_t fs_e)         );
-_PROTOTYPE( void unpause, (int proc_nr_e)                              );
-_PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag,
-             int oflags, int bytes, u64_t position, int notouch)       );
-_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count)   );
-_PROTOTYPE( void revive, (int proc_nr, int bytes)                      );
-_PROTOTYPE( void suspend, (int task)                                   );
-_PROTOTYPE( void pipe_suspend, (struct filp *rfilp, char *buf, size_t size));
-_PROTOTYPE( void unsuspend_by_endpt, (endpoint_t)                      );
-_PROTOTYPE( void wait_for, (endpoint_t)                                        );
-#if DO_SANITYCHECKS
-_PROTOTYPE( int check_pipe, (void)                                     );
-#endif
-
-/* protect.c */
-_PROTOTYPE( int do_access, (void)                                      );
-_PROTOTYPE( int do_chmod, (void)                                       );
-_PROTOTYPE( int do_chown, (void)                                       );
-_PROTOTYPE( int do_umask, (void)                                       );
-_PROTOTYPE( int forbidden, (struct fproc *rfp, struct vnode *vp,
-                           mode_t access_desired)                      );
-_PROTOTYPE( int read_only, (struct vnode *vp)                          );
-
-/* read.c */
-_PROTOTYPE( int do_read, (void)                                                );
-_PROTOTYPE( int do_getdents, (void)                                    );
-_PROTOTYPE( void lock_bsf, (void)                                      );
-_PROTOTYPE( void unlock_bsf, (void)                                    );
-_PROTOTYPE( int do_read_write, (int rw_flag)                           );
-_PROTOTYPE( int read_write, (int rw_flag, struct filp *f, char *buffer,
-                            size_t nbytes, endpoint_t for_e)                           );
-_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr, struct filp *f,
-                        char *buf, size_t req_size)    );
-
-/* request.c */
-_PROTOTYPE( int req_breadwrite, (endpoint_t fs_e, endpoint_t user_e,
-                       dev_t dev, u64_t pos, unsigned int num_of_bytes,
-                       char *user_addr, int rw_flag,
-                       u64_t *new_posp, unsigned int *cum_iop)         );
-_PROTOTYPE( int req_chmod, (int fs_e, ino_t inode_nr, mode_t rmode,
-                                               mode_t *new_modep)      );
-_PROTOTYPE( int req_chown, (endpoint_t fs_e, ino_t inode_nr,
-       uid_t newuid, gid_t newgid, mode_t *new_modep)  );
-_PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode,
-               uid_t uid, gid_t gid, char *path, node_details_t *res)  );
-_PROTOTYPE( int req_flush, (endpoint_t fs_e, dev_t dev)                        );
-_PROTOTYPE( int req_fstatfs, (int fs_e, int who_e, char *buf)          );
-_PROTOTYPE( int req_statvfs, (int fs_e, int who_e, char *buf)          );
-_PROTOTYPE( int req_ftrunc, (endpoint_t fs_e, ino_t inode_nr,
-                                               off_t start, off_t end) );
-_PROTOTYPE( int req_getdents, (endpoint_t fs_e, ino_t inode_nr,
-                       u64_t pos, char *buf, size_t size,
-                       u64_t *new_pos, int direct)                     );
-_PROTOTYPE( int req_inhibread, (endpoint_t fs_e, ino_t inode_nr)       );
-_PROTOTYPE( int req_link, (endpoint_t fs_e, ino_t link_parent,
-                                       char *lastc, ino_t linked_file) );
-_PROTOTYPE( int req_lookup, (endpoint_t fs_e, ino_t dir_ino, ino_t root_ino,
-                            uid_t uid, gid_t gid, struct lookup *resolve,
-                            lookup_res_t *res, struct fproc *rfp)      );
-_PROTOTYPE( int req_mkdir, (endpoint_t fs_e, ino_t inode_nr,
-       char *lastc, uid_t uid, gid_t gid, mode_t dmode)                );
-_PROTOTYPE( int req_mknod, (endpoint_t fs_e, ino_t inode_nr,
-                       char *lastc, uid_t uid, gid_t gid,
-                       mode_t dmode, dev_t dev)                        );
-_PROTOTYPE( int req_mountpoint, (endpoint_t fs_e, ino_t inode_nr)      );
-_PROTOTYPE( int req_newnode, (endpoint_t fs_e, uid_t uid,
-                               gid_t gid, mode_t dmode,
-                               dev_t dev, struct node_details *res)    );
-_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count)     );
-_PROTOTYPE( int req_rdlink, (endpoint_t fs_e, ino_t inode_nr,
-                               endpoint_t who_e, char *buf, size_t len,
-                               int direct)                             );
-_PROTOTYPE( int req_readsuper, (endpoint_t fs_e, char *driver_name,
-                               dev_t dev, int readonly, int isroot,
-                               struct node_details *res_nodep,
-                               int *con_reqs)                          );
-_PROTOTYPE( int req_readwrite, (endpoint_t fs_e, ino_t inode_nr,
-                               u64_t pos, int rw_flag,
-                               endpoint_t user_e, char *user_addr,
-                               unsigned int num_of_bytes, u64_t *new_posp,
-                               unsigned int *cum_iop)                  );
-_PROTOTYPE( int req_rename, (endpoint_t fs_e, ino_t old_dir,
-                       char *old_name, ino_t new_dir, char *new_name)  );
-_PROTOTYPE( int req_rmdir, (endpoint_t fs_e, ino_t inode_nr,
-                                                       char *lastc)    );
-_PROTOTYPE(int req_slink, (endpoint_t fs_e, ino_t inode_nr, char *lastc,
-               endpoint_t who_e, char *path_addr,
-               unsigned short path_length, uid_t uid, gid_t gid)       );
-_PROTOTYPE( int req_stat, (int fs_e, ino_t inode_nr, int who_e,
-                               char *buf, int pos, int stat_version)   );
-_PROTOTYPE( int req_sync, (endpoint_t fs_e)                             );
-_PROTOTYPE( int req_unlink, (endpoint_t fs_e, ino_t inode_nr,
-                                                       char *lastc)    );
-_PROTOTYPE( int req_unmount, (endpoint_t fs_e)                          );
-_PROTOTYPE( int req_utime, (endpoint_t fs_e, ino_t inode_nr,
-                                       time_t actime, time_t modtime)  );
-_PROTOTYPE( int req_newdriver, (endpoint_t fs_e, dev_t dev,
-            char *label)                                               );
-
-/* stadir.c */
-_PROTOTYPE( int do_chdir, (void)                                       );
-_PROTOTYPE( int do_fchdir, (void)                                      );
-_PROTOTYPE( int do_chroot, (void)                                      );
-_PROTOTYPE( int do_fstat, (void)                                       );
-_PROTOTYPE( int do_stat, (void)                                                );
-_PROTOTYPE( int do_fstatfs, (void)                                     );
-_PROTOTYPE( int do_statvfs, (void)                                     );
-_PROTOTYPE( int do_fstatvfs, (void)                                    );
-_PROTOTYPE( int do_rdlink, (void)                                      );
-_PROTOTYPE( int do_lstat, (void)                                       );
-
-/* time.c */
-_PROTOTYPE( int do_utime, (void)                                       );
-
-/* tll.c */
-_PROTOTYPE( void tll_downgrade, (tll_t *tllp)                          );
-_PROTOTYPE( int tll_haspendinglock, (tll_t *tllp)                      );
-_PROTOTYPE( void tll_init, (tll_t *tllp)                               );
-_PROTOTYPE( int tll_islocked, (tll_t *tllp)                            );
-_PROTOTYPE( int tll_lock, (tll_t *tllp, tll_access_t locktype)         );
-_PROTOTYPE( int tll_locked_by_me, (tll_t *tllp)                                );
-_PROTOTYPE( void tll_lockstat, (tll_t *tllp)                           );
-_PROTOTYPE( int tll_unlock, (tll_t *tllp)                              );
-_PROTOTYPE( void tll_upgrade, (tll_t *tllp)                            );
-
-/* utility.c */
-_PROTOTYPE( time_t clock_time, (void)                                  );
-_PROTOTYPE( unsigned conv2, (int norm, int w)                          );
-_PROTOTYPE( long conv4, (int norm, long x)                             );
-_PROTOTYPE( int fetch_name, (char *path, int len, int flag, char *dest)                );
-_PROTOTYPE( int no_sys, (void)                                         );
-_PROTOTYPE( int isokendpt_f, (char *f, int l, endpoint_t e, int *p, int ft));
-_PROTOTYPE( int in_group, (struct fproc *rfp, gid_t grp)               );
-
-#define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1)
-#define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0)
-
-/* vmnt.c */
-_PROTOTYPE( void check_vmnt_locks, (void)                              );
-_PROTOTYPE( void check_vmnt_locks_by_me, (struct fproc *rfp)           );
-_PROTOTYPE( struct vmnt *get_free_vmnt, (void)                         );
-_PROTOTYPE( struct vmnt *find_vmnt, (endpoint_t fs_e)                  );
-_PROTOTYPE( struct vmnt *get_locked_vmnt, (struct fproc *rfp)          );
-_PROTOTYPE( void init_vmnts, (void)                                    );
-_PROTOTYPE( int lock_vmnt, (struct vmnt *vp, tll_access_t locktype)    );
-_PROTOTYPE( void unlock_vmnt, (struct vmnt *vp)                                );
-_PROTOTYPE( void vmnt_unmap_by_endpt, (endpoint_t proc_e)              );
-
-/* vnode.c */
-_PROTOTYPE( void check_vnode_locks, (void)                             );
-_PROTOTYPE( void check_vnode_locks_by_me, (struct fproc *rfp)          );
-_PROTOTYPE( struct vnode *get_free_vnode, (void)                       );
-_PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb)              );
-_PROTOTYPE( void init_vnodes, (void)                                   );
-_PROTOTYPE( int is_vnode_locked, (struct vnode *vp)                    );
-_PROTOTYPE( int lock_vnode, (struct vnode *vp, tll_access_t locktype)  );
-_PROTOTYPE( void unlock_vnode, (struct vnode *vp)                      );
-_PROTOTYPE( void dup_vnode, (struct vnode *vp)                          );
-_PROTOTYPE( void put_vnode, (struct vnode *vp)                         );
-_PROTOTYPE( void vnode_clean_refs, (struct vnode *vp)                   );
-#if DO_SANITYCHECKS
-_PROTOTYPE( int check_vrefs, (void)                    );
-#endif
-
-/* write.c */
-_PROTOTYPE( int do_write, (void)                                       );
-
-/* gcov.c */
-_PROTOTYPE( int do_gcov_flush, (void)                                  );
-#if ! USE_COVERAGE
-#define do_gcov_flush no_sys
-#endif
-
-/* select.c */
-_PROTOTYPE( int do_select, (void)                                      );
-_PROTOTYPE( void init_select, (void)                                   );
-_PROTOTYPE( void select_callback, (struct filp *, int ops)             );
-_PROTOTYPE( void select_forget, (endpoint_t proc_e)                            );
-_PROTOTYPE( void select_reply1, (endpoint_t driver_e, int minor, int status));
-_PROTOTYPE( void select_reply2, (endpoint_t driver_e, int minor, int status));
-_PROTOTYPE( void select_timeout_check, (timer_t *)                     );
-_PROTOTYPE( void select_unsuspend_by_endpt, (endpoint_t proc)          );
-
-/* worker.c */
-_PROTOTYPE( int worker_available, (void)                               );
-_PROTOTYPE( struct worker_thread *worker_get, (thread_t worker_tid)    );
-_PROTOTYPE( struct job *worker_getjob, (thread_t worker_tid)           );
-_PROTOTYPE( void worker_init, (struct worker_thread *worker)           );
-_PROTOTYPE( struct worker_thread *worker_self, (void)                  );
-_PROTOTYPE( void worker_signal, (struct worker_thread *worker)         );
-_PROTOTYPE( void worker_start, (void *(*func)(void *arg))              );
-_PROTOTYPE( void worker_stop, (struct worker_thread *worker)           );
-_PROTOTYPE( void worker_stop_by_endpt, (endpoint_t proc_e)             );
-_PROTOTYPE( void worker_wait, (void)                                   );
-_PROTOTYPE( void sys_worker_start, (void *(*func)(void *arg))          );
-_PROTOTYPE( void dl_worker_start, (void *(*func)(void *arg))           );
-#endif
diff --git a/servers/avfs/read.c b/servers/avfs/read.c
deleted file mode 100644 (file)
index 13df38a..0000000
+++ /dev/null
@@ -1,347 +0,0 @@
-/* This file contains the heart of the mechanism used to read (and write)
- * files.  Read and write requests are split up into chunks that do not cross
- * block boundaries.  Each chunk is then processed in turn.  Reads on special
- * files are also detected and handled.
- *
- * The entry points into this file are
- *   do_read:   perform the READ system call by calling read_write
- *   do_getdents: read entries from a directory (GETDENTS)
- *   read_write: actually do the work of READ and WRITE
- *
- */
-
-#include "fs.h"
-#include <fcntl.h>
-#include <unistd.h>
-#include <minix/com.h>
-#include <minix/u64.h>
-#include "file.h"
-#include "fproc.h"
-#include "scratchpad.h"
-#include "param.h"
-#include <dirent.h>
-#include <assert.h>
-#include <minix/vfsif.h>
-#include "vnode.h"
-#include "vmnt.h"
-
-
-/*===========================================================================*
- *                             do_read                                      *
- *===========================================================================*/
-PUBLIC int do_read()
-{
-  return(do_read_write(READING));
-}
-
-
-/*===========================================================================*
- *                             lock_bsf                                     *
- *===========================================================================*/
-PUBLIC void lock_bsf(void)
-{
-  message org_m_in;
-  struct fproc *org_fp;
-  struct worker_thread *org_self;
-
-  if (mutex_trylock(&bsf_lock) == 0)
-       return;
-
-  org_m_in = m_in;
-  org_fp = fp;
-  org_self = self;
-
-  if (mutex_lock(&bsf_lock) != 0)
-       panic("unable to lock block special file lock");
-
-  m_in = org_m_in;
-  fp = org_fp;
-  self = org_self;
-}
-
-/*===========================================================================*
- *                             unlock_bsf                                   *
- *===========================================================================*/
-PUBLIC void unlock_bsf(void)
-{
-  if (mutex_unlock(&bsf_lock) != 0)
-       panic("failed to unlock block special file lock");
-}
-
-/*===========================================================================*
- *                             do_read_write                                *
- *===========================================================================*/
-PUBLIC int do_read_write(rw_flag)
-int rw_flag;                   /* READING or WRITING */
-{
-/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
-  struct filp *f;
-  tll_access_t locktype;
-  int r;
-
-  scratch(fp).file.fd_nr = m_in.fd;
-  scratch(fp).io.io_buffer = m_in.buffer;
-  scratch(fp).io.io_nbytes = (size_t) m_in.nbytes;
-
-  locktype = (rw_flag == READING) ? VNODE_READ : VNODE_WRITE;
-  if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
-       return(err_code);
-  if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
-       unlock_filp(f);
-       return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
-  }
-  if (scratch(fp).io.io_nbytes == 0) {
-       unlock_filp(f);
-       return(0);      /* so char special files need not check for 0*/
-  }
-
-  r = read_write(rw_flag, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes,
-                who_e);
-
-  unlock_filp(f);
-  return(r);
-}
-
-/*===========================================================================*
- *                             read_write                                   *
- *===========================================================================*/
-PUBLIC int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
-                     endpoint_t for_e)
-{
-  register struct vnode *vp;
-  u64_t position, res_pos, new_pos;
-  unsigned int cum_io, cum_io_incr, res_cum_io;
-  int op, oflags, r, block_spec, char_spec, regular;
-  mode_t mode_word;
-
-  position = f->filp_pos;
-  oflags = f->filp_flags;
-  vp = f->filp_vno;
-  r = OK;
-  cum_io = 0;
-
-  if (size > SSIZE_MAX) return(EINVAL);
-
-  if (vp->v_pipe == I_PIPE) {
-       if (fp->fp_cum_io_partial != 0) {
-               panic("VFS: read_write: fp_cum_io_partial not clear");
-       }
-       r = rw_pipe(rw_flag, for_e, f, buf, size);
-       return(r);
-  }
-
-  op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
-  mode_word = vp->v_mode & I_TYPE;
-  regular = mode_word == I_REGULAR;
-
-  if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
-       if (vp->v_sdev == NO_DEV)
-               panic("VFS: read_write tries to access char dev NO_DEV");
-  }
-
-  if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) {
-       if (vp->v_sdev == NO_DEV)
-               panic("VFS: read_write tries to access block dev NO_DEV");
-  }
-
-  if (char_spec) {                     /* Character special files. */
-       dev_t dev;
-       int suspend_reopen;
-
-       suspend_reopen = (f->filp_state != FS_NORMAL);
-       dev = (dev_t) vp->v_sdev;
-
-       r = dev_io(op, dev, for_e, buf, position, size, oflags,
-                  suspend_reopen);
-       if (r >= 0) {
-               cum_io = r;
-               position = add64ul(position, r);
-               r = OK;
-       }
-  } else if (block_spec) {             /* Block special files. */
-       lock_bsf();
-
-       r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position, size,
-                          buf, rw_flag, &res_pos, &res_cum_io);
-       if (r == OK) {
-               position = res_pos;
-               cum_io += res_cum_io;
-       }
-
-       unlock_bsf();
-  } else {                             /* Regular files */
-       if (rw_flag == WRITING && block_spec == 0) {
-               /* Check for O_APPEND flag. */
-               if (oflags & O_APPEND) position = cvul64(vp->v_size);
-       }
-
-       /* Issue request */
-       r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, for_e,
-                         buf, size, &new_pos, &cum_io_incr);
-
-       if (r >= 0) {
-               if (ex64hi(new_pos))
-                       panic("read_write: bad new pos");
-
-               position = new_pos;
-               cum_io += cum_io_incr;
-       }
-  }
-
-  /* On write, update file size and access time. */
-  if (rw_flag == WRITING) {
-       if (regular || mode_word == I_DIRECTORY) {
-               if (cmp64ul(position, vp->v_size) > 0) {
-                       if (ex64hi(position) != 0) {
-                               panic("read_write: file size too big ");
-                       }
-                       vp->v_size = ex64lo(position);
-               }
-       }
-  }
-
-  f->filp_pos = position;
-
-  if (r == OK) return(cum_io);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_getdents                                  *
- *===========================================================================*/
-PUBLIC int do_getdents()
-{
-/* Perform the getdents(fd, buf, size) system call. */
-  int r = OK;
-  u64_t new_pos;
-  register struct filp *rfilp;
-
-  /* Is the file descriptor valid? */
-  if ( (rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
-
-  if (!(rfilp->filp_mode & R_BIT))
-       r = EBADF;
-  else if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY)
-       r = EBADF;
-
-  if (r == OK) {
-       if (ex64hi(rfilp->filp_pos) != 0)
-               panic("do_getdents: can't handle large offsets");
-
-       r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
-                        rfilp->filp_pos, m_in.buffer, m_in.nbytes,&new_pos,0);
-
-       if (r > 0) rfilp->filp_pos = new_pos;
-  }
-
-  unlock_filp(rfilp);
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             rw_pipe                                      *
- *===========================================================================*/
-PUBLIC int rw_pipe(rw_flag, usr_e, f, buf, req_size)
-int rw_flag;                   /* READING or WRITING */
-endpoint_t usr_e;
-struct filp *f;
-char *buf;
-size_t req_size;
-{
-  int r, oflags, partial_pipe = 0;
-  size_t size, cum_io, cum_io_incr;
-  struct vnode *vp;
-  u64_t position, new_pos;
-
-  /* Must make sure we're operating on locked filp and vnode */
-  assert(tll_islocked(&f->filp_vno->v_lock));
-  assert(mutex_trylock(&f->filp_lock) == -EDEADLK);
-
-  oflags = f->filp_flags;
-  vp = f->filp_vno;
-  position = cvu64((rw_flag == READING) ? vp->v_pipe_rd_pos :
-                                                       vp->v_pipe_wr_pos);
-  /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
-  cum_io = fp->fp_cum_io_partial;
-
-  r = pipe_check(vp, rw_flag, oflags, req_size, position, 0);
-  if (r <= 0) {
-       if (r == SUSPEND) pipe_suspend(f, buf, req_size);
-       return(r);
-  }
-
-  size = r;
-  if (size < req_size) partial_pipe = 1;
-
-  /* Truncate read request at size. */
-  if((rw_flag == READING) &&
-       cmp64ul(add64ul(position, size), vp->v_size) > 0) {
-       /* Position always should fit in an off_t (LONG_MAX). */
-       off_t pos32;
-
-       assert(cmp64ul(position, LONG_MAX) <= 0);
-       pos32 = cv64ul(position);
-       assert(pos32 >= 0);
-       assert(pos32 <= LONG_MAX);
-       size = vp->v_size - pos32;
-  }
-
-  if (vp->v_mapfs_e == 0)
-       panic("unmapped pipe");
-
-  r = req_readwrite(vp->v_mapfs_e, vp->v_mapinode_nr, position, rw_flag, usr_e,
-                   buf, size, &new_pos, &cum_io_incr);
-
-  if (r >= 0) {
-       if (ex64hi(new_pos))
-               panic("rw_pipe: bad new pos");
-
-       position = new_pos;
-       cum_io += cum_io_incr;
-       buf += cum_io_incr;
-       req_size -= cum_io_incr;
-  }
-
-  /* On write, update file size and access time. */
-  if (rw_flag == WRITING) {
-       if (cmp64ul(position, vp->v_size) > 0) {
-               if (ex64hi(position) != 0) {
-                       panic("read_write: file size too big for v_size");
-               }
-               vp->v_size = ex64lo(position);
-       }
-  } else {
-       if (cmp64ul(position, vp->v_size) >= 0) {
-               /* Reset pipe pointers */
-               vp->v_size = 0;
-               vp->v_pipe_rd_pos= 0;
-               vp->v_pipe_wr_pos= 0;
-               position = cvu64(0);
-       }
-  }
-
-  if (rw_flag == READING)
-       vp->v_pipe_rd_pos= cv64ul(position);
-  else
-       vp->v_pipe_wr_pos= cv64ul(position);
-
-  if (r == OK) {
-       if (partial_pipe) {
-               /* partial write on pipe with */
-               /* O_NONBLOCK, return write count */
-               if (!(oflags & O_NONBLOCK)) {
-                       /* partial write on pipe with req_size > PIPE_SIZE,
-                        * non-atomic
-                        */
-                       fp->fp_cum_io_partial = cum_io;
-                       pipe_suspend(f, buf, req_size);
-                       return(SUSPEND);
-               }
-       }
-       fp->fp_cum_io_partial = 0;
-       return(cum_io);
-  }
-
-  return(r);
-}
diff --git a/servers/avfs/request.c b/servers/avfs/request.c
deleted file mode 100644 (file)
index be230da..0000000
+++ /dev/null
@@ -1,1093 +0,0 @@
-/* This file contains the wrapper functions for issuing a request
- * and receiving response from FS processes.
- * Each function builds a request message according to the request
- * parameter, calls the most low-level fs_sendrec, and copies
- * back the response.
- */
-
-#include "fs.h"
-#include <string.h>
-#include <assert.h>
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <sys/statvfs.h>
-#include <minix/vfsif.h>
-#include <minix/com.h>
-#include <minix/const.h>
-#include <minix/endpoint.h>
-#include <minix/u64.h>
-#include <unistd.h>
-#include <minix/vfsif.h>
-#include "fproc.h"
-#include "vmnt.h"
-#include "vnode.h"
-#include "path.h"
-#include "param.h"
-
-
-/*===========================================================================*
- *                     req_breadwrite                                       *
- *===========================================================================*/
-PUBLIC int req_breadwrite(
-  endpoint_t fs_e,
-  endpoint_t user_e,
-  dev_t dev,
-  u64_t pos,
-  unsigned int num_of_bytes,
-  char *user_addr,
-  int rw_flag,
-  u64_t *new_posp,
-  unsigned int *cum_iop
-)
-{
-  int r;
-  cp_grant_id_t grant_id;
-  message m;
-
-  grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes,
-                       (rw_flag == READING ? CPF_WRITE : CPF_READ));
-  if(grant_id == -1)
-         panic("req_breadwrite: cpf_grant_magic failed");
-
-  /* Fill in request message */
-  m.m_type = rw_flag == READING ? REQ_BREAD : REQ_BWRITE;
-  m.REQ_DEV2 = dev;
-  m.REQ_GRANT = grant_id;
-  m.REQ_SEEK_POS_LO = ex64lo(pos);
-  m.REQ_SEEK_POS_HI = ex64hi(pos);
-  m.REQ_NBYTES = num_of_bytes;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-  if (r != OK) return(r);
-
-  /* Fill in response structure */
-  *new_posp = make64(m.RES_SEEK_POS_LO, m.RES_SEEK_POS_HI);
-  *cum_iop = m.RES_NBYTES;
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             req_chmod                                    *
- *===========================================================================*/
-PUBLIC int req_chmod(
-  int fs_e,
-  ino_t inode_nr,
-  mode_t rmode,
-  mode_t *new_modep
-)
-{
-  message m;
-  int r;
-
-  /* Fill in request message */
-  m.m_type = REQ_CHMOD;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_MODE = rmode;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-
-  /* Copy back actual mode. */
-  *new_modep = m.RES_MODE;
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_chown                                    *
- *===========================================================================*/
-PUBLIC int req_chown(
-  endpoint_t fs_e,
-  ino_t inode_nr,
-  uid_t newuid,
-  gid_t newgid,
-  mode_t *new_modep
-)
-{
-  message m;
-  int r;
-
-  /* Fill in request message */
-  m.m_type = REQ_CHOWN;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_UID = newuid;
-  m.REQ_GID = newgid;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-
-  /* Return new mode to caller. */
-  *new_modep = m.RES_MODE;
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_create                                   *
- *===========================================================================*/
-PUBLIC int req_create(
-  int fs_e,
-  ino_t inode_nr,
-  int omode,
-  uid_t uid,
-  gid_t gid,
-  char *path,
-  node_details_t *res
-)
-{
-  int r;
-  cp_grant_id_t grant_id;
-  size_t len;
-  message m;
-
-  if (path[0] == '/')
-       panic("req_create: filename starts with '/'");
-
-  len = strlen(path) + 1;
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes) path, len, CPF_READ);
-  if (grant_id == -1)
-       panic("req_create: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type     = REQ_CREATE;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_MODE   = omode;
-  m.REQ_UID    = uid;
-  m.REQ_GID    = gid;
-  m.REQ_GRANT  = grant_id;
-  m.REQ_PATH_LEN = len;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-  if (r != OK) return(r);
-
-  /* Fill in response structure */
-  res->fs_e    = m.m_source;
-  res->inode_nr        = m.RES_INODE_NR;
-  res->fmode   = m.RES_MODE;
-  res->fsize   = m.RES_FILE_SIZE_LO;
-  res->uid     = m.RES_UID;
-  res->gid     = m.RES_GID;
-  res->dev     = m.RES_DEV;
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             req_flush                                    *
- *===========================================================================*/
-PUBLIC int req_flush(endpoint_t fs_e, dev_t dev)
-{
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_FLUSH;
-  m.REQ_DEV = dev;
-
-  /* Send/rec request */
-  return fs_sendrec(fs_e, &m);
-}
-
-
-/*===========================================================================*
- *                             req_fstatfs                                  *
- *===========================================================================*/
-PUBLIC int req_fstatfs(int fs_e, int proc_e, char *buf)
-{
-  int r;
-  cp_grant_id_t grant_id;
-  message m;
-
-  grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, sizeof(struct statfs),
-                       CPF_WRITE);
-  if(grant_id == -1)
-         panic("req_fstatfs: cpf_grant_magic failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_FSTATFS;
-  m.REQ_GRANT = grant_id;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_statvfs                                  *
- *===========================================================================*/
-PUBLIC int req_statvfs(int fs_e, int proc_e, char *buf)
-{
-  int r;
-  cp_grant_id_t grant_id;
-  message m;
-
-  grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, sizeof(struct statvfs),
-                       CPF_WRITE);
-  if(grant_id == -1)
-         panic("req_statvfs: cpf_grant_magic failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_STATVFS;
-  m.REQ_GRANT = grant_id;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_ftrunc                                   *
- *===========================================================================*/
-PUBLIC int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end)
-{
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_FTRUNC;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_TRC_START_LO = start;
-  m.REQ_TRC_START_HI = 0;      /* Not used for now, so clear it. */
-  m.REQ_TRC_END_LO = end;
-  m.REQ_TRC_END_HI = 0;                /* Not used for now, so clear it. */
-
-  /* Send/rec request */
-  return fs_sendrec(fs_e, &m);
-}
-
-
-/*===========================================================================*
- *                             req_getdents                                 *
- *===========================================================================*/
-PUBLIC int req_getdents(
-  endpoint_t fs_e,
-  ino_t inode_nr,
-  u64_t pos,
-  char *buf,
-  size_t size,
-  u64_t *new_pos,
-  int direct
-)
-{
-  int r;
-  message m;
-  cp_grant_id_t grant_id;
-
-  if (direct) {
-       grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, size,
-                                                               CPF_WRITE);
-  } else {
-       grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, size,
-                                                               CPF_WRITE);
-  }
-
-  if (grant_id < 0)
-       panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
-                                                               grant_id);
-
-  m.m_type = REQ_GETDENTS;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_GRANT = grant_id;
-  m.REQ_MEM_SIZE = size;
-  m.REQ_SEEK_POS_LO = ex64lo(pos);
-  m.REQ_SEEK_POS_HI = 0;       /* Not used for now, so clear it. */
-
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  if (r == OK) {
-         *new_pos = cvul64(m.RES_SEEK_POS_LO);
-         r = m.RES_NBYTES;
-  }
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             req_inhibread                                *
- *===========================================================================*/
-PUBLIC int req_inhibread(endpoint_t fs_e, ino_t inode_nr)
-{
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_INHIBREAD;
-  m.REQ_INODE_NR = inode_nr;
-
-  /* Send/rec request */
-  return fs_sendrec(fs_e, &m);
-}
-
-
-/*===========================================================================*
- *                             req_link                                     *
- *===========================================================================*/
-PUBLIC int req_link(
-  endpoint_t fs_e,
-  ino_t link_parent,
-  char *lastc,
-  ino_t linked_file
-)
-{
-  int r;
-  cp_grant_id_t grant_id;
-  const size_t len = strlen(lastc) + 1;
-  message m;
-
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
-  if(grant_id == -1)
-         panic("req_link: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_LINK;
-  m.REQ_INODE_NR = linked_file;
-  m.REQ_DIR_INO = link_parent;
-  m.REQ_GRANT = grant_id;
-  m.REQ_PATH_LEN = len;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_lookup                                   *
- *===========================================================================*/
-PUBLIC int req_lookup(
-  endpoint_t fs_e,
-  ino_t dir_ino,
-  ino_t root_ino,
-  uid_t uid,
-  gid_t gid,
-  struct lookup *resolve,
-  lookup_res_t *res,
-  struct fproc *rfp
-)
-{
-  int r;
-  size_t len;
-  cp_grant_id_t grant_id=0, grant_id2=0;
-  message m;
-  vfs_ucred_t credentials;
-  int flags;
-
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes) resolve->l_path, PATH_MAX,
-                             CPF_READ | CPF_WRITE);
-  if(grant_id == -1)
-         panic("req_lookup: cpf_grant_direct failed");
-
-  flags = resolve->l_flags;
-  len = strlen(resolve->l_path) + 1;
-
-  m.m_type             = REQ_LOOKUP;
-  m.REQ_GRANT          = grant_id;
-  m.REQ_PATH_LEN       = len;
-  m.REQ_PATH_SIZE      = PATH_MAX + 1;
-  m.REQ_DIR_INO        = dir_ino;
-  m.REQ_ROOT_INO       = root_ino;
-
-  if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
-       /* In that case the FS has to copy the uid/gid credentials */
-       int i;
-
-       /* Set credentials */
-       credentials.vu_uid = rfp->fp_effuid;
-       credentials.vu_gid = rfp->fp_effgid;
-       credentials.vu_ngroups = rfp->fp_ngroups;
-       for (i = 0; i < rfp->fp_ngroups; i++)
-               credentials.vu_sgroups[i] = rfp->fp_sgroups[i];
-
-       grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials,
-                                    sizeof(credentials), CPF_READ);
-       if(grant_id2 == -1)
-               panic("req_lookup: cpf_grant_direct failed");
-
-       m.REQ_GRANT2    = grant_id2;
-       m.REQ_UCRED_SIZE= sizeof(credentials);
-       flags           |= PATH_GET_UCRED;
-  } else {
-       /* When there's only one gid, we can send it directly */
-       m.REQ_UID       = uid;
-       m.REQ_GID       = gid;
-       flags           &= ~PATH_GET_UCRED;
-  }
-
-  m.REQ_FLAGS          = flags;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-  if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2);
-
-  /* Fill in response according to the return value */
-  res->fs_e = m.m_source;
-
-  switch (r) {
-  case OK:
-         res->inode_nr = m.RES_INODE_NR;
-         res->fmode = m.RES_MODE;
-         res->fsize = m.RES_FILE_SIZE_LO;
-         res->dev = m.RES_DEV;
-         res->uid= m.RES_UID;
-         res->gid= m.RES_GID;
-         break;
-  case EENTERMOUNT:
-         res->inode_nr = m.RES_INODE_NR;
-         res->char_processed = m.RES_OFFSET;
-         res->symloop = m.RES_SYMLOOP;
-         break;
-  case ELEAVEMOUNT:
-         res->char_processed = m.RES_OFFSET;
-         res->symloop = m.RES_SYMLOOP;
-         break;
-  case ESYMLINK:
-         res->char_processed = m.RES_OFFSET;
-         res->symloop = m.RES_SYMLOOP;
-         break;
-  default:
-         break;
-  }
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_mkdir                                    *
- *===========================================================================*/
-PUBLIC int req_mkdir(
-  endpoint_t fs_e,
-  ino_t inode_nr,
-  char *lastc,
-  uid_t uid,
-  gid_t gid,
-  mode_t dmode
-)
-{
-  int r;
-  cp_grant_id_t grant_id;
-  size_t len;
-  message m;
-
-  len = strlen(lastc) + 1;
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
-  if(grant_id == -1)
-         panic("req_mkdir: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_MKDIR;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_MODE = dmode;
-  m.REQ_UID = uid;
-  m.REQ_GID = gid;
-  m.REQ_GRANT = grant_id;
-  m.REQ_PATH_LEN = len;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_mknod                                    *
- *===========================================================================*/
-PUBLIC int req_mknod(
-  endpoint_t fs_e,
-  ino_t inode_nr,
-  char *lastc,
-  uid_t uid,
-  gid_t gid,
-  mode_t dmode,
-  dev_t dev
-)
-{
-  int r;
-  size_t len;
-  cp_grant_id_t grant_id;
-  message m;
-
-  len = strlen(lastc) + 1;
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
-  if(grant_id == -1)
-         panic("req_mknod: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_MKNOD;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_MODE = dmode;
-  m.REQ_DEV = dev;
-  m.REQ_UID = uid;
-  m.REQ_GID = gid;
-  m.REQ_GRANT = grant_id;
-  m.REQ_PATH_LEN = len;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_mountpoint                               *
- *===========================================================================*/
-PUBLIC int req_mountpoint(endpoint_t fs_e, ino_t inode_nr)
-{
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_MOUNTPOINT;
-  m.REQ_INODE_NR = inode_nr;
-
-  /* Send/rec request */
-  return fs_sendrec(fs_e, &m);
-}
-
-
-/*===========================================================================*
- *                             req_newnode                                  *
- *===========================================================================*/
-PUBLIC int req_newnode(
-  endpoint_t fs_e,
-  uid_t uid,
-  gid_t gid,
-  mode_t dmode,
-  dev_t dev,
-  struct node_details *res
-)
-{
-  int r;
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_NEWNODE;
-  m.REQ_MODE = dmode;
-  m.REQ_DEV = dev;
-  m.REQ_UID = uid;
-  m.REQ_GID = gid;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-
-  res->fs_e    = m.m_source;
-  res->inode_nr = m.RES_INODE_NR;
-  res->fmode   = m.RES_MODE;
-  res->fsize   = m.RES_FILE_SIZE_LO;
-  res->dev     = m.RES_DEV;
-  res->uid     = m.RES_UID;
-  res->gid     = m.RES_GID;
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_newdriver                                *
- *===========================================================================*/
-PUBLIC int req_newdriver(
-  endpoint_t fs_e,
-  dev_t dev,
-  char *label
-)
-{
-  cp_grant_id_t grant_id;
-  size_t len;
-  message m;
-  int r;
-
-  /* Grant access to label */
-  len = strlen(label) + 1;
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
-  if (grant_id == -1)
-       panic("req_newdriver: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_NEW_DRIVER;
-  m.REQ_DEV = dev;
-  m.REQ_GRANT = grant_id;
-  m.REQ_PATH_LEN = len;
-
-  /* Issue request */
-  r = fs_sendrec(fs_e, &m);
-
-  cpf_revoke(grant_id);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_putnode                                  *
- *===========================================================================*/
-PUBLIC int req_putnode(fs_e, inode_nr, count)
-int fs_e;
-ino_t inode_nr;
-int count;
-{
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_PUTNODE;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_COUNT = count;
-
-  /* Send/rec request */
-  return fs_sendrec(fs_e, &m);
-}
-
-
-/*===========================================================================*
- *                             req_rdlink                                   *
- *===========================================================================*/
-PUBLIC int req_rdlink(fs_e, inode_nr, proc_e, buf, len, direct)
-endpoint_t fs_e;
-ino_t inode_nr;
-endpoint_t proc_e;
-char *buf;
-size_t len;
-int direct; /* set to 1 to use direct grants instead of magic grants */
-{
-  message m;
-  int r;
-  cp_grant_id_t grant_id;
-
-  if (direct) {
-       grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, len, CPF_WRITE);
-  } else {
-       grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, len,
-                                                               CPF_WRITE);
-  }
-  if(grant_id == -1)
-         panic("req_rdlink: cpf_grant_magic failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_RDLINK;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_GRANT = grant_id;
-  m.REQ_MEM_SIZE = len;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  if(r == OK) r = m.RES_NBYTES;
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_readsuper                                *
- *===========================================================================*/
-PUBLIC int req_readsuper(
-  endpoint_t fs_e,
-  char *label,
-  dev_t dev,
-  int readonly,
-  int isroot,
-  struct node_details *res_nodep,
-  int *con_reqs
-)
-{
-  int r;
-  cp_grant_id_t grant_id;
-  size_t len;
-  message m;
-
-  len = strlen(label)+1;
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
-  if (grant_id == -1)
-         panic("req_readsuper: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_READSUPER;
-  m.REQ_FLAGS = 0;
-  if(readonly) m.REQ_FLAGS |= REQ_RDONLY;
-  if(isroot)   m.REQ_FLAGS |= REQ_ISROOT;
-  m.REQ_GRANT = grant_id;
-  m.REQ_DEV = dev;
-  m.REQ_PATH_LEN = len;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  if(r == OK) {
-       /* Fill in response structure */
-       res_nodep->fs_e = m.m_source;
-       res_nodep->inode_nr = m.RES_INODE_NR;
-       res_nodep->fmode = m.RES_MODE;
-       res_nodep->fsize = m.RES_FILE_SIZE_LO;
-       res_nodep->uid = m.RES_UID;
-       res_nodep->gid = m.RES_GID;
-       *con_reqs = m.RES_CONREQS;
-  }
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_readwrite                                *
- *===========================================================================*/
-PUBLIC int req_readwrite(fs_e, inode_nr, pos, rw_flag, user_e,
-       user_addr, num_of_bytes, new_posp, cum_iop)
-endpoint_t fs_e;
-ino_t inode_nr;
-u64_t pos;
-int rw_flag;
-endpoint_t user_e;
-char *user_addr;
-unsigned int num_of_bytes;
-u64_t *new_posp;
-unsigned int *cum_iop;
-{
-  int r;
-  cp_grant_id_t grant_id;
-  message m;
-
-  if (ex64hi(pos) != 0)
-         panic("req_readwrite: pos too large");
-
-  grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes,
-                            (rw_flag==READING ? CPF_WRITE:CPF_READ));
-  if (grant_id == -1)
-         panic("req_readwrite: cpf_grant_magic failed");
-
-  /* Fill in request message */
-  m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_GRANT = grant_id;
-  m.REQ_SEEK_POS_LO = ex64lo(pos);
-  m.REQ_SEEK_POS_HI = 0;       /* Not used for now, so clear it. */
-  m.REQ_NBYTES = num_of_bytes;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  if (r == OK) {
-       /* Fill in response structure */
-       *new_posp = cvul64(m.RES_SEEK_POS_LO);
-       *cum_iop = m.RES_NBYTES;
-  }
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_rename                                   *
- *===========================================================================*/
-PUBLIC int req_rename(fs_e, old_dir, old_name, new_dir, new_name)
-endpoint_t fs_e;
-ino_t old_dir;
-char *old_name;
-ino_t new_dir;
-char *new_name;
-{
-  int r;
-  cp_grant_id_t gid_old, gid_new;
-  size_t len_old, len_new;
-  message m;
-
-  len_old = strlen(old_name) + 1;
-  gid_old = cpf_grant_direct(fs_e, (vir_bytes) old_name, len_old, CPF_READ);
-  if(gid_old == -1)
-         panic("req_rename: cpf_grant_direct failed");
-
-  len_new = strlen(new_name) + 1;
-  gid_new = cpf_grant_direct(fs_e, (vir_bytes) new_name, len_new, CPF_READ);
-  if(gid_new == -1)
-         panic("req_rename: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_RENAME;
-  m.REQ_REN_OLD_DIR = old_dir;
-  m.REQ_REN_NEW_DIR = new_dir;
-  m.REQ_REN_GRANT_OLD = gid_old;
-  m.REQ_REN_LEN_OLD = len_old;
-  m.REQ_REN_GRANT_NEW = gid_new;
-  m.REQ_REN_LEN_NEW = len_new;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(gid_old);
-  cpf_revoke(gid_new);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_rmdir                                    *
- *===========================================================================*/
-PUBLIC int req_rmdir(fs_e, inode_nr, lastc)
-endpoint_t fs_e;
-ino_t inode_nr;
-char *lastc;
-{
-  int r;
-  cp_grant_id_t grant_id;
-  size_t len;
-  message m;
-
-  len = strlen(lastc) + 1;
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
-  if(grant_id == -1)
-         panic("req_rmdir: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_RMDIR;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_GRANT = grant_id;
-  m.REQ_PATH_LEN = len;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_slink                                    *
- *===========================================================================*/
-PUBLIC int req_slink(
-  endpoint_t fs_e,
-  ino_t inode_nr,
-  char *lastc,
-  endpoint_t proc_e,
-  char *path_addr,
-  unsigned short path_length,
-  uid_t uid,
-  gid_t gid
-)
-{
-  int r;
-  size_t len;
-  cp_grant_id_t gid_name, gid_buf;
-  message m;
-
-  len = strlen(lastc) + 1;
-  gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
-  if(gid_name == -1)
-         panic("req_slink: cpf_grant_direct failed");
-
-  gid_buf = cpf_grant_magic(fs_e, proc_e, (vir_bytes) path_addr, path_length,
-                           CPF_READ);
-  if(gid_buf == -1) {
-         cpf_revoke(gid_name);
-         panic("req_slink: cpf_grant_magic failed");
-  }
-
-  /* Fill in request message */
-  m.m_type = REQ_SLINK;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_UID = uid;
-  m.REQ_GID = gid;
-  m.REQ_GRANT = gid_name;
-  m.REQ_PATH_LEN = len;
-  m.REQ_GRANT3 = gid_buf;
-  m.REQ_MEM_SIZE = path_length;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(gid_name);
-  cpf_revoke(gid_buf);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_stat                                     *
- *===========================================================================*/
-PUBLIC int req_stat(fs_e, inode_nr, proc_e, buf, pos, stat_version)
-int fs_e;
-ino_t inode_nr;
-int proc_e;
-char *buf;
-int pos;
-int stat_version;
-{
-  cp_grant_id_t grant_id;
-  int r;
-  message m;
-  struct stat sb;
-  struct minix_prev_stat old_sb; /* for backward compatibility */
-
-  if (pos != 0 || stat_version != 0)
-         grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb,
-                                     sizeof(struct stat), CPF_WRITE);
-  else
-         grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf,
-                               sizeof(struct stat), CPF_WRITE);
-
-  if (grant_id < 0)
-       panic("req_stat: cpf_grant_* failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_STAT;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_GRANT = grant_id;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  if (r != OK || (pos == 0 && stat_version == 0))
-       return(r);
-
-  if (pos != 0)
-       sb.st_size -= pos;
-  if (stat_version == 0) {
-       r = sys_vircopy(SELF, D, (vir_bytes) &sb, proc_e, D, (vir_bytes) buf,
-                       sizeof(struct stat));
-       return(r);
-  }
-
-  /* User needs old struct stat.
-   * Just 1 prev version at this moment */
-  assert(stat_version == 1);
-
-/* XXX until that st_Xtime macroses used, we have to undefine them,
- * because of minix_prev_stat
- */
-#undef st_atime
-#undef st_ctime
-#undef st_mtime
-
-/* Copy field by field because of st_gid type mismath and
- * difference in order after atime.
- */
-  old_sb.st_dev = sb.st_dev;
-  old_sb.st_ino = sb.st_ino;
-  old_sb.st_mode = sb.st_mode;
-  old_sb.st_nlink = sb.st_nlink;
-  old_sb.st_uid = sb.st_uid;
-  old_sb.st_gid = sb.st_gid;
-  old_sb.st_rdev = sb.st_rdev;
-  old_sb.st_size = sb.st_size;
-#if defined(_NETBSD_SOURCE)
-  old_sb.st_atime = sb.st_atimespec.tv_sec;
-  old_sb.st_mtime = sb.st_mtimespec.tv_sec;
-  old_sb.st_ctime = sb.st_ctimespec.tv_sec;
-#else
-  old_sb.st_atime = sb.st_atime;
-  old_sb.st_mtime = sb.st_mtime;
-  old_sb.st_ctime = sb.st_ctime;
-#endif
-
-  r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, proc_e, D, (vir_bytes) buf,
-                 sizeof(struct minix_prev_stat));
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_sync                                     *
- *===========================================================================*/
-PUBLIC int req_sync(fs_e)
-endpoint_t fs_e;
-{
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_SYNC;
-
-  /* Send/rec request */
-  return fs_sendrec(fs_e, &m);
-}
-
-
-/*===========================================================================*
- *                             req_unlink                                   *
- *===========================================================================*/
-PUBLIC int req_unlink(fs_e, inode_nr, lastc)
-endpoint_t fs_e;
-ino_t inode_nr;
-char *lastc;
-{
-  cp_grant_id_t grant_id;
-  size_t len;
-  int r;
-  message m;
-
-  len = strlen(lastc) + 1;
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
-  if(grant_id == -1)
-         panic("req_unlink: cpf_grant_direct failed");
-
-  /* Fill in request message */
-  m.m_type = REQ_UNLINK;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_GRANT = grant_id;
-  m.REQ_PATH_LEN = len;
-
-  /* Send/rec request */
-  r = fs_sendrec(fs_e, &m);
-  cpf_revoke(grant_id);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             req_unmount                                  *
- *===========================================================================*/
-PUBLIC int req_unmount(fs_e)
-endpoint_t fs_e;
-{
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_UNMOUNT;
-
-  /* Send/rec request */
-  return fs_sendrec(fs_e, &m);
-}
-
-
-/*===========================================================================*
- *                             req_utime                                    *
- *===========================================================================*/
-PUBLIC int req_utime(fs_e, inode_nr, actime, modtime)
-endpoint_t fs_e;
-ino_t inode_nr;
-time_t actime;
-time_t modtime;
-{
-  message m;
-
-  /* Fill in request message */
-  m.m_type = REQ_UTIME;
-  m.REQ_INODE_NR = inode_nr;
-  m.REQ_ACTIME = actime;
-  m.REQ_MODTIME = modtime;
-
-  /* Send/rec request */
-  return fs_sendrec(fs_e, &m);
-}
diff --git a/servers/avfs/request.h b/servers/avfs/request.h
deleted file mode 100644 (file)
index 74f612b..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-#ifndef __VFS_REQUEST_H__
-#define __VFS_REQUEST_H__
-
-/* Low level request messages are built and sent by wrapper functions.
- * This file contains the request and response structures for accessing
- * those wrappers functions.
- */
-
-#include <sys/types.h>
-
-/* Structure for response that contains inode details */
-typedef struct node_details {
-  endpoint_t fs_e;
-  ino_t inode_nr;
-  mode_t fmode;
-  off_t fsize;
-  uid_t uid;
-  gid_t gid;
-
-  /* For char/block special files */
-  dev_t dev;
-} node_details_t;
-
-/* Structure for a lookup response */
-typedef struct lookup_res {
-  endpoint_t fs_e;
-  ino_t inode_nr;
-  mode_t fmode;
-  off_t fsize;
-  uid_t uid;
-  gid_t gid;
-  /* For char/block special files */
-  dev_t dev;
-
-  /* Fields used for handling mount point and symbolic links */
-  int char_processed;
-  unsigned char symloop;
-} lookup_res_t;
-
-
-#endif
diff --git a/servers/avfs/select.c b/servers/avfs/select.c
deleted file mode 100644 (file)
index 90e23ab..0000000
+++ /dev/null
@@ -1,1071 +0,0 @@
-/* Implement entry point to select system call.
- *
- * The entry points into this file are
- *   do_select:               perform the SELECT system call
- *   select_callback:  notify select system of possible fd operation
- *   select_unsuspend_by_endpt: cancel a blocking select on exiting driver
- */
-
-#include "fs.h"
-#include <sys/time.h>
-#include <sys/select.h>
-#include <minix/com.h>
-#include <minix/u64.h>
-#include <string.h>
-#include <assert.h>
-
-#include "select.h"
-#include "file.h"
-#include "fproc.h"
-#include "dmap.h"
-#include "vnode.h"
-
-/* max. number of simultaneously pending select() calls */
-#define MAXSELECTS 25
-#define FROM_PROC 0
-#define TO_PROC   1
-
-PRIVATE struct selectentry {
-  struct fproc *requestor;     /* slot is free iff this is NULL */
-  endpoint_t req_endpt;
-  fd_set readfds, writefds, errorfds;
-  fd_set ready_readfds, ready_writefds, ready_errorfds;
-  fd_set *vir_readfds, *vir_writefds, *vir_errorfds;
-  struct filp *filps[OPEN_MAX];
-  int type[OPEN_MAX];
-  int nfds, nreadyfds;
-  int error;
-  char block;
-  clock_t expiry;
-  timer_t timer;       /* if expiry > 0 */
-} selecttab[MAXSELECTS];
-
-FORWARD _PROTOTYPE(int copy_fdsets, (struct selectentry *se, int nfds,
-                                     int direction)                    );
-FORWARD _PROTOTYPE(int do_select_request, (struct selectentry *se, int fd,
-                                          int *ops)                    );
-FORWARD _PROTOTYPE(void filp_status, (struct filp *fp, int status)     );
-FORWARD _PROTOTYPE(int is_deferred, (struct selectentry *se)           );
-FORWARD _PROTOTYPE(void restart_proc, (struct selectentry *se)         );
-FORWARD _PROTOTYPE(void ops2tab, (int ops, int fd, struct selectentry *e));
-FORWARD _PROTOTYPE(int is_regular_file, (struct filp *f)               );
-FORWARD _PROTOTYPE(int is_pipe, (struct filp *f)                       );
-FORWARD _PROTOTYPE(int is_supported_major, (struct filp *f)                    );
-FORWARD _PROTOTYPE(void select_lock_filp, (struct filp *f, int ops)    );
-FORWARD _PROTOTYPE(int select_request_async, (struct filp *f, int *ops,
-                                              int block)               );
-FORWARD _PROTOTYPE(int select_request_file, (struct filp *f, int *ops,
-                                            int block)                 );
-FORWARD _PROTOTYPE(int select_request_major, (struct filp *f, int *ops,
-                                            int block)                 );
-FORWARD _PROTOTYPE(int select_request_pipe, (struct filp *f, int *ops,
-                                            int block)                 );
-FORWARD _PROTOTYPE(int select_request_sync, (struct filp *f, int *ops,
-                                               int block)              );
-FORWARD _PROTOTYPE(void select_cancel_all, (struct selectentry *e)     );
-FORWARD _PROTOTYPE(void select_cancel_filp, (struct filp *f)           );
-FORWARD _PROTOTYPE(void select_return, (struct selectentry *)          );
-FORWARD _PROTOTYPE(void select_restart_filps, (void)                           );
-FORWARD _PROTOTYPE(int tab2ops, (int fd, struct selectentry *e)                );
-FORWARD _PROTOTYPE(void wipe_select, (struct selectentry *s)           );
-
-PRIVATE struct fdtype {
-       int (*select_request)(struct filp *, int *ops, int block);
-       int (*type_match)(struct filp *f);
-} fdtypes[] = {
-       { select_request_major, is_supported_major },
-       { select_request_file, is_regular_file },
-       { select_request_pipe, is_pipe },
-};
-#define SEL_FDS                (sizeof(fdtypes) / sizeof(fdtypes[0]))
-PRIVATE int select_majors[] = { /* List of majors that support selecting on */
-       TTY_MAJOR,
-       INET_MAJOR,
-       UDS_MAJOR,
-       LOG_MAJOR,
-};
-#define SEL_MAJORS     (sizeof(select_majors) / sizeof(select_majors[0]))
-
-/*===========================================================================*
- *                             do_select                                     *
- *===========================================================================*/
-PUBLIC int do_select(void)
-{
-/* Implement the select(nfds, readfds, writefds, errorfds, timeout) system
- * call. First we copy the arguments and verify their sanity. Then we check
- * whether there are file descriptors that satisfy the select call right of the
- * bat. If so, or if there are no ready file descriptors but the process
- * requested to return immediately, we return the result. Otherwise we set a
- * timeout and wait for either the file descriptors to become ready or the
- * timer to go off. If no timeout value was provided, we wait indefinitely. */
-
-  int r, nfds, do_timeout = 0, fd, s;
-  struct timeval timeout;
-  struct selectentry *se;
-
-  nfds = m_in.SEL_NFDS;
-
-  /* Sane amount of file descriptors? */
-  if (nfds < 0 || nfds > OPEN_MAX) return(EINVAL);
-
-  /* Find a slot to store this select request */
-  for (s = 0; s < MAXSELECTS; s++)
-       if (selecttab[s].requestor == NULL) /* Unused slot */
-               break;
-  if (s >= MAXSELECTS) return(ENOSPC);
-
-  se = &selecttab[s];
-  wipe_select(se);     /* Clear results of previous usage */
-  se->req_endpt = who_e;
-  se->vir_readfds = (fd_set *) m_in.SEL_READFDS;
-  se->vir_writefds = (fd_set *) m_in.SEL_WRITEFDS;
-  se->vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS;
-
-  /* Copy fdsets from the process */
-  if ((r = copy_fdsets(se, nfds, FROM_PROC)) != OK) return(r);
-
-  /* Did the process set a timeout value? If so, retrieve it. */
-  if (m_in.SEL_TIMEOUT != NULL) {
-       do_timeout = 1;
-       r = sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_TIMEOUT, SELF, D,
-                       (vir_bytes) &timeout, sizeof(timeout));
-       if (r != OK) return(r);
-  }
-
-  /* No nonsense in the timeval */
-  if (do_timeout && (timeout.tv_sec < 0 || timeout.tv_usec < 0))
-       return(EINVAL);
-
-  /* If there is no timeout, we block forever. Otherwise, we block up to the
-   * specified time interval.
-   */
-  if (!do_timeout)     /* No timeout value set */
-       se->block = 1;
-  else if (do_timeout && (timeout.tv_sec > 0 || timeout.tv_usec > 0))
-       se->block = 1;
-  else                 /* timeout set as (0,0) - this effects a poll */
-       se->block = 0;
-  se->expiry = 0;      /* no timer set (yet) */
-
-  /* Verify that file descriptors are okay to select on */
-  for (fd = 0; fd < nfds; fd++) {
-       struct filp *f;
-       int type, ops;
-
-       /* Because the select() interface implicitly includes file descriptors
-        * you might not want to select on, we have to figure out whether we're
-        * interested in them. Typically, these file descriptors include fd's
-        * inherited from the parent proc and file descriptors that have been
-        * close()d, but had a lower fd than one in the current set.
-        */
-       if (!(ops = tab2ops(fd, se)))
-               continue; /* No operations set; nothing to do for this fd */
-
-       /* Get filp belonging to this fd */
-       f = se->filps[fd] = get_filp(fd, VNODE_READ);
-       if (f == NULL) {
-               if (err_code == EBADF)
-                       r = err_code;
-               else /* File descriptor is 'ready' to return EIO */
-                       r = EINTR;
-
-               return(r);
-       }
-
-       /* Check file types. According to POSIX 2008:
-        * "The pselect() and select() functions shall support regular files,
-        * terminal and pseudo-terminal devices, FIFOs, pipes, and sockets. The
-        * behavior of pselect() and select() on file descriptors that refer to
-        * other types of file is unspecified."
-        *
-        * In our case, terminal and pseudo-terminal devices are handled by the
-        * TTY major and sockets by either INET major (socket type AF_INET) or
-        * PFS major (socket type AF_UNIX). PFS acts as an FS when it handles
-        * pipes and as a driver when it handles sockets. Additionally, we
-        * support select on the LOG major to handle kernel logging, which is
-        * beyond the POSIX spec. */
-
-       se->type[fd] = -1;
-       for (type = 0; type < SEL_FDS; type++) {
-               if (fdtypes[type].type_match(f)) {
-                       se->type[fd] = type;
-                       se->nfds = fd+1;
-                       se->filps[fd]->filp_selectors++;
-                       break;
-               }
-       }
-       unlock_filp(f);
-       if (se->type[fd] == -1) /* Type not found */
-               return(EBADF);
-  }
-
-  /* Check all file descriptors in the set whether one is 'ready' now */
-  for (fd = 0; fd < nfds; fd++) {
-       int ops, r;
-       struct filp *f;
-
-       /* Again, check for involuntarily selected fd's */
-       if (!(ops = tab2ops(fd, se)))
-               continue; /* No operations set; nothing to do for this fd */
-
-       /* Test filp for select operations if not already done so. e.g.,
-        * processes sharing a filp and both doing a select on that filp. */
-       f = se->filps[fd];
-       select_lock_filp(f, f->filp_select_ops | ops);
-       if ((f->filp_select_ops & ops) != ops) {
-               int wantops;
-
-               wantops = (f->filp_select_ops |= ops);
-               r = do_select_request(se, fd, &wantops);
-               unlock_filp(f);
-               if (r != SEL_OK) {
-                       if (r == SEL_DEFERRED) continue;
-                       else break; /* Error or bogus return code; abort */
-               }
-
-               /* The select request above might have turned on/off some
-                * operations because they were 'ready' or not meaningful.
-                * Either way, we might have a result and we need to store them
-                * in the select table entry. */
-               if (wantops & ops) ops2tab(wantops, fd, se);
-       } else {
-               unlock_filp(f);
-       }
-  }
-
-  if ((se->nreadyfds > 0 || !se->block) && !is_deferred(se)) {
-       /* fd's were found that were ready to go right away, and/or
-        * we were instructed not to block at all. Must return
-        * immediately.
-        */
-       r = copy_fdsets(se, se->nfds, TO_PROC);
-       select_cancel_all(se);
-
-       if (r != OK)
-               return(r);
-       else if (se->error != OK)
-               return(se->error);
-
-       return(se->nreadyfds);
-  }
-
-  /* Convert timeval to ticks and set the timer. If it fails, undo
-   * all, return error.
-   */
-  if (do_timeout) {
-       int ticks;
-       /* Open Group:
-        * "If the requested timeout interval requires a finer
-        * granularity than the implementation supports, the
-        * actual timeout interval shall be rounded up to the next
-        * supported value."
-        */
-#define USECPERSEC 1000000
-       while(timeout.tv_usec >= USECPERSEC) {
-               /* this is to avoid overflow with *system_hz below */
-               timeout.tv_usec -= USECPERSEC;
-               timeout.tv_sec++;
-       }
-       ticks = timeout.tv_sec * system_hz +
-               (timeout.tv_usec * system_hz + USECPERSEC-1) / USECPERSEC;
-       se->expiry = ticks;
-       set_timer(&se->timer, ticks, select_timeout_check, s);
-  }
-
-  /* If we're blocking, the table entry is now valid  */
-  se->requestor = fp;
-
-  /* process now blocked */
-  suspend(FP_BLOCKED_ON_SELECT);
-  return(SUSPEND);
-}
-
-/*===========================================================================*
- *                             is_deferred                                  *
- *===========================================================================*/
-PRIVATE int is_deferred(struct selectentry *se)
-{
-/* Find out whether this select has pending initial replies */
-
-  int fd;
-  struct filp *f;
-
-  for (fd = 0; fd < se->nfds; fd++) {
-       if ((f = se->filps[fd]) == NULL) continue;
-       if (f->filp_select_flags & (FSF_UPDATE|FSF_BUSY)) return(TRUE);
-  }
-
-  return(FALSE);
-}
-
-
-/*===========================================================================*
- *                             is_regular_file                              *
- *===========================================================================*/
-PRIVATE int is_regular_file(struct filp *f)
-{
-  return(f && f->filp_vno && (f->filp_vno->v_mode & I_TYPE) == I_REGULAR);
-}
-
-/*===========================================================================*
- *                             is_pipe                                      *
- *===========================================================================*/
-PRIVATE int is_pipe(struct filp *f)
-{
-/* Recognize either anonymous pipe or named pipe (FIFO) */
-  return(f && f->filp_vno && (f->filp_vno->v_mode & I_TYPE) == I_NAMED_PIPE);
-}
-
-/*===========================================================================*
- *                             is_supported_major                                           *
- *===========================================================================*/
-PRIVATE int is_supported_major(struct filp *f)
-{
-/* See if this filp is a handle on a device on which we support select() */
-  int m;
-
-  if (!(f && f->filp_vno)) return(FALSE);
-  if ((f->filp_vno->v_mode & I_TYPE) != I_CHAR_SPECIAL) return(FALSE);
-
-  for (m = 0; m < SEL_MAJORS; m++)
-       if (major(f->filp_vno->v_sdev) == select_majors[m])
-               return(TRUE);
-
-  return(FALSE);
-}
-
-/*===========================================================================*
- *                             select_request_async                         *
- *===========================================================================*/
-PRIVATE int select_request_async(struct filp *f, int *ops, int block)
-{
-  int r, rops, major;
-  struct dmap *dp;
-
-  rops = *ops;
-
-  if (!block && (f->filp_select_flags & FSF_BLOCKED)) {
-       /* This filp is blocked waiting for a reply, but we don't want to
-        * block ourselves. Unless we're awaiting the initial reply, these
-        * operations won't be ready */
-       if (!(f->filp_select_flags & FSF_BUSY)) {
-               if ((rops & SEL_RD) && (f->filp_select_flags & FSF_RD_BLOCK))
-                       rops &= ~SEL_RD;
-               if ((rops & SEL_WR) && (f->filp_select_flags & FSF_WR_BLOCK))
-                       rops &= ~SEL_WR;
-               if ((rops & SEL_ERR) && (f->filp_select_flags & FSF_ERR_BLOCK))
-                       rops &= ~SEL_ERR;
-               if (!(rops & (SEL_RD|SEL_WR|SEL_ERR))) {
-                       /* Nothing left to do */
-                       *ops = 0;
-                       return(SEL_OK);
-               }
-       }
-  }
-
-  f->filp_select_flags |= FSF_UPDATE;
-  if (block) {
-       rops |= SEL_NOTIFY;
-       if (rops & SEL_RD)      f->filp_select_flags |= FSF_RD_BLOCK;
-       if (rops & SEL_WR)      f->filp_select_flags |= FSF_WR_BLOCK;
-       if (rops & SEL_ERR)     f->filp_select_flags |= FSF_ERR_BLOCK;
-  }
-
-  if (f->filp_select_flags & FSF_BUSY)
-       return(SEL_DEFERRED);
-
-  major = major(f->filp_vno->v_sdev);
-  if (major < 0 || major >= NR_DEVICES) return(SEL_ERROR);
-  dp = &dmap[major];
-  if (dp->dmap_sel_filp)
-       return(SEL_DEFERRED);
-
-  f->filp_select_flags &= ~FSF_UPDATE;
-  r = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL,
-            cvu64(0), 0, 0, FALSE);
-  if (r < 0 && r != SUSPEND)
-       return(SEL_ERROR);
-
-  if (r != SUSPEND)
-       panic("select_request_asynch: expected SUSPEND got: %d", r);
-
-  dp->dmap_sel_filp = f;
-  f->filp_select_flags |= FSF_BUSY;
-
-  return(SEL_DEFERRED);
-}
-
-/*===========================================================================*
- *                             select_request_file                          *
- *===========================================================================*/
-PRIVATE int select_request_file(struct filp *UNUSED(f), int *UNUSED(ops),
-  int UNUSED(block))
-{
-  /* Files are always ready, so output *ops is input *ops */
-  return(SEL_OK);
-}
-
-/*===========================================================================*
- *                             select_request_major                         *
- *===========================================================================*/
-PRIVATE int select_request_major(struct filp *f, int *ops, int block)
-{
-  int major, r;
-
-  major = major(f->filp_vno->v_sdev);
-  if (major < 0 || major >= NR_DEVICES) return(SEL_ERROR);
-
-  if (dmap[major].dmap_style == STYLE_DEVA ||
-      dmap[major].dmap_style == STYLE_CLONE_A)
-       r = select_request_async(f, ops, block);
-  else
-       r = select_request_sync(f, ops, block);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             select_request_sync                          *
- *===========================================================================*/
-PRIVATE int select_request_sync(struct filp *f, int *ops, int block)
-{
-  int rops;
-
-  rops = *ops;
-  if (block) rops |= SEL_NOTIFY;
-  *ops = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL,
-               cvu64(0), 0, 0, FALSE);
-  if (*ops < 0)
-       return(SEL_ERROR);
-
-  return(SEL_OK);
-}
-
-/*===========================================================================*
- *                             select_request_pipe                          *
- *===========================================================================*/
-PRIVATE int select_request_pipe(struct filp *f, int *ops, int block)
-{
-  int orig_ops, r = 0, err;
-
-  orig_ops = *ops;
-
-  if ((*ops & (SEL_RD|SEL_ERR))) {
-       err = pipe_check(f->filp_vno, READING, 0, 1, f->filp_pos, 1);
-
-       if (err != SUSPEND)
-               r |= SEL_RD;
-       if (err < 0 && err != SUSPEND)
-               r |= SEL_ERR;
-       if (err == SUSPEND && !(f->filp_mode & R_BIT)) {
-               /* A "meaningless" read select, therefore ready
-                * for reading and no error set. */
-               r |= SEL_RD;
-               r &= ~SEL_ERR;
-       }
-  }
-
-  if ((*ops & (SEL_WR|SEL_ERR))) {
-       err = pipe_check(f->filp_vno, WRITING, 0, 1, f->filp_pos, 1);
-
-       if (err != SUSPEND)
-               r |= SEL_WR;
-       if (err < 0 && err != SUSPEND)
-               r |= SEL_ERR;
-       if (err == SUSPEND && !(f->filp_mode & W_BIT)) {
-               /* A "meaningless" write select, therefore ready
-                   for writing and no error set. */
-               r |= SEL_WR;
-               r &= ~SEL_ERR;
-       }
-  }
-
-  /* Some options we collected might not be requested. */
-  *ops = r & orig_ops;
-
-  if (!*ops && block)
-       f->filp_pipe_select_ops |= orig_ops;
-
-  return(SEL_OK);
-}
-
-/*===========================================================================*
- *                             tab2ops                                      *
- *===========================================================================*/
-PRIVATE int tab2ops(int fd, struct selectentry *e)
-{
-  int ops = 0;
-  if (FD_ISSET(fd, &e->readfds))  ops |= SEL_RD;
-  if (FD_ISSET(fd, &e->writefds)) ops |= SEL_WR;
-  if (FD_ISSET(fd, &e->errorfds)) ops |= SEL_ERR;
-
-  return(ops);
-}
-
-
-/*===========================================================================*
- *                             ops2tab                                      *
- *===========================================================================*/
-PRIVATE void ops2tab(int ops, int fd, struct selectentry *e)
-{
-  if ((ops & SEL_RD) && e->vir_readfds && FD_ISSET(fd, &e->readfds) &&
-      !FD_ISSET(fd, &e->ready_readfds)) {
-       FD_SET(fd, &e->ready_readfds);
-       e->nreadyfds++;
-  }
-
-  if ((ops & SEL_WR) && e->vir_writefds && FD_ISSET(fd, &e->writefds) &&
-      !FD_ISSET(fd, &e->ready_writefds)) {
-       FD_SET(fd, &e->ready_writefds);
-       e->nreadyfds++;
-  }
-
-  if ((ops & SEL_ERR) && e->vir_errorfds && FD_ISSET(fd, &e->errorfds) &&
-      !FD_ISSET(fd, &e->ready_errorfds)) {
-       FD_SET(fd, &e->ready_errorfds);
-       e->nreadyfds++;
-  }
-}
-
-
-/*===========================================================================*
- *                             copy_fdsets                                  *
- *===========================================================================*/
-PRIVATE int copy_fdsets(struct selectentry *se, int nfds, int direction)
-{
-  int r;
-  size_t fd_setsize;
-  endpoint_t src_e, dst_e;
-  fd_set *src_fds, *dst_fds;
-
-  if (nfds < 0 || nfds > OPEN_MAX)
-       panic("select copy_fdsets: nfds wrong: %d", nfds);
-
-  /* Only copy back as many bits as the user expects. */
-#ifdef __NBSD_LIBC
-  fd_setsize = (size_t) (howmany(nfds, __NFDBITS) * sizeof(__fd_mask));
-#else
-  fd_setsize = (size_t) (_FDSETWORDS(nfds) * _FDSETBITSPERWORD/8);
-#endif
-
-  /* Set source and destination endpoints */
-  src_e = (direction == FROM_PROC) ? se->req_endpt : SELF;
-  dst_e = (direction == FROM_PROC) ? SELF : se->req_endpt;
-
-  /* read set */
-  src_fds = (direction == FROM_PROC) ? se->vir_readfds : &se->ready_readfds;
-  dst_fds = (direction == FROM_PROC) ? &se->readfds : se->vir_readfds;
-  if (se->vir_readfds) {
-       r = sys_vircopy(src_e, D, (vir_bytes) src_fds, dst_e, D,
-                       (vir_bytes) dst_fds, fd_setsize);
-       if (r != OK) return(r);
-  }
-
-  /* write set */
-  src_fds = (direction == FROM_PROC) ? se->vir_writefds : &se->ready_writefds;
-  dst_fds = (direction == FROM_PROC) ? &se->writefds : se->vir_writefds;
-  if (se->vir_writefds) {
-       r = sys_vircopy(src_e, D, (vir_bytes) src_fds, dst_e, D,
-                       (vir_bytes) dst_fds, fd_setsize);
-       if (r != OK) return(r);
-  }
-
-  /* error set */
-  src_fds = (direction == FROM_PROC) ? se->vir_errorfds : &se->ready_errorfds;
-  dst_fds = (direction == FROM_PROC) ? &se->errorfds : se->vir_errorfds;
-  if (se->vir_errorfds) {
-       r = sys_vircopy(src_e, D, (vir_bytes) src_fds, dst_e, D,
-                       (vir_bytes) dst_fds, fd_setsize);
-       if (r != OK) return(r);
-  }
-
-  return(OK);
-}
-
-
-/*===========================================================================*
- *                             select_cancel_all                            *
- *===========================================================================*/
-PRIVATE void select_cancel_all(struct selectentry *se)
-{
-/* Cancel select. Decrease select usage and cancel timer */
-
-  int fd;
-  struct filp *f;
-
-  for (fd = 0; fd < se->nfds; fd++) {
-       if ((f = se->filps[fd]) == NULL) continue;
-       se->filps[fd] = NULL;
-       select_cancel_filp(f);
-  }
-
-  if (se->expiry > 0) {
-       cancel_timer(&se->timer);
-       se->expiry = 0;
-  }
-
-  se->requestor = NULL;
-}
-
-/*===========================================================================*
- *                             select_cancel_filp                           *
- *===========================================================================*/
-PRIVATE void select_cancel_filp(struct filp *f)
-{
-/* Reduce number of select users of this filp */
-
-  assert(f);
-  assert(f->filp_selectors >= 0);
-  if (f->filp_selectors == 0) return;
-  if (f->filp_count == 0) return;
-
-  select_lock_filp(f, f->filp_select_ops);
-
-  f->filp_selectors--;
-  if (f->filp_selectors == 0) {
-       /* No one selecting on this filp anymore, forget about select state */
-       f->filp_select_ops = 0;
-       f->filp_select_flags = 0;
-       f->filp_pipe_select_ops = 0;
-  }
-
-  unlock_filp(f);
-}
-
-/*===========================================================================*
- *                             select_return                                *
- *===========================================================================*/
-PRIVATE void select_return(struct selectentry *se)
-{
-  int r, r1;
-
-  assert(!is_deferred(se));    /* Not done yet, first wait for async reply */
-
-  select_cancel_all(se);
-
-  r1 = copy_fdsets(se, se->nfds, TO_PROC);
-  if (r1 != OK)
-       r = r1;
-  else if (se->error != OK)
-       r = se->error;
-  else
-       r = se->nreadyfds;
-
-  revive(se->req_endpt, r);
-}
-
-
-/*===========================================================================*
- *                             select_callback                              *
- *===========================================================================*/
-PUBLIC void select_callback(struct filp *f, int status)
-{
-  filp_status(f, status);
-}
-
-/*===========================================================================*
- *                             init_select                                  *
- *===========================================================================*/
-PUBLIC void init_select(void)
-{
-  int s;
-
-  for (s = 0; s < MAXSELECTS; s++)
-       init_timer(&selecttab[s].timer);
-}
-
-
-/*===========================================================================*
- *                             select_forget                                *
- *===========================================================================*/
-PUBLIC void select_forget(endpoint_t proc_e)
-{
-/* Something has happened (e.g. signal delivered that interrupts select()).
- * Totally forget about the select(). */
-
-  int slot;
-  struct selectentry *se;
-
-  for (slot = 0; slot < MAXSELECTS; slot++) {
-       se = &selecttab[slot];
-       if (se->requestor != NULL && se->req_endpt == proc_e)
-               break;
-  }
-
-  if (slot >= MAXSELECTS) return;      /* Entry not found */
-  se->error = EINTR;
-  if (is_deferred(se)) return;         /* Still awaiting initial reply */
-
-  select_cancel_all(se);
-}
-
-
-/*===========================================================================*
- *                             select_timeout_check                         *
- *===========================================================================*/
-PUBLIC void select_timeout_check(timer_t *timer)
-{
-  int s;
-  struct selectentry *se;
-
-  s = tmr_arg(timer)->ta_int;
-  if (s < 0 || s >= MAXSELECTS) return;        /* Entry does not exist */
-
-  se = &selecttab[s];
-  if (se->requestor == NULL) return;
-  fp = se->requestor;
-  if (se->expiry <= 0) return; /* Strange, did we even ask for a timeout? */
-  se->expiry = 0;
-  if (is_deferred(se)) return; /* Wait for initial replies to DEV_SELECT */
-  select_return(se);
-}
-
-
-/*===========================================================================*
- *                             select_unsuspend_by_endpt                    *
- *===========================================================================*/
-PUBLIC void select_unsuspend_by_endpt(endpoint_t proc_e)
-{
-/* Revive blocked processes when a driver has disappeared */
-
-  int fd, s, major;
-  struct selectentry *se;
-  struct filp *f;
-
-  for (s = 0; s < MAXSELECTS; s++) {
-       int wakehim = 0;
-       se = &selecttab[s];
-       if (se->requestor == NULL) continue;
-       if (se->requestor->fp_endpoint == proc_e) {
-               assert(se->requestor->fp_flags & FP_EXITING);
-               select_cancel_all(se);
-               continue;
-       }
-
-       for (fd = 0; fd < se->nfds; fd++) {
-               if ((f = se->filps[fd]) == NULL || f->filp_vno == NULL)
-                       continue;
-
-               major = major(f->filp_vno->v_sdev);
-               if (dmap_driver_match(proc_e, major)) {
-                       se->filps[fd] = NULL;
-                       se->error = EINTR;
-                       select_cancel_filp(f);
-                       wakehim = 1;
-               }
-       }
-
-       if (wakehim && !is_deferred(se))
-               select_return(se);
-  }
-}
-
-/*===========================================================================*
- *                             select_reply1                                *
- *===========================================================================*/
-PUBLIC void select_reply1(driver_e, minor, status)
-endpoint_t driver_e;
-int minor;
-int status;
-{
-/* Handle reply to DEV_SELECT request */
-
-  int major;
-  dev_t dev;
-  struct filp *f;
-  struct dmap *dp;
-  struct vnode *vp;
-
-  /* Figure out which device is replying */
-  if ((dp = get_dmap(driver_e)) == NULL) return;
-
-  major = dp-dmap;
-  dev = makedev(major, minor);
-
-  /* Get filp belonging to character special file */
-  if ((f = dp->dmap_sel_filp) == NULL) {
-       printf("VFS (%s:%d): major %d was not expecting a DEV_SELECT reply\n",
-               __FILE__, __LINE__, major);
-       return;
-  }
-
-  /* Is the filp still in use and busy waiting for a reply? The owner might
-   * have vanished before the driver was able to reply. */
-  if (f->filp_count >= 1 && (f->filp_select_flags & FSF_BUSY)) {
-       /* Find vnode and check we got a reply from the device we expected */
-       vp = f->filp_vno;
-       assert(vp != NULL);
-       assert((vp->v_mode & I_TYPE) == I_CHAR_SPECIAL); /* Must be char. special */
-       if (vp->v_sdev != dev) {
-               printf("VFS (%s:%d): expected reply from dev %d not %d\n",
-                       __FILE__, __LINE__, vp->v_sdev, dev);
-               return;
-       }
-  }
-
-  /* No longer waiting for a reply from this device */
-  dp->dmap_sel_filp = NULL;
-
-  /* Process select result only if requestor is still around. That is, the
-   * corresponding filp is still in use.
-   */
-  if (f->filp_count >= 1) {
-       select_lock_filp(f, f->filp_select_ops);
-       f->filp_select_flags &= ~FSF_BUSY;
-
-       /* The select call is done now, except when
-        * - another process started a select on the same filp with possibly a
-        *   different set of operations.
-        * - a process does a select on the same filp but using different file
-        *   descriptors.
-        * - the select has a timeout. Upon receiving this reply the operations
-        *   might not be ready yet, so we want to wait for that to ultimately
-        *   happen.
-        *   Therefore we need to keep remembering what the operations are.
-        */
-       if (!(f->filp_select_flags & (FSF_UPDATE|FSF_BLOCKED)))
-               f->filp_select_ops = 0;         /* done selecting */
-       else if (!(f->filp_select_flags & FSF_UPDATE))
-               /* there may be operations pending */
-               f->filp_select_ops &= ~status;
-
-       /* Tell filp owners about result unless we need to wait longer */
-       if (!(status == 0 && (f->filp_select_flags & FSF_BLOCKED))) {
-               if (status > 0) {       /* operations ready */
-                       if (status & SEL_RD)
-                               f->filp_select_flags &= ~FSF_RD_BLOCK;
-                       if (status & SEL_WR)
-                               f->filp_select_flags &= ~FSF_WR_BLOCK;
-                       if (status & SEL_ERR)
-                               f->filp_select_flags &= ~FSF_ERR_BLOCK;
-               } else if (status < 0) { /* error */
-                       /* Always unblock upon error */
-                       f->filp_select_flags &= ~FSF_BLOCKED;
-               }
-
-               unlock_filp(f);
-               filp_status(f, status); /* Tell filp owners about the results */
-       } else {
-               unlock_filp(f);
-       }
-  }
-
-  select_restart_filps();
-}
-
-
-/*===========================================================================*
- *                             select_reply2                                *
- *===========================================================================*/
-PUBLIC void select_reply2(driver_e, minor, status)
-endpoint_t driver_e;
-int minor;
-int status;
-{
-/* Handle secondary reply to DEV_SELECT request. A secondary reply occurs when
- * the select request is 'blocking' until an operation becomes ready. */
-  int major, slot, fd;
-  dev_t dev;
-  struct filp *f;
-  struct dmap *dp;
-  struct vnode *vp;
-  struct selectentry *se;
-
-  if (status == 0) {
-       printf("VFS (%s:%d): weird status (%d) to report\n",
-               __FILE__, __LINE__, status);
-       return;
-  }
-
-  /* Figure out which device is replying */
-  if ((dp = get_dmap(driver_e)) == NULL) {
-       printf("VFS (%s:%d): endpoint %d is not a known driver endpoint\n",
-               __FILE__, __LINE__, driver_e);
-       return;
-  }
-  major = dp-dmap;
-  dev = makedev(major, minor);
-
-  /* Find all file descriptors selecting for this device */
-  for (slot = 0; slot < MAXSELECTS; slot++) {
-       se = &selecttab[slot];
-       if (se->requestor == NULL) continue;    /* empty slot */
-
-       for (fd = 0; fd < se->nfds; fd++) {
-               if ((f = se->filps[fd]) == NULL) continue;
-               if ((vp = f->filp_vno) == NULL) continue;
-               if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
-               if (vp->v_sdev != dev) continue;
-
-               select_lock_filp(f, f->filp_select_ops);
-               if (status > 0) {       /* Operations ready */
-                       /* Clear the replied bits from the request
-                        * mask unless FSF_UPDATE is set.
-                        */
-                       if (!(f->filp_select_flags & FSF_UPDATE))
-                               f->filp_select_ops &= ~status;
-                       if (status & SEL_RD)
-                               f->filp_select_flags &= ~FSF_RD_BLOCK;
-                       if (status & SEL_WR)
-                               f->filp_select_flags &= ~FSF_WR_BLOCK;
-                       if (status & SEL_ERR)
-                               f->filp_select_flags &= ~FSF_ERR_BLOCK;
-
-                       ops2tab(status, fd, se);
-               } else {
-                       f->filp_select_flags &= ~FSF_BLOCKED;
-                       ops2tab(SEL_RD|SEL_WR|SEL_ERR, fd, se);
-               }
-               unlock_filp(f);
-               if (se->nreadyfds > 0) restart_proc(se);
-       }
-  }
-
-  select_restart_filps();
-}
-
-/*===========================================================================*
- *                             select_restart_filps                         *
- *===========================================================================*/
-PRIVATE void select_restart_filps()
-{
-  int fd, slot;
-  struct filp *f;
-  struct vnode *vp;
-  struct selectentry *se;
-
-  /* Locate filps that can be restarted */
-  for (slot = 0; slot < MAXSELECTS; slot++) {
-       se = &selecttab[slot];
-       if (se->requestor == NULL) continue; /* empty slot */
-
-       /* Only 'deferred' processes are eligible to restart */
-       if (!is_deferred(se)) continue;
-
-       /* Find filps that are not waiting for a reply, but have an updated
-        * status (i.e., another select on the same filp with possibly a
-        * different set of operations is to be done), and thus requires the
-        * select request to be sent again).
-        */
-       for (fd = 0; fd < se->nfds; fd++) {
-               int r, wantops, ops;
-               if ((f = se->filps[fd]) == NULL) continue;
-               if (f->filp_select_flags & FSF_BUSY) /* Still waiting for */
-                       continue;                    /* initial reply */
-               if (!(f->filp_select_flags & FSF_UPDATE)) /* Must be in  */
-                       continue;                         /* 'update' state */
-
-               wantops = ops = f->filp_select_ops;
-               select_lock_filp(f, ops);
-               vp = f->filp_vno;
-               assert((vp->v_mode & I_TYPE) == I_CHAR_SPECIAL);
-               r = do_select_request(se, fd, &wantops);
-               unlock_filp(f);
-               if (r != SEL_OK) {
-                       if (r == SEL_DEFERRED) continue;
-                       else break; /* Error or bogus return code; abort */
-               }
-               if (wantops & ops) ops2tab(wantops, fd, se);
-       }
-  }
-}
-
-/*===========================================================================*
- *                             do_select_request                            *
- *===========================================================================*/
-PRIVATE int do_select_request(se, fd, ops)
-struct selectentry *se;
-int fd;
-int *ops;
-{
-/* Perform actual select request for file descriptor fd */
-
-  int r, type;
-  struct filp *f;
-
-  type = se->type[fd];
-  f = se->filps[fd];
-  r = fdtypes[type].select_request(f, ops, se->block);
-  if (r != SEL_OK && r != SEL_DEFERRED) {
-       se->error = EINTR;
-       se->block = 0;  /* Stop blocking to return asap */
-       if (!is_deferred(se)) select_cancel_all(se);
-  }
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             filp_status                                  *
- *===========================================================================*/
-PRIVATE void filp_status(f, status)
-struct filp *f;
-int status;
-{
-/* Tell processes that need to know about the status of this filp */
-  int fd, slot;
-  struct selectentry *se;
-
-  for (slot = 0; slot < MAXSELECTS; slot++) {
-       se = &selecttab[slot];
-       if (se->requestor == NULL) continue; /* empty slot */
-
-       for (fd = 0; fd < se->nfds; fd++) {
-               if (se->filps[fd] != f) continue;
-               if (status < 0)
-                       ops2tab(SEL_RD|SEL_WR|SEL_ERR, fd, se);
-               else
-                       ops2tab(status, fd, se);
-               restart_proc(se);
-       }
-  }
-}
-
-/*===========================================================================*
- *                             restart_proc                                 *
- *===========================================================================*/
-PRIVATE void restart_proc(se)
-struct selectentry *se;
-{
-/* Tell process about select results (if any) unless there are still results
- * pending. */
-
-  if ((se->nreadyfds > 0 || !se->block) && !is_deferred(se))
-       select_return(se);
-}
-
-/*===========================================================================*
- *                             wipe_select                                  *
- *===========================================================================*/
-PRIVATE void wipe_select(struct selectentry *se)
-{
-  se->nfds = 0;
-  se->nreadyfds = 0;
-  se->error = OK;
-  se->block = 0;
-  memset(se->filps, 0, sizeof(se->filps));
-
-  FD_ZERO(&se->readfds);
-  FD_ZERO(&se->writefds);
-  FD_ZERO(&se->errorfds);
-  FD_ZERO(&se->ready_readfds);
-  FD_ZERO(&se->ready_writefds);
-  FD_ZERO(&se->ready_errorfds);
-}
-
-/*===========================================================================*
- *                             select_lock_filp                                     *
- *===========================================================================*/
-PRIVATE void select_lock_filp(struct filp *f, int ops)
-{
-/* Lock a filp and vnode based on which operations are requested */
-  tll_access_t locktype;;
-
-  locktype = VNODE_READ; /* By default */
-
-  if (ops & (SEL_WR|SEL_ERR))
-       /* Selecting for error or writing requires exclusive access */
-       locktype = VNODE_WRITE;
-
-  lock_filp(f, locktype);
-}
diff --git a/servers/avfs/select.h b/servers/avfs/select.h
deleted file mode 100644 (file)
index 5215b1a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-#ifndef __VFS_SELECT_H__
-#define __VFS_SELECT_H__
-
-/* return codes for select_request_* and select_cancel_* */
-#define SEL_OK         0       /* ready */
-#define SEL_ERROR      1       /* failed */
-#define SEL_DEFERRED   2       /* request is sent to driver */
-
-#endif
diff --git a/servers/avfs/stadir.c b/servers/avfs/stadir.c
deleted file mode 100644 (file)
index bc49bf9..0000000
+++ /dev/null
@@ -1,287 +0,0 @@
-/* This file contains the code for performing four system calls relating to
- * status and directories.
- *
- * The entry points into this file are
- *   do_chdir: perform the CHDIR system call
- *   do_chroot:        perform the CHROOT system call
- *   do_lstat:  perform the LSTAT system call
- *   do_stat:  perform the STAT system call
- *   do_fstat: perform the FSTAT system call
- *   do_fstatfs: perform the FSTATFS system call
- *   do_statvfs: perform the STATVFS system call
- *   do_fstatvfs: perform the FSTATVFS system call
- */
-
-#include "fs.h"
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <minix/com.h>
-#include <minix/u64.h>
-#include <string.h>
-#include "file.h"
-#include "fproc.h"
-#include "path.h"
-#include "param.h"
-#include <minix/vfsif.h>
-#include <minix/callnr.h>
-#include "vnode.h"
-#include "vmnt.h"
-
-FORWARD _PROTOTYPE( int change, (struct vnode **iip, char *name_ptr, int len));
-FORWARD _PROTOTYPE( int change_into, (struct vnode **iip, struct vnode *vp));
-
-/*===========================================================================*
- *                             do_fchdir                                    *
- *===========================================================================*/
-PUBLIC int do_fchdir()
-{
-  /* Change directory on already-opened fd. */
-  struct filp *rfilp;
-  int r;
-
-  /* Is the file descriptor valid? */
-  if ((rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
-  r = change_into(&fp->fp_wd, rfilp->filp_vno);
-  unlock_filp(rfilp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_chdir                                     *
- *===========================================================================*/
-PUBLIC int do_chdir()
-{
-/* Perform the chdir(name) system call. */
-
-  return change(&fp->fp_wd, m_in.name, m_in.name_length);
-}
-
-/*===========================================================================*
- *                             do_chroot                                    *
- *===========================================================================*/
-PUBLIC int do_chroot()
-{
-/* Perform the chroot(name) system call. */
-
-  if (!super_user) return(EPERM);      /* only su may chroot() */
-  return change(&fp->fp_rd, m_in.name, m_in.name_length);
-}
-
-/*===========================================================================*
- *                             change                                       *
- *===========================================================================*/
-PRIVATE int change(iip, name_ptr, len)
-struct vnode **iip;            /* pointer to the inode pointer for the dir */
-char *name_ptr;                        /* pointer to the directory name to change to */
-int len;                       /* length of the directory name string */
-{
-/* Do the actual work for chdir() and chroot(). */
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-  int r;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* Try to open the directory */
-  if (fetch_name(name_ptr, len, M3, fullpath) != OK) return(err_code);
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-  r = change_into(iip, vp);
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-  put_vnode(vp);
-  return(r);
-}
-
-/*===========================================================================*
- *                             change_into                                  *
- *===========================================================================*/
-PRIVATE int change_into(iip, vp)
-struct vnode **iip;            /* pointer to the inode pointer for the dir */
-struct vnode *vp;              /* this is what the inode has to become */
-{
-  int r;
-
-  if (*iip == vp) return(OK);  /* Nothing to do */
-
-  /* It must be a directory and also be searchable */
-  if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
-       r = ENOTDIR;
-  else
-       r = forbidden(fp, vp, X_BIT);   /* Check if dir is searchable*/
-  if (r != OK) return(r);
-
-  /* Everything is OK.  Make the change. */
-  put_vnode(*iip);             /* release the old directory */
-  dup_vnode(vp);
-  *iip = vp;                   /* acquire the new one */
-  return(OK);
-}
-
-/*===========================================================================*
- *                             do_stat                                      *
- *===========================================================================*/
-PUBLIC int do_stat()
-{
-/* Perform the stat(name, buf) system call. */
-  int r;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-  int old_stat = 0;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  if (call_nr == PREV_STAT)
-       old_stat = 1;
-
-  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-       return(err_code);
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-  r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat);
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-
-  put_vnode(vp);
-  return r;
-}
-
-/*===========================================================================*
- *                             do_fstat                                     *
- *===========================================================================*/
-PUBLIC int do_fstat()
-{
-/* Perform the fstat(fd, buf) system call. */
-  register struct filp *rfilp;
-  int r;
-  int pipe_pos = 0;
-  int old_stat = 0;
-
-  if (call_nr == PREV_FSTAT)
-       old_stat = 1;
-
-  /* Is the file descriptor valid? */
-  if ((rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
-
-  /* If we read from a pipe, send position too */
-  if (rfilp->filp_vno->v_pipe == I_PIPE) {
-       if (rfilp->filp_mode & R_BIT)
-               if (ex64hi(rfilp->filp_pos) != 0) {
-                       panic("do_fstat: bad position in pipe");
-               }
-       pipe_pos = ex64lo(rfilp->filp_pos);
-  }
-
-  r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
-              who_e, m_in.buffer, pipe_pos, old_stat);
-
-  unlock_filp(rfilp);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_fstatfs                                   *
- *===========================================================================*/
-PUBLIC int do_fstatfs()
-{
-/* Perform the fstatfs(fd, buf) system call. */
-  struct filp *rfilp;
-  int r;
-
-  /* Is the file descriptor valid? */
-  if( (rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
-
-  r = req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, m_in.buffer);
-
-  unlock_filp(rfilp);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_statvfs                                           *
- *===========================================================================*/
-PUBLIC int do_statvfs()
-{
-/* Perform the stat(name, buf) system call. */
-  int r;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  if (fetch_name(m_in.STATVFS_NAME, m_in.STATVFS_LEN, M1, fullpath) != OK)
-       return(err_code);
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-  r = req_statvfs(vp->v_fs_e, who_e, m_in.STATVFS_BUF);
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-
-  put_vnode(vp);
-  return r;
-}
-
-/*===========================================================================*
- *                             do_fstatvfs                                  *
- *===========================================================================*/
-PUBLIC int do_fstatvfs()
-{
-/* Perform the fstat(fd, buf) system call. */
-  register struct filp *rfilp;
-  int r;
-
-  /* Is the file descriptor valid? */
-  if ((rfilp = get_filp(m_in.FSTATVFS_FD, VNODE_READ)) == NULL)
-       return(err_code);
-
-  r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, m_in.FSTATVFS_BUF);
-
-  unlock_filp(rfilp);
-
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_lstat                                             *
- *===========================================================================*/
-PUBLIC int do_lstat()
-{
-/* Perform the lstat(name, buf) system call. */
-  struct vnode *vp;
-  struct vmnt *vmp;
-  int r;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-  int old_stat = 0;
-
-  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_READ;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  if (call_nr == PREV_LSTAT)
-       old_stat = 1;
-  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
-       return(err_code);
-
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-  r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat);
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-
-  put_vnode(vp);
-  return(r);
-}
diff --git a/servers/avfs/table.c b/servers/avfs/table.c
deleted file mode 100644 (file)
index 4429e31..0000000
+++ /dev/null
@@ -1,145 +0,0 @@
-/* This file contains the table used to map system call numbers onto the
- * routines that perform them.
- */
-
-#define _TABLE
-
-#include "fs.h"
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include "file.h"
-#include "fproc.h"
-#include "lock.h"
-#include "scratchpad.h"
-#include "vnode.h"
-#include "vmnt.h"
-
-PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
-       no_sys,         /*  0 = unused  */
-       no_sys,         /*  1 = (exit)  */
-       no_sys,         /*  2 = (fork)  */
-       do_read,        /*  3 = read    */
-       do_write,       /*  4 = write   */
-       do_open,        /*  5 = open    */
-       do_close,       /*  6 = close   */
-       no_sys,         /*  7 = wait    */
-       do_creat,       /*  8 = creat   */
-       do_link,        /*  9 = link    */
-       do_unlink,      /* 10 = unlink  */
-       no_sys,         /* 11 = waitpid */
-       do_chdir,       /* 12 = chdir   */
-       no_sys,         /* 13 = time    */
-       do_mknod,       /* 14 = mknod   */
-       do_chmod,       /* 15 = chmod   */
-       do_chown,       /* 16 = chown   */
-       no_sys,         /* 17 = break   */
-       do_stat,        /* 18 = stat (prev)*/
-       do_lseek,       /* 19 = lseek   */
-       no_sys,         /* 20 = getpid  */
-       do_mount,       /* 21 = mount   */
-       do_umount,      /* 22 = umount  */
-       no_sys,         /* 23 = (setuid) */
-       no_sys,         /* 24 = getuid  */
-       no_sys,         /* 25 = (stime) */
-       no_sys,         /* 26 = ptrace  */
-       no_sys,         /* 27 = alarm   */
-       do_fstat,       /* 28 = fstat (prev)*/
-       no_sys,         /* 29 = pause   */
-       do_utime,       /* 30 = utime   */
-       no_sys,         /* 31 = (stty)  */
-       no_sys,         /* 32 = (gtty)  */
-       do_access,      /* 33 = access  */
-       no_sys,         /* 34 = (nice)  */
-       no_sys,         /* 35 = (ftime) */
-       do_sync,        /* 36 = sync    */
-       no_sys,         /* 37 = kill    */
-       do_rename,      /* 38 = rename  */
-       do_mkdir,       /* 39 = mkdir   */
-       do_unlink,      /* 40 = rmdir   */
-       do_dup,         /* 41 = dup     */
-       do_pipe,        /* 42 = pipe    */
-       no_sys,         /* 43 = times   */
-       no_sys,         /* 44 = (prof)  */
-       do_slink,       /* 45 = symlink */
-       no_sys,         /* 46 = (setgid)*/
-       no_sys,         /* 47 = getgid  */
-       no_sys,         /* 48 = (signal)*/
-       do_rdlink,      /* 49 = readlink*/
-       do_lstat,       /* 50 = lstat (prev)*/
-       do_stat,        /* 51 = stat    */
-       do_fstat,       /* 52 = fstat   */
-       do_lstat,       /* 53 = lstat   */
-       do_ioctl,       /* 54 = ioctl   */
-       do_fcntl,       /* 55 = fcntl   */
-       no_sys,         /* 56 = (mpx)   */
-       do_fsready,     /* 57 = FS proc ready */
-       no_sys,         /* 58 = unused  */
-       no_sys,         /* 59 = (execve)*/
-       do_umask,       /* 60 = umask   */
-       do_chroot,      /* 61 = chroot  */
-       no_sys,         /* 62 = (setsid)*/
-       no_sys,         /* 63 = (getpgrp)*/
-       no_sys,         /* 64 = (itimer)*/
-       do_stat,        /* 65 = stat  - badly numbered, being phased out */
-       do_fstat,       /* 66 = fstat - badly numbered, being phased out */
-       do_lstat,       /* 67 = lstat - badly numbered, being phased out */
-       no_sys,         /* 68 = unused  */
-       no_sys,         /* 69 = unused  */
-       no_sys,         /* 70 = unused  */
-       no_sys,         /* 71 = (sigaction) */
-       no_sys,         /* 72 = (sigsuspend) */
-       no_sys,         /* 73 = (sigpending) */
-       no_sys,         /* 74 = (sigprocmask) */
-       no_sys,         /* 75 = (sigreturn) */
-       no_sys,         /* 76 = (reboot) */
-       do_svrctl,      /* 77 = svrctl */
-       no_sys,         /* 78 = (sysuname) */
-       no_sys,         /* 79 = unused */
-       do_getdents,    /* 80 = getdents */
-       do_llseek,      /* 81 = llseek */
-       do_fstatfs,     /* 82 = fstatfs */
-       do_statvfs,             /* 83 = fstatvfs */
-       do_fstatvfs,            /* 84 = statvfs */
-       do_select,      /* 85 = select */
-       do_fchdir,      /* 86 = fchdir */
-       do_fsync,       /* 87 = fsync */
-       no_sys,         /* 88 = (getpriority) */
-       no_sys,         /* 89 = (setpriority) */
-       no_sys,         /* 90 = (gettimeofday) */
-       no_sys,         /* 91 = (seteuid) */
-       no_sys,         /* 92 = (setegid) */
-       do_truncate,    /* 93 = truncate */
-       do_ftruncate,   /* 94 = truncate */
-       do_chmod,       /* 95 = fchmod */
-       do_chown,       /* 96 = fchown */
-       no_sys,         /* 97 = unused */
-       no_sys,         /* 98 = (sprofile) */
-       no_sys,         /* 99 = (cprofile) */
-       no_sys,         /* 100 = (exec_newmem) */
-       no_sys,         /* 101 = (srv_fork) */
-       no_sys,         /* 102 = (exec_restart) */
-       no_sys,         /* 103 = unused */
-       no_sys,         /* 104 = (getprocnr) */
-       no_sys,         /* 105 = unused */
-       no_sys,         /* 106 = unused */
-       no_sys,         /* 107 = (getepinfo) */
-       no_sys,         /* 108 = unused */
-       no_sys,         /* 109 = unused */
-       no_sys,         /* 110 = unused */
-       no_sys,         /* 111 = (srv_kill) */
-       do_gcov_flush,  /* 112 = gcov_flush */
-       no_sys,         /* 113 = (getsid) */
-};
-/* This should not fail with "array size is negative": */
-extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
-
-PUBLIC _PROTOTYPE (int (*pfs_call_vec[]), (void) ) = {
-
-       no_sys,         /* 0 */
-       do_check_perms, /* 1 */
-       do_verify_fd,   /* 2 */
-       do_set_filp,    /* 3 */
-       do_copy_filp,   /* 4 */
-       do_put_filp,    /* 5 */
-       do_cancel_fd    /* 6 */
-};
diff --git a/servers/avfs/time.c b/servers/avfs/time.c
deleted file mode 100644 (file)
index 29b84e3..0000000
+++ /dev/null
@@ -1,66 +0,0 @@
-/* This file takes care of those system calls that deal with time.
- *
- * The entry points into this file are
- *   do_utime:         perform the UTIME system call
- */
-
-#include "fs.h"
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include "file.h"
-#include "fproc.h"
-#include "path.h"
-#include "param.h"
-#include "vnode.h"
-#include <minix/vfsif.h>
-#include "vmnt.h"
-
-/*===========================================================================*
- *                             do_utime                                     *
- *===========================================================================*/
-PUBLIC int do_utime()
-{
-/* Perform the utime(name, timep) system call. */
-  register int len;
-  int r;
-  time_t actime, modtime;
-  struct vnode *vp;
-  struct vmnt *vmp;
-  char fullpath[PATH_MAX];
-  struct lookup resolve;
-
-  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
-  resolve.l_vmnt_lock = VMNT_WRITE;
-  resolve.l_vnode_lock = VNODE_READ;
-
-  /* Adjust for case of 'timep' being NULL;
-   * utime_strlen then holds the actual size: strlen(name)+1 */
-  len = m_in.utime_length;
-  if (len == 0) len = m_in.utime_strlen;
-
-  /* Temporarily open the file */
-  if (fetch_name(m_in.utime_file, len, M1, fullpath) != OK) return(err_code);
-  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-
-  /* Only the owner of a file or the super user can change its name. */
-  r = OK;
-  if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM;
-  if (m_in.utime_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT);
-  if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */
-  if (r == OK) {
-       /* Issue request */
-       if(m_in.utime_length == 0) {
-               actime = modtime = clock_time();
-       } else {
-               actime = m_in.utime_actime;
-               modtime = m_in.utime_modtime;
-       }
-       r = req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime);
-  }
-
-  unlock_vnode(vp);
-  unlock_vmnt(vmp);
-
-  put_vnode(vp);
-  return(r);
-}
diff --git a/servers/avfs/utility.c b/servers/avfs/utility.c
deleted file mode 100644 (file)
index 71922d8..0000000
+++ /dev/null
@@ -1,153 +0,0 @@
-/* This file contains a few general purpose utility routines.
- *
- * The entry points into this file are
- *   clock_time:  ask the clock task for the real time
- *   copy:       copy a block of data
- *   fetch_name:  go get a path name from user space
- *   no_sys:      reject a system call that FS does not handle
- *   panic:       something awful has occurred;  MINIX cannot continue
- *   conv2:      do byte swapping on a 16-bit int
- *   conv4:      do byte swapping on a 32-bit long
- *   in_group:    determines if group 'grp' is in rfp->fp_sgroups[]
- */
-
-#include "fs.h"
-#include <minix/com.h>
-#include <minix/endpoint.h>
-#include <unistd.h>
-#include <stdlib.h>
-#include <assert.h>
-#include "file.h"
-#include "fproc.h"
-#include "param.h"
-#include "vmnt.h"
-
-/*===========================================================================*
- *                             fetch_name                                   *
- *===========================================================================*/
-PUBLIC int fetch_name(path, len, flag, dest)
-char *path;                    /* pointer to the path in user space */
-int len;                       /* path length, including 0 byte */
-int flag;                      /* M3 means path may be in message */
-char *dest;                    /* pointer to where path is to be stored */
-{
-/* Go get path and put it in 'user_fullpath'.
- * If 'flag' = M3 and 'len' <= M3_STRING, the path is present in 'message'.
- * If it is not, go copy it from user space.
- */
-  register char *rpu, *rpm;
-  int r, count;
-
-  if (len > PATH_MAX) {        /* 'len' includes terminating-nul */
-       err_code = ENAMETOOLONG;
-       return(EGENERIC);
-  }
-
-  /* Check name length for validity. */
-  if (len <= 0) {
-       err_code = EINVAL;
-       return(EGENERIC);
-  }
-
-  if (flag == M3 && len <= M3_STRING) {
-       /* Just copy the path from the message to 'user_fullpath'. */
-       rpu = &dest[0];
-       rpm = m_in.pathname;            /* contained in input message */
-       count = len;
-       do { *rpu++ = *rpm++; } while (--count);
-       r = OK;
-  } else {
-       /* String is not contained in the message.  Get it from user space. */
-       r = sys_datacopy(who_e, (vir_bytes) path,
-               VFS_PROC_NR, (vir_bytes) dest, (phys_bytes) len);
-  }
-
-  if (dest[len - 1] != '\0') {
-       err_code = ENAMETOOLONG;
-       return(EGENERIC);
-  }
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             no_sys                                       *
- *===========================================================================*/
-PUBLIC int no_sys()
-{
-/* Somebody has used an illegal system call number */
-  return(ENOSYS);
-}
-
-
-/*===========================================================================*
- *                             isokendpt_f                                  *
- *===========================================================================*/
-PUBLIC int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc, int fatal)
-{
-  int failed = 0;
-  endpoint_t ke;
-  *proc = _ENDPOINT_P(endpoint);
-  if (endpoint == NONE) {
-       printf("VFS %s:%d: endpoint is NONE\n", file, line);
-       failed = 1;
-  } else if (*proc < 0 || *proc >= NR_PROCS) {
-       printf("VFS %s:%d: proc (%d) from endpoint (%d) out of range\n",
-               file, line, *proc, endpoint);
-       failed = 1;
-  } else if ((ke = fproc[*proc].fp_endpoint) != endpoint) {
-       if(ke == NONE) {
-               printf("VFS %s:%d: endpoint (%d) points to NONE slot (%d)\n",
-                       file, line, endpoint, *proc);
-               assert(fproc[*proc].fp_pid == PID_FREE);
-       } else {
-               printf("VFS %s:%d: proc (%d) from endpoint (%d) doesn't match "
-                       "known endpoint (%d)\n", file, line, *proc, endpoint,
-                       fproc[*proc].fp_endpoint);
-               assert(fproc[*proc].fp_pid != PID_FREE);
-       }
-       failed = 1;
-  }
-
-  if(failed && fatal)
-       panic("isokendpt_f failed");
-
-  return(failed ? EDEADEPT : OK);
-}
-
-
-/*===========================================================================*
- *                             clock_time                                   *
- *===========================================================================*/
-PUBLIC time_t clock_time()
-{
-/* This routine returns the time in seconds since 1.1.1970.  MINIX is an
- * astrophysically naive system that assumes the earth rotates at a constant
- * rate and that such things as leap seconds do not exist.
- */
-
-  register int r;
-  clock_t uptime;
-  time_t boottime;
-
-  r = getuptime2(&uptime, &boottime);
-  if (r != OK)
-       panic("clock_time err: %d", r);
-
-  return( (time_t) (boottime + (uptime/system_hz)));
-}
-
-/*===========================================================================*
- *                              in_group                                     *
- *===========================================================================*/
-PUBLIC int in_group(struct fproc *rfp, gid_t grp)
-{
-  int i;
-
-  for (i = 0; i < rfp->fp_ngroups; i++)
-       if (rfp->fp_sgroups[i] == grp)
-               return(OK);
-
-  return(EINVAL);
-}
diff --git a/servers/avfs/vmnt.c b/servers/avfs/vmnt.c
deleted file mode 100644 (file)
index bb3dc07..0000000
+++ /dev/null
@@ -1,201 +0,0 @@
-/* Virtual mount table related routines.
- *
- */
-
-#include "fs.h"
-#include "threads.h"
-#include "vmnt.h"
-#include <assert.h>
-#include "fproc.h"
-
-FORWARD _PROTOTYPE( int is_vmnt_locked, (struct vmnt *vmp)             );
-FORWARD _PROTOTYPE( void clear_vmnt, (struct vmnt *vmp)                        );
-
-/* Is vmp pointer reasonable? */
-#define SANEVMP(v) ((((v) >= &vmnt[0] && (v) < &vmnt[NR_MNTS])))
-#define BADVMP(v, f, l) printf("%s:%d: bad vmp %p\n", f, l, v)
-/* vp check that panics */
-#define ASSERTVMP(v) if(!SANEVMP(v)) { \
-       BADVMP(v, __FILE__, __LINE__); panic("bad vmp"); }
-
-#if LOCK_DEBUG
-/*===========================================================================*
- *                             check_vmnt_locks_by_me                       *
- *===========================================================================*/
-PUBLIC void check_vmnt_locks_by_me(struct fproc *rfp)
-{
-/* Check whether this thread still has locks held on vmnts */
-  struct vmnt *vmp;
-
-  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
-       if (tll_locked_by_me(&vmp->m_lock))
-               panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n",
-                     mthread_self(), vmp, call_nr);
-  }
-
-  if (rfp->fp_vmnt_rdlocks != 0)
-       panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n",
-             mthread_self(), rfp->fp_vmnt_rdlocks, call_nr);
-}
-#endif
-
-/*===========================================================================*
- *                             check_vmnt_locks                             *
- *===========================================================================*/
-PUBLIC void check_vmnt_locks()
-{
-  struct vmnt *vmp;
-  int count = 0;
-
-  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++)
-       if (is_vmnt_locked(vmp)) {
-               count++;
-               printf("vmnt %p is %s, fs_e=%d dev=%d\n", vmp, (tll_islocked(&vmp->m_lock) ? "locked":"pending locked"), vmp->m_fs_e, vmp->m_dev);
-       }
-
-  if (count) panic("%d locked vmnts\n", count);
-#if 0
-  printf("check_vmnt_locks OK\n");
-#endif
-}
-
-/*===========================================================================*
- *                             clear_vmnt                                   *
- *===========================================================================*/
-PRIVATE void clear_vmnt(struct vmnt *vmp)
-{
-/* Reset vmp to initial parameters */
-  ASSERTVMP(vmp);
-
-  vmp->m_fs_e = NONE;
-  vmp->m_dev = NO_DEV;
-  vmp->m_flags = 0;
-  vmp->m_mounted_on = NULL;
-  vmp->m_root_node = NULL;
-  vmp->m_label[0] = '\0';
-  vmp->m_comm.c_max_reqs = 1;
-  vmp->m_comm.c_cur_reqs = 0;
-  vmp->m_comm.c_req_queue = NULL;
-}
-
-/*===========================================================================*
- *                             get_free_vmnt                                *
- *===========================================================================*/
-PUBLIC struct vmnt *get_free_vmnt(void)
-{
-  struct vmnt *vp;
-
-  for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
-      if (vp->m_dev == NO_DEV) return(vp);
-
-  return(NULL);
-}
-
-/*===========================================================================*
- *                             find_vmnt                                    *
- *===========================================================================*/
-PUBLIC struct vmnt *find_vmnt(endpoint_t fs_e)
-{
-/* Find the vmnt belonging to an FS with endpoint 'fs_e' iff it's in use */
-  struct vmnt *vp;
-
-  for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
-       if (vp->m_fs_e == fs_e && vp->m_dev != NO_DEV)
-               return(vp);
-
-  return(NULL);
-}
-
-/*===========================================================================*
- *                             init_vmnts                                   *
- *===========================================================================*/
-PUBLIC void init_vmnts(void)
-{
-/* Initialize vmnt table */
-  struct vmnt *vmp;
-
-  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
-       clear_vmnt(vmp);
-       tll_init(&vmp->m_lock);
-  }
-}
-
-/*===========================================================================*
- *                             is_vmnt_locked                               *
- *===========================================================================*/
-PRIVATE int is_vmnt_locked(struct vmnt *vmp)
-{
-  ASSERTVMP(vmp);
-  return(tll_islocked(&vmp->m_lock) || tll_haspendinglock(&vmp->m_lock));
-}
-
-/*===========================================================================*
- *                             lock_vmnt                                    *
- *===========================================================================*/
-PUBLIC int lock_vmnt(struct vmnt *vmp, tll_access_t locktype)
-{
-  int r;
-  tll_access_t initial_locktype;
-
-  ASSERTVMP(vmp);
-
-  initial_locktype = (locktype == VMNT_EXCL) ? VMNT_WRITE : locktype;
-
-  if (vmp->m_fs_e == who_e) return(EDEADLK);
-
-  r = tll_lock(&vmp->m_lock, initial_locktype);
-
-  if (r == EBUSY) return(r);
-
-  if (initial_locktype != locktype) {
-       tll_upgrade(&vmp->m_lock);
-  }
-
-#if LOCK_DEBUG
-  if (locktype == VMNT_READ)
-       fp->fp_vmnt_rdlocks++;
-#endif
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                             vmnt_unmap_by_endpoint                       *
- *===========================================================================*/
-PUBLIC void vmnt_unmap_by_endpt(endpoint_t proc_e)
-{
-  struct vmnt *vmp;
-
-  if ((vmp = find_vmnt(proc_e)) != NULL) {
-       fs_cancel(vmp);
-       invalidate_filp_by_endpt(proc_e);
-       if (vmp->m_mounted_on) {
-               /* Only put mount point when it was actually used as mount
-                * point. That is, the mount was succesful. */
-               put_vnode(vmp->m_mounted_on);
-       }
-       clear_vmnt(vmp);
-  }
-}
-
-/*===========================================================================*
- *                             unlock_vmnt                                  *
- *===========================================================================*/
-PUBLIC void unlock_vmnt(struct vmnt *vmp)
-{
-  ASSERTVMP(vmp);
-
-#if LOCK_DEBUG
-  /* Decrease read-only lock counter when not locked as VMNT_WRITE or
-   * VMNT_EXCL */
-  if (!tll_locked_by_me(&vmp->m_lock))
-       fp->fp_vmnt_rdlocks--;
-#endif
-
-  tll_unlock(&vmp->m_lock);
-
-#if LOCK_DEBUG
-  assert(!tll_locked_by_me(&vmp->m_lock));
-#endif
-
-}
diff --git a/servers/avfs/vmnt.h b/servers/avfs/vmnt.h
deleted file mode 100644 (file)
index 14d00b3..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-#ifndef __VFS_VMNT_H__
-#define __VFS_VMNT_H__
-
-EXTERN struct vmnt {
-  int m_fs_e;                  /* FS process' kernel endpoint */
-  tll_t m_lock;
-  comm_t m_comm;
-  dev_t m_dev;                 /* device number */
-  unsigned int m_flags;                /* mount flags */
-  struct vnode *m_mounted_on;  /* vnode on which the partition is mounted */
-  struct vnode *m_root_node;   /* root vnode */
-  char m_label[LABEL_MAX];     /* label of the file system process */
-} vmnt[NR_MNTS];
-
-/* vmnt flags */
-#define VMNT_READONLY          01      /* Device mounted readonly */
-#define VMNT_CALLBACK          02      /* FS did back call */
-#define VMNT_MOUNTING          04      /* Device is being mounted */
-#define VMNT_FORCEROOTBSF      010     /* Force usage of none-device */
-
-/* vmnt lock types mapping */
-#define VMNT_READ TLL_READ
-#define VMNT_WRITE TLL_READSER
-#define VMNT_EXCL TLL_WRITE
-
-#endif
diff --git a/servers/avfs/vnode.c b/servers/avfs/vnode.c
deleted file mode 100644 (file)
index ad854f7..0000000
+++ /dev/null
@@ -1,389 +0,0 @@
-/* This file contains the routines related to vnodes.
- * The entry points are:
- *
- *  get_vnode - increase counter and get details of an inode
- *  get_free_vnode - get a pointer to a free vnode obj
- *  find_vnode - find a vnode according to the FS endpoint and the inode num.
- *  dup_vnode - duplicate vnode (i.e. increase counter)
- *  put_vnode - drop vnode (i.e. decrease counter)
- */
-
-#include "fs.h"
-#include "threads.h"
-#include "vnode.h"
-#include "vmnt.h"
-#include "fproc.h"
-#include "file.h"
-#include <minix/vfsif.h>
-#include <assert.h>
-
-/* Is vnode pointer reasonable? */
-#if NDEBUG
-#define SANEVP(v)
-#define CHECKVN(v)
-#define ASSERTVP(v)
-#else
-#define SANEVP(v) ((((v) >= &vnode[0] && (v) < &vnode[NR_VNODES])))
-
-#define BADVP(v, f, l) printf("%s:%d: bad vp %p\n", f, l, v)
-
-/* vp check that returns 0 for use in check_vrefs() */
-#define CHECKVN(v) if(!SANEVP(v)) {                            \
-       BADVP(v, __FILE__, __LINE__);   \
-       return 0;       \
-}
-
-/* vp check that panics */
-#define ASSERTVP(v) if(!SANEVP(v)) { \
-       BADVP(v, __FILE__, __LINE__); panic("bad vp"); }
-#endif
-
-#if LOCK_DEBUG
-/*===========================================================================*
- *                             check_vnode_locks_by_me                      *
- *===========================================================================*/
-PUBLIC void check_vnode_locks_by_me(struct fproc *rfp)
-{
-/* Check whether this thread still has locks held on vnodes */
-  struct vnode *vp;
-
-  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
-       if (tll_locked_by_me(&vp->v_lock)) {
-               panic("Thread %d still holds vnode lock on vp %x call_nr=%d\n",
-                     mthread_self(), vp, call_nr);
-       }
-  }
-
-  if (rfp->fp_vp_rdlocks != 0)
-       panic("Thread %d still holds read locks on a vnode (%d) call_nr=%d\n",
-             mthread_self(), rfp->fp_vp_rdlocks, call_nr);
-}
-#endif
-
-/*===========================================================================*
- *                             check_vnode_locks                            *
- *===========================================================================*/
-PUBLIC void check_vnode_locks()
-{
-  struct vnode *vp;
-  int count = 0;
-
-  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++)
-       if (is_vnode_locked(vp)) {
-               count++;
-       }
-
-  if (count) panic("%d locked vnodes\n", count);
-#if 0
-  printf("check_vnode_locks OK\n");
-#endif
-}
-
-/*===========================================================================*
- *                             get_free_vnode                               *
- *===========================================================================*/
-PUBLIC struct vnode *get_free_vnode()
-{
-/* Find a free vnode slot in the vnode table (it's not actually allocated) */
-  struct vnode *vp;
-
-  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) {
-       if (vp->v_ref_count == 0 && !is_vnode_locked(vp)) {
-               vp->v_pipe = NO_PIPE;
-               vp->v_uid  = -1;
-               vp->v_gid  = -1;
-               vp->v_sdev = NO_DEV;
-               vp->v_mapfs_e = NONE;
-               vp->v_mapfs_count = 0;
-               vp->v_mapinode_nr = 0;
-               return(vp);
-       }
-  }
-
-  err_code = ENFILE;
-  return(NULL);
-}
-
-
-/*===========================================================================*
- *                             find_vnode                                   *
- *===========================================================================*/
-PUBLIC struct vnode *find_vnode(int fs_e, int ino)
-{
-/* Find a specified (FS endpoint and inode number) vnode in the
- * vnode table */
-  struct vnode *vp;
-
-  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
-       if (vp->v_ref_count > 0 && vp->v_inode_nr == ino && vp->v_fs_e == fs_e)
-               return(vp);
-
-  return(NULL);
-}
-
-/*===========================================================================*
- *                             is_vnode_locked                              *
- *===========================================================================*/
-PUBLIC int is_vnode_locked(struct vnode *vp)
-{
-/* Find out whether a thread holds a lock on this vnode or is trying to obtain
- * a lock. */
-  ASSERTVP(vp);
-
-  return(tll_islocked(&vp->v_lock) || tll_haspendinglock(&vp->v_lock));
-}
-
-/*===========================================================================*
- *                             init_vnodes                                  *
- *===========================================================================*/
-PUBLIC void init_vnodes(void)
-{
-  struct vnode *vp;
-
-  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) {
-       vp->v_fs_e = NONE;
-       vp->v_mapfs_e = NONE;
-       vp->v_inode_nr = 0;
-       vp->v_ref_count = 0;
-       vp->v_fs_count = 0;
-       vp->v_mapfs_count = 0;
-       tll_init(&vp->v_lock);
-  }
-}
-
-/*===========================================================================*
- *                             lock_vnode                                   *
- *===========================================================================*/
-PUBLIC int lock_vnode(struct vnode *vp, tll_access_t locktype)
-{
-  int r;
-
-  ASSERTVP(vp);
-
-  r = tll_lock(&vp->v_lock, locktype);
-
-#if LOCK_DEBUG
-  if (locktype == VNODE_READ) {
-       fp->fp_vp_rdlocks++;
-  }
-#endif
-
-  if (r == EBUSY) return(r);
-  return(OK);
-}
-
-/*===========================================================================*
- *                             unlock_vnode                                 *
- *===========================================================================*/
-PUBLIC void unlock_vnode(struct vnode *vp)
-{
-#if LOCK_DEBUG
-  int i;
-  register struct vnode *rvp;
-  struct worker_thread *w;
-#endif
-  ASSERTVP(vp);
-
-#if LOCK_DEBUG
-  /* Decrease read-only lock counter when not locked as VNODE_OPCL or
-   * VNODE_WRITE */
-  if (!tll_locked_by_me(&vp->v_lock)) {
-       fp->fp_vp_rdlocks--;
-  }
-
-  for (i = 0; i < NR_VNODES; i++) {
-       rvp = &vnode[i];
-
-       w = rvp->v_lock.t_write;
-       assert(w != self);
-       while (w && w->w_next != NULL) {
-               w = w->w_next;
-               assert(w != self);
-       }
-
-       w = rvp->v_lock.t_serial;
-       assert(w != self);
-       while (w && w->w_next != NULL) {
-               w = w->w_next;
-               assert(w != self);
-       }
-  }
-#endif
-
-  tll_unlock(&vp->v_lock);
-}
-
-/*===========================================================================*
- *                             dup_vnode                                    *
- *===========================================================================*/
-PUBLIC void dup_vnode(struct vnode *vp)
-{
-/* dup_vnode() is called to increment the vnode and therefore the
- * referred inode's counter.
- */
-  ASSERTVP(vp);
-  vp->v_ref_count++;
-}
-
-
-/*===========================================================================*
- *                             put_vnode                                    *
- *===========================================================================*/
-PUBLIC void put_vnode(struct vnode *vp)
-{
-/* Decrease vnode's usage counter and decrease inode's usage counter in the
- * corresponding FS process. Decreasing the fs_count each time we decrease the
- * ref count would lead to poor performance. Instead, only decrease fs_count
- * when the ref count hits zero. However, this could lead to fs_count to wrap.
- * To prevent this, we drop the counter to 1 when the counter hits 256.
- * We maintain fs_count as a sanity check to make sure VFS and the FS are in
- * sync.
- */
-  int r, lock_vp;
-
-  ASSERTVP(vp);
-
-  /* Lock vnode. It's quite possible this thread already has a lock on this
-   * vnode. That's no problem, because the reference counter will not decrease
-   * to zero in that case. However, if the counter does decrease to zero *and*
-   * is already locked, we have a consistency problem somewhere. */
-  lock_vp = lock_vnode(vp, VNODE_OPCL);
-
-  if (vp->v_ref_count > 1) {
-       /* Decrease counter */
-       vp->v_ref_count--;
-       if (vp->v_fs_count > 256)
-               vnode_clean_refs(vp);
-       if (lock_vp != EBUSY) unlock_vnode(vp);
-       return;
-  }
-
-  /* If we already had a lock, there is a consistency problem */
-  assert(lock_vp != EBUSY);
-  tll_upgrade(&vp->v_lock);    /* Make sure nobody else accesses this vnode */
-
-  /* A vnode that's not in use can't be put back. */
-  if (vp->v_ref_count <= 0)
-       panic("put_vnode failed: bad v_ref_count %d\n", vp->v_ref_count);
-
-  /* fs_count should indicate that the file is in use. */
-  if (vp->v_fs_count <= 0)
-       panic("put_vnode failed: bad v_fs_count %d\n", vp->v_fs_count);
-
-  /* Tell FS we don't need this inode to be open anymore. */
-  r = req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count);
-
-  if (r != OK) {
-       printf("VFS: putnode failed: %d\n", r);
-       util_stacktrace();
-  }
-
-  /* This inode could've been mapped. If so, tell mapped FS to close it as
-   * well. If mapped onto same FS, this putnode is not needed. */
-  if (vp->v_mapfs_e != NONE && vp->v_mapfs_e != vp->v_fs_e)
-       req_putnode(vp->v_mapfs_e, vp->v_mapinode_nr, vp->v_mapfs_count);
-
-  vp->v_fs_count = 0;
-  vp->v_ref_count = 0;
-  vp->v_mapfs_count = 0;
-
-  unlock_vnode(vp);
-}
-
-
-/*===========================================================================*
- *                             vnode_clean_refs                             *
- *===========================================================================*/
-PUBLIC void vnode_clean_refs(struct vnode *vp)
-{
-/* Tell the underlying FS to drop all reference but one. */
-
-  if (vp == NULL) return;
-  if (vp->v_fs_count <= 1) return;     /* Nothing to do */
-
-  /* Drop all references except one */
-  req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count - 1);
-  vp->v_fs_count = 1;
-}
-
-
-#define REFVP(v) { vp = (v); CHECKVN(v); vp->v_ref_check++; }
-
-#if DO_SANITYCHECKS
-/*===========================================================================*
- *                             check_vrefs                                  *
- *===========================================================================*/
-PUBLIC int check_vrefs()
-{
-       int i, bad;
-       int ispipe_flag, ispipe_mode;
-       struct vnode *vp;
-       struct vmnt *vmp;
-       struct fproc *rfp;
-       struct filp *f;
-
-       /* Clear v_ref_check */
-       for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
-               vp->v_ref_check= 0;
-
-       /* Count reference for processes */
-       for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-               if (rfp->fp_pid == PID_FREE)
-                       continue;
-               if(rfp->fp_rd) REFVP(rfp->fp_rd);
-                if(rfp->fp_wd) REFVP(rfp->fp_wd);
-       }
-
-       /* Count references from filedescriptors */
-       for (f = &filp[0]; f < &filp[NR_FILPS]; f++)
-       {
-               if (f->filp_count == 0)
-                       continue;
-               REFVP(f->filp_vno);
-       }
-
-       /* Count references to mount points */
-       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
-       {
-               if (vmp->m_dev == NO_DEV)
-                       continue;
-               REFVP(vmp->m_root_node);
-               if(vmp->m_mounted_on)
-                       REFVP(vmp->m_mounted_on);
-       }
-
-       /* Check references */
-       bad= 0;
-       for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
-       {
-               if (vp->v_ref_count != vp->v_ref_check)
-               {
-                       printf(
-"Bad reference count for inode %d on device 0x%x: found %d, listed %d\n",
-                               vp->v_inode_nr, vp->v_dev, vp->v_ref_check,
-                               vp->v_ref_count);
-                       printf("last marked at %s, %d\n",
-                               vp->v_file, vp->v_line);
-                       bad= 1;
-               }
-
-               /* Also check v_pipe */
-               if (vp->v_ref_count != 0)
-               {
-                       ispipe_flag= (vp->v_pipe == I_PIPE);
-                       ispipe_mode= ((vp->v_mode & I_TYPE) == I_NAMED_PIPE);
-                       if (ispipe_flag != ispipe_mode)
-                       {
-                               printf(
-"Bad v_pipe for inode %d on device 0x%x: found %d, mode 0%o\n",
-                               vp->v_inode_nr, vp->v_dev, vp->v_pipe,
-                               vp->v_mode);
-                               printf("last marked at %s, %d\n",
-                                       vp->v_file, vp->v_line);
-                               bad= 1;
-                       }
-               }
-       }
-       return !bad;
-}
-#endif
diff --git a/servers/avfs/vnode.h b/servers/avfs/vnode.h
deleted file mode 100644 (file)
index babb6aa..0000000
+++ /dev/null
@@ -1,40 +0,0 @@
-#ifndef __VFS_VNODE_H__
-#define __VFS_VNODE_H__
-
-EXTERN struct vnode {
-  endpoint_t v_fs_e;            /* FS process' endpoint number */
-  endpoint_t v_mapfs_e;                /* mapped FS process' endpoint number */
-  ino_t v_inode_nr;            /* inode number on its (minor) device */
-  ino_t v_mapinode_nr;         /* mapped inode number of mapped FS. */
-  mode_t v_mode;               /* file type, protection, etc. */
-  uid_t v_uid;                 /* uid of inode. */
-  gid_t v_gid;                 /* gid of inode. */
-  off_t v_size;                        /* current file size in bytes */
-  int v_ref_count;             /* # times vnode used; 0 means slot is free */
-  int v_fs_count;              /* # reference at the underlying FS */
-  int v_mapfs_count;           /* # reference at the underlying mapped FS */
-#if 0
-  int v_ref_check;             /* for consistency checks */
-#endif
-  char v_pipe;                 /* set to I_PIPE if pipe */
-  off_t v_pipe_rd_pos;
-  off_t v_pipe_wr_pos;
-  endpoint_t v_bfs_e;          /* endpoint number for the FS proces in case
-                                  of a block special file */
-  dev_t v_dev;                  /* device number on which the corresponding
-                                   inode resides */
-  dev_t v_sdev;                 /* device number for special files */
-  struct vmnt *v_vmnt;          /* vmnt object of the partition */
-  tll_t v_lock;                        /* three-level-lock */
-} vnode[NR_VNODES];
-
-
-/* Field values. */
-#define NO_PIPE            0   /* i_pipe is NO_PIPE if inode is not a pipe */
-#define I_PIPE             1   /* i_pipe is I_PIPE if inode is a pipe */
-
-/* vnode lock types mapping */
-#define VNODE_READ TLL_READ
-#define VNODE_OPCL TLL_READSER
-#define VNODE_WRITE TLL_WRITE
-#endif
diff --git a/servers/avfs/write.c b/servers/avfs/write.c
deleted file mode 100644 (file)
index a3e9d63..0000000
+++ /dev/null
@@ -1,19 +0,0 @@
-/* This file is the counterpart of "read.c".  It contains the code for writing
- * insofar as this is not contained in read_write().
- *
- * The entry points into this file are
- *   do_write:     call read_write to perform the WRITE system call
- */
-
-#include "fs.h"
-#include "file.h"
-
-
-/*===========================================================================*
- *                             do_write                                     *
- *===========================================================================*/
-PUBLIC int do_write()
-{
-/* Perform the write(fd, buffer, nbytes) system call. */
-  return(do_read_write(WRITING));
-}
index 92c22e21f4d18517244dba4881f27f697e3de93d..727ffca953f38576083079312af5ff5d1bd37a6c 100644 (file)
@@ -17,12 +17,6 @@ CPPFLAGS.dmp_kernel.c+=      -I${MINIXSRCDIR}
 CPPFLAGS.dmp_rs.c+=    -I${MINIXSRCDIR}
 CPPFLAGS.dmp_vm.c+=    -I${MINIXSRCDIR}
 
-.if ${BUILDAVFS} == "yes"
-CFLAGS+= -D_USEAVFS
-.else
-CFLAGS+= -D_USEVFS
-.endif
-
 # This setting must match the kernel's, as it affects the IRQ hooks table size.
 .if ${USE_APIC} != "no"
 CFLAGS+= -DUSE_APIC
index 92b7cd7a9c563c9080899cf5eef08f8e2509ce1d..a8c2d8f49dafd1d4e8859194ffd98be67f3cdabb 100644 (file)
 
 #include "inc.h"
 #include "../mfs/const.h"
-#if defined(_USEAVFS)
-# include "../avfs/const.h"
-# include "../avfs/fproc.h"
-# include "../avfs/dmap.h"
-#else
-# include "../vfs/const.h"
-# include "../vfs/fproc.h"
-# include "../vfs/dmap.h"
-#endif
+#include "../vfs/const.h"
+#include "../vfs/fproc.h"
+#include "../vfs/dmap.h"
 #include <minix/dmap.h>
 
 PUBLIC struct fproc fproc[NR_PROCS];
@@ -44,16 +38,6 @@ PUBLIC void fproc_dmp()
        fp = &fproc[i];
        if (fp->fp_pid <= 0) continue;
        if (++n > 22) break;
-#if !defined(_USEAVFS)
-       printf("%3d  %4d  %2d/%d  0x%05x %2d (%2d) %2d (%2d) %3d   %3d %3d ",
-               i, fp->fp_pid, 
-               ((fp->fp_tty>>MAJOR)&BYTE), ((fp->fp_tty>>MINOR)&BYTE), 
-               fp->fp_umask,
-               fp->fp_realuid, fp->fp_effuid, fp->fp_realgid, fp->fp_effgid,
-               fp->fp_sesldr,
-               fp->fp_blocked_on, !!fp->fp_revived
-       );
-#else
        printf("%3d  %4d  %2d/%d  0x%05x %2d (%2d) %2d (%2d) %3d   %3d %3d ",
                i, fp->fp_pid,
                major(fp->fp_tty), minor(fp->fp_tty),
@@ -62,7 +46,6 @@ PUBLIC void fproc_dmp()
                !!(fp->fp_flags & FP_SESLDR),
                fp->fp_blocked_on, !!(fp->fp_flags & FP_REVIVED)
        );
-#endif
        if (fp->fp_blocked_on == FP_BLOCKED_ON_OTHER)
                printf("%4d\n", fp->fp_task);
        else
index ff1a9fad7b3276b25a7455323f093b7acf09924b..18f5305f5ec2afe2d27f8582ced7e3e83224f064 100644 (file)
@@ -1,15 +1,18 @@
 # Makefile for Pipe File System (PFS)
 PROG=  pfs
 SRCS=  open.c table.c inode.c main.c super.c link.c \
-       buffer.c read.c misc.c utility.c stadir.c \
+       buffer.c read.c misc.c mount.c utility.c stadir.c \
        uds.c dev_uds.c
 
 DPADD+=        ${LIBSYS}
 LDADD+=        -lsys
 
+.if ${COMPILER_TYPE} == "gnu"
+LDADD+= -lc
+.endif
+
 MAN=
 
 BINDIR?= /usr/sbin
-INSTALLFLAGS+= -S 128k
 
 .include <minix.bootprog.mk>
index 8e847bac730f6c4aaeed95e3e94fea01757ffc42..cd31f7e84e3e58123205c41d55d72b9326f20b1d 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PFS_BUF_H__
 #define __PFS_BUF_H__
 
-/* Buffer (block) cache.  
+/* Buffer (block) cache.
  */
 
 struct buf {
index e745e419e7d6e6ef00c9895e19890d76706e19c3..a5c77b4a6de737a2f6e22e463ef814d1d34d1e3e 100644 (file)
@@ -28,11 +28,11 @@ PUBLIC struct buf *get_block(dev_t dev, ino_t inum)
   struct buf *bp = front;
 
   while(bp != NULL) {
-       if (bp->b_dev == dev && bp->b_num == inum) {
-               bp->b_count++;
-               return(bp);
-       }
-       bp = bp->b_next;
+       if (bp->b_dev == dev && bp->b_num == inum) {
+               bp->b_count++;
+               return(bp);
+       }
+       bp = bp->b_next;
   }
 
   /* Buffer was not found. Try to allocate a new one */
@@ -48,24 +48,24 @@ PRIVATE struct buf *new_block(dev_t dev, ino_t inum)
 /* Allocate a new buffer and add it to the double linked buffer list */
   struct buf *bp;
 
-  bp = malloc(sizeof(struct buf)); 
+  bp = malloc(sizeof(struct buf));
   if (bp == NULL) {
        err_code = ENOSPC;
-       return(NULL); 
+       return(NULL);
   }
   bp->b_num = inum;
   bp->b_dev = dev;
   bp->b_bytes = 0;
   bp->b_count = 1;
   memset(bp->b_data, 0 , PIPE_BUF);
-  
+
   /* Add at the end of the buffer */
   if (front == NULL) { /* Empty list? */
-       front = bp;
-       bp->b_prev = NULL;
+       front = bp;
+       bp->b_prev = NULL;
   } else {
-       rear->b_next = bp;
-       bp->b_prev = rear;
+       rear->b_next = bp;
+       bp->b_prev = rear;
   }
   bp->b_next = NULL;
   rear = bp;
@@ -84,22 +84,20 @@ PUBLIC void put_block(dev_t dev, ino_t inum)
   bp = get_block(dev, inum);
   if (bp == NULL) return; /* We didn't find the block. Nothing to put. */
 
-  bp->b_count--;       /* Compensate for above 'get_block'. */ 
+  bp->b_count--;       /* Compensate for above 'get_block'. */
   if (--bp->b_count > 0) return;
 
   /* Cut bp out of the loop */
   if (bp->b_prev == NULL)
-       front = bp->b_next;
+       front = bp->b_next;
   else
-       bp->b_prev->b_next = bp->b_next;
+       bp->b_prev->b_next = bp->b_next;
 
   if (bp->b_next == NULL)
-       rear = bp->b_prev;
+       rear = bp->b_prev;
   else
-       bp->b_next->b_prev = bp->b_prev;
+       bp->b_next->b_prev = bp->b_prev;
 
   /* Buffer administration is done. Now it's safe to free up bp. */
   free(bp);
 }
-
-
index 443c61f4020b31a43ae33bf8643b54a7891aba39..f89a239be480b4b6d331813dda45c15e67f8904e 100644 (file)
@@ -3,7 +3,7 @@
 
 #define NR_INODES        256   /* # slots in "in core" inode table */
 
-/* Size of descriptor table for unix domain sockets. This should be 
+/* Size of descriptor table for unix domain sockets. This should be
  * equal to the maximum number of minor devices (currently 256).
  */
 #define NR_FDS           256
@@ -40,4 +40,3 @@
 #define DEV_CALL_VEC_SIZE 25
 
 #endif
-
index 015e5cfd5b1bc0ed1df226327f415980e8d2df3b..7250f071e5f48e9517d96675677b030d3e159685 100644 (file)
@@ -71,8 +71,8 @@ PUBLIC int uds_open(message *dev_m_in, message *dev_m_out)
        if (minor == -1) {
 
                /* descriptor table full */
-               uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                               (cp_grant_id_t) dev_m_in->IO_GRANT, ENFILE);
+               uds_set_reply(dev_m_out, DEV_OPEN_REPL, dev_m_in->USER_ENDPT,
+                             (cp_grant_id_t) dev_m_in->IO_GRANT, ENFILE);
                return ENFILE;
        }
 
@@ -123,7 +123,7 @@ PUBLIC int uds_open(message *dev_m_in, message *dev_m_out)
                uds_fd_table[minor].backlog[i] = -1;
        }
 
-       memset(&uds_fd_table[minor].ancillary_data, '\0', sizeof(struct 
+       memset(&uds_fd_table[minor].ancillary_data, '\0', sizeof(struct
                                                                ancillary));
        for (i = 0; i < OPEN_MAX; i++) {
                uds_fd_table[minor].ancillary_data.fds[i] = -1;
@@ -168,8 +168,8 @@ PUBLIC int uds_open(message *dev_m_in, message *dev_m_out)
                memset(&(uds_fd_table[minor]), '\0', sizeof(uds_fd_t));
 
                /* likely error: invalid endpoint / proc doesn't exist */
-               uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                               (cp_grant_id_t) dev_m_in->IO_GRANT, errno);
+               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;
        }
 
@@ -189,7 +189,7 @@ PUBLIC 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, TASK_REPLY, dev_m_in->USER_ENDPT,
+               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;
        }
@@ -201,8 +201,8 @@ PUBLIC int uds_open(message *dev_m_in, message *dev_m_out)
        /* prepare the reply */
 
        uds_fd_table[minor].syscall_done = 1;
-       uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                       (cp_grant_id_t) dev_m_in->IO_GRANT, minor);
+       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;
 }
 
@@ -222,11 +222,11 @@ PUBLIC int uds_close(message *dev_m_in, message *dev_m_out)
        minor = uds_minor(dev_m_in);
 
        if (uds_fd_table[minor].state != UDS_INUSE) {
-               /* attempted to close a socket that hasn't been opened -- 
+               /* attempted to close a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                       (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
+               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;
        }
 
@@ -246,11 +246,10 @@ PUBLIC int uds_close(message *dev_m_in, message *dev_m_out)
 
                /* if peer was blocked on I/O revive peer */
                if (uds_fd_table[uds_fd_table[minor].peer].suspended) {
-
                        int peer = uds_fd_table[minor].peer;
 
                        uds_fd_table[peer].ready_to_revive = 1;
-                       notify(dev_m_in->m_source);
+                       uds_unsuspend(dev_m_in->m_source, peer);
                }
        }
 
@@ -276,8 +275,8 @@ PUBLIC int uds_close(message *dev_m_in, message *dev_m_out)
                return rc;
        }
 
-       uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                       (cp_grant_id_t) dev_m_in->IO_GRANT, OK);
+       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;
 }
 
@@ -297,12 +296,11 @@ PUBLIC int uds_select(message *dev_m_in, message *dev_m_out)
 
        if (uds_fd_table[minor].state != UDS_INUSE) {
 
-               /* attempted to close a socket that hasn't been opened -- 
+               /* attempted to close a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                               (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
 
+               uds_sel_reply(dev_m_out, DEV_SEL_REPL1, minor, EINVAL);
                return EINVAL;
        }
 
@@ -345,10 +343,8 @@ PUBLIC int uds_select(message *dev_m_in, message *dev_m_out)
        }
 
        uds_fd_table[minor].syscall_done = 1;
-
-       uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT, 
-                       (cp_grant_id_t) dev_m_in->IO_GRANT, 
-                       uds_fd_table[minor].sel_ops_out);
+       uds_sel_reply(dev_m_out, DEV_SEL_REPL1, minor,
+                     uds_fd_table[minor].sel_ops_out);
 
        return uds_fd_table[minor].sel_ops_out;
 }
@@ -384,23 +380,22 @@ PRIVATE int uds_perform_read(int minor, endpoint_t m_source,
                        return SUSPEND;
                }
 
-               /* maybe a process is blocked waiting to write? if 
+               /* maybe a process is blocked waiting to write? if
                 * needed revive the writer
                 */
                if (uds_fd_table[minor].peer != -1 &&
                        uds_fd_table[uds_fd_table[minor].peer].suspended) {
-
                        int peer = uds_fd_table[minor].peer;
 
                        uds_fd_table[peer].ready_to_revive = 1;
-                       notify(m_source);
+                       uds_unsuspend(m_source, peer);
                }
 
 #if DEBUG == 1
                printf("(uds) [%d] suspending read request\n", minor);
 #endif
 
-               /* Process is reading from an empty pipe, 
+               /* Process is reading from an empty pipe,
                 * suspend it so some bytes can be written
                 */
                uds_fd_table[minor].suspended = UDS_SUSPENDED_READ;
@@ -435,7 +430,7 @@ PRIVATE int uds_perform_read(int minor, endpoint_t m_source,
        printf("(uds) [%d] read complete\n", minor);
 #endif
 
-       /* move the position of the data pointer up to data we haven't 
+       /* move the position of the data pointer up to data we haven't
         * read yet
         */
        uds_fd_table[minor].pos += fs_m_out.RES_NBYTES;
@@ -443,29 +438,30 @@ PRIVATE int uds_perform_read(int minor, endpoint_t m_source,
        /* decrease the number of unread bytes */
        uds_fd_table[minor].size -= fs_m_out.RES_NBYTES;
 
-       /* if we have 0 unread bytes, move the data pointer back to the 
+       /* if we have 0 unread bytes, move the data pointer back to the
         * start of the buffer
         */
        if (uds_fd_table[minor].size == 0) {
                uds_fd_table[minor].pos = 0;
        }
 
-       /* maybe a big write was waiting for us to read some data, if 
+       /* maybe a big write was waiting for us to read some data, if
         * needed revive the writer
         */
-       if (uds_fd_table[minor].peer != -1 && 
+       if (uds_fd_table[minor].peer != -1 &&
                        uds_fd_table[uds_fd_table[minor].peer].suspended) {
+               int peer = uds_fd_table[minor].peer;
 
-               uds_fd_table[uds_fd_table[minor].peer].ready_to_revive = 1;
-               notify(m_source);
+               uds_fd_table[peer].ready_to_revive = 1;
+               uds_unsuspend(m_source, peer);
        }
 
-       /* see if peer is blocked on select() and a write is possible 
+       /* see if peer is blocked on select() and a write is possible
         * (from peer to minor)
         */
-       if (uds_fd_table[minor].peer != -1 && 
+       if (uds_fd_table[minor].peer != -1 &&
                uds_fd_table[uds_fd_table[minor].peer].selecting == 1 &&
-               (uds_fd_table[minor].size + uds_fd_table[minor].pos + 1 
+               (uds_fd_table[minor].size + uds_fd_table[minor].pos + 1
                < PIPE_BUF)) {
 
                int peer = uds_fd_table[minor].peer;
@@ -479,7 +475,7 @@ PRIVATE int uds_perform_read(int minor, endpoint_t m_source,
                        /* a write on peer is possible now */
                        uds_fd_table[peer].sel_ops_out |= SEL_WR;
                        uds_fd_table[peer].status_updated = 1;
-                       notify(uds_fd_table[peer].select_proc);
+                       uds_unsuspend(m_source, peer);
                }
        }
 
@@ -520,7 +516,7 @@ PRIVATE int uds_perform_write(int minor, endpoint_t m_source,
        if (uds_fd_table[minor].type == SOCK_STREAM ||
                        uds_fd_table[minor].type == SOCK_SEQPACKET) {
 
-               /* if we're writing with a connection oriented socket, 
+               /* if we're writing with a connection oriented socket,
                 * then it needs a peer to write to
                 */
                if (uds_fd_table[minor].peer == -1) {
@@ -543,7 +539,7 @@ PRIVATE int uds_perform_write(int minor, endpoint_t m_source,
                /* locate the "peer" we want to write to */
                for (i = 0; i < NR_FDS; i++) {
 
-                       /* look for a SOCK_DGRAM socket that is bound on 
+                       /* look for a SOCK_DGRAM socket that is bound on
                         * the target address
                         */
                        if (uds_fd_table[i].type == SOCK_DGRAM &&
@@ -561,14 +557,14 @@ PRIVATE int uds_perform_write(int minor, endpoint_t m_source,
                }
        }
 
-       /* check if write would overrun buffer. check if message 
-        * boundry preserving types (SEQPACKET and DGRAM) wouldn't write 
-        * to an empty buffer. check if connectionless sockets have a 
+       /* check if write would overrun buffer. check if message
+        * boundry preserving types (SEQPACKET and DGRAM) wouldn't write
+        * to an empty buffer. check if connectionless sockets have a
         * target to write to.
         */
        if ((uds_fd_table[peer].pos+uds_fd_table[peer].size+size > PIPE_BUF) ||
                ((uds_fd_table[minor].type == SOCK_SEQPACKET ||
-               uds_fd_table[minor].type == SOCK_DGRAM) && 
+               uds_fd_table[minor].type == SOCK_DGRAM) &&
                uds_fd_table[peer].size > 0) || (peer == -1)) {
 
                if (pretend) {
@@ -577,16 +573,15 @@ PRIVATE 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;
-                       notify(m_source);
+                       uds_unsuspend(m_source, peer);
                }
 
 #if DEBUG == 1
        printf("(uds) [%d] suspending write request\n", minor);
 #endif
 
-               /* Process is reading from an empty pipe, 
+               /* Process is reading from an empty pipe,
                 * suspend it so some bytes can be written
                 */
                uds_fd_table[minor].suspended = UDS_SUSPENDED_WRITE;
@@ -629,9 +624,8 @@ PRIVATE 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;
-               notify(m_source);
+               uds_unsuspend(m_source, peer);
        }
 
        /* see if peer is blocked on select()*/
@@ -647,7 +641,7 @@ PRIVATE int uds_perform_write(int minor, endpoint_t m_source,
                        /* a read on peer is possible now */
                        uds_fd_table[peer].sel_ops_out |= SEL_RD;
                        uds_fd_table[peer].status_updated = 1;
-                       notify(uds_fd_table[peer].select_proc);
+                       uds_unsuspend(m_source, peer);
                }
        }
 
@@ -674,8 +668,8 @@ PUBLIC int uds_read(message *dev_m_in, message *dev_m_out)
                /* attempted to close a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                               (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
+               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;
        }
@@ -698,10 +692,8 @@ PUBLIC int uds_read(message *dev_m_in, message *dev_m_out)
        bytes = uds_perform_read(minor, dev_m_in->m_source,
                                        uds_fd_table[minor].io_gr_size, 0);
 
-       uds_set_reply(dev_m_out, TASK_REPLY,
-                       uds_fd_table[minor].endpoint, 
-                       uds_fd_table[minor].io_gr,
-                       bytes);
+       uds_set_reply(dev_m_out, DEV_REVIVE, uds_fd_table[minor].endpoint,
+                     uds_fd_table[minor].io_gr, bytes);
 
        return bytes;
 }
@@ -715,7 +707,7 @@ PUBLIC int uds_write(message *dev_m_in, message *dev_m_out)
        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, 
+       printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->USER_ENDPT,
                                                        dev_m_in->POSITION);
 #endif
 
@@ -723,11 +715,11 @@ PUBLIC int uds_write(message *dev_m_in, message *dev_m_out)
 
        if (uds_fd_table[minor].state != UDS_INUSE) {
 
-               /* attempted to close a socket that hasn't been opened -- 
+               /* attempted to close a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                               (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
+               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;
        }
@@ -750,10 +742,8 @@ PUBLIC int uds_write(message *dev_m_in, message *dev_m_out)
        bytes = uds_perform_write(minor, dev_m_in->m_source,
                                        uds_fd_table[minor].io_gr_size, 0);
 
-       uds_set_reply(dev_m_out, TASK_REPLY, 
-                       uds_fd_table[minor].endpoint, 
-                       uds_fd_table[minor].io_gr,
-                       bytes);
+       uds_set_reply(dev_m_out, DEV_REVIVE, uds_fd_table[minor].endpoint,
+                     uds_fd_table[minor].io_gr, bytes);
 
        return bytes;
 }
@@ -766,7 +756,7 @@ PUBLIC int uds_ioctl(message *dev_m_in, message *dev_m_out)
        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, 
+       printf("Endpoint: 0x%x | Position 0x%x\n", dev_m_in->USER_ENDPT,
                                                        dev_m_in->POSITION);
 #endif
 
@@ -777,8 +767,8 @@ PUBLIC int uds_ioctl(message *dev_m_in, message *dev_m_out)
                /* attempted to close a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                               (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
+               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;
        }
@@ -821,7 +811,7 @@ PUBLIC int uds_ioctl(message *dev_m_in, message *dev_m_out)
 
                case NWIOSUDSTYPE:
 
-                       /* set the type for this socket (i.e. 
+                       /* set the type for this socket (i.e.
                         * SOCK_STREAM, SOCK_DGRAM, etc) -- socket()
                         */
                        rc = do_socket(dev_m_in, dev_m_out);
@@ -851,7 +841,7 @@ PUBLIC int uds_ioctl(message *dev_m_in, message *dev_m_out)
 
                case NWIOSUDSSHUT:
 
-                       /* shutdown a socket for reading, writing, or 
+                       /* shutdown a socket for reading, writing, or
                         * both -- shutdown()
                         */
                        rc = do_shutdown(dev_m_in, dev_m_out);
@@ -952,8 +942,8 @@ PUBLIC int uds_ioctl(message *dev_m_in, message *dev_m_out)
                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 
+                        * 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.
                         */
@@ -964,137 +954,101 @@ PUBLIC int uds_ioctl(message *dev_m_in, message *dev_m_out)
        if (rc != SUSPEND)
                uds_fd_table[minor].syscall_done = 1;
 
-       uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-               (cp_grant_id_t) dev_m_in->IO_GRANT, rc);
+       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;
 }
 
-PUBLIC int uds_status(message *dev_m_in, message *dev_m_out)
+PUBLIC int uds_unsuspend(endpoint_t m_source, int minor)
 {
-       int i, bytes;
-
-#if DEBUG == 1
-       static int call_count = 0;
-       printf("(uds) [%d] uds_status() 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);
-#endif
+       int r = OK, bytes;
+       message m_out;
+       uds_fd_t *fdp;
 
-       for (i = 0; i < NR_FDS; i++) {
-
-               if (uds_fd_table[i].status_updated == 1) {
-
-                       /* clear the status_updated flag */
-                       uds_fd_table[i].status_updated = 0;
-                       uds_fd_table[i].selecting = 0;
-
-                       /* prepare the response */
-                       dev_m_out->m_type = DEV_IO_READY;
-                       dev_m_out->DEV_MINOR = i;
-                       dev_m_out->DEV_SEL_OPS = uds_fd_table[i].sel_ops_out;
-
-                       return uds_fd_table[i].sel_ops_out;
-               }
+       fdp = &uds_fd_table[minor];
 
-               if (uds_fd_table[i].ready_to_revive == 1) {
+       if (fdp->status_updated == 1) {
 
-                       /* clear the ready to revive flag */
-                       uds_fd_table[i].ready_to_revive = 0;
+               /* clear the status_updated flag */
+               fdp->status_updated = 0;
+               fdp->selecting = 0;
 
-                       switch (uds_fd_table[i].suspended) {
+               /* prepare the response */
+               uds_sel_reply(&m_out, DEV_SEL_REPL2, minor, fdp->sel_ops_out);
+       } else if (fdp->ready_to_revive == 1) {
 
-                               case UDS_SUSPENDED_READ:
+               /* clear the ready to revive flag */
+               fdp->ready_to_revive = 0;
 
-                                       bytes = uds_perform_read(i, 
-                                               dev_m_in->m_source,
-                                               uds_fd_table[i].io_gr_size,
-                                               0);
+               switch (fdp->suspended) {
 
-                                       if (bytes == SUSPEND) {
+                       case UDS_SUSPENDED_READ:
 
-                                               dev_m_out->m_type =
-                                                       DEV_NO_STATUS;
+                               bytes = uds_perform_read(minor, m_source,
+                                                        fdp->io_gr_size, 0);
 
-                                               return OK;
-
-                                       }
-
-                                       uds_fd_table[i].suspended =
-                                               UDS_NOT_SUSPENDED;
-
-                                       uds_set_reply(dev_m_out,
-                                               DEV_REVIVE, 
-                                               uds_fd_table[i].endpoint,
-                                               uds_fd_table[i].io_gr,
-                                               bytes);
-
-                                       return bytes;
-
-                               case UDS_SUSPENDED_WRITE:
+                               if (bytes == SUSPEND) {
+                                       r = SUSPEND;
+                                       break;
+                               }
 
-                                       bytes = uds_perform_write(i,
-                                               dev_m_in->m_source, 
-                                               uds_fd_table[i].io_gr_size,
-                                               0);
+                               fdp->suspended = UDS_NOT_SUSPENDED;
 
-                                       if (bytes == SUSPEND) {
+                               uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
+                                             fdp->io_gr, bytes);
 
-                                               dev_m_out->m_type =
-                                                       DEV_NO_STATUS;
+                               break;
 
-                                               return OK;
+                       case UDS_SUSPENDED_WRITE:
 
-                                       }
+                               bytes = uds_perform_write(minor, m_source,
+                                                         fdp->io_gr_size, 0);
 
-                                       uds_fd_table[i].suspended =
-                                               UDS_NOT_SUSPENDED;
+                               if (bytes == SUSPEND) {
+                                       r = SUSPEND;
+                                       break;
+                               }
 
-                                       uds_set_reply(dev_m_out, 
-                                               DEV_REVIVE, 
-                                               uds_fd_table[i].endpoint,
-                                               uds_fd_table[i].io_gr,
-                                               bytes);
+                               fdp->suspended = UDS_NOT_SUSPENDED;
 
-                                       return bytes;
+                               uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
+                                             fdp->io_gr, bytes);
 
-                               case UDS_SUSPENDED_CONNECT:
-                               case UDS_SUSPENDED_ACCEPT:
+                               break;
 
-                                       /* In both cases, the process 
-                                        * that send the notify() 
-                                        * already performed the connection. 
-                                        * The only thing to do here is 
-                                        * unblock.
-                                        */
+                       case UDS_SUSPENDED_CONNECT:
+                       case UDS_SUSPENDED_ACCEPT:
 
-                                       uds_fd_table[i].suspended = 
-                                                       UDS_NOT_SUSPENDED;
+                               /* In both cases, the process
+                                * that send the notify()
+                                * already performed the connection.
+                                * The only thing to do here is
+                                * unblock.
+                                */
 
-                                       uds_set_reply(dev_m_out,
-                                               DEV_REVIVE, 
-                                               uds_fd_table[i].endpoint,
-                                               uds_fd_table[i].io_gr,
-                                               OK);
+                               fdp->suspended = UDS_NOT_SUSPENDED;
 
-                                       return OK;
+                               uds_set_reply(&m_out, DEV_REVIVE, fdp->endpoint,
+                                             fdp->io_gr, OK);
 
-                               default:
-                                       continue;
-                       }
+                               break;
 
+                       default:
+                               return(OK);
                }
+
        }
 
-       dev_m_out->m_type = DEV_NO_STATUS;
-       return OK;
+       if (r == OK) reply(m_source, &m_out);
+       return(r);
 }
 
 PUBLIC int uds_cancel(message *dev_m_in, message *dev_m_out)
 {
        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),
@@ -1109,8 +1063,8 @@ PUBLIC int uds_cancel(message *dev_m_in, message *dev_m_out)
                /* attempted to close a socket that hasn't been opened --
                 * something is very wrong :(
                 */
-               uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
-                               (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
+               uds_set_reply(dev_m_out, DEV_NO_STATUS, dev_m_in->USER_ENDPT,
+                             (cp_grant_id_t) dev_m_in->IO_GRANT, EINVAL);
 
                return EINVAL;
        }
@@ -1136,14 +1090,14 @@ PUBLIC int uds_cancel(message *dev_m_in, message *dev_m_out)
 
                                case NWIOSUDSACCEPT:    /* accept() */
 
-                                       /* partial accept() only changes 
+                                       /* 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;
 
                                                }
@@ -1153,7 +1107,7 @@ PUBLIC int uds_cancel(message *dev_m_in, message *dev_m_out)
 
                                case NWIOSUDSCONN:      /* connect() */
 
-                                       /* partial connect() sets addr 
+                                       /* partial connect() sets addr
                                         * and adds minor to server backlog
                                         */
 
@@ -1166,7 +1120,7 @@ PUBLIC int uds_cancel(message *dev_m_in, message *dev_m_out)
                                                        UDS_INUSE) {
 
                                                        /* see if minor is in
-                                                        * the backlog 
+                                                        * the backlog
                                                         */
                        for (j = 0; j < uds_fd_table[i].backlog_size; j++) {
 
@@ -1206,9 +1160,9 @@ PUBLIC int uds_cancel(message *dev_m_in, message *dev_m_out)
 
                }
 
-               /* 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 
+               /* 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.
                 */
 
@@ -1216,9 +1170,8 @@ PUBLIC int uds_cancel(message *dev_m_in, message *dev_m_out)
        }
 
 
-       uds_set_reply(dev_m_out, TASK_REPLY, dev_m_in->USER_ENDPT,
+       uds_set_reply(dev_m_out, DEV_NO_STATUS, dev_m_in->USER_ENDPT,
                        (cp_grant_id_t) dev_m_in->IO_GRANT, EINTR);
 
        return EINTR;
 }
-
index 76338599b30dd371be1518641ab8e1de92f00a74..175b4fc8e1e981af8a89f068e5c55b4b6541f0f4 100644 (file)
@@ -21,8 +21,9 @@ EXTERN int req_nr;
 EXTERN int SELF_E;
 EXTERN int exitsignaled;
 EXTERN int busy;
+EXTERN int unmountdone;
 
 /* Inode map. */
-EXTERN bitchunk_t inodemap[FS_BITMAP_CHUNKS(NR_INODES)]; 
+EXTERN bitchunk_t inodemap[FS_BITMAP_CHUNKS(NR_INODES)];
 
 #endif
index f8a0eb9153015ed047c710ebdab790a2bf522db0..4484e8038a58335e115c16ff2aba036ebcd7324f 100644 (file)
@@ -39,4 +39,3 @@
 #include <signal.h>
 
 #include "proto.h"
-
index a2b42e8b6e81a54a4212daef6bf3cddfb3750082..98be69203f0edb4de6f47f81e493ef53b3da564a 100644 (file)
@@ -19,7 +19,7 @@
 #include "inode.h"
 #include <minix/vfsif.h>
 
-FORWARD _PROTOTYPE( void addhash_inode, (struct inode * const node)            ); 
+FORWARD _PROTOTYPE( void addhash_inode, (struct inode * const node)            );
 FORWARD _PROTOTYPE( void unhash_inode, (struct inode * const node)             );
 
 
@@ -34,7 +34,7 @@ PUBLIC int fs_putnode(message *fs_m_in, message *fs_m_out)
   int count;
   dev_t dev;
   ino_t inum;
-  
+
   rip = find_inode( (ino_t) fs_m_in->REQ_INODE_NR);
 
   if(!rip) {
@@ -55,7 +55,7 @@ PUBLIC int fs_putnode(message *fs_m_in, message *fs_m_out)
   }
 
   /* Decrease reference counter, but keep one reference; it will be consumed by
-   * put_inode(). */ 
+   * put_inode(). */
   rip->i_count -= count - 1;
   dev = rip->i_dev;
   inum = rip->i_num;
@@ -75,9 +75,9 @@ PUBLIC void init_inode_cache()
 
   /* init free/unused list */
   TAILQ_INIT(&unused_inodes);
-  
+
   /* init hash lists */
-  for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp) 
+  for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp)
       LIST_INIT(rlp);
 
   /* add free inodes to unused/free list */
@@ -95,10 +95,10 @@ PUBLIC void init_inode_cache()
 /*===========================================================================*
  *                             addhash_inode                                *
  *===========================================================================*/
-PRIVATE void addhash_inode(struct inode * const node) 
+PRIVATE void addhash_inode(struct inode * const node)
 {
   int hashi = (int) (node->i_num & INODE_HASH_MASK);
-  
+
   /* insert into hash table */
   LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash);
 }
@@ -107,7 +107,7 @@ PRIVATE void addhash_inode(struct inode * const node)
 /*===========================================================================*
  *                             unhash_inode                                 *
  *===========================================================================*/
-PRIVATE void unhash_inode(struct inode * const node) 
+PRIVATE void unhash_inode(struct inode * const node)
 {
   /* remove from hash table */
   LIST_REMOVE(node, i_hash);
@@ -123,7 +123,7 @@ PUBLIC struct inode *get_inode(
 )
 {
 /* Find the inode in the hash table. If it is not there, get a free inode
- * load it from the disk if it's necessary and put on the hash list 
+ * load it from the disk if it's necessary and put on the hash list
  */
   register struct inode *rip;
   int hashi;
@@ -152,7 +152,7 @@ PUBLIC struct inode *get_inode(
 
   /* If not free unhash it */
   if (rip->i_num != NO_ENTRY) unhash_inode(rip);
-  
+
   /* Inode is not unused any more */
   TAILQ_REMOVE(&unused_inodes, rip, i_unused);
 
@@ -165,7 +165,7 @@ PUBLIC struct inode *get_inode(
   /* Add to hash */
   addhash_inode(rip);
 
-  
+
   return(rip);
 }
 
@@ -189,7 +189,7 @@ ino_t numb;         /* inode number */
           return(rip);
       }
   }
-  
+
   return(NULL);
 }
 
@@ -245,15 +245,19 @@ PUBLIC struct inode *alloc_inode(dev_t dev, mode_t bits)
   register struct inode *rip;
   bit_t b;
   ino_t i_num;
+  int print_oos_msg = 1;
 
   b = alloc_bit();
   if (b == NO_BIT) {
-       err_code = ENOSPC;
-       printf("PipeFS is out of inodes\n");
-       return(NULL);
+       err_code = ENOSPC;
+       if (print_oos_msg)
+               printf("PipeFS is out of inodes\n");
+       print_oos_msg = 0;      /* Don't repeat message */
+       return(NULL);
   }
   i_num = (ino_t) b;
-  
+  print_oos_msg = 1;
+
 
   /* Try to acquire a slot in the inode table. */
   if ((rip = get_inode(dev, i_num)) == NULL) {
@@ -320,7 +324,7 @@ struct inode *rip;  /* pointer to inode to be read/written */
 /* Various system calls are required by the standard to update atime, ctime,
  * or mtime.  Since updating a time requires sending a message to the clock
  * task--an expensive business--the times are marked for update by setting
- * bits in i_update.  When a stat, fstat, or sync is done, or an inode is 
+ * bits in i_update.  When a stat, fstat, or sync is done, or an inode is
  * released, update_times() may be called to actually fill in the times.
  */
 
@@ -332,4 +336,3 @@ struct inode *rip;  /* pointer to inode to be read/written */
   if (rip->i_update & MTIME) rip->i_mtime = cur_time;
   rip->i_update = 0;           /* they are all up-to-date now */
 }
-
index 8614aa0f70ee25d95e2f56277461113426e02938..19e58259378c503f68ebd841a96793e97c918ae7 100644 (file)
@@ -1,7 +1,7 @@
 #ifndef __PFS_INODE_H__
 #define __PFS_INODE_H__
 
-/* Inode table.  This table holds inodes that are currently in use. 
+/* Inode table.  This table holds inodes that are currently in use.
  */
 
 #include <sys/queue.h>
@@ -15,7 +15,7 @@ EXTERN struct inode {
   time_t i_atime;              /* time of last access (V2 only) */
   time_t i_mtime;              /* when was file data last changed */
   time_t i_ctime;              /* when was inode itself changed (V2 only)*/
-  
+
   /* The following items are not present on the disk. */
   dev_t i_dev;                 /* which device is the inode on */
   dev_t i_rdev;                        /* which special device is the inode on */
@@ -26,10 +26,10 @@ EXTERN struct inode {
   LIST_ENTRY(inode) i_hash;     /* hash list */
   TAILQ_ENTRY(inode) i_unused;  /* free and unused list */
 
-  
+
 } inode[NR_INODES];
 
-/* list of unused/free inodes */ 
+/* list of unused/free inodes */
 EXTERN TAILQ_HEAD(unused_inodes_t, inode)  unused_inodes;
 
 /* inode hashtable */
index 4a5e901cb5d96d065579598246bc64b555cfa576..4ec064ef9a5095bdacf13a673fa5f179aac4035e 100644 (file)
@@ -11,7 +11,7 @@ PUBLIC int fs_ftrunc(message *fs_m_in, message *fs_m_out)
   struct inode *rip;
   off_t start, end;
   ino_t inumb;
-  
+
   inumb = (ino_t) fs_m_in->REQ_INODE_NR;
 
   if( (rip = find_inode(inumb)) == NULL) return(EINVAL);
@@ -21,7 +21,7 @@ PUBLIC int fs_ftrunc(message *fs_m_in, message *fs_m_out)
 
   return truncate_inode(rip, start);
 }
-    
+
 
 /*===========================================================================*
  *                             truncate_inode                               *
@@ -35,17 +35,16 @@ off_t newsize;                      /* inode must become this size */
  * extra space is a hole that reads as zeroes.
  *
  * Nothing special has to happen to file pointers if inode is opened in
- * O_APPEND mode, as this is different per fd and is checked when 
+ * O_APPEND mode, as this is different per fd and is checked when
  * writing is done.
  */
 
   /* Pipes can shrink, so adjust size to make sure all zones are removed. */
   if(newsize != 0) return(EINVAL);     /* Only truncate pipes to 0. */
   rip->i_size = newsize;
-  
+
   /* Next correct the inode size. */
   wipe_inode(rip);     /* Pipes can only be truncated to 0. */
 
   return(OK);
 }
-
index b449e1239cd229b617c35e0a092feab470c4786f..f4f20f8dde864c3e0b2717eb3f2ad29c63d52a9b 100644 (file)
@@ -4,7 +4,10 @@
 #include <minix/dmap.h>
 #include <minix/driver.h>
 #include <minix/endpoint.h>
+#include <minix/rs.h>
 #include <minix/vfsif.h>
+#include <sys/types.h>
+#include <pwd.h>
 #include "buf.h"
 #include "inode.h"
 #include "uds.h"
@@ -21,11 +24,11 @@ FORWARD _PROTOTYPE( void sef_cb_signal_handler, (int signo) );
  *===========================================================================*/
 PUBLIC int main(int argc, char *argv[])
 {
-/* This is the main routine of this service. The main loop consists of 
+/* This is the main routine of this service. The main loop consists of
  * three major activities: getting new work, processing the work, and
  * sending the reply. The loop never terminates, unless a panic occurs.
  */
-  int ind, transid;
+  int ind, do_reply, transid;
   message pfs_m_in;
   message pfs_m_out;
 
@@ -33,9 +36,10 @@ PUBLIC int main(int argc, char *argv[])
   env_setargs(argc, argv);
   sef_local_startup();
 
-  while(!exitsignaled || busy) {
+  while(!unmountdone || !exitsignaled) {
        endpoint_t src;
 
+       do_reply = 1;
        /* Wait for request message. */
        get_work(&pfs_m_in);
 
@@ -59,7 +63,13 @@ PUBLIC int main(int argc, char *argv[])
                        printf("pfs: bad DEV request %d\n", req_nr);
                        pfs_m_out.m_type = EINVAL;
                } else {
-                       (*dev_call_vec[ind])(&pfs_m_in, &pfs_m_out);
+                       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)) {
                ind = req_nr - VFS_BASE;
@@ -75,10 +85,13 @@ PUBLIC int main(int argc, char *argv[])
                pfs_m_out.m_type = EINVAL;
        }
 
-       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);
+       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);
        }
-       reply(src, &pfs_m_out);
   }
   return(OK);
 }
@@ -108,6 +121,7 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
 {
 /* Initialize the pipe file server. */
   int i;
+  struct passwd *pw;
 
   /* Initialize main loop parameters. */
   exitsignaled = 0;    /* No exit request seen yet. */
@@ -117,12 +131,21 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
   for (i = 0; i < NR_INODES; ++i) {
        inode[i].i_count = 0;
   }
-       
+
   init_inode_cache();
   uds_init();
+  buf_pool();
+
+
+  /* Drop root privileges */
+  if ((pw = getpwnam(SERVICE_LOGIN)) == NULL) {
+       printf("PFS: unable to retrieve uid of SERVICE_LOGIN, "
+               "still running as root");
+  } else if (setuid(pw->pw_uid) != 0) {
+       panic("unable to drop privileges");
+  }
 
   SELF_E = getprocnr();
-  buf_pool();
 
   return(OK);
 }
@@ -135,6 +158,7 @@ PRIVATE void sef_cb_signal_handler(int signo)
   /* Only check for termination signal, ignore anything else. */
   if (signo != SIGTERM) return;
 
+
   exitsignaled = 1;
 }
 
@@ -148,7 +172,7 @@ message *m_in;                              /* pointer to message */
   endpoint_t src;
 
   do {
-       /* wait for a message */
+       /* wait for a message */
        if ((r = sef_receive_status(ANY, m_in, &status)) != OK)
                panic("sef_receive_status failed: %d", r);
        src = m_in->m_source;
@@ -165,7 +189,7 @@ message *m_in;                              /* pointer to message */
  *                             reply                                        *
  *===========================================================================*/
 PUBLIC void reply(who, m_out)
-endpoint_t who;        
+endpoint_t who;
 message *m_out;                        /* report result */
 {
   if (OK != send(who, m_out))  /* send the message */
index dc8da9e6ec26c52051dbd5dd2f97c3af83bb0b1a..2f8e3010d89b55b40881be1a4cac72749fe6ea55 100644 (file)
@@ -10,5 +10,3 @@ PUBLIC int fs_sync(message *fs_m_in, message *fs_m_out)
 
   return(OK);          /* sync() can't fail */
 }
-
-
similarity index 100%
rename from servers/apfs/mount.c
rename to servers/pfs/mount.c
index 4abf5b1cf4334fcdbb4b1b1023a2677e16095507..a7e27575778ac99f7f941830041a5989d5f8786f 100644 (file)
@@ -24,8 +24,8 @@ PUBLIC int fs_newnode(message *fs_m_in, message *fs_m_out)
   if( (rip = alloc_inode(dev, bits) ) == NULL) return(err_code);
 
   switch (bits & S_IFMT) {
-       case S_IFBLK:
-       case S_IFCHR:
+       case S_IFBLK:
+       case S_IFCHR:
                rip->i_rdev = dev;              /* Major/minor dev numbers */
                break;
        case S_IFIFO:
@@ -50,4 +50,3 @@ PUBLIC int fs_newnode(message *fs_m_in, message *fs_m_out)
 
   return(r);
 }
-
index d6465e0acd800de379228e644b626cf59d9ca47c..210e9d1d4126aa24744f3c83f87eb6d914714ffe 100644 (file)
@@ -39,6 +39,9 @@ _PROTOTYPE( void reply, (endpoint_t who, message *m_out)              );
 /* misc.c */
 _PROTOTYPE( int fs_sync, (message *fs_m_in, message *fs_m_out)         );
 
+/* mount.c */
+_PROTOTYPE( int fs_unmount, (message *fs_m_in, message *fs_m_out)      );
+
 /* open.c */
 _PROTOTYPE( int fs_newnode, (message *fs_m_in, message *fs_m_out)      );
 
@@ -63,7 +66,7 @@ _PROTOTYPE( int uds_read, (message *dev_m_in, message *dev_m_out)     );
 _PROTOTYPE( int uds_write, (message *dev_m_in, message *dev_m_out)     );
 _PROTOTYPE( int uds_ioctl, (message *dev_m_in, message *dev_m_out)     );
 _PROTOTYPE( int uds_select, (message *dev_m_in, message *dev_m_out)    );
-_PROTOTYPE( int uds_status, (message *dev_m_in, message *dev_m_out)    );
+_PROTOTYPE( int uds_unsuspend, (endpoint_t m_source, int minor)                );
 _PROTOTYPE( int uds_cancel, (message *dev_m_in, message *dev_m_out)    );
 
 /* uds.c */
@@ -97,8 +100,8 @@ _PROTOTYPE( int do_recvfrom, (message *dev_m_in, message *dev_m_out) );
 _PROTOTYPE( int do_sendmsg, (message *dev_m_in, message *dev_m_out)    );
 _PROTOTYPE( int do_recvmsg, (message *dev_m_in, message *dev_m_out)    );
 _PROTOTYPE( int perform_connection,
-                               (message *dev_m_in, message *dev_m_out, 
-                               struct sockaddr_un *addr, int minorx, 
+                               (message *dev_m_in, message *dev_m_out,
+                               struct sockaddr_un *addr, int minorx,
                                int minory)                             );
 _PROTOTYPE( int clear_fds, (int minor, struct ancillary *data)         );
 #endif
index 3a6579f0a8cae61f042a493a57a00d9ff9a84d22..b4f06b8466787cfb95a56bc29c62707202105239 100644 (file)
@@ -28,8 +28,8 @@ PUBLIC int fs_readwrite(message *fs_m_in, message *fs_m_out)
   mode_word = rip->i_mode & I_TYPE;
   if (mode_word != I_NAMED_PIPE) return(EIO);
   f_size = rip->i_size;
-  
-  /* Get the values from the request message */ 
+
+  /* Get the values from the request message */
   rw_flag = (fs_m_in->m_type == REQ_READ ? READING : WRITING);
   gid = (cp_grant_id_t) fs_m_in->REQ_GRANT;
   position = fs_m_in->REQ_SEEK_POS_LO;
@@ -37,7 +37,7 @@ PUBLIC int fs_readwrite(message *fs_m_in, message *fs_m_out)
 
   /* We can't read beyond the max file position */
   if (nrbytes > MAX_FILE_POS) return(EFBIG);
-  
+
   if (rw_flag == WRITING) {
          /* Check in advance to see if file will grow too big. */
          /* Casting nrbytes to signed is safe, because it's guaranteed not to
@@ -66,7 +66,7 @@ PUBLIC int fs_readwrite(message *fs_m_in, message *fs_m_out)
 
   fs_m_out->RES_SEEK_POS_LO = position; /* It might change later and the VFS
                                           has to know this value */
-  
+
   /* On write, update file size and access time. */
   if (rw_flag == WRITING) {
          if (position > f_size) rip->i_size = position;
@@ -87,4 +87,3 @@ PUBLIC int fs_readwrite(message *fs_m_in, message *fs_m_out)
 
   return(r);
 }
-
index 345d24ec91f025ae764e8bfa0725936d94e76c43..7a49caff5d71ac5d6260c85e06a763ff03600ed9 100644 (file)
@@ -48,8 +48,8 @@ PRIVATE int stat_inode(
 
   /* Copy the struct to user space. */
   r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf,
-               (size_t) sizeof(statbuf), D);
-  
+               (size_t) sizeof(statbuf), D);
+
   return(r);
 }
 
@@ -63,9 +63,8 @@ PUBLIC int fs_stat(message *fs_m_in, message *fs_m_out)
   register struct inode *rip;  /* target inode */
 
   if( (rip = find_inode(fs_m_in->REQ_INODE_NR)) == NULL) return(EINVAL);
-  get_inode(rip->i_dev, rip->i_num);   /* mark inode in use */  
+  get_inode(rip->i_dev, rip->i_num);   /* mark inode in use */
   r = stat_inode(rip, fs_m_in->m_source, (cp_grant_id_t) fs_m_in->REQ_GRANT);
   put_inode(rip);                      /* release the inode */
   return(r);
 }
-
index 84559cc1cc28514eb7a7f21f03e7ba28350da84e..50f4e0ba59e9add49794ee61ba18c1ce20c1a9bd 100644 (file)
@@ -20,7 +20,7 @@
 PUBLIC bit_t alloc_bit(void)
 {
 /* Allocate a bit from a bit map and return its bit number. */
-  bitchunk_t *wptr, *wlim; 
+  bitchunk_t *wptr, *wlim;
   bit_t b;
   unsigned int i, bcount;
 
@@ -28,24 +28,24 @@ PUBLIC bit_t alloc_bit(void)
   wlim = &inodemap[bcount]; /* Point to last chunk in inodemap. */
 
   for (wptr = &inodemap[0]; wptr < wlim; wptr++) {
-       /* Does this word contain a free bit? */
-       if (*wptr == (bitchunk_t) ~0) continue; /* No. Go to next word */
+       /* Does this word contain a free bit? */
+       if (*wptr == (bitchunk_t) ~0) continue; /* No. Go to next word */
 
-       /* Find and allocate the free bit. */
-       for (i = 0; (*wptr & (1 << i)) != 0; ++i) {}
+       /* Find and allocate the free bit. */
+       for (i = 0; (*wptr & (1 << i)) != 0; ++i) {}
 
        /* Get inode number */
-       b = (bit_t) ((wptr - &inodemap[0]) * FS_BITCHUNK_BITS + i);
-       
-       /* Don't allocate bits beyond end of map. */ 
-       if (b >= NR_INODES) break;
+       b = (bit_t) ((wptr - &inodemap[0]) * FS_BITCHUNK_BITS + i);
 
-       /* Allocate and return bit number. */
-       *wptr |= 1 << i;
+       /* Don't allocate bits beyond end of map. */
+       if (b >= NR_INODES) break;
+
+       /* Allocate and return bit number. */
+       *wptr |= 1 << i;
 
        /* Mark server 'busy' */
        busy++;
-       return(b);
+       return(b);
   }
 
   return(NO_BIT);                      /* no bit could be allocated */
@@ -73,5 +73,3 @@ bit_t bit_returned;           /* number of bit to insert into the inode map*/
 
   busy--; /* One inode less in use. */
 }
-
-
index 95e5c5a404699a3ebe35a513e1b9d9ba5b36a0dd..760e5b21e2dcf8bc247e32d363fdba74117b6180 100644 (file)
@@ -29,7 +29,7 @@ PUBLIC _PROTOTYPE (int (*fs_call_vec[]),
         no_sys,             /* 12  */
         no_sys,                    /* 13  */
         no_sys,             /* 14  */
-        no_sys,             /* 15  */
+        fs_unmount,         /* 15  */
        fs_sync,            /* 16  */
         no_sys,             /* 17  */
         no_sys,                    /* 18  */
@@ -53,30 +53,30 @@ PUBLIC _PROTOTYPE (int (*fs_call_vec[]),
 PUBLIC _PROTOTYPE (int (*dev_call_vec[]),
                                (message *dev_m_in, message *dev_m_out) ) = {
 
-        uds_cancel,         /* 0   */
+        uds_cancel,         /* 0  CANCEL */
         no_sys,             /* 1   */
         no_sys,             /* 2   */
         no_sys,             /* 3   */
         no_sys,             /* 4   */
         no_sys,             /* 5   */
-       uds_open,           /* 6   */
-        uds_close,          /* 7   */
+       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  */
-        uds_status,         /* 13  */
-        uds_open,           /* 14  */
+        no_sys,             /* 10 TTY_SETPGRP */
+        no_sys,             /* 11 TTY_EXIT */
+        uds_select,         /* 12 DEV_SELECT */
+        no_sys,             /* 13 DEV_STATUS */
+        uds_open,           /* 14 DEV_REOPEN */
         no_sys,             /* 15  */
        no_sys,             /* 16  */
         no_sys,             /* 17  */
         no_sys,                    /* 18  */
         no_sys,                    /* 19  */
-        uds_read,          /* 20  */
-        uds_write,          /* 21  */
-        no_sys,             /* 22  */
-        no_sys,             /* 23  */
-        uds_ioctl,          /* 24  */
-        no_sys,             /* 25  */
+        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 7a1309cf423176cdf137472f3818939bb0c2521b..18c70e1034bb0ce776ac9ca64075b29d3bff5748 100644 (file)
@@ -47,7 +47,7 @@ uds_fd_t uds_fd_table[NR_FDS];
 PUBLIC void uds_init(void)
 {
        /*
-        * Setting everything to NULL implicitly sets the 
+        * Setting everything to NULL implicitly sets the
         * state to UDS_FREE.
         */
        memset(uds_fd_table, '\0', sizeof(uds_fd_t) * NR_FDS);
@@ -74,7 +74,7 @@ PRIVATE int check_perms(int minor, struct sockaddr_un *addr)
        rc = sendrec(VFS_PROC_NR, &vfs_m);
        cpf_revoke(grant_id);
        if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",  
+                printf("(uds) sendrec error... req_nr: %d err: %d\n",
                        vfs_m.m_type, rc);
 
                return EIO;
@@ -95,7 +95,7 @@ PRIVATE filp_id_t verify_fd(endpoint_t ep, int fd)
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) verify_fd(%d,%d) call_count=%d\n", ep, fd, 
+       printf("(uds) verify_fd(%d,%d) call_count=%d\n", ep, fd,
                                                        ++call_count);
 #endif
 
@@ -107,7 +107,7 @@ PRIVATE filp_id_t verify_fd(endpoint_t ep, int fd)
 
        rc = sendrec(VFS_PROC_NR, &vfs_m);
        if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",  
+                printf("(uds) sendrec error... req_nr: %d err: %d\n",
                        vfs_m.m_type, rc);
                return NULL;
        }
@@ -136,7 +136,7 @@ PRIVATE int set_filp(filp_id_t sfilp)
 
        rc = sendrec(VFS_PROC_NR, &vfs_m);
        if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",  
+                printf("(uds) sendrec error... req_nr: %d err: %d\n",
                        vfs_m.m_type, rc);
                return EIO;
        }
@@ -154,7 +154,7 @@ PRIVATE 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, 0x%x) call_count=%d\n",to_ep, cfilp,
                                                        ++call_count);
 #endif
 
@@ -166,7 +166,7 @@ PRIVATE int copy_filp(endpoint_t to_ep, filp_id_t cfilp)
 
        rc = sendrec(VFS_PROC_NR, &vfs_m);
        if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",  
+                printf("(uds) sendrec error... req_nr: %d err: %d\n",
                        vfs_m.m_type, rc);
                return EIO;
        }
@@ -194,7 +194,7 @@ PRIVATE int put_filp(filp_id_t pfilp)
 
        rc = sendrec(VFS_PROC_NR, &vfs_m);
        if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",  
+                printf("(uds) sendrec error... req_nr: %d err: %d\n",
                        vfs_m.m_type, rc);
                return EIO;
        }
@@ -223,7 +223,7 @@ PRIVATE int cancel_fd(endpoint_t ep, int fd)
 
        rc = sendrec(VFS_PROC_NR, &vfs_m);
        if (OK != rc) {
-                printf("(uds) sendrec error... req_nr: %d err: %d\n",  
+                printf("(uds) sendrec error... req_nr: %d err: %d\n",
                        vfs_m.m_type, rc);
                return EIO;
        }
@@ -234,7 +234,7 @@ PRIVATE int cancel_fd(endpoint_t ep, int fd)
        return vfs_m.m_type; /* return reply code OK, ELOOP, etc. */
 }
 
-PUBLIC int perform_connection(message *dev_m_in, message *dev_m_out, 
+PUBLIC int perform_connection(message *dev_m_in, message *dev_m_out,
                        struct sockaddr_un *addr, int minorx, int minory)
 {
        /* there are several places were a connection is established. */
@@ -244,14 +244,14 @@ PUBLIC 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", 
+       printf("(uds) [%d] perform_connection() call_count=%d\n",
                                        uds_minor(dev_m_in), ++call_count);
 #endif
 
-       /* only connection oriented types are acceptable and only like 
+       /* only connection oriented types are acceptable and only like
         * types can connect to each other
         */
-       if ((uds_fd_table[minorx].type != SOCK_SEQPACKET && 
+       if ((uds_fd_table[minorx].type != SOCK_SEQPACKET &&
                uds_fd_table[minorx].type != SOCK_STREAM) ||
                uds_fd_table[minorx].type != uds_fd_table[minory].type) {
 
@@ -281,16 +281,16 @@ PUBLIC int do_accept(message *dev_m_in, message *dev_m_out)
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] do_accept() call_count=%d\n", 
+       printf("(uds) [%d] do_accept() call_count=%d\n",
                                        uds_minor(dev_m_in), ++call_count);
 #endif
 
-       /* Somewhat weird logic is used in this function, so here's an 
-        * overview... The minor number is the server's client socket 
-        * (the socket to be returned by accept()). The data waiting 
-        * for us in the IO Grant is the address that the server is 
-        * listening on. This function uses the address to find the 
-        * server's descriptor. From there we can perform the 
+       /* Somewhat weird logic is used in this function, so here's an
+        * overview... The minor number is the server's client socket
+        * (the socket to be returned by accept()). The data waiting
+        * for us in the IO Grant is the address that the server is
+        * listening on. This function uses the address to find the
+        * server's descriptor. From there we can perform the
         * connection or suspend and wait for a connect().
         */
 
@@ -316,7 +316,7 @@ PUBLIC int do_accept(message *dev_m_in, message *dev_m_out)
        for (i = 0; i < NR_FDS; i++) {
 
                if (uds_fd_table[i].addr.sun_family == AF_UNIX &&
-                               !strncmp(addr.sun_path, 
+                               !strncmp(addr.sun_path,
                                uds_fd_table[i].addr.sun_path,
                                UNIX_PATH_MAX) &&
                                uds_fd_table[i].listening == 1) {
@@ -327,7 +327,7 @@ PUBLIC int do_accept(message *dev_m_in, message *dev_m_out)
        }
 
        if (rc == -1) {
-               /* there is no server listening on addr. Maybe someone 
+               /* there is no server listening on addr. Maybe someone
                 * screwed up the ioctl()?
                 */
                return EINVAL;
@@ -338,7 +338,7 @@ PUBLIC int do_accept(message *dev_m_in, message *dev_m_out)
        /* we are the parent's child */
        uds_fd_table[minorparent].child = minor;
 
-       /* the peer has the same type as the parent. we need to be that 
+       /* the peer has the same type as the parent. we need to be that
         * type too.
         */
        uds_fd_table[minor].type = uds_fd_table[minorparent].type;
@@ -360,7 +360,7 @@ PUBLIC int do_accept(message *dev_m_in, message *dev_m_out)
                printf("(uds) [%d] {do_accept} suspend\n", minor);
 #endif
 
-               /* there are no peers in the backlog, suspend and wait 
+               /* there are no peers in the backlog, suspend and wait
                 * for some to show up
                 */
                uds_fd_table[minor].suspended = UDS_SUSPENDED_ACCEPT;
@@ -369,7 +369,7 @@ PUBLIC int do_accept(message *dev_m_in, message *dev_m_out)
        }
 
 #if DEBUG == 1
-       printf("(uds) [%d] connecting to %d -- parent is %d\n", minor, 
+       printf("(uds) [%d] connecting to %d -- parent is %d\n", minor,
                                                minorpeer, minorparent);
 #endif
 
@@ -387,11 +387,11 @@ PUBLIC int do_accept(message *dev_m_in, message *dev_m_out)
        /* if peer is blocked on connect() revive peer */
        if (uds_fd_table[minorpeer].suspended) {
 #if DEBUG == 1
-               printf("(uds) [%d] {do_accept} revive %d\n", minor, 
+               printf("(uds) [%d] {do_accept} revive %d\n", minor,
                                                                minorpeer);
 #endif
                uds_fd_table[minorpeer].ready_to_revive = 1;
-               notify(dev_m_in->m_source);
+               uds_unsuspend(dev_m_in->m_source, minorpeer);
        }
 
        return OK;
@@ -423,7 +423,7 @@ PUBLIC int do_connect(message *dev_m_in, message *dev_m_out)
        }
 
        rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                               (vir_bytes) 0, (vir_bytes) &addr, 
+                               (vir_bytes) 0, (vir_bytes) &addr,
                                sizeof(struct sockaddr_un), D);
 
        if (rc != OK) {
@@ -436,7 +436,7 @@ PUBLIC int do_connect(message *dev_m_in, message *dev_m_out)
                return rc;
        }
 
-       /* look for a socket of the same type that is listening on the 
+       /* look for a socket of the same type that is listening on the
         * address we want to connect to
         */
        for (i = 0; i < NR_FDS; i++) {
@@ -466,7 +466,7 @@ PUBLIC int do_connect(message *dev_m_in, message *dev_m_out)
 
                                        /* wake the parent (server) */
                                        uds_fd_table[i].ready_to_revive = 1;
-                                       notify(dev_m_in->m_source);
+                                       uds_unsuspend(dev_m_in->m_source, i);
                                }
 
                                return rc;
@@ -504,26 +504,24 @@ PUBLIC int do_connect(message *dev_m_in, message *dev_m_out)
                                /* 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 
+                                       /* 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_in & 
-                                               SEL_RD) && 
+                                       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;
 
-                                               notify(
-                                               uds_fd_table[i].select_proc
-                                               );
+                                               uds_unsuspend(
+                                               dev_m_in->m_source, i);
                                        }
                                }
 
@@ -540,7 +538,7 @@ PUBLIC int do_connect(message *dev_m_in, message *dev_m_out)
        }
 
        if (uds_fd_table[minor].peer == -1) {
-               /* could not find another open socket listening on the 
+               /* could not find another open socket listening on the
                 * specified address with room in the backlog
                 */
                return ECONNREFUSED;
@@ -580,7 +578,7 @@ PUBLIC int do_listen(message *dev_m_in, message *dev_m_out)
                return EINVAL;
        }
 
-       /* the two supported types for listen(2) are SOCK_STREAM and 
+       /* the two supported types for listen(2) are SOCK_STREAM and
         * SOCK_SEQPACKET
         */
        if (uds_fd_table[minor].type != SOCK_STREAM &&
@@ -590,9 +588,9 @@ PUBLIC int do_listen(message *dev_m_in, message *dev_m_out)
                return EOPNOTSUPP;
        }
 
-       /* The POSIX standard doesn't say what to do if listen() has 
-        * already been called. Well, there isn't an errno. we silently 
-        * let it happen, but if listen() has already been called, we 
+       /* The POSIX standard doesn't say what to do if listen() has
+        * already been called. Well, there isn't an errno. we silently
+        * 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,
@@ -612,7 +610,7 @@ PUBLIC int do_listen(message *dev_m_in, message *dev_m_out)
 
                } else {
 
-                       /* the user gave an invalid size, use 
+                       /* the user gave an invalid size, use
                         * UDS_SOMAXCONN instead
                         */
                        uds_fd_table[minor].backlog_size = UDS_SOMAXCONN;
@@ -627,7 +625,7 @@ PUBLIC int do_listen(message *dev_m_in, message *dev_m_out)
                        uds_fd_table[minor].backlog_size = backlog_size;
                }
 
-               /* Don't let the user shrink the backlog_size (we might 
+               /* Don't let the user shrink the backlog_size (we might
                 * have clients waiting in those slots
                 */
        }
@@ -679,7 +677,7 @@ PUBLIC int do_socket(message *dev_m_in, message *dev_m_out)
 
                default:
 
-                       /* if the type isn't one of the 3 valid socket 
+                       /* if the type isn't one of the 3 valid socket
                         * types, then it must be invalid.
                         */
 
@@ -715,7 +713,7 @@ PUBLIC int do_bind(message *dev_m_in, message *dev_m_out)
        }
 
        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), 
+               (vir_bytes) 0, (vir_bytes) &addr, sizeof(struct sockaddr_un),
                D);
 
        if (rc != OK) {
@@ -744,7 +742,7 @@ PUBLIC int do_bind(message *dev_m_in, message *dev_m_out)
        /* make sure the address isn't already in use by another socket. */
        for (i = 0; i < NR_FDS; i++) {
                if ((uds_fd_table[i].addr.sun_family == AF_UNIX) &&
-                       !strncmp(addr.sun_path, 
+                       !strncmp(addr.sun_path,
                        uds_fd_table[i].addr.sun_path, UNIX_PATH_MAX)) {
 
                        /* another socket is bound to this sun_path */
@@ -772,13 +770,13 @@ PUBLIC int do_getsockname(message *dev_m_in, message *dev_m_out)
        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 
+        * 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), 
+               (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].addr),
                sizeof(struct sockaddr_un), D);
 
        return rc ? EIO : OK;
@@ -867,7 +865,7 @@ PUBLIC int do_shutdown(message *dev_m_in, message *dev_m_out)
 
                case SHUT_WR:
                        /* take away write permission */
-                       uds_fd_table[minor].mode = 
+                       uds_fd_table[minor].mode =
                                uds_fd_table[minor].mode ^ S_IWUSR;
                        break;
 
@@ -1000,7 +998,7 @@ PUBLIC int do_getsockopt_sotype(message *dev_m_in, message *dev_m_out)
        }
 
        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), 
+               (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].type),
                sizeof(int), D);
 
        return rc ? EIO : OK;
@@ -1095,7 +1093,7 @@ PUBLIC int do_getsockopt_peercred_old(message *dev_m_in, message *dev_m_out)
        return rc ? EIO : OK;
 }
 
-int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out) 
+int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
 {
        int minor;
        int rc;
@@ -1110,13 +1108,13 @@ int do_getsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
        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) &(sndbuf), 
+               (vir_bytes) 0, (vir_bytes) &(sndbuf),
                sizeof(size_t), D);
 
        return rc ? EIO : OK;
 }
 
-int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out) 
+int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
 {
        int minor;
        int rc;
@@ -1132,7 +1130,7 @@ int do_setsockopt_sndbuf(message *dev_m_in, message *dev_m_out)
 
 
        rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                               (vir_bytes) 0, (vir_bytes) &sndbuf, 
+                               (vir_bytes) 0, (vir_bytes) &sndbuf,
                                sizeof(size_t), D);
 
        if (rc != OK) {
@@ -1150,7 +1148,7 @@ 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) 
+int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
 {
        int minor;
        int rc;
@@ -1165,7 +1163,7 @@ int do_getsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
        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) &(rcvbuf), 
+               (vir_bytes) 0, (vir_bytes) &(rcvbuf),
                sizeof(size_t), D);
 
        return rc ? EIO : OK;
@@ -1187,7 +1185,7 @@ int do_setsockopt_rcvbuf(message *dev_m_in, message *dev_m_out)
 
 
        rc = sys_safecopyfrom(VFS_PROC_NR, (cp_grant_id_t) dev_m_in->IO_GRANT,
-                               (vir_bytes) 0, (vir_bytes) &rcvbuf, 
+                               (vir_bytes) 0, (vir_bytes) &rcvbuf,
                                sizeof(size_t), D);
 
        if (rc != OK) {
@@ -1264,7 +1262,7 @@ PUBLIC int do_recvfrom(message *dev_m_in, message *dev_m_out)
        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), 
+               (vir_bytes) 0, (vir_bytes) &(uds_fd_table[minor].source),
                sizeof(struct sockaddr_un), D);
 
        return rc ? EIO : OK;
@@ -1279,7 +1277,7 @@ int msg_control_read(struct msg_control *msg_ctrl, struct ancillary *data,
 
 #if DEBUG == 1
        static int call_count = 0;
-       printf("(uds) [%d] msg_control_read() call_count=%d\n", minor, 
+       printf("(uds) [%d] msg_control_read() call_count=%d\n", minor,
                                                        ++call_count);
 #endif
 
@@ -1366,8 +1364,8 @@ PRIVATE int send_fds(int minor, struct ancillary *data)
 PUBLIC int clear_fds(int 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 
- * exists references to file descriptors that haven't been received 
+ * This is used when a Unix Domain Socket is closed and there
+ * exists references to file descriptors that haven't been received
  * with recvmsg().
  */
        int i;
@@ -1536,12 +1534,12 @@ PUBLIC int do_sendmsg(message *dev_m_in, message *dev_m_out)
 #if DEBUG == 1
        printf("(uds) [%d] sendmsg() -- peer=%d\n", minor, peer);
 #endif
-       /* note: it's possible that there is already some file 
+       /* note: it's possible that there is already some file
         * descriptors in ancillary_data if the peer didn't call
         * recvmsg() yet. That's okay. The receiver will
         * get the current file descriptors plus the new ones.
         */
-       rc = msg_control_read(&msg_ctrl, &uds_fd_table[peer].ancillary_data, 
+       rc = msg_control_read(&msg_ctrl, &uds_fd_table[peer].ancillary_data,
                                                                minor);
        if (rc != OK) {
                return rc;
@@ -1591,7 +1589,7 @@ PUBLIC int do_recvmsg(message *dev_m_in, message *dev_m_out)
        controllen_avail = MIN(msg_ctrl.msg_controllen, MSG_CONTROL_MAX);
 
        if (uds_fd_table[minor].ancillary_data.nfiledes > 0) {
-               controllen_needed = CMSG_LEN(sizeof(int) * 
+               controllen_needed = CMSG_LEN(sizeof(int) *
                                (uds_fd_table[minor].ancillary_data.nfiledes));
        }
 
@@ -1618,7 +1616,7 @@ PUBLIC 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, 
+               (vir_bytes) 0, (vir_bytes) &msg_ctrl,
                sizeof(struct msg_control), D);
 
        return rc ? EIO : OK;
index facfdbc33a883af2326186a430af41f3fa13b05d..efcb9c1da9a35b682fd5b50560d20b6fe8168d80 100644 (file)
@@ -43,8 +43,8 @@ struct uds_fd {
                /* OR it is UDS_INUSE and can't be allocated. */
                UDS_INUSE = 1
 
-       /* state is set to UDS_INUSE in uds_open(). state is Set to 
-        * UDS_FREE in uds_init() and uds_close(). state should be 
+       /* state is set to UDS_INUSE in uds_open(). state is Set to
+        * UDS_FREE in uds_init() and uds_close(). state should be
         * checked prior to all operations.
         */
        } state;
@@ -103,7 +103,7 @@ struct uds_fd {
        unsigned char backlog_size;
 
        /* index of peer in uds_fd_table for connected sockets.
-        * -1 is used to mean no peer. Assumptions: peer != -1 means 
+        * -1 is used to mean no peer. Assumptions: peer != -1 means
         * connected.
         */
        int peer;
@@ -131,7 +131,7 @@ struct uds_fd {
         */
        int listening;
 
-       /* stores file pointers and credentials being sent between 
+       /* stores file pointers and credentials being sent between
         * processes with sendmsg(2) and recvmsg(2).
         */
        struct ancillary ancillary_data;
@@ -144,7 +144,7 @@ struct uds_fd {
 
 /* Suspend/Revive Housekeeping */
 
-       
+
        /* SUSPEND State Flags */
        enum UDS_SUSPENDED {
 
@@ -232,11 +232,20 @@ EXTERN uds_fd_t uds_fd_table[NR_FDS];
  */
 #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;               \
+               (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 b4bd955f1a73d2f359b91e741325cd6fdc8934fd..fac9ec6259ec57d682ce3c78808a30dee38fc82a 100644 (file)
@@ -28,7 +28,6 @@ PUBLIC time_t clock_time()
 
   if ((r = getuptime2(&uptime, &boottime)) != OK)
                panic("clock_time: getuptme2 failed: %d", r);
-  
+
   return( (time_t) (boottime + (uptime/sys_hz())));
 }
-
index 5836e8dabb90e3d5b53c41faf157a6cf46ad6ff7..6c233fd6bc2abd2b2e3190904932e46998396c97 100644 (file)
@@ -8,10 +8,6 @@ SRCS=  buf.c main.c pid.c root.c tree.c util.c cpuinfo.c
 
 CPPFLAGS+= -I${MINIXSRCDIR} -I${MINIXSRCDIR}/servers
 
-.if ${BUILDAVFS} == "yes"
-CFLAGS+= -D_USEAVFS
-.endif
-
 DPADD+=        ${LIBVTREEFS} ${LIBSYS}
 LDADD+=        -lvtreefs -lsys
 
index f1c0b88510f1628f7fe30c764590476a95d1a31b..7a10ab5716ffc550cd1af330e20ee316272a2ffe 100644 (file)
 #include "kernel/type.h"
 #include "kernel/proc.h"
 #include "pm/mproc.h"
-#if defined(_USEAVFS)
-# include "avfs/const.h"
-# include "avfs/fproc.h"
-# include "avfs/dmap.h"
-#else
-# include "vfs/const.h"
-# include "vfs/fproc.h"
-# include "vfs/dmap.h"
-#endif
+#include "vfs/const.h"
+#include "vfs/fproc.h"
+#include "vfs/dmap.h"
 
 #include <minix/vtreefs.h>
 #include <minix/procfs.h>
index 1dc9057230ccc9079923e6c2177671931449b94b..ec0553f981a1650a3f2ac4aca7caba07778d3ca9 100644 (file)
@@ -6,15 +6,20 @@ SRCS= main.c open.c read.c write.c pipe.c dmap.c \
        path.c device.c mount.c link.c exec.c \
        filedes.c stadir.c protect.c time.c \
        lock.c misc.c utility.c select.c table.c \
-       vnode.c vmnt.c request.c fscall.c elf_core_dump.c
+       vnode.c vmnt.c request.c fscall.c \
+       tll.c comm.c worker.c coredump.c
 
 .if ${MKCOVERAGE} != "no"
-SRCS+= gcov.c
+SRCS+=  gcov.c
 CPPFLAGS+= -DUSE_COVERAGE
 .endif
 
 DPADD+=        ${LIBSYS} ${LIBTIMERS} ${LIBEXEC}
-LDADD+=        -lsys -ltimers -lexec
+LDADD+=        -lsys -ltimers -lexec -lmthread
+
+.if ${COMPILER_TYPE} == "gnu"
+LDADD+=        -lc
+.endif
 
 MAN=
 
similarity index 100%
rename from servers/avfs/comm.c
rename to servers/vfs/comm.c
similarity index 100%
rename from servers/avfs/comm.h
rename to servers/vfs/comm.h
index 0c4de2dd696c38038690e6a92379e61d859f3e2e..44a339d7c511f613676efe74af1b3a44110964dc 100644 (file)
@@ -1,8 +1,12 @@
+#ifndef __VFS_CONST_H__
+#define __VFS_CONST_H__
+
 /* Tables sizes */
 #define NR_FILPS         512   /* # slots in filp table */
 #define NR_LOCKS           8   /* # slots in the file locking table */
-#define NR_MNTS            16  /* # slots in mount table */
-#define NR_VNODES         512  /* # slots in vnode table */
+#define NR_MNTS           16   /* # slots in mount table */
+#define NR_VNODES        512   /* # slots in vnode table */
+#define NR_WTHREADS       8    /* # slots in worker thread table */
 
 #define NR_NONEDEVS    NR_MNTS /* # slots in nonedev bitmap */
 
@@ -17,7 +21,7 @@
 #define FP_BLOCKED_ON_POPEN    3 /* susp'd on pipe open */
 #define FP_BLOCKED_ON_SELECT   4 /* susp'd on select */
 #define FP_BLOCKED_ON_DOPEN    5 /* susp'd on device open */
-#define FP_BLOCKED_ON_OTHER    6 /* blocked on other process, check 
+#define FP_BLOCKED_ON_OTHER    6 /* blocked on other process, check
                                     fp_task to find out */
 
 /* test if the process is blocked on something */
@@ -28,7 +32,7 @@
 #define LOOK_UP            0 /* tells search_dir to lookup string */
 #define ENTER              1 /* tells search_dir to make dir entry */
 #define DELETE             2 /* tells search_dir to delete entry */
-#define IS_EMPTY           3 /* tells search_dir to ret. OK or ENOTEMPTY */  
+#define IS_EMPTY           3 /* tells search_dir to ret. OK or ENOTEMPTY */
 
 #define SYMLOOP                16
 
@@ -40,7 +44,7 @@
 /* Args to dev_io */
 #define VFS_DEV_READ   2001
 #define        VFS_DEV_WRITE   2002
-#define VFS_DEV_SCATTER        2003
-#define VFS_DEV_GATHER 2004
 #define VFS_DEV_IOCTL  2005
 #define VFS_DEV_SELECT 2006
+
+#endif
index 14f7370d133e082d614ac83fb01d3437cacaa4ab..926cf322a00e22a1e2eef71cba563d27b4816ddf 100644 (file)
@@ -16,8 +16,8 @@
  *   tty_opcl:   perform tty-specific processing for open/close
  *   ctty_opcl:  perform controlling-tty-specific processing for open/close
  *   ctty_io:    perform controlling-tty-specific processing for I/O
+ *   pm_setsid:         perform VFS's side of setsid system call
  *   do_ioctl:  perform the IOCTL system call
- *   do_setsid:         perform the SETSID system call (FS side)
  */
 
 #include "fs.h"
 #include <minix/u64.h>
 #include "file.h"
 #include "fproc.h"
+#include "scratchpad.h"
+#include "dmap.h"
 #include <minix/vfsif.h>
 #include "vnode.h"
 #include "vmnt.h"
 #include "param.h"
 
-#define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
-
+FORWARD _PROTOTYPE( void restart_reopen, (int major)                   );
 FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t, cp_grant_id_t *,
-                                            int *, cp_grant_id_t *, int,
-                                            endpoint_t *, void **, int *,
-                                            vir_bytes, u32_t *)        );
-FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *,
-                                          int)                         );
-FORWARD _PROTOTYPE( void restart_reopen, (int maj)                     );
-
-extern int dmap_size;
+                                            int *,
+                                            endpoint_t *, void **,
+                                            size_t, u32_t *)   );
+
 PRIVATE int dummyproc;
 
 
@@ -56,23 +53,21 @@ PRIVATE int dummyproc;
  *===========================================================================*/
 PUBLIC int dev_open(
   dev_t dev,                   /* device to open */
-  int proc,                    /* process to open for */
+  endpoint_t proc_e,           /* process to open for */
   int flags                    /* mode bits and flags */
 )
 {
 /* Open a character device. */
   int major, r;
-  struct dmap *dp;
 
   /* Determine the major device number so as to call the device class specific
    * open/close routine.  (This is the only routine that must check the
    * device number for being in range.  All others can trust this check.)
    */
-  major = (dev >> MAJOR) & BYTE;
-  if (major >= NR_DEVICES) major = 0;
-  dp = &dmap[major];
-  if (dp->dmap_driver == NONE) return(ENXIO);
-  r = (*dp->dmap_opcl)(DEV_OPEN, dev, proc, flags);
+  major = major(dev);
+  if (major < 0 || major >= NR_DEVICES) major = 0;
+  if (dmap[major].dmap_driver == NONE) return(ENXIO);
+  r = (*dmap[major].dmap_opcl)(DEV_OPEN, dev, proc_e, flags);
   return(r);
 }
 
@@ -87,19 +82,20 @@ PUBLIC int dev_reopen(
 )
 {
 /* Reopen a character device after a failing device driver. */
+
   int major, r;
   struct dmap *dp;
 
-  /* Determine the major device number call the device class specific
-   * open/close routine.  (This is the only routine that must check the
-   * device number for being in range.  All others can trust this check.)
+  /* Determine the major device number and call the device class specific
+   * open/close routine.  (This is the only routine that must check the device
+   * number for being in range.  All others can trust this check.)
    */
-  major = (dev >> MAJOR) & BYTE;
-  if (major >= NR_DEVICES) major = 0;
+
+  major = major(dev);
+  if (major < 0 || major >= NR_DEVICES) major = 0;
   dp = &dmap[major];
   if (dp->dmap_driver == NONE) return(ENXIO);
   r = (*dp->dmap_opcl)(DEV_REOPEN, dev, filp_no, flags);
-  if (r == OK) panic("OK on reopen from: %d", dp->dmap_driver);
   if (r == SUSPEND) r = OK;
   return(r);
 }
@@ -114,17 +110,19 @@ PUBLIC int dev_close(
 )
 {
 /* Close a character device. */
-  int r;
+  int r, major;
 
   /* See if driver is roughly valid. */
-  if (dmap[(dev >> MAJOR)].dmap_driver == NONE) return(ENXIO);
-  r = (*dmap[(dev >> MAJOR) & BYTE].dmap_opcl)(DEV_CLOSE, dev, filp_no, 0);
+  major = major(dev);
+  if (major < 0 || major >= NR_DEVICES) return(ENXIO);
+  if (dmap[major].dmap_driver == NONE) return(ENXIO);
+  r = (*dmap[major].dmap_opcl)(DEV_CLOSE, dev, filp_no, 0);
   return(r);
 }
 
 
 /*===========================================================================*
- *                             bdev_open                                    *
+ *                             dev_open                                     *
  *===========================================================================*/
 PUBLIC int bdev_open(dev_t dev, int access)
 {
@@ -165,7 +163,7 @@ PRIVATE int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
   u32_t dummy;
   cp_grant_id_t gid;
   message dev_mess;
-  int op, safe, major_dev, minor_dev, vec_grants;
+  int op, major_dev, minor_dev;
 
   major_dev = major(dev);
   minor_dev = minor(dev);
@@ -179,8 +177,8 @@ PRIVATE int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
 
   /* Set up a grant if necessary. */
   op = VFS_DEV_IOCTL;
-  safe = safe_io_conversion(dp->dmap_driver, &gid, &op, NULL, 0, &proc_e, &buf,
-       &vec_grants, 0, &dummy);
+  (void) safe_io_conversion(dp->dmap_driver, &gid, &op, &proc_e, &buf, 0,
+       &dummy);
 
   /* Set up the message passed to the task. */
   memset(&dev_mess, 0, sizeof(dev_mess));
@@ -195,7 +193,7 @@ PRIVATE int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
   (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
 
   /* Clean up. */
-  if (safe) safe_io_cleanup(gid, NULL, vec_grants);
+  if (GRANT_VALID(gid)) cpf_revoke(gid);
 
   if (dp->dmap_driver == NONE) {
        printf("VFS: block driver gone!?\n");
@@ -203,27 +201,29 @@ PRIVATE int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
   }
 
   /* Return the result. */
-  return dev_mess.BDEV_STATUS;
+  return(dev_mess.BDEV_STATUS);
 }
 
 
 /*===========================================================================*
- *                             suspended_ep                                 *
+ *                             find_suspended_ep                            *
  *===========================================================================*/
-endpoint_t suspended_ep(endpoint_t driver, cp_grant_id_t g)
+endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g)
 {
-/* A process is suspended on a driver for which FS issued
- * a grant. Find out which process it was.
+/* A process is suspended on a driver for which VFS issued a grant. Find out
+ * which process it was.
  */
   struct fproc *rfp;
   for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-       if(rfp->fp_pid == PID_FREE) continue;
-        if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
+       if(rfp->fp_pid == PID_FREE)
+               continue;
+
+       if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
           rfp->fp_task == driver && rfp->fp_grant == g)
-               return rfp->fp_endpoint;
-    }
+               return(rfp->fp_endpoint);
+  }
 
-    return(NONE);
+  return(NONE);
 }
 
 
@@ -232,191 +232,136 @@ endpoint_t suspended_ep(endpoint_t driver, cp_grant_id_t g)
  *===========================================================================*/
 PUBLIC void dev_status(message *m)
 {
+/* A device sent us a notification it has something for us. Retrieve it. */
+
   message st;
-  int d, get_more = 1;
+  int major, get_more = 1;
   endpoint_t endpt;
 
-  for(d = 0; d < NR_DEVICES; d++)
-       if (dmap[d].dmap_driver != NONE && dmap[d].dmap_driver == m->m_source)
-               break;
+  for (major = 0; major < NR_DEVICES; major++)
+       if (dmap_driver_match(m->m_source, major))
+               break; /* 'major' is the device that sent the message */
 
-       if (d >= NR_DEVICES) return;
-       if (dmap[d].dmap_style == STYLE_DEVA) {
-               printf("dev_status: not doing dev_status for async driver %d\n",
-                       m->m_source);
-               return;
-       }
+  if (major >= NR_DEVICES)     /* Device endpoint not found; nothing to do */
+       return;
 
-       do {
-               int r;
-               st.m_type = DEV_STATUS;
-               r = sendrec(m->m_source, &st);
-               if(r == OK && st.REP_STATUS == ERESTART) r = EDEADEPT;
-               if (r != OK) {
-                       printf("DEV_STATUS failed to %d: %d\n", m->m_source, r);
-                       if (r == EDEADSRCDST || r == EDEADEPT) return;
-                       panic("couldn't sendrec for DEV_STATUS: %d", r);
-               }
+  if (dmap[major].dmap_style == STYLE_DEVA ||
+      dmap[major].dmap_style == STYLE_CLONE_A) {
+       printf("VFS: not doing dev_status for async driver %d\n", m->m_source);
+       return;
+  }
 
-               switch(st.m_type) {
-                       case DEV_REVIVE:
-                               endpt = st.REP_ENDPT;
-                               if(endpt == VFS_PROC_NR) {
-                                       endpt = suspended_ep(m->m_source,
-                                               st.REP_IO_GRANT);
-                                       if(endpt == NONE) {
-                                               printf("FS: proc with grant %d"
-                                               " from %d not found (revive)\n",
-                                               st.REP_IO_GRANT, st.m_source);
-                                               continue;
-                                       }
-                               }
-                               revive(endpt, st.REP_STATUS);
-                               break;
-                       case DEV_IO_READY:
-                               select_reply2(st.m_source, st.DEV_MINOR,
-                                             st.DEV_SEL_OPS);
-                               break;
-                       default:
-                               printf("FS: unrecognized reply %d to "
-                                       "DEV_STATUS\n", st.m_type);
-                               /* Fall through. */
-                       case DEV_NO_STATUS:
-                               get_more = 0;
-                               break;
-               }
-       } while(get_more);
+  /* Continuously send DEV_STATUS messages until the device has nothing to
+   * say to us anymore. */
+  do {
+       int r;
+       st.m_type = DEV_STATUS;
+       r = sendrec(m->m_source, &st);
+       if (r == OK && st.REP_STATUS == ERESTART) r = EDEADEPT;
+       if (r != OK) {
+               printf("VFS: DEV_STATUS failed to %d: %d\n", m->m_source, r);
+               if (r == EDEADSRCDST || r == EDEADEPT) return;
+               panic("VFS: couldn't sendrec for DEV_STATUS: %d", r);
+       }
 
-       return;
+       switch(st.m_type) {
+         case DEV_REVIVE:
+               /* We've got results for a read/write/ioctl call to a
+                * synchronous character driver */
+               endpt = st.REP_ENDPT;
+               if (endpt == VFS_PROC_NR) {
+                       endpt = find_suspended_ep(m->m_source,st.REP_IO_GRANT);
+                       if(endpt == NONE) {
+                         printf("VFS: proc with grant %d from %d not found\n",
+                                st.REP_IO_GRANT, st.m_source);
+                         continue;
+                       }
+               }
+               revive(endpt, st.REP_STATUS);
+               break;
+         case DEV_IO_READY:
+               /* Reply to a select request: driver is ready for I/O */
+               select_reply2(st.m_source, st.DEV_MINOR, st.DEV_SEL_OPS);
+               break;
+         default:
+               printf("VFS: unrecognized reply %d to DEV_STATUS\n",st.m_type);
+               /* Fall through. */
+         case DEV_NO_STATUS:
+               get_more = 0;
+               break;
+       }
+  } while(get_more);
 }
 
-
 /*===========================================================================*
  *                             safe_io_conversion                           *
  *===========================================================================*/
-PRIVATE int safe_io_conversion(driver, gid, op, gids, gids_size,
-       io_ept, buf, vec_grants, bytes, pos_lo)
+PRIVATE int safe_io_conversion(driver, gid, op, io_ept, buf, bytes, pos_lo)
 endpoint_t driver;
 cp_grant_id_t *gid;
 int *op;
-cp_grant_id_t *gids;
-int gids_size;
 endpoint_t *io_ept;
 void **buf;
-int *vec_grants;
-vir_bytes bytes;
+size_t bytes;
 u32_t *pos_lo;
 {
-  int access = 0, size, j;
-  iovec_t *v;
-  static iovec_t new_iovec[NR_IOREQS];
+/* Convert operation to the 'safe' variant (i.e., grant based) if applicable.
+ * If no copying of data is involved, there is also no need to convert. */
 
-  /* Number of grants allocated in vector I/O. */
-  *vec_grants = 0;
+  int access = 0;
+  size_t size;
 
-  /* Driver can handle it - change request to a safe one. */
-  *gid = GRANT_INVALID;
+  *gid = GRANT_INVALID;                /* Grant to buffer */
 
   switch(*op) {
-       case VFS_DEV_READ:
-       case VFS_DEV_WRITE:
-          /* Change to safe op. */
-          *op = *op == VFS_DEV_READ ? DEV_READ_S : DEV_WRITE_S;
-
-          *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, bytes,
-                                 *op == DEV_READ_S ? CPF_WRITE : CPF_READ);
-          if (*gid < 0)
-               panic("cpf_grant_magic of buffer failed");
-          break;
-       case VFS_DEV_GATHER:
-       case VFS_DEV_SCATTER:
-          /* Change to safe op. */
-          *op = *op == VFS_DEV_GATHER ? DEV_GATHER_S : DEV_SCATTER_S;
-
-          /* Grant access to my new i/o vector. */
-          *gid = cpf_grant_direct(driver, (vir_bytes) new_iovec,
-                                 bytes * sizeof(iovec_t), CPF_READ|CPF_WRITE);
-          if (*gid < 0) 
-               panic("cpf_grant_direct of vector failed");
-                       
-          v = (iovec_t *) *buf;
-          /* Grant access to i/o buffers. */
-          for(j = 0; j < bytes; j++) {
-               if(j >= NR_IOREQS) panic("vec too big: %d", bytes);
-
-               new_iovec[j].iov_addr = 
-               gids[j] = 
-               cpf_grant_direct(driver, (vir_bytes) v[j].iov_addr, v[j].iov_size,
-                                *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ);
-
-               if(!GRANT_VALID(gids[j])) 
-                       panic("grant to iovec buf failed");
-                          
-               new_iovec[j].iov_size = v[j].iov_size;
-               (*vec_grants)++;
-          }
-
-          /* Set user's vector to the new one. */
-          *buf = new_iovec;
-          break;
-       case VFS_DEV_IOCTL:
-          *pos_lo = *io_ept; /* Old endpoint in POSITION field. */
-          *op = DEV_IOCTL_S;
-          if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE;
-          if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ;
-          if(_MINIX_IOCTL_BIG(m_in.REQUEST))
+    case VFS_DEV_READ:
+    case VFS_DEV_WRITE:
+       /* Change to safe op. */
+       *op = (*op == VFS_DEV_READ) ? DEV_READ_S : DEV_WRITE_S;
+       *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, bytes,
+                              *op == DEV_READ_S ? CPF_WRITE : CPF_READ);
+       if (*gid < 0)
+               panic("VFS: cpf_grant_magic of READ/WRITE buffer failed");
+       break;
+    case VFS_DEV_IOCTL:
+       *pos_lo = *io_ept; /* Old endpoint in POSITION field. */
+       *op = DEV_IOCTL_S;
+       if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE;
+       if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ;
+       if(_MINIX_IOCTL_BIG(m_in.REQUEST))
                size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST);
-          else
+       else
                size = _MINIX_IOCTL_SIZE(m_in.REQUEST);
 
-
-          /* Do this even if no I/O happens with the ioctl, in
-           * order to disambiguate requests with DEV_IOCTL_S.
-           */
-          *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, size,
-                                 access);
-          if (*gid < 0) 
-               panic("cpf_grant_magic failed (ioctl)");
-                       
-          break;
-       case VFS_DEV_SELECT:
-          *op = DEV_SELECT;
-          break;
-       default:
-          panic("safe_io_conversion: unknown operation: %d", *op);
+       /* Grant access to the buffer even if no I/O happens with the ioctl, in
+        * order to disambiguate requests with DEV_IOCTL_S.
+        */
+       *gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, size, access);
+       if (*gid < 0)
+               panic("VFS: cpf_grant_magic IOCTL buffer failed");
+
+       break;
+    case VFS_DEV_SELECT:
+       *op = DEV_SELECT;
+       break;
+    default:
+       panic("VFS: unknown operation %d for safe I/O conversion", *op);
   }
 
-  /* If we have converted to a safe operation, I/O
-   * endpoint becomes FS if it wasn't already.
+  /* If we have converted to a safe operation, I/O endpoint becomes VFS if it
+   * wasn't already.
    */
   if(GRANT_VALID(*gid)) {
        *io_ept = VFS_PROC_NR;
-       return 1;
-   }
-
-   /* Not converted to a safe operation (because there is no
-    * copying involved in this operation).
-    */
-  return 0;
-}
-
-/*===========================================================================*
- *                     safe_io_cleanup                                      *
- *===========================================================================*/
-PRIVATE void safe_io_cleanup(gid, gids, gids_size)
-cp_grant_id_t gid;
-cp_grant_id_t *gids;
-int gids_size;
-{
-/* Free resources (specifically, grants) allocated by safe_io_conversion(). */
-  int j;
+       return(1);
+  }
 
-  cpf_revoke(gid);
-  for(j = 0; j < gids_size; j++)
-       cpf_revoke(gids[j]);
+  /* Not converted to a safe operation (because there is no copying involved in
+   * this operation).
+   */
+  return(0);
 }
 
-
 /*===========================================================================*
  *                             dev_io                                       *
  *===========================================================================*/
@@ -426,30 +371,31 @@ PUBLIC int dev_io(
   int proc_e,                  /* in whose address space is buf? */
   void *buf,                   /* virtual address of the buffer */
   u64_t pos,                   /* byte position */
-  int bytes,                   /* how many bytes to transfer */
+  size_t bytes,                        /* how many bytes to transfer */
   int flags,                   /* special flags, like O_NONBLOCK */
   int suspend_reopen           /* Just suspend the process */
 )
 {
-/* Read or write from a device.  The parameter 'dev' tells which one. */
+/* Read from or write to a device.  The parameter 'dev' tells which one. */
   struct dmap *dp;
   u32_t pos_lo, pos_high;
   message dev_mess;
   cp_grant_id_t gid = GRANT_INVALID;
-  static cp_grant_id_t gids[NR_IOREQS];
-  int vec_grants = 0, safe;
+  int safe, minor_dev, major_dev;
   void *buf_used;
   endpoint_t ioproc;
 
-  pos_lo= ex64lo(pos);
-  pos_high= ex64hi(pos);
+  pos_lo = ex64lo(pos);
+  pos_high = ex64hi(pos);
+  major_dev = major(dev);
+  minor_dev = minor(dev);
 
   /* Determine task dmap. */
-  dp = &dmap[(dev >> MAJOR) & BYTE];
+  dp = &dmap[major_dev];
 
   /* See if driver is roughly valid. */
   if (dp->dmap_driver == NONE) {
-       printf("FS: dev_io: no driver for dev %x\n", dev);
+       printf("VFS: dev_io: no driver for major %d\n", major_dev);
        return(ENXIO);
   }
 
@@ -458,12 +404,13 @@ PUBLIC int dev_io(
        fp->fp_grant = GRANT_INVALID;
        fp->fp_ioproc = NONE;
        wait_for(dp->dmap_driver);
-       fp->fp_flags |= SUSP_REOPEN;
+       fp->fp_flags |= FP_SUSP_REOPEN;
        return(SUSPEND);
   }
 
   if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
-       printf("FS: dev_io: old driver for dev %x (%d)\n",dev,dp->dmap_driver);
+       printf("VFS: dev_io: old driver for major %x (%d)\n", major_dev,
+               dp->dmap_driver);
        return(ENXIO);
   }
 
@@ -473,21 +420,18 @@ PUBLIC int dev_io(
 
   /* Convert DEV_* to DEV_*_S variants. */
   buf_used = buf;
-  safe = safe_io_conversion(dp->dmap_driver, &gid, &op, gids, NR_IOREQS,
-                           (endpoint_t*) &dev_mess.USER_ENDPT, &buf_used,
-                           &vec_grants, bytes, &pos_lo);
-
-  if(buf != buf_used)
-       panic("dev_io: safe_io_conversion changed buffer");
+  safe = safe_io_conversion(dp->dmap_driver, &gid, &op,
+                           (endpoint_t *) &dev_mess.USER_ENDPT, &buf_used,
+                           bytes, &pos_lo);
 
-  /* If the safe conversion was done, set the ADDRESS to
+  /* If the safe conversion was done, set the IO_GRANT to
    * the grant id.
    */
   if(safe) dev_mess.IO_GRANT = (char *) gid;
 
   /* Set up the rest of the message passed to task. */
   dev_mess.m_type   = op;
-  dev_mess.DEVICE   = (dev >> MINOR) & BYTE;
+  dev_mess.DEVICE   = minor_dev;
   dev_mess.POSITION = pos_lo;
   dev_mess.COUNT    = bytes;
   dev_mess.HIGHPOS  = pos_high;
@@ -499,20 +443,16 @@ PUBLIC int dev_io(
   (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
 
   if(dp->dmap_driver == NONE) {
-       /* Driver has vanished. */
-       printf("Driver gone?\n");
-       if(safe) safe_io_cleanup(gid, gids, vec_grants);
+       /* Driver has vanished. */
+       printf("VFS: driver gone?!\n");
+       if(safe) cpf_revoke(gid);
        return(EIO);
   }
 
   /* Task has completed.  See if call completed. */
   if (dev_mess.REP_STATUS == SUSPEND) {
-       if(vec_grants > 0) panic("SUSPEND on vectored i/o");
-       
-       /* fp is uninitialized at init time. */
-       if(!fp) panic("SUSPEND on NULL fp");
-
-       if ((flags & O_NONBLOCK) && !(dp->dmap_style == STYLE_DEVA)) {
+       if ((flags & O_NONBLOCK) && !(dp->dmap_style == STYLE_DEVA ||
+                                     dp->dmap_style == STYLE_CLONE_A)) {
                /* Not supposed to block. */
                dev_mess.m_type = CANCEL;
                dev_mess.USER_ENDPT = ioproc;
@@ -524,7 +464,7 @@ PUBLIC int dev_io(
                dev_mess.COUNT = 0;
                if (call_nr == READ)            dev_mess.COUNT = R_BIT;
                else if (call_nr == WRITE)      dev_mess.COUNT = W_BIT;
-               dev_mess.DEVICE = (dev >> MINOR) & BYTE;
+               dev_mess.DEVICE = minor_dev;
                (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
                if (dev_mess.REP_STATUS == EINTR) dev_mess.REP_STATUS = EAGAIN;
        } else {
@@ -549,7 +489,7 @@ PUBLIC int dev_io(
                        dev_mess.COUNT = 0;
                        if(call_nr == READ)             dev_mess.COUNT = R_BIT;
                        else if(call_nr == WRITE)       dev_mess.COUNT = W_BIT;
-                       dev_mess.DEVICE = (dev >> MINOR) & BYTE;
+                       dev_mess.DEVICE = minor_dev;
                        (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
 
                        /* Should do something about EINTR -> EAGAIN mapping */
@@ -559,7 +499,7 @@ PUBLIC int dev_io(
   }
 
   /* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */
-  if(safe) safe_io_cleanup(gid, gids, vec_grants);
+  if(safe) cpf_revoke(gid);
 
   return(dev_mess.REP_STATUS);
 }
@@ -570,42 +510,46 @@ PUBLIC int dev_io(
 PUBLIC int gen_opcl(
   int op,                      /* operation, (B)DEV_OPEN or (B)DEV_CLOSE */
   dev_t dev,                   /* device to open or close */
-  int proc_e,                  /* process to open/close for */
+  endpoint_t proc_e,           /* process to open/close for */
   int flags                    /* mode bits and flags */
 )
 {
-/* Called from the dmap struct in table.c on opens & closes of special files.*/
-  int r, is_bdev;
+/* Called from the dmap struct on opens & closes of special files.*/
+  int r, minor_dev, major_dev, is_bdev;
   struct dmap *dp;
   message dev_mess;
 
   /* Determine task dmap. */
-  dp = &dmap[major(dev)];
+  major_dev = major(dev);
+  minor_dev = minor(dev);
+  assert(major_dev >= 0 && major_dev < NR_DEVICES);
+  dp = &dmap[major_dev];
+  assert(dp->dmap_driver != NONE);
 
   is_bdev = IS_BDEV_RQ(op);
 
   if (is_bdev) {
        memset(&dev_mess, 0, sizeof(dev_mess));
        dev_mess.m_type = op;
-       dev_mess.BDEV_MINOR = minor(dev);
+       dev_mess.BDEV_MINOR = minor_dev;
        dev_mess.BDEV_ACCESS = flags;
        dev_mess.BDEV_ID = 0;
   } else {
        dev_mess.m_type = op;
-       dev_mess.DEVICE = minor(dev);
+       dev_mess.DEVICE = minor_dev;
        dev_mess.USER_ENDPT = proc_e;
        dev_mess.COUNT = flags;
   }
 
-  if (dp->dmap_driver == NONE) {
-       printf("FS: gen_opcl: no driver for dev %x\n", dev);
-       return(ENXIO);
-  }
-
   /* Call the task. */
-  r= (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
+  r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
   if (r != OK) return(r);
 
+  if (op == DEV_OPEN && dp->dmap_style == STYLE_DEVA) {
+       fp->fp_task = dp->dmap_driver;
+       worker_wait();
+  }
+
   if (is_bdev)
        return(dev_mess.BDEV_STATUS);
   else
@@ -618,12 +562,12 @@ PUBLIC int gen_opcl(
 PUBLIC int tty_opcl(
   int op,                      /* operation, DEV_OPEN or DEV_CLOSE */
   dev_t dev,                   /* device to open or close */
-  int proc_e,                  /* process to open/close for */
+  endpoint_t proc_e,           /* process to open/close for */
   int flags                    /* mode bits and flags */
 )
 {
 /* This procedure is called from the dmap struct on tty open/close. */
+
   int r;
   register struct fproc *rfp;
 
@@ -633,7 +577,7 @@ PUBLIC int tty_opcl(
    * if it already has a controlling tty, or if it is someone elses
    * controlling tty.
    */
-  if (!fp->fp_sesldr || fp->fp_tty != 0) {
+  if (!(fp->fp_flags & FP_SESLDR) || fp->fp_tty != 0) {
        flags |= O_NOCTTY;
   } else {
        for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
@@ -649,6 +593,7 @@ PUBLIC int tty_opcl(
        fp->fp_tty = dev;
        r = OK;
   }
+
   return(r);
 }
 
@@ -658,15 +603,15 @@ PUBLIC int tty_opcl(
  *===========================================================================*/
 PUBLIC int ctty_opcl(
   int op,                      /* operation, DEV_OPEN or DEV_CLOSE */
-  dev_t dev,                   /* device to open or close */
-  int proc_e,                  /* process to open/close for */
-  int flags                    /* mode bits and flags */
+  dev_t UNUSED(dev),           /* device to open or close */
+  endpoint_t UNUSED(proc_e),   /* process to open/close for */
+  int UNUSED(flags)            /* mode bits and flags */
 )
 {
-/* This procedure is called from the dmap struct in table.c on opening/closing
+/* This procedure is called from the dmap struct on opening or closing
  * /dev/tty, the magic device that translates to the controlling tty.
  */
+
   assert(!IS_BDEV_RQ(op));
 
   return(fp->fp_tty == 0 ? ENXIO : OK);
@@ -679,7 +624,7 @@ PUBLIC int ctty_opcl(
 PUBLIC void pm_setsid(proc_e)
 int proc_e;
 {
-/* Perform the FS side of the SETSID call, i.e. get rid of the controlling
+/* Perform the VFS side of the SETSID call, i.e. get rid of the controlling
  * terminal of a process, and make the process a session leader.
  */
   register struct fproc *rfp;
@@ -688,7 +633,7 @@ int proc_e;
   /* Make the process a session leader with no controlling tty. */
   okendpt(proc_e, &slot);
   rfp = &fproc[slot];
-  rfp->fp_sesldr = TRUE;
+  rfp->fp_flags |= FP_SESLDR;
   rfp->fp_tty = 0;
 }
 
@@ -700,91 +645,82 @@ PUBLIC int do_ioctl()
 {
 /* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
 
-  int suspend_reopen;
+  int r = OK, suspend_reopen;
   struct filp *f;
   register struct vnode *vp;
   dev_t dev;
 
-  if ((f = get_filp(m_in.ls_fd)) == NULL) return(err_code);
+  scratch(fp).file.fd_nr = m_in.ls_fd;
+
+  if ((f = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
+       return(err_code);
   vp = f->filp_vno;            /* get vnode pointer */
   if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL &&
-      (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
-  suspend_reopen= (f->filp_state != FS_NORMAL);
-  dev = (dev_t) vp->v_sdev;
+      (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) {
+       r = ENOTTY;
+  }
 
-  if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL)
-       return bdev_ioctl(dev, who_e, m_in.REQUEST, m_in.ADDRESS);
+  if (r == OK) {
+       suspend_reopen = (f->filp_state != FS_NORMAL);
+       dev = (dev_t) vp->v_sdev;
 
-  return dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
-               m_in.REQUEST, f->filp_flags, suspend_reopen);
+       if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL)
+               r = bdev_ioctl(dev, who_e, m_in.REQUEST, m_in.ADDRESS);
+       else
+               r = dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
+                  m_in.REQUEST, f->filp_flags, suspend_reopen);
+  }
+
+  unlock_filp(f);
+
+  return(r);
 }
 
 
 /*===========================================================================*
  *                             gen_io                                       *
  *===========================================================================*/
-PUBLIC int gen_io(task_nr, mess_ptr)
-int task_nr;                   /* which task to call */
+PUBLIC int gen_io(driver_e, mess_ptr)
+endpoint_t driver_e;           /* which endpoint to call */
 message *mess_ptr;             /* pointer to message for task */
 {
 /* All file system I/O ultimately comes down to I/O on major/minor device
  * pairs.  These lead to calls on the following routines via the dmap table.
  */
-
-  int r, status, proc_e, is_bdev;
-
-  if(task_nr == SYSTEM) {
-       printf("VFS: sending %d to SYSTEM\n", mess_ptr->m_type);
-  }
+  int r, status, proc_e = NONE, is_bdev;
 
   is_bdev = IS_BDEV_RQ(mess_ptr->m_type);
 
   if (!is_bdev) proc_e = mess_ptr->USER_ENDPT;
 
-  for (;;) {
-
-       r = sendrec(task_nr, mess_ptr);
-       if(r == OK) {
-               if (is_bdev)
-                       status = mess_ptr->BDEV_STATUS;
-               else
-                       status = mess_ptr->REP_STATUS;
-               if (status == ERESTART) r = EDEADEPT;
-       }
-       if (r != OK) {
-               if (r == EDEADSRCDST || r == EDEADEPT) {
-                       printf("fs: dead driver %d\n", task_nr);
-                       dmap_unmap_by_endpt(task_nr);
-                       return(r);
-               }
-               if (r == ELOCKED) {
-                       printf("fs: ELOCKED talking to %d\n", task_nr);
-                       return(r);
-               }
-               panic("call_task: can't send/receive: %d", r);
+  r = sendrec(driver_e, mess_ptr);
+  if (r == OK) {
+       if (is_bdev)
+               status = mess_ptr->BDEV_STATUS;
+       else
+               status = mess_ptr->REP_STATUS;
+       if (status == ERESTART)
+               r = EDEADEPT;
+  }
+  if (r != OK) {
+       if (r == EDEADSRCDST || r == EDEADEPT) {
+               printf("VFS: dead driver %d\n", driver_e);
+               dmap_unmap_by_endpt(driver_e);
+               return(r);
+       } else if (r == ELOCKED) {
+               printf("VFS: ELOCKED talking to %d\n", driver_e);
+               return(r);
        }
+       panic("call_task: can't send/receive: %d", r);
+  }
 
-       /* Did the process we did the sendrec() for get a result? */
-       if (!is_bdev &&
-               mess_ptr->REP_ENDPT != proc_e && VFS_PROC_NR != proc_e) {
-
-               printf("fs: strange device reply from %d, type = %d, "
-               "proc = %d (not %d) (2) ignored\n", mess_ptr->m_source, 
+  /* Did the process we did the sendrec() for get a result? */
+  if (!is_bdev && mess_ptr->REP_ENDPT != proc_e) {
+       printf("VFS: strange device reply from %d, type = %d, "
+               "proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
                mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
 
-               return(EIO);
-       }
-
-       if (mess_ptr->m_type == TASK_REPLY ||
-               IS_DEV_RS(mess_ptr->m_type) ||
-               IS_BDEV_RS(mess_ptr->m_type) ||
-               mess_ptr->m_type <= 0) {
-
-               break; /* reply */
-       } else {
-
-               nested_dev_call(mess_ptr);
-       }
+       return(EIO);
   }
 
   return(OK);
@@ -799,15 +735,17 @@ int task_nr;                      /* which task to call */
 message *mess_ptr;             /* pointer to message for task */
 {
 /* All file system I/O ultimately comes down to I/O on major/minor device
- * pairs.  These lead to calls on the following routines via the dmap table.
+ * pairs. These lead to calls on the following routines via the dmap table.
  */
 
   int r;
 
   assert(!IS_BDEV_RQ(mess_ptr->m_type));
 
-  r = asynsend(task_nr, mess_ptr);
-  if (r != OK) panic("asyn_io: asynsend failed: %d", r);
+  fp->fp_sendrec = mess_ptr;   /* Remember where result should be stored */
+  r = asynsend3(task_nr, mess_ptr, AMF_NOREPLY);
+
+  if (r != OK) panic("VFS: asynsend in asyn_io failed: %d", r);
 
   /* Fake a SUSPEND */
   mess_ptr->REP_STATUS = SUSPEND;
@@ -818,9 +756,10 @@ message *mess_ptr;         /* pointer to message for task */
 /*===========================================================================*
  *                             ctty_io                                      *
  *===========================================================================*/
-PUBLIC int ctty_io(task_nr, mess_ptr)
-int task_nr;                   /* not used - for compatibility with dmap_t */
-message *mess_ptr;             /* pointer to message for task */
+PUBLIC int ctty_io(
+  endpoint_t UNUSED(task_nr),  /* not used - for compatibility with dmap_t */
+  message *mess_ptr            /* pointer to message for task */
+)
 {
 /* This routine is only called for one device, namely /dev/tty.  Its job
  * is to change the message to use the controlling terminal, instead of the
@@ -834,21 +773,22 @@ message *mess_ptr;                /* pointer to message for task */
        mess_ptr->REP_STATUS = EIO;
   } else {
        /* Substitute the controlling terminal device. */
-       dp = &dmap[(fp->fp_tty >> MAJOR) & BYTE];
-       mess_ptr->DEVICE = (fp->fp_tty >> MINOR) & BYTE;
+       dp = &dmap[major(fp->fp_tty)];
+       mess_ptr->DEVICE = minor(fp->fp_tty);
 
        if (dp->dmap_driver == NONE) {
                printf("FS: ctty_io: no driver for dev\n");
                return(EIO);
        }
 
-       if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
-               printf("FS: ctty_io: old driver %d\n", dp->dmap_driver);
+       if (isokendpt(dp->dmap_driver, &dummyproc) != OK) {
+               printf("VFS: ctty_io: old driver %d\n", dp->dmap_driver);
                return(EIO);
        }
 
        (*dp->dmap_io)(dp->dmap_driver, mess_ptr);
   }
+
   return(OK);
 }
 
@@ -870,7 +810,7 @@ PUBLIC int no_dev(
 /*===========================================================================*
  *                             no_dev_io                                    *
  *===========================================================================*/
-PUBLIC int no_dev_io(int proc, message *m)
+PUBLIC int no_dev_io(endpoint_t UNUSED(proc), message *UNUSED(m))
 {
 /* Called when doing i/o on a nonexistent device. */
   printf("VFS: I/O on unmapped device number\n");
@@ -894,45 +834,48 @@ PUBLIC int clone_opcl(
  * as a new network connection) that has been allocated within a task.
  */
   struct dmap *dp;
-  int r, minor;
+  int r, minor_dev, major_dev;
   message dev_mess;
 
   assert(!IS_BDEV_RQ(op));
 
   /* Determine task dmap. */
-  dp = &dmap[(dev >> MAJOR) & BYTE];
-  minor = (dev >> MINOR) & BYTE;
+  minor_dev = minor(dev);
+  major_dev = major(dev);
+  assert(major_dev >= 0 && major_dev < NR_DEVICES);
+  dp = &dmap[major_dev];
+  assert(dp->dmap_driver != NONE);
 
   dev_mess.m_type   = op;
-  dev_mess.DEVICE   = minor;
+  dev_mess.DEVICE   = minor_dev;
   dev_mess.USER_ENDPT = proc_e;
   dev_mess.COUNT    = flags;
 
-
-  if (dp->dmap_driver == NONE) {
-       printf("VFS clone_opcl: no driver for dev %x\n", dev);
-       return(ENXIO);
-  }
-
   if(isokendpt(dp->dmap_driver, &dummyproc) != OK) {
-       printf("VFS clone_opcl: bad driver endpoint for dev %x (%d)\n", dev,
-              dp->dmap_driver);
-       return(ENXIO);
+       printf("VFS clone_opcl: bad driver endpoint for major %d (%d)\n",
+              major_dev, dp->dmap_driver);
+       return(ENXIO);
   }
 
   /* Call the task. */
   r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
   if (r != OK) return(r);
 
+  if (op == DEV_OPEN && dp->dmap_style == STYLE_CLONE_A) {
+       /* Wait for reply when driver is asynchronous */
+       fp->fp_task = dp->dmap_driver;
+       worker_wait();
+  }
+
   if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) {
-       if (dev_mess.REP_STATUS != minor) {
+       if (dev_mess.REP_STATUS != minor_dev) {
                 struct vnode *vp;
                 struct node_details res;
 
                /* A new minor device number has been returned.
-                 * Request PFS to create a temporary device file to hold it. 
+                 * Request PFS to create a temporary device file to hold it.
                  */
-               
+
                 /* Device number of the new device. */
                dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
 
@@ -940,27 +883,31 @@ PUBLIC int clone_opcl(
                r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid,
                        ALL_MODES | I_CHAR_SPECIAL, dev, &res);
                 if (r != OK) {
-                    (void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
-                    return r;
+                       (void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
+                       return r;
                 }
 
                 /* Drop old node and use the new values */
-                vp = fp->fp_filp[m_in.fd]->filp_vno;
-               
+                assert(FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse));
+                vp = fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno;
+
+               unlock_vnode(vp);
                 put_vnode(vp);
-               if ((vp = get_free_vnode()) == NULL) 
-                       vp = fp->fp_filp[m_in.fd]->filp_vno;
-               
+               if ((vp = get_free_vnode()) == NULL)
+                       return(err_code);
+
+               lock_vnode(vp, VNODE_OPCL);
+
                 vp->v_fs_e = res.fs_e;
                 vp->v_vmnt = NULL;
-                vp->v_dev = NO_DEV; 
+                vp->v_dev = NO_DEV;
                vp->v_fs_e = res.fs_e;
                 vp->v_inode_nr = res.inode_nr;
-                vp->v_mode = res.fmode; 
+                vp->v_mode = res.fmode;
                 vp->v_sdev = dev;
                 vp->v_fs_count = 1;
                 vp->v_ref_count = 1;
-               fp->fp_filp[m_in.fd]->filp_vno = vp;
+               fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno = vp;
        }
        dev_mess.REP_STATUS = OK;
   }
@@ -977,14 +924,15 @@ PUBLIC void bdev_up(int maj)
    * file systems and open block-special files.
    */
   int r, found, bits;
-  struct filp *fp;
+  struct filp *rfilp;
   struct vmnt *vmp;
   struct vnode *vp;
   char *label;
 
+  if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major");
   label = dmap[maj].dmap_label;
 
-  /* Tell each affected mounted file system about the new driver. This code
+  /* Tell each affected mounted file system about the new endpoint. This code
    * is currently useless, as driver endpoints do not change across restarts.
    */
   for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
@@ -992,7 +940,7 @@ PUBLIC void bdev_up(int maj)
 
        /* Send the driver label to the mounted file system. */
        if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, label))
-               printf("VFSdev_up: error sending new driver label to %d\n",
+               printf("VFS dev_up: error sending new driver label to %d\n",
                       vmp->m_fs_e);
   }
 
@@ -1000,13 +948,13 @@ PUBLIC void bdev_up(int maj)
    * device, we need to reopen it on the new driver.
    */
   found = 0;
-  for (fp = filp; fp < &filp[NR_FILPS]; fp++) {
-       if(fp->filp_count < 1 || !(vp = fp->filp_vno)) continue;
-       if(major(vp->v_sdev) != maj) continue;
-       if(!S_ISBLK(vp->v_mode)) continue;
+  for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
+       if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
+       if (major(vp->v_sdev) != maj) continue;
+       if (!S_ISBLK(vp->v_mode)) continue;
 
        /* Reopen the device on the driver, once per filp. */
-       bits = mode_map[fp->filp_mode & O_ACCMODE];
+       bits = mode_map[rfilp->filp_mode & O_ACCMODE];
        if ((r = bdev_open(vp->v_sdev, bits)) != OK)
                printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
                        maj, minor(vp->v_sdev), r);
@@ -1015,14 +963,14 @@ PUBLIC void bdev_up(int maj)
   }
 
   /* If any block-special file was open for this major at all, also inform the
-   * root file system about the endpoint update of the driver. We do this even
-   * if the block-special file is linked to another mounted file system, merely
+   * root file system about the new driver. We do this even if the
+   * block-special file is linked to another mounted file system, merely
    * because it is more work to check for that case.
    */
   if (found) {
        if (OK != req_newdriver(ROOT_FS_E, makedev(maj, 0), label))
                printf("VFSdev_up: error sending new driver label to %d\n",
-                      ROOT_FS_E);
+                       ROOT_FS_E);
   }
 }
 
@@ -1033,38 +981,38 @@ PUBLIC void bdev_up(int maj)
 PUBLIC void cdev_up(int maj)
 {
   /* A new character device driver has been mapped in.
-   */
+  */
   int needs_reopen, fd_nr;
-  struct filp *fp;
+  struct filp *rfilp;
   struct fproc *rfp;
   struct vnode *vp;
 
-  /* Look for processes that are suspened in an OPEN call. Set SUSP_REOPEN
+  /* Look for processes that are suspened in an OPEN call. Set FP_SUSP_REOPEN
    * to indicate that this process was suspended before the call to dev_up.
    */
   for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
        if(rfp->fp_pid == PID_FREE) continue;
        if(rfp->fp_blocked_on != FP_BLOCKED_ON_DOPEN) continue;
 
-       printf("dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
-               rfp->fp_block_fd);
-       fd_nr = rfp->fp_block_fd;
-       fp = rfp->fp_filp[fd_nr];
-       vp = fp->filp_vno;
-       if (!vp) panic("restart_reopen: no vp");
+       fd_nr = scratch(rfp).file.fd_nr;
+       printf("VFS: dev_up: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
+               fd_nr);
+       rfilp = rfp->fp_filp[fd_nr];
+       vp = rfilp->filp_vno;
+       if (!vp) panic("VFS: cdev_up: no vp");
        if ((vp->v_mode &  I_TYPE) != I_CHAR_SPECIAL) continue;
-       if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue;
+       if (major(vp->v_sdev) != maj) continue;
 
-       rfp->fp_flags |= SUSP_REOPEN;
+       rfp->fp_flags |= FP_SUSP_REOPEN;
   }
 
   needs_reopen= FALSE;
-  for (fp = filp; fp < &filp[NR_FILPS]; fp++) {
-       if(fp->filp_count < 1 || !(vp = fp->filp_vno)) continue;
-       if(((vp->v_sdev >> MAJOR) & BYTE) != maj) continue;
-       if(!S_ISCHR(vp->v_mode)) continue;
+  for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
+       if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
+       if (major(vp->v_sdev) != maj) continue;
+       if (!S_ISCHR(vp->v_mode)) continue;
 
-       fp->filp_state = FS_NEEDS_REOPEN;
+       rfilp->filp_state = FS_NEEDS_REOPEN;
        needs_reopen = TRUE;
   }
 
@@ -1072,6 +1020,21 @@ PUBLIC void cdev_up(int maj)
        restart_reopen(maj);
 }
 
+/*===========================================================================*
+ *                             open_reply                                   *
+ *===========================================================================*/
+PUBLIC void open_reply(void)
+{
+  struct fproc *rfp;
+  endpoint_t proc_e;
+  int slot;
+
+  proc_e = m_in.REP_ENDPT;
+  if (isokendpt(proc_e, &slot) != OK) return;
+  rfp = &fproc[slot];
+  *rfp->fp_sendrec = m_in;
+  worker_signal(worker_get(rfp->fp_wtid));     /* Continue open */
+}
 
 /*===========================================================================*
  *                             restart_reopen                               *
@@ -1079,52 +1042,55 @@ PUBLIC void cdev_up(int maj)
 PRIVATE void restart_reopen(maj)
 int maj;
 {
-  int n, r, minor, fd_nr;
+  int n, r, minor_dev, major_dev, fd_nr;
   endpoint_t driver_e;
   struct vnode *vp;
-  struct filp *fp;
+  struct filp *rfilp;
   struct fproc *rfp;
 
-  for (fp = filp; fp < &filp[NR_FILPS]; fp++) {
-       if (fp->filp_count < 1 || !(vp = fp->filp_vno)) continue;
-       if (fp->filp_state != FS_NEEDS_REOPEN) continue;
-       if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue;
+  if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major");
+  for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) {
+       if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue;
+       if (rfilp->filp_state != FS_NEEDS_REOPEN) continue;
        if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
-       minor = ((vp->v_sdev >> MINOR) & BYTE);
-       
-       if (!(fp->filp_flags & O_REOPEN)) {
+
+       major_dev = major(vp->v_sdev);
+       minor_dev = minor(vp->v_sdev);
+       if (major_dev != maj) continue;
+
+       if (!(rfilp->filp_flags & O_REOPEN)) {
                /* File descriptor is to be closed when driver restarts. */
-               n = invalidate(fp);
-               if (n != fp->filp_count) {
+               n = invalidate_filp(rfilp);
+               if (n != rfilp->filp_count) {
                        printf("VFS: warning: invalidate/count "
-                               "discrepancy (%d, %d)\n", n, fp->filp_count);
+                              "discrepancy (%d, %d)\n", n, rfilp->filp_count);
                }
-               fp->filp_count = 0;
+               rfilp->filp_count = 0;
                continue;
        }
 
-       r = dev_reopen(vp->v_sdev, fp-filp, vp->v_mode & (R_BIT|W_BIT));
+       r = dev_reopen(vp->v_sdev, rfilp-filp, vp->v_mode & (R_BIT|W_BIT));
        if (r == OK) return;
 
        /* Device could not be reopened. Invalidate all filps on that device.*/
-       n = invalidate(fp);
-       if (n != fp->filp_count) {
+       n = invalidate_filp(rfilp);
+       if (n != rfilp->filp_count) {
                printf("VFS: warning: invalidate/count "
-                       "discrepancy (%d, %d)\n", n, fp->filp_count);
+                       "discrepancy (%d, %d)\n", n, rfilp->filp_count);
        }
-       fp->filp_count = 0;
+       rfilp->filp_count = 0;
        printf("VFS: file on dev %d/%d re-open failed: %d; "
-               "invalidated %d fd's.\n", maj, minor, r, n);
+               "invalidated %d fd's.\n", major_dev, minor_dev, r, n);
   }
 
   /* Nothing more to re-open. Restart suspended processes */
-  driver_e= dmap[maj].dmap_driver;
+  driver_e = dmap[maj].dmap_driver;
 
   for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
        if(rfp->fp_pid == PID_FREE) continue;
        if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
-          rfp->fp_task == driver_e && (rfp->fp_flags & SUSP_REOPEN)) {
-               rfp->fp_flags &= ~SUSP_REOPEN;
+          rfp->fp_task == driver_e && (rfp->fp_flags & FP_SUSP_REOPEN)) {
+               rfp->fp_flags &= ~FP_SUSP_REOPEN;
                rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
                reply(rfp->fp_endpoint, ERESTART);
        }
@@ -1134,14 +1100,14 @@ int maj;
   for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
        if (rfp->fp_pid == PID_FREE) continue;
        if (rfp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
-           !(rfp->fp_flags & SUSP_REOPEN)) continue;
+           !(rfp->fp_flags & FP_SUSP_REOPEN)) continue;
 
-       printf("restart_reopen: found process in FP_BLOCKED_ON_DOPEN, fd %d\n",
-               rfp->fp_block_fd);
-       fd_nr = rfp->fp_block_fd;
-       fp = rfp->fp_filp[fd_nr];
+       fd_nr = scratch(rfp).file.fd_nr;
+       printf("VFS: restart_reopen: process in FP_BLOCKED_ON_DOPEN fd=%d\n",
+               fd_nr);
+       rfilp = rfp->fp_filp[fd_nr];
 
-       if (!fp) {
+       if (!rfilp) {
                /* Open failed, and automatic reopen was not requested */
                rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
                FD_CLR(fd_nr, &rfp->fp_filp_inuse);
@@ -1149,10 +1115,10 @@ int maj;
                continue;
        }
 
-       vp = fp->filp_vno;
-       if (!vp) panic("restart_reopen: no vp");
+       vp = rfilp->filp_vno;
+       if (!vp) panic("VFS: restart_reopen: no vp");
        if ((vp->v_mode &  I_TYPE) != I_CHAR_SPECIAL) continue;
-       if (((vp->v_sdev >> MAJOR) & BYTE) != maj) continue;
+       if (major(vp->v_sdev) != maj) continue;
 
        rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
        reply(rfp->fp_endpoint, fd_nr);
@@ -1167,7 +1133,7 @@ PUBLIC void reopen_reply()
 {
   endpoint_t driver_e;
   int filp_no, status, maj;
-  struct filp *fp;
+  struct filp *rfilp;
   struct vnode *vp;
   struct dmap *dp;
 
@@ -1176,50 +1142,50 @@ PUBLIC void reopen_reply()
   status = m_in.REP_STATUS;
 
   if (filp_no < 0 || filp_no >= NR_FILPS) {
-       printf("reopen_reply: bad filp number %d from driver %d\n", filp_no,
-              driver_e);
+       printf("VFS: reopen_reply: bad filp number %d from driver %d\n",
+               filp_no, driver_e);
        return;
   }
 
-  fp = &filp[filp_no];
-  if (fp->filp_count < 1) {
-       printf("reopen_reply: filp number %d not inuse (from driver %d)\n",
+  rfilp = &filp[filp_no];
+  if (rfilp->filp_count < 1) {
+       printf("VFS: reopen_reply: filp number %d not inuse (from driver %d)\n",
               filp_no, driver_e);
        return;
   }
 
-  vp = fp->filp_vno;
+  vp = rfilp->filp_vno;
   if (!vp) {
-       printf("reopen_reply: no vnode for filp number %d (from driver %d)\n",
-               filp_no, driver_e);
+       printf("VFS: reopen_reply: no vnode for filp number %d (from driver "
+               "%d)\n", filp_no, driver_e);
        return;
   }
 
-  if (fp->filp_state != FS_NEEDS_REOPEN) {
-       printf("reopen_reply: bad state %d for filp number %d" 
-              " (from driver %d)\n", fp->filp_state, filp_no, driver_e);
+  if (rfilp->filp_state != FS_NEEDS_REOPEN) {
+       printf("VFS: reopen_reply: bad state %d for filp number %d"
+              " (from driver %d)\n", rfilp->filp_state, filp_no, driver_e);
        return;
   }
 
   if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) {
-       printf("reopen_reply: bad mode 0%o for filp number %d"
+       printf("VFS: reopen_reply: bad mode 0%o for filp number %d"
               " (from driver %d)\n", vp->v_mode, filp_no, driver_e);
        return;
   }
 
-  maj = ((vp->v_sdev >> MAJOR) & BYTE);
+  maj = major(vp->v_sdev);
   dp = &dmap[maj];
   if (dp->dmap_driver != driver_e) {
-       printf("reopen_reply: bad major %d for filp number %d "
+       printf("VFS: reopen_reply: bad major %d for filp number %d "
                "(from driver %d, current driver is %d)\n", maj, filp_no,
                driver_e, dp->dmap_driver);
        return;
   }
 
   if (status == OK) {
-       fp->filp_state= FS_NORMAL;
+       rfilp->filp_state= FS_NORMAL;
   } else {
-       printf("reopen_reply: should handle error status\n");
+       printf("VFS: reopen_reply: should handle error status\n");
        return;
   }
 
index fddb2fb79e0b94efa0c8eb394cdb305b34e2336c..eb5d13b1b65bcd6b35b38e27f09ec31843475db0 100644 (file)
@@ -1,24 +1,23 @@
 /* This file contains the table with device <-> driver mappings. It also
  * contains some routines to dynamically add and/ or remove device drivers
- * or change mappings.  
+ * or change mappings.
  */
 
 #include "fs.h"
-#include "fproc.h"
 #include <string.h>
 #include <stdlib.h>
 #include <ctype.h>
 #include <unistd.h>
 #include <minix/com.h>
 #include <minix/ds.h>
+#include "fproc.h"
+#include "dmap.h"
 #include "param.h"
 
-#define NC(x) (NR_CTRLRS >= (x))
-
 /* The order of the entries in the table determines the mapping between major
  * device numbers and device drivers. Character and block devices
  * can be intermixed at random.  The ordering determines the device numbers in
- * /dev. Note that the major device numbers used in /dev are NOT the same as 
+ * /dev. Note that the major device numbers used in /dev are NOT the same as
  * the process numbers of the device drivers. See <minix/dmap.h> for mappings.
  */
 
@@ -31,53 +30,47 @@ struct dmap dmap[NR_DEVICES];
  *===========================================================================*/
 PUBLIC int do_mapdriver()
 {
-       int r, flags, major;
-       endpoint_t endpoint;
-       vir_bytes label_vir;
-       size_t label_len;
-       char label[LABEL_MAX];
-
-       /* Only RS can map drivers. */
-       if (who_e != RS_PROC_NR)
-       {
-               printf("vfs: unauthorized call of do_mapdriver by proc %d\n",
-                       who_e);
-               return(EPERM);
-       }
+/* Create a device->driver mapping. RS will tell us which major is driven by
+ * this driver, what type of device it is (regular, TTY, asynchronous, clone,
+ * etc), and its label. This label is registered with DS, and allows us to
+ * retrieve the driver's endpoint.
+ */
+  int r, flags, major;
+  endpoint_t endpoint;
+  vir_bytes label_vir;
+  size_t label_len;
+  char label[LABEL_MAX];
 
-       /* Get the label */
-       label_vir= (vir_bytes)m_in.md_label;
-       label_len= m_in.md_label_len;
+  /* Only RS can map drivers. */
+  if (who_e != RS_PROC_NR) return(EPERM);
 
-       if (label_len+1 > sizeof(label))
-       {
-               printf("vfs:do_mapdriver: label too long\n");
-               return EINVAL;
-       }
+  /* Get the label */
+  label_vir = (vir_bytes) m_in.md_label;
+  label_len = (size_t) m_in.md_label_len;
 
-       r= sys_vircopy(who_e, D, label_vir, SELF, D, (vir_bytes)label,
-               label_len);
-       if (r != OK)
-       {
-               printf("vfs:do_mapdriver: sys_vircopy failed: %d\n", r);
-               return EINVAL;
-       }
-
-       label[label_len]= '\0';
+  if (label_len+1 > sizeof(label)) { /* Can we store this label? */
+       printf("VFS: do_mapdriver: label too long\n");
+       return(EINVAL);
+  }
+  r = sys_vircopy(who_e, D, label_vir, SELF, D, (vir_bytes) label, label_len);
+  if (r != OK) {
+       printf("VFS: do_mapdriver: sys_vircopy failed: %d\n", r);
+       return(EINVAL);
+  }
+  label[label_len] = '\0';     /* Terminate label */
 
-       r= ds_retrieve_label_endpt(label, &endpoint);
-       if (r != OK)
-       {
-               printf("vfs:do_mapdriver: ds doesn't know '%s'\n", label);
-               return EINVAL;
-       }
+  /* Now we know how the driver is called, fetch its endpoint */
+  r = ds_retrieve_label_endpt(label, &endpoint);
+  if (r != OK) {
+       printf("VFS: do_mapdriver: label '%s' unknown\n", label);
+       return(EINVAL);
+  }
 
-       /* Try to update device mapping. */
-       major= m_in.md_major;
-       flags= m_in.md_flags;
-       r= map_driver(label, major, endpoint, m_in.md_style, flags);
+  /* Try to update device mapping. */
+  major = m_in.md_major;
+  flags = m_in.md_flags;
 
-       return(r);
+  return map_driver(label, major, endpoint, m_in.md_style, flags);
 }
 
 /*===========================================================================*
@@ -90,19 +83,20 @@ endpoint_t proc_nr_e;               /* process number of the driver */
 int style;                     /* style of the device */
 int flags;                     /* device flags */
 {
-/* Set a new device driver mapping in the dmap table.
- * If the proc_nr is set to NONE, we're supposed to unmap it.
+/* Add a new device driver mapping in the dmap table. If the proc_nr is set to
+ * NONE, we're supposed to unmap it.
  */
-  int proc_nr_n;
+
+  int slot;
   size_t len;
   struct dmap *dp;
 
   /* Get pointer to device entry in the dmap table. */
   if (major < 0 || major >= NR_DEVICES) return(ENODEV);
-  dp = &dmap[major];           
+  dp = &dmap[major];
 
   /* Check if we're supposed to unmap it. */
- if(proc_nr_e == NONE) {
+ if (proc_nr_e == NONE) {
        dp->dmap_opcl = no_dev;
        dp->dmap_io = no_dev_io;
        dp->dmap_driver = NONE;
@@ -110,66 +104,78 @@ int flags;                        /* device flags */
        return(OK);
   }
 
-  /* Check process number of new driver if requested. */
-  if (! (flags & DRV_FORCED))
-  {
-       if (isokendpt(proc_nr_e, &proc_nr_n) != OK)
+  /* Check process number of new driver if it was alive before mapping */
+  if (! (flags & DRV_FORCED)) {
+       struct fproc *rfp;
+
+       if (isokendpt(proc_nr_e, &slot) != OK)
                return(EINVAL);
+
+       rfp = &fproc[slot];
+       rfp->fp_flags |= FP_SYS_PROC;   /* Process is a driver */
   }
 
   if (label != NULL) {
-       len= strlen(label);
+       len = strlen(label);
        if (len+1 > sizeof(dp->dmap_label))
-               panic("map_driver: label too long: %d", len);
+               panic("VFS: map_driver: label too long: %d", len);
        strcpy(dp->dmap_label, label);
   }
 
-  /* Try to update the entry. */
+  /* Store driver I/O routines based on type of device */
   switch (style) {
-  case STYLE_DEV:
+    case STYLE_DEV:
        dp->dmap_opcl = gen_opcl;
        dp->dmap_io = gen_io;
        break;
-  case STYLE_DEVA:
+    case STYLE_DEVA:
        dp->dmap_opcl = gen_opcl;
        dp->dmap_io = asyn_io;
        break;
-  case STYLE_TTY:
+    case STYLE_TTY:
        dp->dmap_opcl = tty_opcl;
        dp->dmap_io = gen_io;
        break;
-  case STYLE_CTTY:
+    case STYLE_CTTY:
        dp->dmap_opcl = ctty_opcl;
        dp->dmap_io = ctty_io;
        break;
-  case STYLE_CLONE:
-  case STYLE_CLONE_A:
+    case STYLE_CLONE:
        dp->dmap_opcl = clone_opcl;
        dp->dmap_io = gen_io;
        break;
-  default:
+    case STYLE_CLONE_A:
+       dp->dmap_opcl = clone_opcl;
+       dp->dmap_io = asyn_io;
+       break;
+    default:
        return(EINVAL);
   }
+
   dp->dmap_driver = proc_nr_e;
   dp->dmap_flags = flags;
   dp->dmap_style = style;
 
-  return(OK); 
+  return(OK);
 }
 
 /*===========================================================================*
  *                             dmap_unmap_by_endpt                          *
  *===========================================================================*/
-PUBLIC void dmap_unmap_by_endpt(int proc_nr_e)
+PUBLIC void dmap_unmap_by_endpt(endpoint_t proc_e)
 {
-       int i, r;
-       for (i=0; i<NR_DEVICES; i++)
-         if(dmap[i].dmap_driver && dmap[i].dmap_driver == proc_nr_e)
-           if((r=map_driver(NULL, i, NONE, 0, 0)) != OK)
-               printf("FS: unmap of p %d / d %d failed: %d\n", proc_nr_e,i,r);
-
-       return;
-
+/* Lookup driver in dmap table by endpoint and unmap it */
+  int major, r;
+
+  for (major = 0; major < NR_DEVICES; major++) {
+       if (dmap_driver_match(proc_e, major)) {
+               /* Found driver; overwrite it with a NULL entry */
+               if ((r = map_driver(NULL, major, NONE, 0, 0)) != OK) {
+                       printf("VFS: unmapping driver %d for major %d failed:"
+                               " %d\n", proc_e, major, r);
+               }
+       }
+  }
 }
 
 /*===========================================================================*
@@ -181,75 +187,71 @@ PUBLIC int map_service(struct rprocpub *rpub)
   int r;
 
   /* Not a driver, nothing more to do. */
-  if(!rpub->dev_nr) {
-       return OK;
-  }
+  if(rpub->dev_nr == NO_DEV) return(OK);
 
   /* Map driver. */
-  r = map_driver(rpub->label, rpub->dev_nr, rpub->endpoint,
-       rpub->dev_style, rpub->dev_flags);
-  if(r != OK) {
-       return r;
-  }
+  r = map_driver(rpub->label, rpub->dev_nr, rpub->endpoint, rpub->dev_style,
+                rpub->dev_flags);
+  if(r != OK) return(r);
 
   /* If driver has two major numbers associated, also map the other one. */
   if(rpub->dev_style2 != STYLE_NDEV) {
        r = map_driver(rpub->label, rpub->dev_nr+1, rpub->endpoint,
-               rpub->dev_style2, rpub->dev_flags);
-       if(r != OK) {
-               return r;
-       }
+                      rpub->dev_style2, rpub->dev_flags);
+       if(r != OK) return(r);
   }
 
-  return OK;
+  return(OK);
 }
 
 /*===========================================================================*
- *                             build_dmap                                   *
+ *                             init_dmap                                    *
  *===========================================================================*/
-PUBLIC void build_dmap()
+PUBLIC void init_dmap()
 {
 /* Initialize the table with empty device <-> driver mappings. */
   int i;
   struct dmap dmap_default = DT_EMPTY;
 
-  for (i=0; i<NR_DEVICES; i++) {
+  for (i = 0; i < NR_DEVICES; i++)
        dmap[i] = dmap_default;
-  }
 }
 
 /*===========================================================================*
  *                             dmap_driver_match                            *
- *===========================================================================*/ 
+ *===========================================================================*/
 PUBLIC int dmap_driver_match(endpoint_t proc, int major)
 {
-       if (major < 0 || major >= NR_DEVICES) return(0);
-       if(dmap[major].dmap_driver != NONE && dmap[major].dmap_driver == proc)
-               return 1;
-       return 0;
+  if (major < 0 || major >= NR_DEVICES) return(0);
+  if (dmap[major].dmap_driver != NONE && dmap[major].dmap_driver == proc)
+       return(1);
+
+  return(0);
 }
 
 /*===========================================================================*
  *                             dmap_endpt_up                                *
- *===========================================================================*/ 
-PUBLIC void dmap_endpt_up(int proc_e, int is_blk)
+ *===========================================================================*/
+PUBLIC void dmap_endpt_up(endpoint_t proc_e, int is_blk)
 {
-       int i;
-       for (i=0; i<NR_DEVICES; i++) {
-               if(dmap[i].dmap_driver != NONE
-                       && dmap[i].dmap_driver == proc_e) {
-
-                       if (is_blk)
-                               bdev_up(i);
-                       else
-                               cdev_up(i);
-               }
+/* A device driver with endpoint proc_e has been restarted. Go tell everyone
+ * that might be blocking on it that this device is 'up'.
+ */
+
+  int major;
+  for (major = 0; major < NR_DEVICES; major++) {
+       if (dmap_driver_match(proc_e, major)) {
+               if (is_blk)
+                       bdev_up(major);
+               else
+                       cdev_up(major);
        }
+  }
 }
 
 /*===========================================================================*
  *                             get_dmap                                     *
- *===========================================================================*/ 
+ *===========================================================================*/
 PUBLIC struct dmap *get_dmap(endpoint_t proc_e)
 {
 /* See if 'proc_e' endpoint belongs to a valid dmap entry. If so, return a
@@ -257,9 +259,8 @@ PUBLIC struct dmap *get_dmap(endpoint_t proc_e)
 
   int major;
   for (major = 0; major < NR_DEVICES; major++)
-       if (dmap_driver_match(proc_e, major))
-               return(&dmap[major]);
+       if (dmap_driver_match(proc_e, major))
+               return(&dmap[major]);
 
   return(NULL);
 }
-
index 1430d5287a3511357897b78e345f74ba02257a68..6a83bf55198d2fddd05322cc2e1b9df4889f778a 100644 (file)
@@ -11,8 +11,8 @@ dmap.h
 
 /* Device table.  This table is indexed by major device number.  It provides
  * the link between major device numbers and the routines that process them.
- * The table can be update dynamically. The field 'dmap_flags' describe an 
- * entry's current status and determines what control options are possible. 
+ * The table can be update dynamically. The field 'dmap_flags' describe an
+ * entry's current status and determines what control options are possible.
  */
 
 extern struct dmap {
diff --git a/servers/vfs/elf_core_dump.c b/servers/vfs/elf_core_dump.c
deleted file mode 100644 (file)
index c3425b5..0000000
+++ /dev/null
@@ -1,314 +0,0 @@
-#include "fs.h"
-#include <fcntl.h>
-#include <string.h>
-#include "fproc.h"
-#include <minix/vm.h>
-#include <sys/mman.h>
-#include <machine/elf.h>
-#include "param.h"
-
-/* Include ELF headers */
-#include <sys/elf_core.h>
-
-FORWARD _PROTOTYPE( void fill_elf_header, (Elf32_Ehdr *elf_header,
-               int phnum)                                                 );
-FORWARD _PROTOTYPE( void fill_prog_header, (Elf32_Phdr *prog_header,
-       Elf32_Word p_type, Elf32_Off p_offset, Elf32_Addr p_vaddr,
-       Elf32_Word p_flags, Elf32_Word p_filesz, Elf32_Word p_memsz)       );
-FORWARD _PROTOTYPE( int get_memory_regions, (Elf32_Phdr phdrs[])           );
-FORWARD _PROTOTYPE( void fill_note_segment_and_entries_hdrs,
-       (Elf32_Phdr phdrs[], Elf32_Nhdr nhdrs[])                              );
-FORWARD _PROTOTYPE( void adjust_offsets, (Elf32_Phdr phdrs[], int phnum)   );
-FORWARD _PROTOTYPE( void dump_elf_header, (Elf32_Ehdr elf_header)          );
-FORWARD _PROTOTYPE( void dump_notes, (Elf32_Nhdr nhdrs[], int csig,
-       char *exe_name)                                                    );
-FORWARD _PROTOTYPE( void dump_program_headers, (Elf_Phdr phdrs[],
-       int phnum)                                                         );
-FORWARD _PROTOTYPE( void dump_segments, (Elf32_Phdr phdrs[], int phnum)    );
-
-/*===========================================================================*
- *                             write_elf_core_file                          *
- *===========================================================================*/
-/* First, fill in all the required headers, second, adjust the offsets,
- * third, dump everything into the core file
- */
-PUBLIC void write_elf_core_file(int csig, char *exe_name)
-{
-#define MAX_REGIONS 20
-#define NR_NOTE_ENTRIES 2
-  Elf_Ehdr elf_header;
-  Elf_Phdr phdrs[MAX_REGIONS + 1];
-  Elf_Nhdr nhdrs[NR_NOTE_ENTRIES];
-  int phnum;
-
-  /* Fill in the NOTE Program Header - at phdrs[0] - and
-   * note entries' headers
-   */
-  fill_note_segment_and_entries_hdrs(phdrs, nhdrs);
-
-  /* Get the memory segments and fill in the Program headers */
-  phnum = get_memory_regions(phdrs) + 1;
-
-  /* Fill in the ELF header */
-  fill_elf_header(&elf_header, phnum);
-
-  /* Adjust offsets in program headers - The layout in the ELF core file
-   * is the following: the ELF Header, the Note Program Header,
-   * the rest of Program Headers (memory segments), Note contents,
-   * the program segments' contents
-   */
-  adjust_offsets(phdrs, phnum);
-
-  /* Write ELF header */
-  dump_elf_header(elf_header);
-
-  /* Write Program headers (Including the NOTE) */
-  dump_program_headers(phdrs, phnum);
-
-  /* Write NOTE contents */
-  dump_notes(nhdrs, csig, exe_name);
-
-  /* Write segments' contents */
-  dump_segments(phdrs, phnum);
-}
-
-/*===========================================================================*
- *                             fill_elf_header                              *
- *===========================================================================*/
-PRIVATE void fill_elf_header (Elf_Ehdr *elf_header, int phnum)
-{
-  memset((void *) elf_header, 0, sizeof(Elf_Ehdr));
-
-  elf_header->e_ident[EI_MAG0] = ELFMAG0;
-  elf_header->e_ident[EI_MAG1] = ELFMAG1;
-  elf_header->e_ident[EI_MAG2] = ELFMAG2;
-  elf_header->e_ident[EI_MAG3] = ELFMAG3;
-  elf_header->e_ident[EI_CLASS] = ELF_TARG_CLASS;
-  elf_header->e_ident[EI_DATA] = ELF_TARG_DATA;
-  elf_header->e_ident[EI_VERSION] = EV_CURRENT;
-  elf_header->e_ident[EI_OSABI] = ELFOSABI_FREEBSD;
-  elf_header->e_type = ET_CORE;
-  elf_header->e_machine = ELF_TARG_MACH;
-  elf_header->e_version = EV_CURRENT;
-  elf_header->e_ehsize = sizeof(Elf_Ehdr);
-  elf_header->e_phoff = sizeof(Elf_Ehdr);
-  elf_header->e_phentsize = sizeof(Elf_Phdr);
-  elf_header->e_phnum = phnum;
-}
-
-/*===========================================================================*
- *                             fill_prog_header                             *
- *===========================================================================*/
-PRIVATE void fill_prog_header (Elf_Phdr *prog_header, Elf_Word p_type,
-       Elf_Off p_offset, Elf_Addr p_vaddr, Elf_Word p_flags,
-       Elf_Word p_filesz, Elf_Word p_memsz)
-{
-
-  memset((void *) prog_header, 0, sizeof(Elf_Phdr));
-
-  prog_header->p_type = p_type;
-  prog_header->p_offset = p_offset;
-  prog_header->p_vaddr = p_vaddr;
-  prog_header->p_flags = p_flags;
-  prog_header->p_filesz = p_filesz;
-  prog_header->p_memsz = p_memsz;
-
-}
-
-#define PADBYTES    4
-#define PAD_LEN(x)  ((x + (PADBYTES - 1)) & ~(PADBYTES - 1))
-
-/*===========================================================================*
- *                     fill_note_segment_and_entries_hdrs                   *
- *===========================================================================*/
-PRIVATE void fill_note_segment_and_entries_hdrs(Elf_Phdr phdrs[],
-                               Elf_Nhdr nhdrs[])
-{
-  int filesize;
-  const char *note_name = ELF_NOTE_MINIX_ELFCORE_NAME "\0";
-  int name_len, mei_len, gregs_len;
-
-  /* Size of notes in the core file is rather fixed:
-   * sizeof(minix_elfcore_info_t) +
-   * 2 * sizeof(Elf_Nhdr) + the size of the padded name of the note
-   * - i.e. "MINIX-CORE\0" padded to 4-byte alignment => 2 * 8 bytes
-   */
-
-  name_len = strlen(note_name) + 1;
-  mei_len = sizeof(minix_elfcore_info_t);
-  gregs_len = sizeof(gregset_t);
-
-  /* Make sure to also count the padding bytes */
-  filesize = PAD_LEN(mei_len) + PAD_LEN(gregs_len) +
-       2 * sizeof(Elf_Nhdr) + 2 * PAD_LEN(name_len);
-  fill_prog_header(&phdrs[0], PT_NOTE, 0, 0, PF_R, filesize, 0);
-
-  /* First note entry header */
-  nhdrs[0].n_namesz = name_len;
-  nhdrs[0].n_descsz = sizeof(minix_elfcore_info_t);
-  nhdrs[0].n_type = NT_MINIX_ELFCORE_INFO;
-
-  /* Second note entry header */
-  nhdrs[1].n_namesz = name_len;
-  nhdrs[1].n_descsz = sizeof(gregset_t);
-  nhdrs[1].n_type = NT_MINIX_ELFCORE_GREGS;
-}
-
-/*===========================================================================*
- *                             adjust_offset                                *
- *===========================================================================*/
-PRIVATE void adjust_offsets(Elf_Phdr phdrs[], int phnum)
-{
-  int i;
-  long offset = sizeof(Elf_Ehdr) + phnum * sizeof(Elf_Phdr);
-
-  for (i = 0; i < phnum; i++) {
-       phdrs[i].p_offset = offset;
-       offset += phdrs[i].p_filesz;
-  }
-}
-
-/*===========================================================================*
- *                             write_buf                                    *
- *===========================================================================*/
-PRIVATE void write_buf(char *buf, int size)
-{
-  m_in.buffer = buf;
-  m_in.nbytes = size;
-  read_write(WRITING);
-}
-
-/*===========================================================================*
- *                             get_memory_regions                           *
- *===========================================================================*/
-/* The same as dump_regions from procfs/pid.c */
-PRIVATE int get_memory_regions(Elf_Phdr phdrs[])
-{
-  /* Print the virtual memory regions of a process. */
-  struct vm_region_info vri[MAX_VRI_COUNT];
-  vir_bytes next;
-  int i, r, count;
-  Elf_Word pflags;
-
-  count = 0;
-  next = 0;
-
-  do {
-       r = vm_info_region(fp->fp_endpoint, vri, MAX_VRI_COUNT,
-                       &next);
-       if (r < 0) return r;
-       if (r == 0) break;
-
-       for (i = 0; i < r; i++) {
-
-               pflags = (vri[i].vri_prot & PROT_READ ? PF_R : 0)
-                       | (vri[i].vri_prot & PROT_WRITE ? PF_W : 0)
-                       | (vri[i].vri_prot & PROT_EXEC ? PF_X : 0);
-
-               fill_prog_header (&phdrs[count + 1], PT_LOAD,
-                               0, vri[i].vri_addr, pflags,
-                               vri[i].vri_length, vri[i].vri_length);
-               count++;
-
-               if (count >= MAX_REGIONS) {
-                       printf("VFS: get_memory_regions Warning: "
-                               "Program has too many regions\n");
-                       return count;
-               }
-       }
-  } while (r == MAX_VRI_COUNT);
-
-  return count;
-}
-
-/*===========================================================================*
- *                             dump_notes                                   *
- *===========================================================================*/
-PRIVATE void dump_notes(Elf_Nhdr nhdrs[], int csig, char *exe_name)
-{
-  char *note_name = ELF_NOTE_MINIX_ELFCORE_NAME "\0";
-  char pad[4];
-  minix_elfcore_info_t mei;
-  int mei_len = sizeof(minix_elfcore_info_t);
-  int gregs_len = sizeof(gregset_t);
-  struct stackframe_s regs;
-  char proc_name[PROC_NAME_LEN];
-
-  /* Get process's name */
-  if (sys_datacopy(PM_PROC_NR, (vir_bytes) exe_name,
-               VFS_PROC_NR, (vir_bytes) proc_name, PROC_NAME_LEN) != OK)
-       printf("VFS: Cannot get process's name\n");
-
-  /* Dump first note entry */
-  mei.mei_version = MINIX_ELFCORE_VERSION;
-  mei.mei_meisize = mei_len;
-  mei.mei_signo = csig;
-  mei.mei_pid = fp->fp_pid;
-  memcpy(mei.mei_command, proc_name, sizeof(mei.mei_command));
-
-  write_buf((char *)&nhdrs[0], sizeof(Elf_Nhdr));
-  write_buf(note_name, nhdrs[0].n_namesz);
-  write_buf(pad, PAD_LEN(nhdrs[0].n_namesz) - nhdrs[0].n_namesz);
-  write_buf((char *)&mei, mei_len);
-  write_buf(pad, PAD_LEN(mei_len) - mei_len);
-
-  /* Get registers */
-  if (sys_getregs(&regs, fp->fp_endpoint) != OK)
-       printf("VFS: Could not read registers\n");
-
-  if (sizeof(regs) != gregs_len)
-       printf("VFS: Wrong core register structure size\n");
-
-  /* Dump second note entry - the general registers */
-  write_buf((char *)&nhdrs[1], sizeof(Elf_Nhdr));
-  write_buf(note_name, nhdrs[1].n_namesz);
-  write_buf(pad, PAD_LEN(nhdrs[1].n_namesz) - nhdrs[1].n_namesz);
-  write_buf((char *)&regs, gregs_len);
-  write_buf(pad, PAD_LEN(gregs_len) - gregs_len);
-}
-
-/*===========================================================================*
- *                             dump_elf_header                              *
- *===========================================================================*/
-PRIVATE void dump_elf_header(Elf_Ehdr elf_header)
-{
-  write_buf((char *)&elf_header, sizeof(Elf_Ehdr));
-}
-
-/*===========================================================================*
- *                       dump_program_headers                               *
- *===========================================================================*/
-PRIVATE void dump_program_headers(Elf_Phdr phdrs[], int phnum)
-{
-  int i;
-
-  for (i = 0; i < phnum; i++)
-       write_buf((char *)&phdrs[i], sizeof(Elf_Phdr));
-}
-
-/*===========================================================================*
- *                           dump_segments                                  *
- *===========================================================================*/
-PRIVATE void dump_segments(Elf_Phdr phdrs[], int phnum)
-{
-  int i;
-  vir_bytes len;
-  off_t off, seg_off;
-  int r;
-  static u8_t buf[CLICK_SIZE];
-
-  for (i = 1; i < phnum; i++) {
-       len = phdrs[i].p_memsz;
-       seg_off = phdrs[i].p_vaddr;
-
-       for (off = 0; off < len; off += CLICK_SIZE) {
-               r = sys_vircopy(fp->fp_endpoint, D,
-                       (vir_bytes) (seg_off + off),
-                       SELF, D, (vir_bytes) buf,
-                       (phys_bytes) CLICK_SIZE);
-
-               write_buf((char *)buf, (off + CLICK_SIZE <= len) ?
-                                       CLICK_SIZE : (len - off));
-       }
-  }
-}
index e91cb6ceead9b13f5a354aee64a49751b06b5338..3f6e4a7e2b8268a2de4eb6ea26e9238990970c1e 100644 (file)
 #include <dirent.h>
 #include <sys/param.h>
 #include "fproc.h"
+#include "path.h"
 #include "param.h"
 #include "vnode.h"
-#include "vmnt.h"
 #include <minix/vfsif.h>
 #include <assert.h>
 #include <libexec.h>
 #include "exec.h"
 
-static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes,
+FORWARD _PROTOTYPE( void lock_exec, (void)                             );
+FORWARD _PROTOTYPE( void unlock_exec, (void)                           );
+FORWARD _PROTOTYPE( int exec_newmem, (int proc_e, vir_bytes text_addr, vir_bytes text_bytes,
                       vir_bytes data_addr, vir_bytes data_bytes,
                       vir_bytes tot_bytes, vir_bytes frame_len, int sep_id,
                       int is_elf, dev_t st_dev, ino_t st_ino, time_t ctime,
                       char *progname, int new_uid, int new_gid,
                       vir_bytes *stack_topp, int *load_textp,
-                      int *setugidp);
-static int is_script(const char *exec_hdr, size_t exec_len);
-static int patch_stack(struct vnode *vp, char stack[ARG_MAX],
-                      vir_bytes *stk_bytes);
-static int insert_arg(char stack[ARG_MAX], vir_bytes *stk_bytes, char *arg,
-                     int replace);
-static void patch_ptr(char stack[ARG_MAX], vir_bytes base);
-static void clo_exec(struct fproc *rfp);
-static int read_seg(struct vnode *vp, off_t off, int proc_e, int seg,
-                   vir_bytes seg_addr, phys_bytes seg_bytes);
-static int load_aout(struct exec_info *execi);
-static int load_elf(struct exec_info *execi);
-static int map_header(char **exec_hdr, const struct vnode *vp);
+                      int *setugidp)                                   );
+FORWARD _PROTOTYPE( int is_script, (const char *exec_hdr, size_t exec_len));
+FORWARD _PROTOTYPE( int patch_stack, (struct vnode *vp, char stack[ARG_MAX],
+                      vir_bytes *stk_bytes, char path[PATH_MAX])       );
+FORWARD _PROTOTYPE( int insert_arg, (char stack[ARG_MAX], vir_bytes *stk_bytes,
+                                       char *arg, int replace)         );
+FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX], vir_bytes base));
+FORWARD _PROTOTYPE( void clo_exec, (struct fproc *rfp)                 );
+FORWARD _PROTOTYPE( int read_seg, (struct vnode *vp, off_t off, int proc_e,
+                                       int seg, vir_bytes seg_addr,
+                                       phys_bytes seg_bytes)           );
+FORWARD _PROTOTYPE( int load_aout, (struct exec_info *execi)           );
+FORWARD _PROTOTYPE( int load_elf, (struct exec_info *execi)            );
+FORWARD _PROTOTYPE( int map_header, (char **exec_hdr,
+                                       const struct vnode *vp)         );
 
 #define PTRSIZE        sizeof(char *) /* Size of pointers in argv[] and envp[]. */
 
 /* Array of loaders for different object file formats */
 struct exec_loaders {
        int (*load_object)(struct exec_info *);
-} static const exec_loaders[] = {
+};
+
+PRIVATE const struct exec_loaders exec_loaders[] = {
        { load_aout },
        { load_elf },
        { NULL }
 };
 
+PRIVATE char hdr[PAGE_SIZE]; /* Assume that header is not larger than a page */
+
+/*===========================================================================*
+ *                             lock_exec                                    *
+ *===========================================================================*/
+PRIVATE void lock_exec(void)
+{
+  message org_m_in;
+  struct fproc *org_fp;
+  struct worker_thread *org_self;
+
+  /* First try to get it right off the bat */
+  if (mutex_trylock(&exec_lock) == 0)
+       return;
+
+  org_m_in = m_in;
+  org_fp = fp;
+  org_self = self;
+
+  if (mutex_lock(&exec_lock) != 0)
+       panic("Could not obtain lock on exec");
+
+  m_in = org_m_in;
+  fp = org_fp;
+  self = org_self;
+}
+
+/*===========================================================================*
+ *                             unlock_exec                                  *
+ *===========================================================================*/
+PRIVATE void unlock_exec(void)
+{
+  if (mutex_unlock(&exec_lock) != 0)
+       panic("Could not release lock on exec");
+}
+
 /*===========================================================================*
  *                             pm_exec                                      *
  *===========================================================================*/
@@ -76,65 +118,73 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame,
  * complete stack image, including pointers, args, environ, etc.  The stack
  * is copied to a buffer inside VFS, and then to the new core image.
  */
-  int r, r1, round, proc_s;
+  int r, r1, round, slot;
   vir_bytes vsp;
   struct fproc *rfp;
   struct vnode *vp;
+  struct vmnt *vmp;
   char *cp;
   static char mbuf[ARG_MAX];   /* buffer for stack and zeroes */
   struct exec_info execi;
   int i;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lock_exec();
+
+  okendpt(proc_e, &slot);
+  rfp = fp = &fproc[slot];
+  vp = NULL;
 
-  okendpt(proc_e, &proc_s);
-  rfp = fp = &fproc[proc_s];
-  who_e = proc_e;
-  who_p = proc_s;
-  super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
 
   /* Get the exec file name. */
-  if ((r = fetch_name(path, path_len, 0)) != OK) return(r);
+  if ((r = fetch_name(path, path_len, 0, fullpath)) != OK)
+       goto pm_execfinal;
 
   /* Fetch the stack from the user before destroying the old core image. */
   if (frame_len > ARG_MAX) {
-               printf("VFS: pm_exec: stack too big\n");
-               return(ENOMEM); /* stack too big */
-       }
+               r = ENOMEM; /* stack too big */
+               goto pm_execfinal;
+  }
   r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
-                  (phys_bytes) frame_len);
+                  (phys_bytes) frame_len);
   if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
-        printf("pm_exec: sys_datacopy failed\n");
-        return(r);     
+        printf("VFS: pm_exec: sys_datacopy failed\n");
+        goto pm_execfinal;
   }
 
   /* The default is to keep the original user and group IDs */
   execi.new_uid = rfp->fp_effuid;
   execi.new_gid = rfp->fp_effgid;
 
-  for (round= 0; round < 2; round++) {
+  for (round = 0; round < 2; round++) {
        /* round = 0 (first attempt), or 1 (interpreted script) */
-
        /* Save the name of the program */
-       (cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);
+       (cp = strrchr(fullpath, '/')) ? cp++ : (cp = fullpath);
 
        strncpy(execi.progname, cp, PROC_NAME_LEN-1);
        execi.progname[PROC_NAME_LEN-1] = '\0';
        execi.setugid = 0;
 
        /* Open executable */
-       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+       if ((vp = eat_path(&resolve, fp)) == NULL) {
+               r = err_code;
+               goto pm_execfinal;
+       }
        execi.vp = vp;
+       unlock_vmnt(vmp);
 
-       if ((vp->v_mode & I_TYPE) != I_REGULAR) 
+       if ((vp->v_mode & I_TYPE) != I_REGULAR)
                r = ENOEXEC;
        else if ((r1 = forbidden(fp, vp, X_BIT)) != OK)
                r = r1;
        else
                r = req_stat(vp->v_fs_e, vp->v_inode_nr, VFS_PROC_NR,
                             (char *) &(execi.sb), 0, 0);
-       if (r != OK) {
-           put_vnode(vp);
-           return(r);
-       }
+       if (r != OK) goto pm_execfinal;
 
         if (round == 0) {
                /* Deal with setuid/setgid executables */
@@ -149,36 +199,35 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame,
         }
 
        r = map_header(&execi.hdr, execi.vp);
-       if (r != OK) {
-           put_vnode(vp);
-           return(r);
-       }
+       if (r != OK) goto pm_execfinal;
 
        if (!is_script(execi.hdr, execi.vp->v_size) || round != 0)
                break;
 
        /* Get fresh copy of the file name. */
-       if ((r = fetch_name(path, path_len, 0)) != OK) 
+       if ((r = fetch_name(path, path_len, 0, fullpath)) != OK)
                printf("VFS pm_exec: 2nd fetch_name failed\n");
-       else if ((r = patch_stack(vp, mbuf, &frame_len)) != OK) 
-               printf("VFS pm_exec: patch_stack failed\n");
+       else
+               r = patch_stack(vp, mbuf, &frame_len, fullpath);
+
+       unlock_vnode(vp);
        put_vnode(vp);
-       if (r != OK) return(r);
+       vp = NULL;
+       if (r != OK) goto pm_execfinal;
   }
 
   execi.proc_e = proc_e;
   execi.frame_len = frame_len;
 
-  for(i = 0; exec_loaders[i].load_object != NULL; i++) {
+  for (i = 0; exec_loaders[i].load_object != NULL; i++) {
       r = (*exec_loaders[i].load_object)(&execi);
       /* Loaded successfully, so no need to try other loaders */
       if (r == OK) break;
   }
-  put_vnode(vp);
 
-  /* No exec loader could load the object */
-  if (r != OK) {
-       return(ENOEXEC);
+  if (r != OK) {   /* No exec loader could load the object */
+       r = ENOEXEC;
+       goto pm_execfinal;
   }
 
   /* Save off PC */
@@ -191,26 +240,32 @@ PUBLIC int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame,
   if ((r = sys_datacopy(SELF, (vir_bytes) mbuf, proc_e, (vir_bytes) vsp,
                   (phys_bytes)frame_len)) != OK) {
        printf("VFS: datacopy failed (%d) trying to copy to %lu\n", r, vsp);
-       return(r);
+       goto pm_execfinal;
   }
 
-  if (r != OK) return(r);
+  if (r != OK) goto pm_execfinal;
   clo_exec(rfp);
 
   if (execi.setugid) {
        /* If after loading the image we're still allowed to run with
-        * setuid or setgid, change the credentials now */
+        * setuid or setgid, change credentials now */
        rfp->fp_effuid = execi.new_uid;
        rfp->fp_effgid = execi.new_gid;
   }
 
-  /* This child has now exec()ced. */
-  rfp->fp_execced = 1;
-
-  return(OK);
+pm_execfinal:
+  if (vp != NULL) {
+       unlock_vnode(vp);
+       put_vnode(vp);
+  }
+  unlock_exec();
+  return(r);
 }
 
-static int load_aout(struct exec_info *execi)
+/*===========================================================================*
+ *                             load_aout                                    *
+ *===========================================================================*/
+PRIVATE int load_aout(struct exec_info *execi)
 {
   int r;
   struct vnode *vp;
@@ -249,14 +304,19 @@ static int load_aout(struct exec_info *execi)
   off = hdrlen;
 
   /* Read in text and data segments. */
-  if (execi->load_text) r = read_seg(vp, off, proc_e, T, 0, text_bytes);
+  if (execi->load_text)
+       r = read_seg(vp, off, proc_e, T, 0, text_bytes);
   off += text_bytes;
-  if (r == OK) r = read_seg(vp, off, proc_e, D, 0, data_bytes);
+  if (r == OK)
+       r = read_seg(vp, off, proc_e, D, 0, data_bytes);
 
-  return (r);
+  return(r);
 }
 
-static int load_elf(struct exec_info *execi)
+/*===========================================================================*
+ *                             load_elf                                     *
+ *===========================================================================*/
+PRIVATE int load_elf(struct exec_info *execi)
 {
   int r;
   struct vnode *vp;
@@ -311,7 +371,7 @@ static int load_elf(struct exec_info *execi)
 /*===========================================================================*
  *                             exec_newmem                                  *
  *===========================================================================*/
-static int exec_newmem(
+PRIVATE int exec_newmem(
   int proc_e,
   vir_bytes text_addr,
   vir_bytes text_bytes,
@@ -332,6 +392,7 @@ static int exec_newmem(
   int *setugidp
 )
 {
+/* Allocate a new memory map for a process that tries to exec */
   int r;
   struct exec_newmem e;
   message m;
@@ -367,25 +428,25 @@ static int exec_newmem(
   return(m.m_type);
 }
 
-/* Is Interpreted script? */
-static int is_script(const char *exec_hdr, size_t exec_len)
+/*===========================================================================*
+ *                             is_script                                    *
+ *===========================================================================*/
+PRIVATE int is_script(const char *exec_hdr, size_t exec_len)
 {
+/* Is Interpreted script? */
   assert(exec_hdr != NULL);
 
-  if (exec_hdr[0] == '#' && exec_hdr[1] == '!' && exec_len >= 2)
-      return(TRUE);
-  else
-      return(FALSE);
+  return(exec_hdr[0] == '#' && exec_hdr[1] == '!' && exec_len >= 2);
 }
 
 /*===========================================================================*
  *                             patch_stack                                  *
  *===========================================================================*/
-static int patch_stack(
-struct vnode *vp,              /* pointer for open script file */
-char stack[ARG_MAX],           /* pointer to stack image within VFS */
-vir_bytes *stk_bytes           /* size of initial stack */
-)
+PRIVATE int patch_stack(vp, stack, stk_bytes, path)
+struct vnode *vp;              /* pointer for open script file */
+char stack[ARG_MAX];           /* pointer to stack image within VFS */
+vir_bytes *stk_bytes;          /* size of initial stack */
+char path[PATH_MAX];           /* path to script file */
 {
 /* Patch the argument vector to include the path name of the script to be
  * interpreted, and all strings on the #! line.  Returns the path name of
@@ -399,43 +460,40 @@ vir_bytes *stk_bytes              /* size of initial stack */
   unsigned int cum_io;
   char buf[_MAX_BLOCK_SIZE];
 
-  /* Make user_fullpath the new argv[0]. */
-  if (!insert_arg(stack, stk_bytes, user_fullpath, REPLACE)) {
-               printf("VFS: patch_stack: insert_arg for argv[0] failed\n");
-               return(ENOMEM);
-       }
+  /* Make 'path' the new argv[0]. */
+  if (!insert_arg(stack, stk_bytes, path, REPLACE)) return(ENOMEM);
 
   pos = 0;     /* Read from the start of the file */
 
   /* Issue request */
   r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, cvul64(pos), READING,
-                   VFS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io);
+                   VFS_PROC_NR, buf, _MAX_BLOCK_SIZE, &new_pos, &cum_io);
   if (r != OK) return(r);
-  
+
   n = vp->v_size;
   if (n > _MAX_BLOCK_SIZE)
        n = _MAX_BLOCK_SIZE;
   if (n < 2) return ENOEXEC;
-  
+
   sp = &(buf[2]);                              /* just behind the #! */
   n -= 2;
   if (n > PATH_MAX) n = PATH_MAX;
 
-  /* Use the user_fullpath variable for temporary storage */
-  memcpy(user_fullpath, sp, n);
+  /* Use the 'path' variable for temporary storage */
+  memcpy(path, sp, n);
 
-  if ((sp = memchr(user_fullpath, '\n', n)) == NULL) /* must be a proper line */
+  if ((sp = memchr(path, '\n', n)) == NULL) /* must be a proper line */
        return(ENOEXEC);
 
   /* Move sp backwards through script[], prepending each string to stack. */
   for (;;) {
        /* skip spaces behind argument. */
-       while (sp > user_fullpath && (*--sp == ' ' || *sp == '\t')) {}
-       if (sp == user_fullpath) break;
+       while (sp > path && (*--sp == ' ' || *sp == '\t')) {}
+       if (sp == path) break;
 
        sp[1] = 0;
        /* Move to the start of the argument. */
-       while (sp > user_fullpath && sp[-1] != ' ' && sp[-1] != '\t') --sp;
+       while (sp > path && sp[-1] != ' ' && sp[-1] != '\t') --sp;
 
        interp = sp;
        if (!insert_arg(stack, stk_bytes, sp, INSERT)) {
@@ -450,15 +508,15 @@ vir_bytes *stk_bytes              /* size of initial stack */
   /* Round *stk_bytes up to the size of a pointer for alignment contraints. */
   *stk_bytes= ((*stk_bytes + PTRSIZE - 1) / PTRSIZE) * PTRSIZE;
 
-  if (interp != user_fullpath)
-       memmove(user_fullpath, interp, strlen(interp)+1);
+  if (interp != path)
+       memmove(path, interp, strlen(interp)+1);
   return(OK);
 }
 
 /*===========================================================================*
  *                             insert_arg                                   *
  *===========================================================================*/
-static int insert_arg(
+PRIVATE int insert_arg(
 char stack[ARG_MAX],           /* pointer to stack image within PM */
 vir_bytes *stk_bytes,          /* size of initial stack */
 char *arg,                     /* argument to prepend/replace as new argv[0] */
@@ -516,7 +574,7 @@ int replace
 /*===========================================================================*
  *                             patch_ptr                                    *
  *===========================================================================*/
-static void patch_ptr(
+PRIVATE void patch_ptr(
 char stack[ARG_MAX],           /* pointer to stack image within PM */
 vir_bytes base                 /* virtual address of stack base inside user */
 )
@@ -549,7 +607,7 @@ vir_bytes base                      /* virtual address of stack base inside user */
 /*===========================================================================*
  *                             read_seg                                     *
  *===========================================================================*/
-static int read_seg(
+PRIVATE int read_seg(
 struct vnode *vp,              /* inode descriptor to read from */
 off_t off,                     /* offset in file */
 int proc_e,                    /* process number (endpoint) */
@@ -612,7 +670,7 @@ phys_bytes seg_bytes                /* how much is to be transferred? */
            printf("VFS: read_seg: req_readwrite failed (data)\n");
            return(r);
        }
-  
+
        if (r == OK && cum_io != seg_bytes)
            printf("VFS: read_seg segment has not been read properly by exec()\n");
 
@@ -626,9 +684,9 @@ phys_bytes seg_bytes                /* how much is to be transferred? */
 /*===========================================================================*
  *                             clo_exec                                     *
  *===========================================================================*/
-static void clo_exec(struct fproc *rfp)
+PRIVATE void clo_exec(struct fproc *rfp)
 {
-/* Files can be marked with the FD_CLOEXEC bit (in fp->fp_cloexec).  
+/* Files can be marked with the FD_CLOEXEC bit (in fp->fp_cloexec).
  */
   int i;
 
@@ -638,13 +696,15 @@ static void clo_exec(struct fproc *rfp)
                (void) close_fd(rfp, i);
 }
 
-static int map_header(char **exec_hdr, const struct vnode *vp)
+/*===========================================================================*
+ *                             map_header                                   *
+ *===========================================================================*/
+PRIVATE int map_header(char **exec_hdr, const struct vnode *vp)
 {
   int r;
   u64_t new_pos;
   unsigned int cum_io;
   off_t pos;
-  static char hdr[PAGE_SIZE]; /* Assume that header is not larger than a page */
 
   pos = 0;     /* Read from the start of the file */
 
index fe3b99971d3e3520a84432b179c473a4a31a89b0..52a5773c6825fb3658b7517914f1c8d41d1967ac 100644 (file)
@@ -12,6 +12,10 @@ EXTERN struct filp {
   int filp_count;              /* how many file descriptors share this slot?*/
   struct vnode *filp_vno;      /* vnode belonging to this file */
   u64_t filp_pos;              /* file position */
+  mutex_t filp_lock;           /* lock to gain exclusive access */
+  struct fproc *filp_softlock; /* if not NULL; this filp didn't lock the
+                                * vnode. Another filp already holds a lock
+                                * for this thread */
 
   /* the following fields are for select() and are owned by the generic
    * select() code (i.e., fd-type-specific select() code can't touch these).
@@ -32,14 +36,13 @@ EXTERN struct filp {
 #define FSF_UPDATE     001     /* The driver should be informed about new
                                 * state.
                                 */
-#define FSF_BUSY       002     /* Select operation sent to driver but no 
+#define FSF_BUSY       002     /* Select operation sent to driver but no
                                 * reply yet.
                                 */
-#define FSF_RD_BLOCK   010     /* Read request is blocking, the driver should 
+#define FSF_RD_BLOCK   010     /* Read request is blocking, the driver should
                                 * keep state.
                                 */
 #define FSF_WR_BLOCK   020     /* Write request is blocking */
 #define FSF_ERR_BLOCK  040     /* Exception request is blocking */
 #define FSF_BLOCKED    070
 #endif
-
index a8e85dc1b908012866ddc2f27d57bca985398940..1d3cbc0765886528541a219d4e05977226a9262b 100644 (file)
@@ -6,12 +6,12 @@
  *   find_filp:            find a filp slot that points to a given vnode
  *   inval_filp:    invalidate a filp and associated fd's, only let close()
  *                  happen on it
- *   do_verify_fd:  verify whether the given file descriptor is valid for 
+ *   do_verify_fd:  verify whether the given file descriptor is valid for
  *                  the given endpoint.
  *   do_set_filp:   marks a filp as in-flight.
  *   do_copy_filp:  copies a filp to another endpoint.
  *   do_put_filp:   marks a filp as not in-flight anymore.
- *   do_cancel_fd:  cancel the transaction when something goes wrong for 
+ *   do_cancel_fd:  cancel the transaction when something goes wrong for
  *                  the receiver.
  */
 
 #include "fproc.h"
 #include "vnode.h"
 
+
+FORWARD _PROTOTYPE( filp_id_t verify_fd, (endpoint_t ep, int fd)       );
+
+#if LOCK_DEBUG
+/*===========================================================================*
+ *                             check_filp_locks                             *
+ *===========================================================================*/
+PUBLIC void check_filp_locks_by_me(void)
+{
+/* Check whether this thread still has filp locks held */
+  struct filp *f;
+  int r;
+
+  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+       r = mutex_trylock(&f->filp_lock);
+       if (r == -EDEADLK)
+               panic("Thread %d still holds filp lock on filp %p call_nr=%d\n",
+                     mthread_self(), f, call_nr);
+       else if (r == 0) {
+               /* We just obtained the lock, release it */
+               mutex_unlock(&f->filp_lock);
+       }
+  }
+}
+#endif
+
+/*===========================================================================*
+ *                             check_filp_locks                             *
+ *===========================================================================*/
+PUBLIC void check_filp_locks(void)
+{
+  struct filp *f;
+  int r, count = 0;
+
+  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+       r = mutex_trylock(&f->filp_lock);
+       if (r == -EBUSY) {
+               /* Mutex is still locked */
+               count++;
+       } else if (r == 0) {
+               /* We just obtained a lock, don't want it */
+               mutex_unlock(&f->filp_lock);
+       } else
+               panic("filp_lock weird state");
+  }
+  if (count) panic("locked filps");
+#if 0
+  else printf("check_filp_locks OK\n");
+#endif
+}
+
+/*===========================================================================*
+ *                             init_filps                                           *
+ *===========================================================================*/
+PUBLIC void init_filps(void)
+{
+/* Initialize filps */
+  struct filp *f;
+
+  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+       mutex_init(&f->filp_lock, NULL);
+  }
+
+}
+
 /*===========================================================================*
  *                             get_fd                                       *
  *===========================================================================*/
@@ -49,10 +114,13 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
   /* Check to see if a file descriptor has been found. */
   if (i >= OPEN_MAX) return(EMFILE);
 
+  /* If we don't care about a filp, return now */
+  if (fpt == NULL) return(OK);
+
   /* Now that a file descriptor has been found, look for a free filp slot. */
   for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
        assert(f->filp_count >= 0);
-       if (f->filp_count == 0) {
+       if (f->filp_count == 0 && mutex_trylock(&f->filp_lock) == 0) {
                f->filp_mode = bits;
                f->filp_pos = cvu64(0);
                f->filp_selectors = 0;
@@ -61,6 +129,7 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
                f->filp_flags = 0;
                f->filp_state = FS_NORMAL;
                f->filp_select_flags = 0;
+               f->filp_softlock = NULL;
                *fpt = f;
                return(OK);
        }
@@ -74,38 +143,42 @@ PUBLIC int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
 /*===========================================================================*
  *                             get_filp                                     *
  *===========================================================================*/
-PUBLIC struct filp *get_filp(fild)
+PUBLIC struct filp *get_filp(fild, locktype)
 int fild;                      /* file descriptor */
+tll_access_t locktype;
 {
 /* See if 'fild' refers to a valid file descr.  If so, return its filp ptr. */
 
-  return get_filp2(fp, fild);
+  return get_filp2(fp, fild, locktype);
 }
 
 
 /*===========================================================================*
  *                             get_filp2                                    *
  *===========================================================================*/
-PUBLIC struct filp *get_filp2(rfp, fild)
+PUBLIC struct filp *get_filp2(rfp, fild, locktype)
 register struct fproc *rfp;
 int fild;                      /* file descriptor */
+tll_access_t locktype;
 {
 /* See if 'fild' refers to a valid file descr.  If so, return its filp ptr. */
+  struct filp *filp;
 
   err_code = EBADF;
   if (fild < 0 || fild >= OPEN_MAX ) return(NULL);
-  if (rfp->fp_filp[fild] == NULL && FD_ISSET(fild, &rfp->fp_filp_inuse)) 
+  if (rfp->fp_filp[fild] == NULL && FD_ISSET(fild, &rfp->fp_filp_inuse))
        err_code = EIO; /* The filedes is not there, but is not closed either.
                         */
-  
-  return(rfp->fp_filp[fild]);  /* may also be NULL */
+  if ((filp = rfp->fp_filp[fild]) != NULL) lock_filp(filp, locktype);
+
+  return(filp);        /* may also be NULL */
 }
 
 
 /*===========================================================================*
  *                             find_filp                                    *
  *===========================================================================*/
-PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits)
+PUBLIC struct filp *find_filp(struct vnode *vp, mode_t bits)
 {
 /* Find a filp slot that refers to the vnode 'vp' in a way as described
  * by the mode bit 'bits'. Used for determining whether somebody is still
@@ -114,10 +187,10 @@ PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits)
  * Like 'get_fd' it performs its job by linear search through the filp table.
  */
 
-  register struct filp *f;
+  struct filp *f;
 
   for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-       if (f->filp_count != 0 && f->filp_vno == vp && (f->filp_mode & bits)){
+       if (f->filp_count != 0 && f->filp_vno == vp && (f->filp_mode & bits)) {
                return(f);
        }
   }
@@ -127,18 +200,18 @@ PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits)
 }
 
 /*===========================================================================*
- *                             invalidate                                   *
+ *                             invalidate_filp                              *
  *===========================================================================*/
-PUBLIC int invalidate(struct filp *fp)
+PUBLIC int invalidate_filp(struct filp *rfilp)
 {
 /* Invalidate filp. fp_filp_inuse is not cleared, so filp can't be reused
    until it is closed first. */
 
   int f, fd, n = 0;
-  for(f = 0; f < NR_PROCS; f++) {
-       if(fproc[f].fp_pid == PID_FREE) continue;
-       for(fd = 0; fd < OPEN_MAX; fd++) {
-               if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) {
+  for (f = 0; f < NR_PROCS; f++) {
+       if (fproc[f].fp_pid == PID_FREE) continue;
+       for (fd = 0; fd < OPEN_MAX; fd++) {
+               if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == rfilp) {
                        fproc[f].fp_filp[fd] = NULL;
                        n++;
                }
@@ -149,24 +222,145 @@ PUBLIC int invalidate(struct filp *fp)
 }
 
 /*===========================================================================*
- *                              verify_fd                                    *
+ *                     invalidate_filp_by_endpt                             *
+ *===========================================================================*/
+PUBLIC void invalidate_filp_by_endpt(endpoint_t proc_e)
+{
+  struct filp *f;
+
+  for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+       if (f->filp_count != 0 && f->filp_vno != NULL) {
+               if (f->filp_vno->v_fs_e == proc_e)
+                       (void) invalidate_filp(f);
+       }
+  }
+}
+
+/*===========================================================================*
+ *                             lock_filp                                    *
+ *===========================================================================*/
+PUBLIC void lock_filp(filp, locktype)
+struct filp *filp;
+tll_access_t locktype;
+{
+  message org_m_in;
+  struct fproc *org_fp;
+  struct worker_thread *org_self;
+  struct vnode *vp;
+
+  assert(filp->filp_count > 0);
+  vp = filp->filp_vno;
+  assert(vp != NULL);
+
+  /* Lock vnode only if we haven't already locked it. If already locked by us,
+   * we're allowed to have one additional 'soft' lock. */
+  if (tll_locked_by_me(&vp->v_lock)) {
+       assert(filp->filp_softlock == NULL);
+       filp->filp_softlock = fp;
+  } else {
+       lock_vnode(vp, locktype);
+  }
+
+  assert(vp->v_ref_count > 0); /* vnode still in use? */
+  assert(filp->filp_vno == vp);        /* vnode still what we think it is? */
+  assert(filp->filp_count > 0); /* filp still in use? */
+
+  /* First try to get filp lock right off the bat */
+  if (mutex_trylock(&filp->filp_lock) != 0) {
+
+       /* Already in use, let's wait for our turn */
+       org_m_in = m_in;
+       org_fp = fp;
+       org_self = self;
+
+       if (mutex_lock(&filp->filp_lock) != 0)
+               panic("unable to obtain lock on filp");
+
+       m_in = org_m_in;
+       fp = org_fp;
+       self = org_self;
+  }
+
+  assert(filp->filp_count > 0);        /* Yet again; filp still in use? */
+}
+
+/*===========================================================================*
+ *                             unlock_filp                                  *
+ *===========================================================================*/
+PUBLIC void unlock_filp(filp)
+struct filp *filp;
+{
+  /* If this filp holds a soft lock on the vnode, we must be the owner */
+  if (filp->filp_softlock != NULL)
+       assert(filp->filp_softlock == fp);
+
+  if (filp->filp_count > 0) {
+       /* Only unlock vnode if filp is still in use */
+
+       /* and if we don't hold a soft lock */
+       if (filp->filp_softlock == NULL) {
+               assert(tll_islocked(&(filp->filp_vno->v_lock)));
+               unlock_vnode(filp->filp_vno);
+       }
+  }
+
+  filp->filp_softlock = NULL;
+  if (mutex_unlock(&filp->filp_lock) != 0)
+       panic("unable to release lock on filp");
+}
+
+/*===========================================================================*
+ *                             unlock_filps                                 *
+ *===========================================================================*/
+PUBLIC void unlock_filps(filp1, filp2)
+struct filp *filp1;
+struct filp *filp2;
+{
+/* Unlock two filps that are tied to the same vnode. As a thread can lock a
+ * vnode only once, unlocking the vnode twice would result in an error. */
+
+  /* No NULL pointers and not equal */
+  assert(filp1);
+  assert(filp2);
+  assert(filp1 != filp2);
+
+  /* Must be tied to the same vnode and not NULL */
+  assert(filp1->filp_vno == filp2->filp_vno);
+  assert(filp1->filp_vno != NULL);
+
+  if (filp1->filp_count > 0 && filp2->filp_count > 0) {
+       /* Only unlock vnode if filps are still in use */
+       unlock_vnode(filp1->filp_vno);
+  }
+
+  filp1->filp_softlock = NULL;
+  filp2->filp_softlock = NULL;
+  if (mutex_unlock(&filp2->filp_lock) != 0)
+       panic("unable to release filp lock on filp2");
+  if (mutex_unlock(&filp1->filp_lock) != 0)
+       panic("unable to release filp lock on filp1");
+}
+
+/*===========================================================================*
+ *                             verify_fd                                    *
  *===========================================================================*/
-PUBLIC filp_id_t verify_fd(ep, fd)
+PRIVATE filp_id_t verify_fd(ep, fd)
 endpoint_t ep;
 int fd;
 {
-  /*
-   * verify whether the given file descriptor 'fd' is valid for the
-   * endpoint 'ep'. When the file descriptor is valid verify_fd returns a 
-   * pointer to that filp, else it returns NULL.
-   */
-  int proc;
-
-  if (isokendpt(ep, &proc) != OK) {
-       return NULL;
-  }
+/* Verify whether the file descriptor 'fd' is valid for the endpoint 'ep'. When
+ * the file descriptor is valid, verify_fd returns a pointer to that filp, else
+ * it returns NULL.
+ */
+  int slot;
+  struct filp *rfilp;
 
-  return get_filp2(&fproc[proc], fd);
+  if (isokendpt(ep, &slot) != OK)
+       return(NULL);
+
+  rfilp = get_filp2(&fproc[slot], fd, VNODE_READ);
+
+  return(rfilp);
 }
 
 /*===========================================================================*
@@ -174,8 +368,11 @@ int fd;
  *===========================================================================*/
 PUBLIC int do_verify_fd(void)
 {
-  m_out.ADDRESS = (void *) verify_fd(m_in.USER_ENDPT, m_in.COUNT);
-  return (m_out.ADDRESS != NULL) ? OK : EINVAL;
+  struct filp *rfilp;
+  rfilp = (struct filp *) verify_fd(m_in.USER_ENDPT, m_in.COUNT);
+  m_out.ADDRESS = (void *) rfilp;
+  if (rfilp != NULL) unlock_filp(rfilp);
+  return (rfilp != NULL) ? OK : EINVAL;
 }
 
 /*===========================================================================*
@@ -184,12 +381,13 @@ PUBLIC int do_verify_fd(void)
 PUBLIC int set_filp(sfilp)
 filp_id_t sfilp;
 {
-  if (sfilp == NULL) {
-       return EINVAL;
-  } else {
-       sfilp->filp_count++;
-       return OK;
-  }
+  if (sfilp == NULL) return(EINVAL);
+
+  lock_filp(sfilp, VNODE_READ);
+  sfilp->filp_count++;
+  unlock_filp(sfilp);
+
+  return(OK);
 }
 
 /*===========================================================================*
@@ -197,7 +395,7 @@ filp_id_t sfilp;
  *===========================================================================*/
 PUBLIC int do_set_filp(void)
 {
-  return set_filp((filp_id_t) m_in.ADDRESS);;
+  return set_filp((filp_id_t) m_in.ADDRESS);
 }
 
 /*===========================================================================*
@@ -207,28 +405,28 @@ PUBLIC int copy_filp(to_ep, cfilp)
 endpoint_t to_ep;
 filp_id_t cfilp;
 {
-  int j;
-  int proc;
+  int fd;
+  int slot;
+  struct fproc *rfp;
 
-  if (isokendpt(to_ep, &proc) != OK) {
-       return EINVAL;
-  }
+  if (isokendpt(to_ep, &slot) != OK) return(EINVAL);
+  rfp = &fproc[slot];
 
   /* Find an open slot in fp_filp */
-  for (j = 0; j < OPEN_MAX; j++) {
-       if (fproc[proc].fp_filp[j] == NULL && 
-                       !FD_ISSET(j, &fproc[proc].fp_filp_inuse)) {
+  for (fd = 0; fd < OPEN_MAX; fd++) {
+       if (rfp->fp_filp[fd] == NULL &&
+           !FD_ISSET(fd, &rfp->fp_filp_inuse)) {
 
                /* Found a free slot, add descriptor */
-               FD_SET(j, &fproc[proc].fp_filp_inuse);
-               fproc[proc].fp_filp[j] = cfilp;
-               fproc[proc].fp_filp[j]->filp_count++;
-               return j;
+               FD_SET(fd, &rfp->fp_filp_inuse);
+               rfp->fp_filp[fd] = cfilp;
+               rfp->fp_filp[fd]->filp_count++;
+               return(fd);
        }
   }
 
-  /* File Descriptor Table is Full */
-  return EMFILE;
+  /* File descriptor table is full */
+  return(EMFILE);
 }
 
 /*===========================================================================*
@@ -248,8 +446,9 @@ filp_id_t pfilp;
   if (pfilp == NULL) {
        return EINVAL;
   } else {
+       lock_filp(pfilp, VNODE_OPCL);
        close_filp(pfilp);
-       return OK;
+       return(OK);
   }
 }
 
@@ -262,31 +461,38 @@ PUBLIC int do_put_filp(void)
 }
 
 /*===========================================================================*
- *                             cancel_fd                                     *
+ *                             cancel_fd                                    *
  *===========================================================================*/
 PUBLIC int cancel_fd(ep, fd)
 endpoint_t ep;
 int fd;
 {
-  int proc;
+  int slot;
+  struct fproc *rfp;
+  struct filp *rfilp;
 
-  if (isokendpt(ep, &proc) != OK) {
-       return EINVAL;
-  }
+  if (isokendpt(ep, &slot) != OK) return(EINVAL);
+  rfp = &fproc[slot];
 
   /* Check that the input 'fd' is valid */
-  if (verify_fd(ep, fd) != NULL) {
-
+  rfilp = (struct filp *) verify_fd(ep, fd);
+  if (rfilp != NULL) {
        /* Found a valid descriptor, remove it */
-       FD_CLR(fd, &fproc[proc].fp_filp_inuse);
-       fproc[proc].fp_filp[fd]->filp_count--;
-       fproc[proc].fp_filp[fd] = NULL;
-
-       return fd;
+       FD_CLR(fd, &rfp->fp_filp_inuse);
+       if (rfp->fp_filp[fd]->filp_count == 0) {
+               unlock_filp(rfilp);
+               printf("VFS: filp_count for slot %d fd %d already zero", slot,
+                     fd);
+               return(EINVAL);
+       }
+       rfp->fp_filp[fd]->filp_count--;
+       rfp->fp_filp[fd] = NULL;
+       unlock_filp(rfilp);
+       return(fd);
   }
 
   /* File descriptor is not valid for the endpoint. */
-  return EINVAL;
+  return(EINVAL);
 }
 
 /*===========================================================================*
@@ -300,56 +506,73 @@ PUBLIC int do_cancel_fd(void)
 /*===========================================================================*
  *                             close_filp                                   *
  *===========================================================================*/
-PUBLIC void close_filp(fp)
-struct filp *fp;
+PUBLIC void close_filp(f)
+struct filp *f;
 {
+/* Close a file. Will also unlock filp when done */
+
   int mode_word, rw;
   dev_t dev;
   struct vnode *vp;
 
-  vp = fp->filp_vno;
-  if (fp->filp_count - 1 == 0 && fp->filp_mode != FILP_CLOSED) {
+  /* Must be locked */
+  assert(mutex_trylock(&f->filp_lock) == -EDEADLK);
+  assert(tll_islocked(&f->filp_vno->v_lock));
+
+  vp = f->filp_vno;
+
+  if (f->filp_count - 1 == 0 && f->filp_mode != FILP_CLOSED) {
        /* Check to see if the file is special. */
        mode_word = vp->v_mode & I_TYPE;
        if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
                dev = (dev_t) vp->v_sdev;
                if (mode_word == I_BLOCK_SPECIAL)  {
+                       lock_bsf();
                        if (vp->v_bfs_e == ROOT_FS_E) {
                                /* Invalidate the cache unless the special is
                                 * mounted. Assume that the root filesystem's
                                 * is open only for fsck.
-                                */
-                               req_flush(vp->v_bfs_e, dev);
-                       }
+                                */
+                               req_flush(vp->v_bfs_e, dev);
+                       }
+                       unlock_bsf();
                }
 
                /* Do any special processing on device close.
                 * Ignore any errors, even SUSPEND.
-                */
+                 */
                if (mode_word == I_BLOCK_SPECIAL)
                        (void) bdev_close(dev);
                else
-                       (void) dev_close(dev, fp-filp);
+                       (void) dev_close(dev, f-filp);
 
-               fp->filp_mode = FILP_CLOSED;
+               f->filp_mode = FILP_CLOSED;
        }
   }
 
   /* If the inode being closed is a pipe, release everyone hanging on it. */
   if (vp->v_pipe == I_PIPE) {
-       rw = (fp->filp_mode & R_BIT ? WRITE : READ);
+       rw = (f->filp_mode & R_BIT ? WRITE : READ);
        release(vp, rw, NR_PROCS);
   }
 
   /* If a write has been done, the inode is already marked as DIRTY. */
-  if (--fp->filp_count == 0) {
+  if (--f->filp_count == 0) {
        if (vp->v_pipe == I_PIPE) {
                /* Last reader or writer is going. Tell PFS about latest
                 * pipe size.
                 */
                truncate_vnode(vp, vp->v_size);
        }
-               
-       put_vnode(fp->filp_vno);
+
+       unlock_vnode(f->filp_vno);
+       put_vnode(f->filp_vno);
+  } else if (f->filp_count < 0) {
+       panic("VFS: invalid filp count: %d ino %d/%d", f->filp_count,
+             vp->v_dev, vp->v_inode_nr);
+  } else {
+       unlock_vnode(f->filp_vno);
   }
+
+  mutex_unlock(&f->filp_lock);
 }
index aab719e1f9f558e87bc06de690d201aa53c58ef7..79ede32f71e811c072d20c04ad1564bf457e282a 100644 (file)
@@ -1,56 +1,69 @@
 #ifndef __VFS_FPROC_H__
 #define __VFS_FPROC_H__
 
+#include "threads.h"
+
 #include <sys/select.h>
 #include <minix/safecopies.h>
 
 /* This is the per-process information.  A slot is reserved for each potential
- * process. Thus NR_PROCS must be the same as in the kernel. It is not 
+ * process. Thus NR_PROCS must be the same as in the kernel. It is not
  * possible or even necessary to tell when a slot is free here.
  */
+#define LOCK_DEBUG 0
 EXTERN struct fproc {
   unsigned fp_flags;
 
-  mode_t fp_umask;             /* mask set by umask system call */
+  pid_t fp_pid;                        /* process id */
+  endpoint_t fp_endpoint;      /* kernel endpoint number of this process */
+
   struct vnode *fp_wd;         /* working directory; NULL during reboot */
   struct vnode *fp_rd;         /* root directory; NULL during reboot */
-  
-  struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
 
+  struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
   fd_set fp_filp_inuse;                /* which fd's are in use? */
-  uid_t fp_realuid;            /* real user id */
-  uid_t fp_effuid;             /* effective user id */
-  gid_t fp_realgid;            /* real group id */
-  gid_t fp_effgid;             /* effective group id */
-  int fp_ngroups;              /* number of supplemental groups */
-  gid_t fp_sgroups[NGROUPS_MAX];/* supplemental groups */
+  fd_set fp_cloexec_set;       /* bit map for POSIX Table 6-2 FD_CLOEXEC */
+
   dev_t fp_tty;                        /* major/minor of controlling tty */
-  int fp_block_fd;             /* place to save fd if rd/wr can't finish */
+
+  int fp_blocked_on;           /* what is it blocked on */
   int fp_block_callnr;         /* blocked call if rd/wr can't finish */
-  char *fp_buffer;             /* place to save buffer if rd/wr can't finish*/
-  int  fp_nbytes;              /* place to save bytes if rd/wr can't finish */
   int  fp_cum_io_partial;      /* partial byte count if rd/wr can't finish */
-  int fp_revived;              /* set to indicate process being revived */
   endpoint_t fp_task;          /* which task is proc suspended on */
-  int fp_blocked_on;           /* what is it blocked on */
-  
   endpoint_t fp_ioproc;                /* proc no. in suspended-on i/o message */
+
   cp_grant_id_t fp_grant;      /* revoke this grant on unsuspend if > -1 */
-  
-  char fp_sesldr;              /* true if proc is a session leader */
-  char fp_execced;             /* true if proc has exec()ced after fork */
-  pid_t fp_pid;                        /* process id */
-  
-  fd_set fp_cloexec_set;       /* bit map for POSIX Table 6-2 FD_CLOEXEC */
-  endpoint_t fp_endpoint;      /* kernel endpoint number of this process */
+
+  uid_t fp_realuid;            /* real user id */
+  uid_t fp_effuid;             /* effective user id */
+  gid_t fp_realgid;            /* real group id */
+  gid_t fp_effgid;             /* effective group id */
+  int fp_ngroups;              /* number of supplemental groups */
+  gid_t fp_sgroups[NGROUPS_MAX];/* supplemental groups */
+  mode_t fp_umask;             /* mask set by umask system call */
+
+  message *fp_sendrec;         /* request/reply to/from FS/driver */
+  mutex_t fp_lock;             /* mutex to lock fproc object */
+  struct job fp_job;           /* pending job */
+  thread_t fp_wtid;            /* Thread ID of worker */
+#if LOCK_DEBUG
+  int fp_vp_rdlocks;           /* number of read-only locks on vnodes */
+  int fp_vmnt_rdlocks;         /* number of read-only locks on vmnts */
+#endif
 } fproc[NR_PROCS];
 
 /* fp_flags */
-#define NO_FLAGS       0
-#define SUSP_REOPEN    1       /* Process is suspended until the reopens are
+#define FP_NOFLAGS     00
+#define FP_SUSP_REOPEN 01      /* Process is suspended until the reopens are
                                 * completed (after the restart of a driver).
                                 */
+#define FP_REVIVED      0002   /* Indicates process is being revived */
+#define FP_SESLDR       0004   /* Set if process is session leader */
+#define FP_PENDING      0010   /* Set if process has pending work */
+#define FP_EXITING      0020   /* Set if process is exiting */
+#define FP_PM_PENDING   0040   /* Set if process has pending PM request */
+#define FP_SYS_PROC     0100   /* Set if process is a driver or FS */
+#define FP_DROP_WORK    0200   /* Set if process won't accept new work */
 
 /* Field values. */
 #define NOT_REVIVING       0xC0FFEEE   /* process is not being revived */
index 216225de95f98f5e99f49b4e69a457177b8d04cd..9531c2207964ce308b30637e094bec1289c14966 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef __VFS_FS_H__
+#define __VFS_FS_H__
+
 /* This is the master header for fs.  It includes some other files
  * and defines the principal constants.
  */
@@ -40,4 +43,9 @@
 #include "const.h"
 #include "dmap.h"
 #include "proto.h"
+#include "threads.h"
 #include "glo.h"
+#include "comm.h"
+#include "vmnt.h"
+
+#endif
index 214457afbb071189d726e1e313893120c3f866ca..257afb32ed5cd73622904e7b911a5a989b4c3aa7 100644 (file)
@@ -45,25 +45,16 @@ PRIVATE int push_globals()
  */
 
   if (depth == MAX_DEPTH)
-       return EPERM;
+       return(EPERM);
 
   globals[depth].g_fp = fp;
   globals[depth].g_m_in = m_in;
   globals[depth].g_m_out = m_out;
-  globals[depth].g_who_e = who_e;
-  globals[depth].g_who_p = who_p;
-  globals[depth].g_call_nr = call_nr;
   globals[depth].g_super_user = super_user;
 
-  /* XXX is it safe to strcpy this? */
-  assert(sizeof(globals[0].g_user_fullpath) == sizeof(user_fullpath));
-  memcpy(globals[depth].g_user_fullpath, user_fullpath, sizeof(user_fullpath));
-
   /* err_code is not used across blocking calls */
-
   depth++;
-
-  return OK;
+  return(OK);
 }
 
 /*===========================================================================*
@@ -82,12 +73,7 @@ PRIVATE void pop_globals()
   fp = globals[depth].g_fp;
   m_in = globals[depth].g_m_in;
   m_out = globals[depth].g_m_out;
-  who_e = globals[depth].g_who_e;
-  who_p = globals[depth].g_who_p;
-  call_nr = globals[depth].g_call_nr;
-  super_user = globals[depth].g_super_user;
 
-  memcpy(user_fullpath, globals[depth].g_user_fullpath, sizeof(user_fullpath));
 }
 
 /*===========================================================================*
@@ -98,13 +84,13 @@ message *m;                         /* request message */
 {
 /* Initialize global variables based on a request message.
  */
+  int proc_p;
 
   m_in = *m;
-  who_e = m_in.m_source;
-  who_p = _ENDPOINT_P(who_e);
-  call_nr = m_in.m_type;
-  fp = &fproc[who_p];
-  super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);
+
+  proc_p = _ENDPOINT_P(m_in.m_source);
+  fp = &fproc[proc_p];
+
   /* the rest need not be initialized */
 }
 
@@ -144,51 +130,3 @@ message *m;                                /* request/reply message pointer */
 
   m->m_type = r;
 }
-
-/*===========================================================================*
- *                             nested_dev_call                              *
- *===========================================================================*/
-PUBLIC void nested_dev_call(m)
-message *m;                            /* request/reply message pointer */
-{
-/* Handle a nested call from a device driver server.
- */
-  int r;
-
-  /* Save global variables of the current call */
-  if ((r = push_globals()) != OK) {
-       printf("VFS: error saving globals in call %d from driver %d\n",
-               m->m_type, m->m_source);
-  } else {
-       /* Initialize global variables for the nested call */
-       set_globals(m);
-
-       if (call_nr >= PFS_BASE) {
-               call_nr -= PFS_BASE;
-       }
-
-       /* Perform the nested call */
-       if (call_nr < 0 || call_nr >= PFS_NREQS) {
-
-               printf("VFS: invalid nested call %d from driver %d\n",
-                       call_nr, who_e);
-
-               r = ENOSYS;
-       } else if (who_e == PFS_PROC_NR) {
-
-               r = (*pfs_call_vec[call_nr])();
-       } else {
-
-               printf("VFS: only the PFS device can make nested VFS calls\n");
-
-               r = ENOSYS;
-       }
-
-       /* Store the result, and restore original global variables */
-       *m = m_out;
-
-       pop_globals();
-  }
-
-  m->m_type = r;
-}
index 374322f73c470505dd6df0c851eeec66c9ea8e07..50bed6451b071d37e7edcb5a55685a3258e4e6de 100644 (file)
@@ -16,58 +16,51 @@ PUBLIC int do_gcov_flush()
  * makes the target copy its buffer to the caller (incl vfs
  * itself).
  */
-       struct fproc *rfp;
-       ssize_t size;
-       cp_grant_id_t grantid;
-       int r;
-       int n;
-       pid_t target;
-
-       size = m_in.GCOV_BUFF_SZ;
-       target = m_in.GCOV_PID;
-
-       /* If the wrong process is sent to, the system hangs;
-        * so make this root-only.
-        */
-
-       if (!super_user) return(EPERM);
-
-       /* Find target gcov process. */
-
-       for(n = 0; n < NR_PROCS; n++) {
-                if(fproc[n].fp_endpoint != NONE &&
-                        fproc[n].fp_pid == target)
-                                break;
-       }
-
-       if(n >= NR_PROCS) {
-                printf("VFS: gcov proccess %d not found.\n", target);
-                return ESRCH;
-       }
-
-       rfp = &fproc[n];
-
-       /* Grant target process to requestor's buffer. */
-
-       if((grantid = cpf_grant_magic(rfp->fp_endpoint,
-                who_e, (vir_bytes) m_in.GCOV_BUFF_P,
-                size, CPF_WRITE)) < 0) {
-                printf("VFS: gcov_flush: grant failed\n");
-                return ENOMEM;
-       }
-
-       if(target == getpid()) {
-                /* Request is for VFS itself. */
-               r = gcov_flush(grantid, size);
-       } else {
-               /* Perform generic GCOV request. */
-               m_out.GCOV_GRANT = grantid;
-               m_out.GCOV_BUFF_SZ = size;
-               r = _taskcall(rfp->fp_endpoint, COMMON_REQ_GCOV_DATA, &m_out);
-       }
-
-       cpf_revoke(grantid);
-
-       return r;
+  struct fproc *rfp;
+  ssize_t size;
+  cp_grant_id_t grantid;
+  int r, n;
+  pid_t target;
+  message m;
+
+  size = m_in.GCOV_BUFF_SZ;
+  target = m_in.GCOV_PID;
+
+  /* If the wrong process is sent to, the system hangs; so make this root-only.
+   */
+
+  if (!super_user) return(EPERM);
+
+  /* Find target gcov process. */
+  for(n = 0; n < NR_PROCS; n++) {
+       if(fproc[n].fp_endpoint != NONE && fproc[n].fp_pid == target)
+                break;
+  }
+  if(n >= NR_PROCS) {
+       printf("VFS: gcov process %d not found\n", target);
+       return(ESRCH);
+  }
+  rfp = &fproc[n];
+
+  /* Grant target process to requestor's buffer. */
+  if ((grantid = cpf_grant_magic(rfp->fp_endpoint, who_e,
+                                (vir_bytes) m_in.GCOV_BUFF_P, size,
+                                CPF_WRITE)) < 0) {
+       printf("VFS: gcov_flush: grant failed\n");
+       return(ENOMEM);
+  }
+
+  if(rfp->fp_endpoint == VFS_PROC_NR) {
+       /* Request is for VFS itself. */
+       r = gcov_flush(grantid, size);
+  } else {
+       /* Perform generic GCOV request. */
+       m.GCOV_GRANT = grantid;
+       m.GCOV_BUFF_SZ = size;
+       r = _taskcall(rfp->fp_endpoint, COMMON_REQ_GCOV_DATA, &m);
+  }
+
+  cpf_revoke(grantid);
+
+  return(r);
 }
-
index 6ecb0a4cd0e81cc768355a9be643723d5320a623..c07220aa0b0c10dac35382f089253936880d3caf 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef __VFS_GLO_H__
+#define __VFS_GLO_H__
+
 /* EXTERN should be extern except for the table file */
 #ifdef _TABLE
 #undef EXTERN
@@ -6,26 +9,41 @@
 
 /* File System global variables */
 EXTERN struct fproc *fp;       /* pointer to caller's fproc struct */
-EXTERN int super_user;         /* 1 if caller is super_user, else 0 */
 EXTERN int susp_count;         /* number of procs suspended on pipe */
 EXTERN int nr_locks;           /* number of locks currently in place */
 EXTERN int reviving;           /* number of pipe processes to be revived */
+EXTERN int pending;
+EXTERN int sending;
 
-EXTERN dev_t root_dev;         /* device number of the root device */
+EXTERN dev_t ROOT_DEV;         /* device number of the root device */
 EXTERN int ROOT_FS_E;           /* kernel endpoint of the root FS proc */
 EXTERN u32_t system_hz;                /* system clock frequency. */
 
 /* The parameters of the call are kept here. */
 EXTERN message m_in;           /* the input message itself */
 EXTERN message m_out;          /* the output message used for reply */
-EXTERN int who_p, who_e;       /* caller's proc number, endpoint */
-EXTERN int call_nr;            /* system call number */
-
-EXTERN message mount_m_in;     /* the input message for a mount request */
+# define who_p         ((int) (fp - fproc))
+# define isokslot(p)   (p >= 0 && \
+                        p < (int)(sizeof(fproc) / sizeof(struct fproc)))
+#if 0
+# define who_e         (isokslot(who_p) ? fp->fp_endpoint : m_in.m_source)
+#else
+# define who_e         (isokslot(who_p) && fp->fp_endpoint != NONE ? \
+                                       fp->fp_endpoint : m_in.m_source)
+#endif
+# define call_nr       (m_in.m_type)
+# define super_user    (fp->fp_effuid == SU_UID ? 1 : 0)
+# define scratch(p)            (scratchpad[((int) ((p) - fproc))])
+EXTERN struct worker_thread *self;
+EXTERN int force_sync;         /* toggle forced synchronous communication */
+EXTERN int deadlock_resolving;
+EXTERN mutex_t exec_lock;
+EXTERN mutex_t bsf_lock;/* Global lock for access to block special files */
+EXTERN struct worker_thread workers[NR_WTHREADS];
+EXTERN struct worker_thread sys_worker;
+EXTERN struct worker_thread dl_worker;
 EXTERN char mount_label[LABEL_MAX];    /* label of file system to mount */
 
-EXTERN char user_fullpath[PATH_MAX];    /* storage for user path name */
-
 /* The following variables are used for returning results to the caller. */
 EXTERN int err_code;           /* temporary storage for error number */
 
@@ -35,3 +53,5 @@ extern _PROTOTYPE (int (*pfs_call_vec[]), (void) ); /* pfs callback table */
 extern char dot1[2];   /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
 extern char dot2[3];   /* meaning to search_dir: no access permission check. */
 extern char mode_map[];        /* mapping from O_ACCMODE mask to R_BIT/W_BIT flags */
+
+#endif
similarity index 100%
rename from servers/avfs/job.h
rename to servers/vfs/job.h
index 5a1f81564e19a9cedba6cd959bcd2ded47a0af5d..1c0b4af86af547e3cd4725fd13a048939dbd9432 100644 (file)
 #include <string.h>
 #include <minix/com.h>
 #include <minix/callnr.h>
+#include <minix/vfsif.h>
 #include <dirent.h>
+#include <assert.h>
 #include "file.h"
 #include "fproc.h"
-#include "param.h"
-#include <minix/vfsif.h>
+#include "path.h"
 #include "vnode.h"
+#include "param.h"
 
 /*===========================================================================*
  *                             do_link                                      *
@@ -30,34 +32,52 @@ PUBLIC int do_link()
 {
 /* Perform the link(name1, name2) system call. */
   int r = OK;
-  struct vnode *vp = NULL, *vp_d = NULL;
+  struct vnode *vp = NULL, *dirp = NULL;
+  struct vmnt *vmp1 = NULL, *vmp2 = NULL;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
 
-  /* See if 'name1' (file to be linked to) exists. */ 
-  if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp1, &vp);
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_READ;
+
+  /* See if 'name1' (file to be linked to) exists. */
+  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+       return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
 
   /* Does the final directory of 'name2' exist? */
-  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) 
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp2, &dirp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
+       r = err_code;
+  else if ((dirp = last_dir(&resolve, fp)) == NULL)
        r = err_code;
-  else if ((vp_d = last_dir(fp)) == NULL)
-       r = err_code; 
+
   if (r != OK) {
-         put_vnode(vp);
-         return(r);
+       unlock_vnode(vp);
+       unlock_vmnt(vmp1);
+       put_vnode(vp);
+       return(r);
   }
 
   /* Check for links across devices. */
-  if(vp->v_fs_e != vp_d->v_fs_e)
-       r = EXDEV;
-  else 
-       r = forbidden(fp, vp_d, W_BIT | X_BIT);
+  if (vp->v_fs_e != dirp->v_fs_e)
+       r = EXDEV;
+  else
+       r = forbidden(fp, dirp, W_BIT | X_BIT);
 
   if (r == OK)
-       r = req_link(vp->v_fs_e, vp_d->v_inode_nr, user_fullpath,
+       r = req_link(vp->v_fs_e, dirp->v_inode_nr, fullpath,
                     vp->v_inode_nr);
 
+  unlock_vnode(vp);
+  unlock_vnode(dirp);
+  if (vmp2 != NULL) unlock_vmnt(vmp2);
+  unlock_vmnt(vmp1);
   put_vnode(vp);
-  put_vnode(vp_d);
+  put_vnode(dirp);
   return(r);
 }
 
@@ -71,52 +91,78 @@ PUBLIC int do_unlink()
  * is almost the same.  They differ only in some condition testing.  Unlink()
  * may be used by the superuser to do dangerous things; rmdir() may not.
  */
-  struct vnode *vldirp, *vp;
+  struct vnode *dirp, *vp;
+  struct vmnt *vmp, *vmp2;
   int r;
-  
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &dirp);
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_READ;
+
   /* Get the last directory in the path. */
-  if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  if ((vldirp = last_dir(fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
+       return(err_code);
+
+  if ((dirp = last_dir(&resolve, fp)) == NULL) return(err_code);
+  assert(vmp != NULL);
 
   /* Make sure that the object is a directory */
-  if((vldirp->v_mode & I_TYPE) != I_DIRECTORY) {
-         put_vnode(vldirp);
-         return(ENOTDIR);
+  if ((dirp->v_mode & I_TYPE) != I_DIRECTORY) {
+       unlock_vnode(dirp);
+       unlock_vmnt(vmp);
+       put_vnode(dirp);
+       return(ENOTDIR);
   }
 
   /* The caller must have both search and execute permission */
-  if ((r = forbidden(fp, vldirp, X_BIT | W_BIT)) != OK) {
-       put_vnode(vldirp);
+  if ((r = forbidden(fp, dirp, X_BIT | W_BIT)) != OK) {
+       unlock_vnode(dirp);
+       unlock_vmnt(vmp);
+       put_vnode(dirp);
        return(r);
   }
-  
+
   /* Also, if the sticky bit is set, only the owner of the file or a privileged
      user is allowed to unlink */
-  if ((vldirp->v_mode & S_ISVTX) == S_ISVTX) {
+  if ((dirp->v_mode & S_ISVTX) == S_ISVTX) {
        /* Look up inode of file to unlink to retrieve owner */
-       vp = advance(vldirp, PATH_RET_SYMLINK, fp);
+       resolve.l_flags = PATH_RET_SYMLINK;
+       resolve.l_vmp = &vmp2;  /* Shouldn't actually get locked */
+       resolve.l_vmnt_lock = VMNT_READ;
+       resolve.l_vnode = &vp;
+       resolve.l_vnode_lock = VNODE_READ;
+       vp = advance(dirp, &resolve, fp);
+       assert(vmp2 == NULL);
        if (vp != NULL) {
-               if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) 
+               if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
                        r = EPERM;
+               unlock_vnode(vp);
                put_vnode(vp);
        } else
                r = err_code;
        if (r != OK) {
-               put_vnode(vldirp);
+               unlock_vnode(dirp);
+               unlock_vmnt(vmp);
+               put_vnode(dirp);
                return(r);
        }
   }
-  
-  if(call_nr == UNLINK) 
-         r = req_unlink(vldirp->v_fs_e, vldirp->v_inode_nr, user_fullpath);
-  else 
-         r = req_rmdir(vldirp->v_fs_e, vldirp->v_inode_nr, user_fullpath);
-  
-  put_vnode(vldirp);
+
+  assert(vmp != NULL);
+  tll_upgrade(&vmp->m_lock);
+
+  if (call_nr == UNLINK)
+         r = req_unlink(dirp->v_fs_e, dirp->v_inode_nr, fullpath);
+  else
+         r = req_rmdir(dirp->v_fs_e, dirp->v_inode_nr, fullpath);
+  unlock_vnode(dirp);
+  unlock_vmnt(vmp);
+  put_vnode(dirp);
   return(r);
 }
 
-
 /*===========================================================================*
  *                             do_rename                                    *
  *===========================================================================*/
@@ -125,61 +171,93 @@ PUBLIC int do_rename()
 /* Perform the rename(name1, name2) system call. */
   int r = OK, r1;
   struct vnode *old_dirp, *new_dirp = NULL, *vp;
+  struct vmnt *oldvmp, *newvmp, *vmp2;
   char old_name[PATH_MAX];
-  
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &oldvmp, &old_dirp);
+  /* Do not yet request exclusive lock on vmnt to prevent deadlocks later on */
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_READ;
+
   /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
-  if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((old_dirp = last_dir(fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+       return(err_code);
+  if ((old_dirp = last_dir(&resolve, fp)) == NULL)
+       return(err_code);
 
   /* If the sticky bit is set, only the owner of the file or a privileged
      user is allowed to rename */
-  if((old_dirp->v_mode & S_ISVTX) == S_ISVTX) {
+  if ((old_dirp->v_mode & S_ISVTX) == S_ISVTX) {
        /* Look up inode of file to unlink to retrieve owner */
-       vp = advance(old_dirp, PATH_RET_SYMLINK, fp);
+       lookup_init(&resolve, resolve.l_path, PATH_RET_SYMLINK, &vmp2, &vp);
+       resolve.l_vmnt_lock = VMNT_READ;
+       resolve.l_vnode_lock = VNODE_READ;
+       vp = advance(old_dirp, &resolve, fp);
+       assert(vmp2 == NULL);
        if (vp != NULL) {
-               if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) 
+               if(vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID)
                        r = EPERM;
+               unlock_vnode(vp);
                put_vnode(vp);
        } else
                r = err_code;
-       if (r != OK) {  
+       if (r != OK) {
+               unlock_vnode(old_dirp);
+               unlock_vmnt(oldvmp);
                put_vnode(old_dirp);
                return(r);
        }
   }
-  
+
   /* Save the last component of the old name */
-  if(strlen(user_fullpath) >= sizeof(old_name)) {
+  if(strlen(fullpath) >= sizeof(old_name)) {
+       unlock_vnode(old_dirp);
+       unlock_vmnt(oldvmp);
        put_vnode(old_dirp);
        return(ENAMETOOLONG);
   }
-  strcpy(old_name, user_fullpath);
-  
+  strcpy(old_name, fullpath);
+
   /* See if 'name2' (new name) exists.  Get dir inode */
-  if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK) 
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &newvmp, &new_dirp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
+       r = err_code;
+  else if ((new_dirp = last_dir(&resolve, fp)) == NULL)
        r = err_code;
-  else if ((new_dirp = last_dir(fp)) == NULL)
-       r = err_code; 
+
   if (r != OK) {
-       put_vnode(old_dirp);
-       return r;
+       unlock_vnode(old_dirp);
+       unlock_vmnt(oldvmp);
+       put_vnode(old_dirp);
+       return(r);
   }
 
   /* Both parent directories must be on the same device. */
-  if(old_dirp->v_fs_e != new_dirp->v_fs_e) r = EXDEV; 
+  if (old_dirp->v_fs_e != new_dirp->v_fs_e) r = EXDEV;
 
   /* Parent dirs must be writable, searchable and on a writable device */
   if ((r1 = forbidden(fp, old_dirp, W_BIT|X_BIT)) != OK ||
       (r1 = forbidden(fp, new_dirp, W_BIT|X_BIT)) != OK) r = r1;
-  
-  if(r == OK)
-         r = req_rename(old_dirp->v_fs_e, old_dirp->v_inode_nr, old_name,
-                        new_dirp->v_inode_nr, user_fullpath);
+
+  if (r == OK) {
+       tll_upgrade(&oldvmp->m_lock); /* Upgrade to exclusive access */
+       r = req_rename(old_dirp->v_fs_e, old_dirp->v_inode_nr, old_name,
+                      new_dirp->v_inode_nr, fullpath);
+  }
+  unlock_vnode(old_dirp);
+  unlock_vnode(new_dirp);
+  unlock_vmnt(oldvmp);
+  if (newvmp) unlock_vmnt(newvmp);
+
   put_vnode(old_dirp);
   put_vnode(new_dirp);
+
   return(r);
 }
-  
 
 /*===========================================================================*
  *                             do_truncate                                  *
@@ -192,23 +270,31 @@ PUBLIC int do_truncate()
  * work.
  */
   struct vnode *vp;
+  struct vmnt *vmp;
   int r;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_EXCL;
+  resolve.l_vnode_lock = VNODE_WRITE;
 
   if ((off_t) m_in.flength < 0) return(EINVAL);
 
   /* Temporarily open file */
-  if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
-  
+  if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1, fullpath) != OK) return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
+
   /* Ask FS to truncate the file */
   if ((r = forbidden(fp, vp, W_BIT)) == OK)
-       r = truncate_vnode(vp, m_in.flength);
-  
+       r = truncate_vnode(vp, m_in.flength);
+
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
   put_vnode(vp);
   return(r);
 }
 
-
 /*===========================================================================*
  *                             do_ftruncate                                 *
  *===========================================================================*/
@@ -216,13 +302,20 @@ PUBLIC int do_ftruncate()
 {
 /* As with do_truncate(), truncate_vnode() does the actual work. */
   struct filp *rfilp;
-  
+  int r;
+
   if ((off_t) m_in.flength < 0) return(EINVAL);
 
   /* File is already opened; get a vnode pointer from filp */
-  if ((rfilp = get_filp(m_in.m2_i1)) == NULL) return(err_code);
-  if (!(rfilp->filp_mode & W_BIT)) return(EBADF);
-  return truncate_vnode(rfilp->filp_vno, m_in.flength);
+  if ((rfilp = get_filp(m_in.m2_i1, VNODE_WRITE)) == NULL) return(err_code);
+
+  if (!(rfilp->filp_mode & W_BIT))
+       r = EBADF;
+  else
+       r = truncate_vnode(rfilp->filp_vno, m_in.flength);
+
+  unlock_filp(rfilp);
+  return(r);
 }
 
 
@@ -233,14 +326,14 @@ PUBLIC int truncate_vnode(vp, newsize)
 struct vnode *vp;
 off_t newsize;
 {
+/* Truncate a regular file or a pipe */
   int r, file_type;
 
+  assert(tll_locked_by_me(&vp->v_lock));
   file_type = vp->v_mode & I_TYPE;
   if (file_type != I_REGULAR && file_type != I_NAMED_PIPE) return(EINVAL);
-        
   if ((r = req_ftrunc(vp->v_fs_e, vp->v_inode_nr, newsize, 0)) == OK)
        vp->v_size = newsize;
-
   return(r);
 }
 
@@ -253,21 +346,33 @@ PUBLIC int do_slink()
 /* Perform the symlink(name1, name2) system call. */
   int r;
   struct vnode *vp;
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_READ;
+
+  if (m_in.name1_length <= 1) return(ENOENT);
+  if (m_in.name1_length >= SYMLINK_MAX) return(ENAMETOOLONG);
 
-  if(m_in.name1_length <= 1) return(ENOENT);
-  if(m_in.name1_length >= SYMLINK_MAX) return(ENAMETOOLONG);
-  
   /* Get dir inode of 'name2' */
-  if(fetch_name(m_in.name2, m_in.name2_length, M1) != OK) return(err_code);
-  if ((vp = last_dir(fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
+       return(err_code);
+
+  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
 
   if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
-       r = req_slink(vp->v_fs_e, vp->v_inode_nr, user_fullpath, who_e,
+       r = req_slink(vp->v_fs_e, vp->v_inode_nr, fullpath, who_e,
                      m_in.name1, m_in.name1_length - 1, fp->fp_effuid,
                      fp->fp_effgid);
   }
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
   put_vnode(vp);
+
   return(r);
 }
 
@@ -276,55 +381,75 @@ PUBLIC int do_slink()
  *===========================================================================*/
 PUBLIC int rdlink_direct(orig_path, link_path, rfp)
 char *orig_path;
-char *link_path; /* should have length PATH_MAX */
+char link_path[PATH_MAX]; /* should have length PATH_MAX */
 struct fproc *rfp;
 {
 /* Perform a readlink()-like call from within the VFS */
   int r;
   struct vnode *vp;
+  struct vmnt *vmp;
+  struct lookup resolve;
 
-  /* Temporarily open the file containing the symbolic link */
-  orig_path[PATH_MAX - 1] = '\0';
-  strncpy(user_fullpath, orig_path, PATH_MAX);
-  if ((vp = eat_path(PATH_RET_SYMLINK, rfp)) == NULL) return(err_code);
+  lookup_init(&resolve, link_path, PATH_RET_SYMLINK, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+
+  /* Temporarily open the file containing the symbolic link. Use link_path
+   * for temporary storage to keep orig_path untouched. */
+  strncpy(link_path, orig_path, PATH_MAX);     /* PATH_MAX includes '\0' */
+  link_path[PATH_MAX - 1] = '\0';
+  if ((vp = eat_path(&resolve, rfp)) == NULL) return(err_code);
 
   /* Make sure this is a symbolic link */
-  if((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
+  if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
        r = EINVAL;
   else
-       r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, (endpoint_t) 0,
-                                               link_path, PATH_MAX - 1, 1);
-  if (r > 0) link_path[r] = '\0';
+       r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, NONE, link_path,
+                      PATH_MAX - 1, 1);
+
+  if (r > 0) link_path[r] = '\0';      /* Terminate string when succesful */
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
   put_vnode(vp);
+
   return r;
 }
 
 /*===========================================================================*
- *                             do_rdlink                                    *
+ *                             do_rdlink                                    *
  *===========================================================================*/
 PUBLIC int do_rdlink()
 {
 /* Perform the readlink(name, buf, bufsize) system call. */
   int r, copylen;
   struct vnode *vp;
-  
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+
   copylen = m_in.nbytes;
-  if(copylen < 0) return(EINVAL);
+  if (copylen < 0) return(EINVAL);
 
   /* Temporarily open the file containing the symbolic link */
-  if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_RET_SYMLINK, fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+       return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
 
   /* Make sure this is a symbolic link */
-  if((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK) 
+  if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
        r = EINVAL;
   else
        r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2,
-                                                               copylen, 0);
+                      copylen, 0);
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
   put_vnode(vp);
+
   return(r);
 }
-
-
index 340642f41f5833ef01254c7b1dc182bd5f1c8bd0..36ab59351c56942a642fc85cc06fe057f0b47d5b 100644 (file)
 #include <unistd.h>
 #include "file.h"
 #include "fproc.h"
+#include "scratchpad.h"
 #include "lock.h"
-#include "param.h"
 #include "vnode.h"
+#include "param.h"
 
 /*===========================================================================*
  *                             lock_op                                      *
@@ -29,13 +30,11 @@ int req;                    /* either F_SETLK or F_SETLKW */
   mode_t mo;
   off_t first, last;
   struct flock flock;
-  vir_bytes user_flock;
   struct file_lock *flp, *flp2, *empty;
 
   /* Fetch the flock structure from user space. */
-  user_flock = (vir_bytes) m_in.name1;
-  r = sys_datacopy(who_e, (vir_bytes) user_flock, VFS_PROC_NR,
-                  (vir_bytes) &flock, (phys_bytes) sizeof(flock));
+  r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer, VFS_PROC_NR,
+                  (vir_bytes) &flock, sizeof(flock));
   if (r != OK) return(EINVAL);
 
   /* Make some error checks. */
@@ -43,26 +42,27 @@ int req;                    /* either F_SETLK or F_SETLKW */
   mo = f->filp_mode;
   if (ltype != F_UNLCK && ltype != F_RDLCK && ltype != F_WRLCK) return(EINVAL);
   if (req == F_GETLK && ltype == F_UNLCK) return(EINVAL);
-  if ( (f->filp_vno->v_mode & I_TYPE) != I_REGULAR) return(EINVAL);
+  if ( (f->filp_vno->v_mode & I_TYPE) != I_REGULAR &&
+       (f->filp_vno->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(EINVAL);
   if (req != F_GETLK && ltype == F_RDLCK && (mo & R_BIT) == 0) return(EBADF);
   if (req != F_GETLK && ltype == F_WRLCK && (mo & W_BIT) == 0) return(EBADF);
 
   /* Compute the first and last bytes in the lock region. */
   switch (flock.l_whence) {
-       case SEEK_SET:  first = 0; break;
-       case SEEK_CUR:
-          if (ex64hi(f->filp_pos) != 0) 
+    case SEEK_SET:     first = 0; break;
+    case SEEK_CUR:
+       if (ex64hi(f->filp_pos) != 0)
                panic("lock_op: position in file too high");
-          first = ex64lo(f->filp_pos);
-          break;
-       case SEEK_END:  first = f->filp_vno->v_size; break;
-       default:        return(EINVAL);
+       first = ex64lo(f->filp_pos);
+       break;
+    case SEEK_END:     first = f->filp_vno->v_size; break;
+    default:   return(EINVAL);
   }
 
   /* Check for overflow. */
-  if (((long)flock.l_start > 0) && ((first + flock.l_start) < first))
+  if (((long) flock.l_start > 0) && ((first + flock.l_start) < first))
        return(EINVAL);
-  if (((long)flock.l_start < 0) && ((first + flock.l_start) > first))
+  if (((long) flock.l_start < 0) && ((first + flock.l_start) > first))
        return(EINVAL);
   first = first + flock.l_start;
   last = first + flock.l_len - 1;
@@ -81,7 +81,7 @@ int req;                      /* either F_SETLK or F_SETLKW */
        if (first > flp->lock_last) continue;   /* new one is afterwards */
        if (ltype == F_RDLCK && flp->lock_type == F_RDLCK) continue;
        if (ltype != F_UNLCK && flp->lock_pid == fp->fp_pid) continue;
-  
+
        /* There might be a conflict.  Process it. */
        conflict = 1;
        if (req == F_GETLK) break;
@@ -116,7 +116,7 @@ int req;                    /* either F_SETLK or F_SETLKW */
                flp->lock_last = first - 1;
                continue;
        }
-       
+
        /* Bad luck. A lock has been split in two by unlocking the middle. */
        if (nr_locks == NR_LOCKS) return(ENOLCK);
        for (i = 0; i < NR_LOCKS; i++)
@@ -148,7 +148,7 @@ int req;                    /* either F_SETLK or F_SETLKW */
 
        /* Copy the flock structure back to the caller. */
        r = sys_datacopy(VFS_PROC_NR, (vir_bytes) &flock,
-               who_e, (vir_bytes) user_flock, (phys_bytes) sizeof(flock));
+               who_e, (vir_bytes) scratch(fp).io.io_buffer, sizeof(flock));
        return(r);
   }
 
@@ -171,22 +171,21 @@ int req;                  /* either F_SETLK or F_SETLKW */
  *===========================================================================*/
 PUBLIC void lock_revive()
 {
-/* Go find all the processes that are waiting for any kind of lock and 
- * revive them all.  The ones that are still blocked will block again when 
- * they run.  The others will complete.  This strategy is a space-time 
- * tradeoff.  Figuring out exactly which ones to unblock now would take 
- * extra code, and the only thing it would win would be some performance in 
- * extremely rare circumstances (namely, that somebody actually used 
+/* Go find all the processes that are waiting for any kind of lock and
+ * revive them all.  The ones that are still blocked will block again when
+ * they run.  The others will complete.  This strategy is a space-time
+ * tradeoff.  Figuring out exactly which ones to unblock now would take
+ * extra code, and the only thing it would win would be some performance in
+ * extremely rare circumstances (namely, that somebody actually used
  * locking).
  */
 
   struct fproc *fptr;
 
   for (fptr = &fproc[0]; fptr < &fproc[NR_PROCS]; fptr++){
-       if(fptr->fp_pid == PID_FREE) continue;
+       if (fptr->fp_pid == PID_FREE) continue;
        if (fptr->fp_blocked_on == FP_BLOCKED_ON_LOCK) {
                revive(fptr->fp_endpoint, 0);
        }
   }
 }
-
index 95ab56c83743a88c975e5b11a02ccb3b20a78626..c2baa651efe8e3273d3233762a0c96d3ab28c383 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef __VFS_LOCK_H__
+#define __VFS_LOCK_H__
+
 /* This is the file locking table.  Like the filp table, it points to the
  * inode table, however, in this case to achieve advisory locking.
  */
@@ -9,4 +12,4 @@ EXTERN struct file_lock {
   off_t lock_last;             /* offset of last byte locked */
 } file_lock[NR_LOCKS];
 
-
+#endif
index c9bd692e34f9d0861ca94f02bb9d3fa0c9a7d9d1..27d99bf079f71141d7f5500dfb890c096c84c456 100644 (file)
@@ -6,8 +6,6 @@
  *   main:     main program of the Virtual File System
  *   reply:    send a reply to a process after the requested work is done
  *
- * Changes for VFS:
- *   Jul 2006 (Balazs Gerofi)
  */
 
 #include "fs.h"
 #include <minix/endpoint.h>
 #include <minix/safecopies.h>
 #include <minix/debug.h>
+#include <minix/vfsif.h>
 #include "file.h"
+#include "dmap.h"
 #include "fproc.h"
-#include "param.h"
-
-#include <minix/vfsif.h>
+#include "scratchpad.h"
 #include "vmnt.h"
 #include "vnode.h"
+#include "job.h"
+#include "param.h"
 
 #if ENABLE_SYSCALL_STATS
 EXTERN unsigned long calls_stats[NCALLS];
 #endif
 
+/* Thread related prototypes */
+FORWARD _PROTOTYPE( void thread_cleanup_f, (struct fproc *rfp, char *f,
+                                           int l)                      );
+#define thread_cleanup(x) thread_cleanup_f(x, __FILE__, __LINE__)
+FORWARD _PROTOTYPE( void *do_async_dev_result, (void *arg)             );
+FORWARD _PROTOTYPE( void *do_control_msgs, (void *arg)                 );
+FORWARD _PROTOTYPE( void *do_fs_reply, (struct job *job)                       );
+FORWARD _PROTOTYPE( void *do_work, (void *arg)                         );
+FORWARD _PROTOTYPE( void *do_pm, (void *arg)                           );
+FORWARD _PROTOTYPE( void *do_init_root, (void *arg)                    );
+FORWARD _PROTOTYPE( void handle_work, (void *(*func)(void *arg))               );
+
 FORWARD _PROTOTYPE( void get_work, (void)                              );
-FORWARD _PROTOTYPE( void init_root, (void)                             );
+FORWARD _PROTOTYPE( void lock_pm, (void)                               );
+FORWARD _PROTOTYPE( void unlock_pm, (void)                             );
 FORWARD _PROTOTYPE( void service_pm, (void)                            );
+FORWARD _PROTOTYPE( void service_pm_postponed, (void)                          );
+FORWARD _PROTOTYPE( int unblock, (struct fproc *rfp)                   );
 
 /* SEF functions and variables. */
 FORWARD _PROTOTYPE( void sef_local_startup, (void) );
 FORWARD _PROTOTYPE( int sef_cb_init_fresh, (int type, sef_init_info_t *info) );
+PRIVATE mutex_t pm_lock;
+PRIVATE endpoint_t receive_from;
 
 /*===========================================================================*
  *                             main                                         *
@@ -56,144 +73,387 @@ PUBLIC int main(void)
  * three major activities: getting new work, processing the work, and sending
  * the reply.  This loop never terminates as long as the file system runs.
  */
-  int error;
+  int transid, req;
+  struct job *job;
 
   /* SEF local startup. */
   sef_local_startup();
 
+  printf("Started VFS: %d worker thread(s)\n", NR_WTHREADS);
+
   /* This is the main loop that gets work, processes it, and sends replies. */
   while (TRUE) {
-       SANITYCHECK;
-       get_work();             /* sets who and call_nr */
-
-       if (call_nr == DEV_OPEN_REPL)   /* XXX: hack to make DEV_OPEN_REPL */
-               call_nr = DEV_REVIVE;   /* work on synchronous VFS */
-
-       if (call_nr == DEV_REVIVE)
-       {
-               endpoint_t endpt;
-
-               endpt = m_in.REP_ENDPT;
-               if(endpt == VFS_PROC_NR) {
-                       endpt = suspended_ep(m_in.m_source, m_in.REP_IO_GRANT);
-                       if(endpt == NONE) {
-                               printf("FS: proc with "
-                       "grant %d from %d not found (revive)\n",
-                                       m_in.REP_IO_GRANT, m_in.m_source);
-                               continue;
-                       }
-               }
-               revive(endpt, m_in.REP_STATUS);
+       yield_all();    /* let other threads run */
+       send_work();
+       get_work();
+
+       transid = TRNS_GET_ID(m_in.m_type);
+       req = TRNS_DEL_ID(m_in.m_type);
+       job = worker_getjob( (thread_t) transid - VFS_TRANSID);
+
+       /* Transaction encoding changes original m_type value; restore. */
+       if (job == NULL)
+               m_in.m_type = transid;
+       else
+               m_in.m_type = req;
+
+       if (job != NULL) {
+               do_fs_reply(job);
                continue;
-       }
-       if (call_nr == DEV_REOPEN_REPL)
-       {
-               reopen_reply();
+       } else if (who_e == PM_PROC_NR) { /* Calls from PM */
+               /* Special control messages from PM */
+               sys_worker_start(do_pm);
                continue;
-       }
-       if (call_nr == DEV_CLOSE_REPL)
-       {
-               close_reply();
-               continue;
-       }
-       if (call_nr == DEV_SEL_REPL1)
-       {
-               select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
+       } else if (is_notify(call_nr)) {
+               /* A task notify()ed us */
+               sys_worker_start(do_control_msgs);
                continue;
+       } else if (who_p < 0) { /* i.e., message comes from a task */
+               /* We're going to ignore this message. Tasks should
+                * send notify()s only.
+                */
+                printf("VFS: ignoring message from %d (%d)\n", who_e, call_nr);
+                continue;
        }
-       if (call_nr == DEV_SEL_REPL2)
-       {
-               select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
+
+       /* At this point we either have results from an asynchronous device
+        * or a new system call. In both cases a new worker thread has to be
+        * started and there might not be one available from the pool. This is
+        * not a problem (requests/replies are simply queued), except when
+        * they're from an FS endpoint, because these can cause a deadlock.
+        * handle_work() takes care of the details. */
+       if (IS_DEV_RS(call_nr)) {
+               /* We've got results for a device request */
+               handle_work(do_async_dev_result);
                continue;
+       } else {
+               /* Normal syscall. */
+               handle_work(do_work);
        }
+  }
+  return(OK);                          /* shouldn't come here */
+}
 
-       /* Check for special control messages first. */
-        if (is_notify(call_nr)) {
-               if (who_e == CLOCK)
-               {
-                       /* Alarm timer expired. Used only for select().
-                        * Check it.
-                        */
-                       expire_timers(m_in.NOTIFY_TIMESTAMP);
-               }
-               else if(who_e == DS_PROC_NR)
-               {
-                       /* DS notifies us of an event. */
-                       ds_event();
-               }
-               else
-               {
-                       /* Device notifies us of an event. */
-                       dev_status(&m_in);
+/*===========================================================================*
+ *                            handle_work                                   *
+ *===========================================================================*/
+PRIVATE void handle_work(void *(*func)(void *arg))
+{
+/* Handle asynchronous device replies and new system calls. If the originating
+ * endpoint is an FS endpoint, take extra care not to get in deadlock. */
+  struct vmnt *vmp = NULL;
+
+  if ((vmp = find_vmnt(who_e)) != NULL) {
+       /* A call back or dev result from an FS endpoint */
+
+       /* Set call back flag. We assume that an FS does only one call back
+        * at a time */
+       vmp->m_flags |= VMNT_CALLBACK;
+
+       /* When an FS point has to make a call back in order to mount, force
+        * its device to a "none device" so block reads/writes will be handled
+        * by ROOT_FS_E.
+        */
+       if (vmp->m_flags & VMNT_MOUNTING)
+               vmp->m_flags |= VMNT_FORCEROOTBSF;
+
+       if (worker_available() == 0) {
+               /* No worker threads available to handle call */
+               if (deadlock_resolving) {
+                       /* Already trying to resolve a deadlock, can't
+                        * handle more, sorry */
+                       vmp->m_flags &= ~VMNT_CALLBACK;
+                       reply(who_e, EAGAIN);
+                       return;
                }
-               SANITYCHECK;
-               continue;
+               deadlock_resolving = 1;
+               dl_worker_start(func);
+               return;
        }
+  }
 
-       /* We only expect notify()s from tasks. */
-       if(who_p < 0) {
-               printf("FS: ignoring message from %d (%d)\n",
-                       who_e, m_in.m_type);
-               continue;
-       }
+  worker_start(func);
+}
 
-       /* Now it's safe to set and check fp. */
-       fp = &fproc[who_p];     /* pointer to proc table struct */
-       super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
+/*===========================================================================*
+ *                            do_async_dev_result                                   *
+ *===========================================================================*/
+PRIVATE void *do_async_dev_result(void *arg)
+{
+  endpoint_t endpt;
+  struct job my_job;
+
+  my_job = *((struct job *) arg);
+  fp = my_job.j_fp;
+  m_in = my_job.j_m_in;
+
+  /* An asynchronous character driver has results for us */
+  if (call_nr == DEV_REVIVE) {
+       endpt = m_in.REP_ENDPT;
+       if (endpt == VFS_PROC_NR)
+               endpt = find_suspended_ep(m_in.m_source, m_in.REP_IO_GRANT);
+
+       if (endpt == NONE) {
+               printf("VFS: proc with grant %d from %d not found\n",
+                       m_in.REP_IO_GRANT, m_in.m_source);
+       } else if (m_in.REP_STATUS == SUSPEND) {
+               printf("VFS: got SUSPEND on DEV_REVIVE: not reviving proc\n");
+       } else
+               revive(endpt, m_in.REP_STATUS);
+  }
+  else if (call_nr == DEV_OPEN_REPL) open_reply();
+  else if (call_nr == DEV_REOPEN_REPL) reopen_reply();
+  else if (call_nr == DEV_CLOSE_REPL) close_reply();
+  else if (call_nr == DEV_SEL_REPL1)
+       select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
+  else if (call_nr == DEV_SEL_REPL2)
+       select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
+
+  if (deadlock_resolving) {
+       if (fp != NULL && fp->fp_wtid == dl_worker.w_tid)
+               deadlock_resolving = 0;
+  }
 
-#if DO_SANITYCHECKS
-       if(fp_is_blocked(fp)) {
-               printf("VFS: requester %d call %d: suspended\n",
-                       who_e, call_nr);
-               panic("requester suspended");
-       }
-#endif
+  if (fp != NULL && (fp->fp_flags & FP_SYS_PROC)) {
+       struct vmnt *vmp;
 
-       /* Calls from PM. */
-       if (who_e == PM_PROC_NR) {
-               service_pm();
+       if ((vmp = find_vmnt(fp->fp_endpoint)) != NULL)
+               vmp->m_flags &= ~VMNT_CALLBACK;
+  }
 
-               continue;
-       }
+  thread_cleanup(NULL);
+  return(NULL);
+}
+
+/*===========================================================================*
+ *                            do_control_msgs                               *
+ *===========================================================================*/
+PRIVATE void *do_control_msgs(void *arg)
+{
+  struct job my_job;
+
+  my_job = *((struct job *) arg);
+  fp = my_job.j_fp;
+  m_in = my_job.j_m_in;
+
+  /* Check for special control messages. */
+  if (who_e == CLOCK) {
+       /* Alarm timer expired. Used only for select(). Check it. */
+       expire_timers(m_in.NOTIFY_TIMESTAMP);
+  } else if (who_e == DS_PROC_NR) {
+       /* DS notifies us of an event. */
+       ds_event();
+  } else {
+       /* Device notifies us of an event. */
+       dev_status(&m_in);
+  }
+
+  thread_cleanup(NULL);
+  return(NULL);
+}
+
+/*===========================================================================*
+ *                            do_fs_reply                                   *
+ *===========================================================================*/
+PRIVATE void *do_fs_reply(struct job *job)
+{
+  struct vmnt *vmp;
+  struct fproc *rfp;
 
-               SANITYCHECK;
-
-         /* Other calls. */
-         switch(call_nr)
-         {
-             case MAPDRIVER:
-               error= do_mapdriver();
-               if (error != SUSPEND) reply(who_e, error);
-               break;
-             case COMMON_GETSYSINFO:
-               error= do_getsysinfo();
-               if (error != SUSPEND) reply(who_e, error);
-               break;
-             default:
-               /* Call the internal function that does the work. */
-               if (call_nr < 0 || call_nr >= NCALLS) { 
-                       error = ENOSYS;
-                       /* Not supposed to happen. */
-               } else if (fp->fp_pid == PID_FREE) {
-                       error = ENOSYS;
-                       printf(
-               "FS, bad process, who = %d, call_nr = %d, endpt1 = %d\n",
-                                who_e, call_nr, m_in.endpt1);
-               } else {
+  if ((vmp = find_vmnt(who_e)) == NULL)
+       panic("Couldn't find vmnt for endpoint %d", who_e);
+
+  rfp = job->j_fp;
+
+  if (rfp == NULL || rfp->fp_endpoint == NONE) {
+       printf("VFS: spurious reply from %d\n", who_e);
+       return(NULL);
+  }
+
+  if (rfp->fp_task != who_e)
+       printf("VFS: expected %d to reply, not %d\n", rfp->fp_task, who_e);
+  *rfp->fp_sendrec = m_in;
+  rfp->fp_task = NONE;
+  vmp->m_comm.c_cur_reqs--;    /* We've got our reply, make room for others */
+  worker_signal(worker_get(rfp->fp_wtid));/* Continue this worker thread */
+  return(NULL);
+}
+
+/*===========================================================================*
+ *                             lock_pm                                      *
+ *===========================================================================*/
+PRIVATE void lock_pm(void)
+{
+  message org_m_in;
+  struct fproc *org_fp;
+  struct worker_thread *org_self;
+
+  /* First try to get it right off the bat */
+  if (mutex_trylock(&pm_lock) == 0)
+       return;
+
+  org_m_in = m_in;
+  org_fp = fp;
+  org_self = self;
+
+  if (mutex_lock(&pm_lock) != 0)
+       panic("Could not obtain lock on pm\n");
+
+  m_in = org_m_in;
+  fp = org_fp;
+  self = org_self;
+}
+
+/*===========================================================================*
+ *                             unlock_pm                                    *
+ *===========================================================================*/
+PRIVATE void unlock_pm(void)
+{
+  if (mutex_unlock(&pm_lock) != 0)
+       panic("Could not release lock on pm");
+}
+
+/*===========================================================================*
+ *                            do_pm                                         *
+ *===========================================================================*/
+PRIVATE void *do_pm(void *arg)
+{
+  struct job my_job;
+  struct fproc *rfp;
+
+  my_job = *((struct job *) arg);
+  rfp = fp = my_job.j_fp;
+  m_in = my_job.j_m_in;
+
+  lock_pm();
+  service_pm();
+  unlock_pm();
+
+  thread_cleanup(NULL);
+  return(NULL);
+}
+
+/*===========================================================================*
+ *                            do_pending_pipe                                       *
+ *===========================================================================*/
+PRIVATE void *do_pending_pipe(void *arg)
+{
+  int r, op;
+  struct job my_job;
+  struct filp *f;
+  tll_access_t locktype;
+
+  my_job = *((struct job *) arg);
+  fp = my_job.j_fp;
+  m_in = my_job.j_m_in;
+
+  lock_proc(fp, 1 /* force lock */);
+
+  f = scratch(fp).file.filp;
+  assert(f != NULL);
+  scratch(fp).file.filp = NULL;
+
+  locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE;
+  op = (call_nr == READ) ? READING : WRITING;
+  lock_filp(f, locktype);
+
+  r = rw_pipe(op, who_e, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes);
+
+  if (r != SUSPEND)  /* Do we have results to report? */
+       reply(who_e, r);
+
+  unlock_filp(f);
+
+  thread_cleanup(fp);
+  return(NULL);
+}
+
+/*===========================================================================*
+ *                            do_dummy                                      *
+ *===========================================================================*/
+PUBLIC void *do_dummy(void *arg)
+{
+  struct job my_job;
+  int r;
+
+  my_job = *((struct job *) arg);
+  fp = my_job.j_fp;
+  m_in = my_job.j_m_in;
+
+  if ((r = mutex_trylock(&fp->fp_lock)) == 0) {
+       thread_cleanup(fp);
+  } else {
+       /* Proc is busy, let that worker thread carry out the work */
+       thread_cleanup(NULL);
+  }
+  return(NULL);
+}
+
+/*===========================================================================*
+ *                            do_work                                       *
+ *===========================================================================*/
+PRIVATE void *do_work(void *arg)
+{
+  int error;
+  struct job my_job;
+
+  my_job = *((struct job *) arg);
+  fp = my_job.j_fp;
+  m_in = my_job.j_m_in;
+
+  lock_proc(fp, 0); /* This proc is busy */
+
+  if (call_nr == MAPDRIVER) {
+       error = do_mapdriver();
+  } else if (call_nr == COMMON_GETSYSINFO) {
+       error = do_getsysinfo();
+  } else if (IS_PFS_VFS_RQ(call_nr)) {
+       if (who_e != PFS_PROC_NR) {
+               printf("VFS: only PFS is allowed to make nested VFS calls\n");
+               error = ENOSYS;
+       } else if (call_nr <= PFS_BASE || call_nr >= PFS_BASE + PFS_NREQS) {
+               error = ENOSYS;
+       } else {
+               call_nr -= PFS_BASE;
+               error = (*pfs_call_vec[call_nr])();
+       }
+  } else {
+       /* We're dealing with a POSIX system call from a normal
+        * process. Call the internal function that does the work.
+        */
+       if (call_nr < 0 || call_nr >= NCALLS) {
+               error = ENOSYS;
+       } else if (fp->fp_pid == PID_FREE) {
+               /* Process vanished before we were able to handle request.
+                * Replying has no use. Just drop it. */
+               error = SUSPEND;
+       } else {
 #if ENABLE_SYSCALL_STATS
-                       calls_stats[call_nr]++;
+               calls_stats[call_nr]++;
 #endif
-                       SANITYCHECK;
-                       error = (*call_vec[call_nr])();
-                       SANITYCHECK;
-               }
+               error = (*call_vec[call_nr])();
+       }
+  }
+
+  /* Copy the results back to the user and send reply. */
+  if (error != SUSPEND) {
 
-               /* Copy the results back to the user and send reply. */
-               if (error != SUSPEND) { reply(who_e, error); }
+       if ((fp->fp_flags & FP_SYS_PROC)) {
+               struct vmnt *vmp;
+
+               if ((vmp = find_vmnt(fp->fp_endpoint)) != NULL)
+                       vmp->m_flags &= ~VMNT_CALLBACK;
+       }
+
+       if (deadlock_resolving) {
+               if (fp->fp_wtid == dl_worker.w_tid)
+                       deadlock_resolving = 0;
        }
-       SANITYCHECK;
+       reply(who_e, error);
   }
-  return(OK);                          /* shouldn't come here */
+
+  thread_cleanup(fp);
+  return(NULL);
 }
 
 /*===========================================================================*
@@ -214,198 +474,296 @@ PRIVATE void sef_local_startup()
 /*===========================================================================*
  *                             sef_cb_init_fresh                            *
  *===========================================================================*/
-PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info)
+PRIVATE int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info)
 {
 /* Initialize the virtual file server. */
   int s, i;
-  register struct fproc *rfp;
-  struct vmnt *vmp;
-  struct vnode *root_vp;
+  struct fproc *rfp;
   message mess;
   struct rprocpub rprocpub[NR_BOOT_PROCS];
 
-  /* Clear endpoint field */
-  mount_m_in.m1_p3 = (char *) NONE;
+  force_sync = 0;
+  receive_from = ANY;
+
+  /* Initialize proc endpoints to NONE */
+  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+       rfp->fp_endpoint = NONE;
+       rfp->fp_pid = PID_FREE;
+  }
 
-  /* Initialize the process table with help of the process manager messages. 
-   * Expect one message for each system process with its slot number and pid. 
-   * When no more processes follow, the magic process number NONE is sent. 
+  /* Initialize the process table with help of the process manager messages.
+   * Expect one message for each system process with its slot number and pid.
+   * When no more processes follow, the magic process number NONE is sent.
    * Then, stop and synchronize with the PM.
    */
   do {
-       if (OK != (s=sef_receive(PM_PROC_NR, &mess)))
-               panic("FS couldn't receive from PM: %d", s);
+       if ((s = sef_receive(PM_PROC_NR, &mess)) != OK)
+               panic("VFS: couldn't receive from PM: %d", s);
 
        if (mess.m_type != PM_INIT)
                panic("unexpected message from PM: %d", mess.m_type);
 
-       if (NONE == mess.PM_PROC) break; 
+       if (NONE == mess.PM_PROC) break;
 
        rfp = &fproc[mess.PM_SLOT];
+       rfp->fp_flags = FP_NOFLAGS;
        rfp->fp_pid = mess.PM_PID;
        rfp->fp_endpoint = mess.PM_PROC;
+       rfp->fp_grant = GRANT_INVALID;
+       rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
        rfp->fp_realuid = (uid_t) SYS_UID;
        rfp->fp_effuid = (uid_t) SYS_UID;
        rfp->fp_realgid = (gid_t) SYS_GID;
        rfp->fp_effgid = (gid_t) SYS_GID;
        rfp->fp_umask = ~0;
-       rfp->fp_grant = GRANT_INVALID;
-       rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-       rfp->fp_revived = NOT_REVIVING;
-   
   } while (TRUE);                      /* continue until process NONE */
   mess.m_type = OK;                    /* tell PM that we succeeded */
   s = send(PM_PROC_NR, &mess);         /* send synchronization message */
 
   /* All process table entries have been set. Continue with initialization. */
-  
-  /* The following initializations are needed to let dev_opcl succeed .*/
-  fp = (struct fproc *) NULL;
-  who_e = who_p = VFS_PROC_NR;
-
-  /* Initialize device table. */
-  build_dmap();
+  fp = &fproc[_ENDPOINT_P(VFS_PROC_NR)];/* During init all communication with
+                                        * FSes is on behalf of myself */
+  init_dmap();                 /* Initialize device table. */
+  system_hz = sys_hz();
 
   /* Map all the services in the boot image. */
-  if((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
-       (vir_bytes) rprocpub, sizeof(rprocpub), S)) != OK) {
+  if ((s = sys_safecopyfrom(RS_PROC_NR, info->rproctab_gid, 0,
+                           (vir_bytes) rprocpub, sizeof(rprocpub), S)) != OK){
        panic("sys_safecopyfrom failed: %d", s);
   }
-  for(i=0;i < NR_BOOT_PROCS;i++) {
-       if(rprocpub[i].in_use) {
-               if((s = map_service(&rprocpub[i])) != OK) {
-                       panic("unable to map service: %d", s);
+  for (i = 0; i < NR_BOOT_PROCS; i++) {
+       if (rprocpub[i].in_use) {
+               if ((s = map_service(&rprocpub[i])) != OK) {
+                       panic("VFS: unable to map service: %d", s);
                }
        }
   }
 
-  init_root();                 /* init root device and load super block */
+  /* Subscribe to block and character driver events. */
+  s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
+  if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);
+
+#if DO_SANITYCHECKS
+  FIXME("VFS: DO_SANITYCHECKS is on");
+#endif
+
+  /* Initialize worker threads */
+  for (i = 0; i < NR_WTHREADS; i++)  {
+       worker_init(&workers[i]);
+  }
+  worker_init(&sys_worker); /* exclusive system worker thread */
+  worker_init(&dl_worker); /* exclusive worker thread to resolve deadlocks */
+
+  /* Initialize global locks */
+  if (mthread_mutex_init(&pm_lock, NULL) != 0)
+       panic("VFS: couldn't initialize pm lock mutex");
+  if (mthread_mutex_init(&exec_lock, NULL) != 0)
+       panic("VFS: couldn't initialize exec lock");
+  if (mthread_mutex_init(&bsf_lock, NULL) != 0)
+       panic("VFS: couldn't initialize block special file lock");
+
+  /* Initialize event resources for boot procs and locks for all procs */
+  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+       if (mutex_init(&rfp->fp_lock, NULL) != 0)
+               panic("unable to initialize fproc lock");
+#if LOCK_DEBUG
+       rfp->fp_vp_rdlocks = 0;
+       rfp->fp_vmnt_rdlocks = 0;
+#endif
+  }
+
+  init_vnodes();               /* init vnodes */
+  init_vmnts();                        /* init vmnt structures */
   init_select();               /* init select() structures */
+  init_filps();                        /* Init filp structures */
+  mount_pfs();                 /* mount Pipe File Server */
+  worker_start(do_init_root);  /* mount initial ramdisk as file system root */
+  yield();                     /* force do_init_root to start */
+
+  return(OK);
+}
 
+/*===========================================================================*
+ *                            do_init_root                                  *
+ *===========================================================================*/
+PRIVATE void *do_init_root(void *arg)
+{
+  struct fproc *rfp;
+  struct job my_job;
+  int r;
+  char *mount_label = "fs_imgrd"; /* FIXME: obtain this from RS */
+
+  my_job = *((struct job *) arg);
+  fp = my_job.j_fp;
 
-  vmp = &vmnt[0];              /* Should be the root filesystem */
-  if (vmp->m_dev == NO_DEV)
-       panic("vfs: no root filesystem");
-  root_vp= vmp->m_root_node;
+  lock_proc(fp, 1 /* force lock */); /* This proc is busy */
+  lock_pm();
 
-  /* The root device can now be accessed; set process directories. */
-  for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+  /* Initialize process directories. mount_fs will set them to the correct
+   * values */
+  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
        FD_ZERO(&(rfp->fp_filp_inuse));
-       if (rfp->fp_pid != PID_FREE) {
-                
-               dup_vnode(root_vp);
-                rfp->fp_rd = root_vp;
-               dup_vnode(root_vp);
-                rfp->fp_wd = root_vp;
-               
-       } else  rfp->fp_endpoint = NONE;
+       rfp->fp_rd = NULL;
+       rfp->fp_wd = NULL;
   }
 
-  system_hz = sys_hz();
+  receive_from = MFS_PROC_NR;
+  if ((r = mount_fs(DEV_IMGRD, "/", MFS_PROC_NR, 0, mount_label)) != OK)
+       panic("Failed to initialize root");
+  receive_from = ANY;
 
-  /* Subscribe to block and character driver events. */
-  s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
-  if(s != OK) {
-       panic("vfs: can't subscribe to driver events");
+  unlock_pm();
+  thread_cleanup(fp);
+  return(NULL);
+}
+
+/*===========================================================================*
+ *                             lock_proc                                    *
+ *===========================================================================*/
+PUBLIC void lock_proc(struct fproc *rfp, int force_lock)
+{
+  int r;
+  message org_m_in;
+  struct fproc *org_fp;
+  struct worker_thread *org_self;
+
+  r = mutex_trylock(&rfp->fp_lock);
+
+  /* Were we supposed to obtain this lock immediately? */
+  if (force_lock) {
+       assert(r == 0);
+       return;
   }
 
-  SANITYCHECK;
+  if (r == 0) return;
 
-#if DO_SANITYCHECKS
-  FIXME("VFS: DO_SANITYCHECKS is on");
+  org_m_in = m_in;
+  org_fp = fp;
+  org_self = self;
+  if ((r = mutex_lock(&rfp->fp_lock)) != 0)
+       panic("unable to lock fproc lock: %d", r);
+  m_in = org_m_in;
+  fp = org_fp;
+  self = org_self;
+}
+
+/*===========================================================================*
+ *                             unlock_proc                                  *
+ *===========================================================================*/
+PUBLIC void unlock_proc(struct fproc *rfp)
+{
+  int r;
+
+  if ((r = mutex_unlock(&rfp->fp_lock)) != 0)
+       panic("Failed to unlock: %d", r);
+}
+
+/*===========================================================================*
+ *                             thread_cleanup                               *
+ *===========================================================================*/
+PRIVATE void thread_cleanup_f(struct fproc *rfp, char *f, int l)
+{
+/* Clean up worker thread. Skip parts if this thread is not associated
+ * with a particular process (i.e., rfp is NULL) */
+
+  assert(mthread_self() != -1);
+
+#if LOCK_DEBUG
+  if (rfp != NULL) {
+       check_filp_locks_by_me();
+       check_vnode_locks_by_me(rfp);
+       check_vmnt_locks_by_me(rfp);
+  }
 #endif
 
-  return(OK);
+  if (rfp != NULL && rfp->fp_flags & FP_PM_PENDING) {  /* Postponed PM call */
+       m_in = rfp->fp_job.j_m_in;
+       rfp->fp_flags &= ~FP_PM_PENDING;
+       service_pm_postponed();
+  }
+
+#if LOCK_DEBUG
+  if (rfp != NULL) {
+       check_filp_locks_by_me();
+       check_vnode_locks_by_me(rfp);
+       check_vmnt_locks_by_me(rfp);
+  }
+#endif
+
+  if (rfp != NULL) {
+       rfp->fp_flags &= ~FP_DROP_WORK;
+       unlock_proc(rfp);
+  }
+
+#if 0
+  mthread_exit(NULL);
+#endif
 }
 
 /*===========================================================================*
  *                             get_work                                     *
  *===========================================================================*/
 PRIVATE void get_work()
-{  
+{
   /* Normally wait for new input.  However, if 'reviving' is
    * nonzero, a suspended process must be awakened.
    */
-  int r, found_one, fd_nr;
-  struct filp *f;
+  int r, found_one, proc_p;
   register struct fproc *rp;
 
   while (reviving != 0) {
-       found_one= FALSE;
-
-       /* Revive a suspended process. */
-       for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) 
-               if (rp->fp_pid != PID_FREE && rp->fp_revived == REVIVING) {
-                       int blocked_on = rp->fp_blocked_on;
-                       found_one= TRUE;
-                       who_p = (int)(rp - fproc);
-                       who_e = rp->fp_endpoint;
-                       call_nr = rp->fp_block_callnr;
-
-                       m_in.fd = rp->fp_block_fd;
-                       m_in.buffer = rp->fp_buffer;
-                       m_in.nbytes = rp->fp_nbytes;
-                       /*no longer hanging*/
-                       rp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-                       rp->fp_revived = NOT_REVIVING;
-                       reviving--;
-                       /* This should be a pipe I/O, not a device I/O.
-                        * If it is, it'll 'leak' grants.
-                        */
-                       assert(!GRANT_VALID(rp->fp_grant));
-
-                       if (blocked_on == FP_BLOCKED_ON_PIPE)
-                       {
-                               fp= rp;
-                               fd_nr= rp->fp_block_fd;
-                               f= get_filp(fd_nr);
-                               assert(f != NULL);
-                               r= rw_pipe((call_nr == READ) ? READING :
-                                       WRITING, who_e, fd_nr, f,
-                                       rp->fp_buffer, rp->fp_nbytes);
-                               if (r != SUSPEND)
-                                       reply(who_e, r);
-                               continue;
-                       }
-
-                       return;
+       found_one = FALSE;
+
+       /* Find a suspended process. */
+       for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++)
+               if (rp->fp_pid != PID_FREE && (rp->fp_flags & FP_REVIVED)) {
+                       found_one = TRUE; /* Found a suspended process */
+                       if (unblock(rp))
+                               return; /* So main loop can process job */
+                       send_work();
                }
-       if (!found_one)
-               panic("get_work couldn't revive anyone");
+
+       if (!found_one) /* Consistency error */
+               panic("VFS: get_work couldn't revive anyone");
   }
 
   for(;;) {
-    int r;
-    /* Normal case.  No one to revive. */
-    if ((r=sef_receive(ANY, &m_in)) != OK)
-       panic("fs sef_receive error: %d", r);
-    who_e = m_in.m_source;
-    who_p = _ENDPOINT_P(who_e);
-
-    /* 
-     * negative who_p is never used to access the fproc array. Negative numbers
-     * (kernel tasks) are treated in a special way
-     */
-    if(who_p >= (int)(sizeof(fproc) / sizeof(struct fproc)))
-       panic("receive process out of range: %d", who_p);
-    if(who_p >= 0 && fproc[who_p].fp_endpoint == NONE) {
-       printf("FS: ignoring request from %d, endpointless slot %d (%d)\n",
-               m_in.m_source, who_p, m_in.m_type);
-       continue;
-    }
-    if(who_p >= 0 && fproc[who_p].fp_endpoint != who_e) {
-       if(fproc[who_p].fp_endpoint == NONE) { 
-               printf("slot unknown even\n");
+       /* Normal case.  No one to revive. Get a useful request. */
+       if ((r = sef_receive(receive_from, &m_in)) != OK) {
+               panic("VFS: sef_receive error: %d", r);
        }
-       printf("FS: receive endpoint inconsistent (source %d, who_p %d, stored ep %d, who_e %d).\n",
-               m_in.m_source, who_p, fproc[who_p].fp_endpoint, who_e);
-#if 0
-       panic("FS: inconsistent endpoint ");
-#endif
-       continue;
-    }
-    call_nr = m_in.m_type;
-    return;
+
+       proc_p = _ENDPOINT_P(m_in.m_source);
+       if (proc_p < 0) fp = NULL;
+       else fp = &fproc[proc_p];
+
+       if (m_in.m_type == EDEADSRCDST) return; /* Failed 'sendrec' */
+
+       /* Negative who_p is never used to access the fproc array. Negative
+        * numbers (kernel tasks) are treated in a special way.
+        */
+       if (who_p >= (int)(sizeof(fproc) / sizeof(struct fproc)))
+               panic("receive process out of range: %d", who_p);
+       if (who_p >= 0 && fproc[who_p].fp_endpoint == NONE) {
+               printf("VFS: ignoring request from %d, endpointless slot %d (%d)\n",
+                       m_in.m_source, who_p, m_in.m_type);
+               continue;
+       }
+
+       /* Internal consistency check; our mental image of process numbers and
+        * endpoints must match with how the rest of the system thinks of them.
+        */
+       if (who_p >= 0 && fproc[who_p].fp_endpoint != who_e) {
+               if (fproc[who_p].fp_endpoint == NONE)
+                       printf("slot unknown even\n");
+
+               printf("VFS: receive endpoint inconsistent (source %d, who_p "
+                       "%d, stored ep %d, who_e %d).\n", m_in.m_source, who_p,
+                       fproc[who_p].fp_endpoint, who_e);
+               panic("VFS: inconsistent endpoint ");
+       }
+
+       return;
   }
 }
 
@@ -418,87 +776,68 @@ int whom;                 /* process to reply to */
 int result;                    /* result of the call (usually OK or error #) */
 {
 /* Send a reply to a user process.  If the send fails, just ignore it. */
-  int s;
-
-#if 0
-  if (call_nr == SYMLINK)
-       printf("vfs:reply: replying %d for call %d\n", result, call_nr);
-#endif
+  int r;
 
   m_out.reply_type = result;
-  s = sendnb(whom, &m_out);
-  if (s != OK) printf("VFS: couldn't send reply %d to %d: %d\n",
-       result, whom, s);
+  r = sendnb(whom, &m_out);
+  if (r != OK) {
+       printf("VFS: couldn't send reply %d to %d: %d\n", result, whom, r);
+  }
 }
 
 /*===========================================================================*
- *                             init_root                                    *
+ *                             service_pm_postponed                         *
  *===========================================================================*/
-PRIVATE void init_root()
+PRIVATE void service_pm_postponed(void)
 {
-  int r = OK;
-  struct vmnt *vmp;
-  struct vnode *root_node;
-  struct dmap *dp;
-  char *label;
-  struct node_details res;
-  
-  /* Open the root device. */
-  root_dev = DEV_IMGRD;
-  ROOT_FS_E = MFS_PROC_NR;
-  
-  /* Initialize vmnt table */
-  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
-      vmp->m_dev = NO_DEV;
-  
-  vmp = &vmnt[0];
-  /* We'll need a vnode for the root inode, check whether there is one */
-  if ((root_node = get_free_vnode()) == NULL) 
-       panic("Cannot get free vnode: %d", r);
-
-  
-  /* Get driver process' endpoint */  
-  dp = &dmap[(root_dev >> MAJOR) & BYTE];
-  if (dp->dmap_driver == NONE) {
-       panic("No driver for root device: %d", r);
-  }
+  int r;
+  vir_bytes pc;
 
-  label= dp->dmap_label;
-  if (strlen(label) == 0)
-  {
-       panic("vfs:init_root: no label for major: %d", root_dev >> MAJOR);
-  }
+  switch(call_nr) {
+    case PM_EXEC:
+       r = pm_exec(m_in.PM_PROC, m_in.PM_PATH, m_in.PM_PATH_LEN,
+                   m_in.PM_FRAME, m_in.PM_FRAME_LEN, &pc);
 
-  /* Issue request */
-  r = req_readsuper(ROOT_FS_E, label, root_dev, 0 /*!readonly*/,
-       1 /*isroot*/, &res);
-  if (r != OK) {
-      panic("Cannot read superblock from root: %d", r);
+       /* Reply status to PM */
+       m_out.m_type = PM_EXEC_REPLY;
+       m_out.PM_PROC = m_in.PM_PROC;
+       m_out.PM_PC = (void*)pc;
+       m_out.PM_STATUS = r;
+
+       break;
+
+    case PM_EXIT:
+       pm_exit(m_in.PM_PROC);
+
+       /* Reply dummy status to PM for synchronization */
+       m_out.m_type = PM_EXIT_REPLY;
+       m_out.PM_PROC = m_in.PM_PROC;
+
+       break;
+
+    case PM_DUMPCORE:
+       /* Copy parameters first. m_in gets overwritten when creating core
+        * file.
+        */
+
+       r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG,
+                       (vir_bytes) m_in.PM_PATH);
+
+       /* Reply status to PM */
+       m_out.m_type = PM_CORE_REPLY;
+       m_out.PM_PROC = m_in.PM_PROC;
+       m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC;
+       m_out.PM_STATUS = r;
+
+       break;
+
+    default:
+       panic("Unhandled postponed PM call %d", m_in.m_type);
   }
-  
-  /* Fill in root node's fields */
-  root_node->v_fs_e = res.fs_e;
-  root_node->v_inode_nr = res.inode_nr;
-  root_node->v_mode = res.fmode;
-  root_node->v_size = res.fsize;
-  root_node->v_sdev = NO_DEV;
-  root_node->v_fs_count = 1;
-  root_node->v_ref_count = 1;
-
-  /* Fill in max file size and blocksize for the vmnt */
-  vmp->m_fs_e = res.fs_e;
-  vmp->m_dev = root_dev;
-  vmp->m_flags = 0;
-  
-  /* Root node is indeed on the partition */
-  root_node->v_vmnt = vmp;
-  root_node->v_dev = vmp->m_dev;
-
-  /* Root directory is not mounted on a vnode. */
-  vmp->m_mounted_on = NULL;
-  vmp->m_root_node = root_node;
-  strcpy(vmp->m_label, "fs_imgrd");    /* FIXME: obtain this from RS */
+
+  r = send(PM_PROC_NR, &m_out);
+  if (r != OK)
+       panic("service_pm_postponed: send failed: %d", r);
 }
 
 /*===========================================================================*
@@ -506,11 +845,10 @@ PRIVATE void init_root()
  *===========================================================================*/
 PRIVATE void service_pm()
 {
-  int r;
-  vir_bytes pc;
+  int r, slot;
 
   switch (call_nr) {
-  case PM_SETUID:
+    case PM_SETUID:
        pm_setuid(m_in.PM_PROC, m_in.PM_EID, m_in.PM_RID);
 
        m_out.m_type = PM_SETUID_REPLY;
@@ -518,7 +856,7 @@ PRIVATE void service_pm()
 
        break;
 
-  case PM_SETGID:
+    case PM_SETGID:
        pm_setgid(m_in.PM_PROC, m_in.PM_EID, m_in.PM_RID);
 
        m_out.m_type = PM_SETGID_REPLY;
@@ -526,7 +864,7 @@ PRIVATE void service_pm()
 
        break;
 
-  case PM_SETSID:
+    case PM_SETSID:
        pm_setsid(m_in.PM_PROC);
 
        m_out.m_type = PM_SETSID_REPLY;
@@ -534,40 +872,38 @@ PRIVATE void service_pm()
 
        break;
 
-  case PM_EXEC:
-       r = pm_exec(m_in.PM_PROC, m_in.PM_PATH, m_in.PM_PATH_LEN,
-                   m_in.PM_FRAME, m_in.PM_FRAME_LEN, &pc);
-
-       /* Reply status to PM */
-       m_out.m_type = PM_EXEC_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-       m_out.PM_PC = (void*)pc;
-       m_out.PM_STATUS = r;
-
-       break;
-
-  case PM_EXIT:
-       pm_exit(m_in.PM_PROC);
+    case PM_EXEC:
+    case PM_EXIT:
+    case PM_DUMPCORE:
+       okendpt(m_in.PM_PROC, &slot);
+       fp = &fproc[slot];
+
+       if (fp->fp_flags & FP_PENDING) {
+               /* This process has a request pending, but PM wants it gone.
+                * Forget about the pending request and satisfy PM's request
+                * instead. Note that a pending request AND an EXEC request
+                * are mutually exclusive. Also, PM should send only one
+                * request/process at a time.
+                */
+                assert(fp->fp_job.j_m_in.m_source != PM_PROC_NR);
+       }
 
-       /* Reply dummy status to PM for synchronization */
-       m_out.m_type = PM_EXIT_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
+        /* PM requests on behalf of a proc are handled after the system call
+         * that might be in progress for that proc has finished. If the proc
+         * is not busy, we start a dummy call */
+       if (!(fp->fp_flags & FP_PENDING) && mutex_trylock(&fp->fp_lock) == 0) {
+               mutex_unlock(&fp->fp_lock);
+               worker_start(do_dummy);
+               fp->fp_flags |= FP_DROP_WORK;
+        }
 
-       break;
+       fp->fp_job.j_m_in = m_in;
+       fp->fp_flags |= FP_PM_PENDING;
 
-  case PM_DUMPCORE:
-       r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG, m_in.PM_PATH);
-
-       /* Reply status to PM */
-       m_out.m_type = PM_CORE_REPLY;
-       m_out.PM_PROC = m_in.PM_PROC;
-       m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC;
-       m_out.PM_STATUS = r;
-       
-       break;
+       return;
 
-  case PM_FORK:
-  case PM_SRV_FORK:
+    case PM_FORK:
+    case PM_SRV_FORK:
        pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID);
        m_out.m_type = PM_FORK_REPLY;
 
@@ -580,15 +916,16 @@ PRIVATE void service_pm()
        m_out.PM_PROC = m_in.PM_PROC;
 
        break;
-  case PM_SETGROUPS:
-       pm_setgroups(m_in.PM_PROC, m_in.PM_GROUP_NO, (gid_t *) m_in.PM_GROUP_ADDR);
+    case PM_SETGROUPS:
+       pm_setgroups(m_in.PM_PROC, m_in.PM_GROUP_NO,
+                       (gid_t *) m_in.PM_GROUP_ADDR);
 
        m_out.m_type = PM_SETGROUPS_REPLY;
        m_out.PM_PROC = m_in.PM_PROC;
 
        break;
 
-  case PM_UNPAUSE:
+    case PM_UNPAUSE:
        unpause(m_in.PM_PROC);
 
        m_out.m_type = PM_UNPAUSE_REPLY;
@@ -596,7 +933,7 @@ PRIVATE void service_pm()
 
        break;
 
-  case PM_REBOOT:
+    case PM_REBOOT:
        pm_reboot();
 
        /* Reply dummy status to PM for synchronization */
@@ -604,8 +941,8 @@ PRIVATE void service_pm()
 
        break;
 
-  default:
-       printf("VFS: don't know how to handle PM request %x\n", call_nr);
+    default:
+       printf("VFS: don't know how to handle PM request %d\n", call_nr);
 
        return;
   }
@@ -616,3 +953,38 @@ PRIVATE void service_pm()
 
 }
 
+
+/*===========================================================================*
+ *                             unblock                                      *
+ *===========================================================================*/
+PRIVATE int unblock(rfp)
+struct fproc *rfp;
+{
+  int blocked_on;
+
+  fp = rfp;
+  blocked_on = rfp->fp_blocked_on;
+  m_in.m_type = rfp->fp_block_callnr;
+  m_in.fd = scratch(fp).file.fd_nr;
+  m_in.buffer = scratch(fp).io.io_buffer;
+  m_in.nbytes = scratch(fp).io.io_nbytes;
+
+  rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;     /* no longer blocked */
+  rfp->fp_flags &= ~FP_REVIVED;
+  reviving--;
+  assert(reviving >= 0);
+
+  /* This should be a pipe I/O, not a device I/O. If it is, it'll 'leak'
+   * grants.
+   */
+  assert(!GRANT_VALID(rfp->fp_grant));
+
+  /* Pending pipe reads/writes can be handled directly */
+  if (blocked_on == FP_BLOCKED_ON_PIPE) {
+       worker_start(do_pending_pipe);
+       yield();        /* Give thread a chance to run */
+       return(0);      /* Retrieve more work */
+  }
+
+  return(1);   /* We've unblocked a process */
+}
index 569b3220252afe3fbd507d79269bfae6510e131b..5497bf76e309d2869b91cfd71e051b0d9a7ff320 100644 (file)
@@ -7,7 +7,7 @@
  *   do_fcntl:   perform the FCNTL system call
  *   do_sync:    perform the SYNC system call
  *   do_fsync:   perform the FSYNC system call
- *   do_reboot:          sync disks and prepare for shutdown
+ *   pm_reboot:          sync disks and prepare for shutdown
  *   pm_fork:    adjust the tables after PM has performed a FORK system call
  *   do_exec:    handle files with FD_CLOEXEC on after PM has done an EXEC
  *   do_exit:    a process has exited; note that in the tables
 #include <sys/svrctl.h>
 #include "file.h"
 #include "fproc.h"
-#include "param.h"
+#include "scratchpad.h"
+#include "dmap.h"
 #include <minix/vfsif.h>
 #include "vnode.h"
 #include "vmnt.h"
+#include "param.h"
 
 #define CORE_NAME      "core"
 #define CORE_MODE      0777    /* mode to use on core image files */
@@ -46,7 +48,6 @@ PUBLIC unsigned long calls_stats[NCALLS];
 #endif
 
 FORWARD _PROTOTYPE( void free_proc, (struct fproc *freed, int flags)   );
-FORWARD _PROTOTYPE( void unmount_all, (void)                           );
 /*
 FORWARD _PROTOTYPE( int dumpcore, (int proc_e, struct mem_map *seg_ptr)        );
 FORWARD _PROTOTYPE( int write_bytes, (struct inode *rip, off_t off,
@@ -55,9 +56,6 @@ FORWARD _PROTOTYPE( int write_seg, (struct inode *rip, off_t off, int proc_e,
                        int seg, off_t seg_off, phys_bytes seg_bytes)   );
 */
 
-#define FP_EXITING     1
-
-
 /*===========================================================================*
  *                             do_getsysinfo                                *
  *===========================================================================*/
@@ -74,22 +72,22 @@ PUBLIC int do_getsysinfo()
   if (!super_user) return(EPERM);
 
   switch(m_in.SI_WHAT) {
-  case SI_PROC_TAB:
-       src_addr = (vir_bytes) fproc;
-       len = sizeof(struct fproc) * NR_PROCS;
-       break; 
-  case SI_DMAP_TAB:
-       src_addr = (vir_bytes) dmap;
-       len = sizeof(struct dmap) * NR_DEVICES;
-       break; 
+    case SI_PROC_TAB:
+       src_addr = (vir_bytes) fproc;
+       len = sizeof(struct fproc) * NR_PROCS;
+       break;
+    case SI_DMAP_TAB:
+       src_addr = (vir_bytes) dmap;
+       len = sizeof(struct dmap) * NR_DEVICES;
+       break;
 #if ENABLE_SYSCALL_STATS
-  case SI_CALL_STATS:
-       src_addr = (vir_bytes) calls_stats;
-       len = sizeof(calls_stats);
-       break; 
+    case SI_CALL_STATS:
+       src_addr = (vir_bytes) calls_stats;
+       len = sizeof(calls_stats);
+       break;
 #endif
-  default:
-       return(EINVAL);
+    default:
+       return(EINVAL);
   }
 
   if (len != m_in.SI_SIZE)
@@ -112,32 +110,42 @@ PUBLIC int do_dup()
 
   register int rfd;
   register struct filp *f;
-  struct filp *dummy;
-  int r;
+  int r = OK;
 
   /* Is the file descriptor valid? */
   rfd = m_in.fd & ~DUP_MASK;           /* kill off dup2 bit, if on */
-  if ((f = get_filp(rfd)) == NULL) return(err_code);
+  if ((f = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
 
   /* Distinguish between dup and dup2. */
   if (m_in.fd == rfd) {                        /* bit not on */
        /* dup(fd) */
-       if ((r = get_fd(0, 0, &m_in.fd2, &dummy)) != OK) return(r);
+       r = get_fd(0, 0, &m_in.fd2, NULL);
   } else {
-       /* dup2(fd, fd2) */
-       if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) return(EBADF);
-       if (rfd == m_in.fd2) return(m_in.fd2);  /* ignore the call: dup2(x, x) */
-       m_in.fd = m_in.fd2;             /* prepare to close fd2 */
-       (void) do_close();      /* cannot fail */
+       /* dup2(old_fd, new_fd) */
+       if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) {
+               r = EBADF;
+       } else if (rfd == m_in.fd2) {   /* ignore the call: dup2(x, x) */
+               r = m_in.fd2;
+       } else {
+               /* All is fine, close new_fd if necessary */
+               m_in.fd = m_in.fd2;     /* prepare to close fd2 */
+               unlock_filp(f);         /* or it might deadlock on do_close */
+               (void) do_close();      /* cannot fail */
+               f = get_filp(rfd, VNODE_READ); /* lock old_fd again */
+       }
   }
 
-  /* Success. Set up new file descriptors. */
-  f->filp_count++;
-  fp->fp_filp[m_in.fd2] = f;
-  FD_SET(m_in.fd2, &fp->fp_filp_inuse);
-  return(m_in.fd2);
-}
+  if (r == OK) {
+       /* Success. Set up new file descriptors. */
+       f->filp_count++;
+       fp->fp_filp[m_in.fd2] = f;
+       FD_SET(m_in.fd2, &fp->fp_filp_inuse);
+       r = m_in.fd2;
+  }
 
+  unlock_filp(f);
+  return(r);
+}
 
 /*===========================================================================*
  *                             do_fcntl                                     *
@@ -147,113 +155,131 @@ PUBLIC int do_fcntl()
 /* Perform the fcntl(fd, request, ...) system call. */
 
   register struct filp *f;
-  int new_fd, r, fl;
-  struct filp *dummy;
+  int new_fd, fl, r = OK;
+  tll_access_t locktype;
+
+  scratch(fp).file.fd_nr = m_in.fd;
+  scratch(fp).io.io_buffer = m_in.buffer;
+  scratch(fp).io.io_nbytes = m_in.nbytes;      /* a.k.a. m_in.request */
 
   /* Is the file descriptor valid? */
-  if ((f = get_filp(m_in.fd)) == NULL) return(err_code);
-  
+  locktype = (m_in.request == F_FREESP) ? VNODE_WRITE : VNODE_READ;
+  if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
+       return(err_code);
+
   switch (m_in.request) {
-     case F_DUPFD:
+    case F_DUPFD:
        /* This replaces the old dup() system call. */
-       if (m_in.addr < 0 || m_in.addr >= OPEN_MAX) return(EINVAL);
-       if ((r = get_fd(m_in.addr, 0, &new_fd, &dummy)) != OK) return(r);
-       f->filp_count++;
-       fp->fp_filp[new_fd] = f;
-       return(new_fd);
+       if (m_in.addr < 0 || m_in.addr >= OPEN_MAX) r = EINVAL;
+       else if ((r = get_fd(m_in.addr, 0, &new_fd, NULL)) == OK) {
+               f->filp_count++;
+               fp->fp_filp[new_fd] = f;
+               FD_SET(new_fd, &fp->fp_filp_inuse);
+               r = new_fd;
+       }
+       break;
 
-     case F_GETFD:
+    case F_GETFD:
        /* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
-       return( FD_ISSET(m_in.fd, &fp->fp_cloexec_set) ? FD_CLOEXEC : 0);
+       r = 0;
+       if (FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set))
+               r = FD_CLOEXEC;
+       break;
 
-     case F_SETFD:
+    case F_SETFD:
        /* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
        if(m_in.addr & FD_CLOEXEC)
-               FD_SET(m_in.fd, &fp->fp_cloexec_set);
+               FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
        else
-               FD_CLR(m_in.fd, &fp->fp_cloexec_set);
-       return(OK);
+               FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
+       break;
 
-     case F_GETFL:
+    case F_GETFL:
        /* Get file status flags (O_NONBLOCK and O_APPEND). */
        fl = f->filp_flags & (O_NONBLOCK | O_APPEND | O_ACCMODE);
-       return(fl);     
+       r = fl;
+       break;
 
-     case F_SETFL:
+    case F_SETFL:
        /* Set file status flags (O_NONBLOCK and O_APPEND). */
        fl = O_NONBLOCK | O_APPEND | O_REOPEN;
        f->filp_flags = (f->filp_flags & ~fl) | (m_in.addr & fl);
-       return(OK);
+       break;
 
-     case F_GETLK:
-     case F_SETLK:
-     case F_SETLKW:
+    case F_GETLK:
+    case F_SETLK:
+    case F_SETLKW:
        /* Set or clear a file lock. */
        r = lock_op(f, m_in.request);
-       return(r);
+       break;
 
-     case F_FREESP:
+    case F_FREESP:
      {
-       /* Free a section of a file. Preparation is done here, actual freeing
-        * in freesp_inode().
-        */
+       /* Free a section of a file */
        off_t start, end;
        struct flock flock_arg;
        signed long offset;
 
        /* Check if it's a regular file. */
-       if((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) return(EINVAL);
-       if (!(f->filp_mode & W_BIT)) return(EBADF);
+       if ((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) r = EINVAL;
+       else if (!(f->filp_mode & W_BIT)) r = EBADF;
+       else
+               /* Copy flock data from userspace. */
+               r = sys_datacopy(who_e, (vir_bytes) m_in.name1, SELF,
+                                (vir_bytes) &flock_arg,
+                                (phys_bytes) sizeof(flock_arg));
 
-       /* Copy flock data from userspace. */
-       if((r = sys_datacopy(who_e, (vir_bytes) m_in.name1, SELF, 
-            (vir_bytes) &flock_arg, (phys_bytes) sizeof(flock_arg))) != OK)
-               return(r);
+       if (r != OK) break;
 
        /* Convert starting offset to signed. */
        offset = (signed long) flock_arg.l_start;
 
        /* Figure out starting position base. */
        switch(flock_arg.l_whence) {
-          case SEEK_SET: start = 0; break;
-          case SEEK_CUR:
-             if (ex64hi(f->filp_pos) != 0) 
+         case SEEK_SET: start = 0; break;
+         case SEEK_CUR:
+               if (ex64hi(f->filp_pos) != 0)
                        panic("do_fcntl: position in file too high");
-             start = ex64lo(f->filp_pos);
-             break;
-          case SEEK_END: start = f->filp_vno->v_size; break;
-          default: return EINVAL;
+               start = ex64lo(f->filp_pos);
+               break;
+         case SEEK_END: start = f->filp_vno->v_size; break;
+         default: r = EINVAL;
        }
+       if (r != OK) break;
 
        /* Check for overflow or underflow. */
-       if(offset > 0 && start + offset < start) return EINVAL;
-       if(offset < 0 && start + offset > start) return EINVAL; 
-       start += offset;
-       if(start < 0) return EINVAL;
-
-       if(flock_arg.l_len != 0) {
-               if(start >= f->filp_vno->v_size) return EINVAL;
-               end = start + flock_arg.l_len;
-               if(end <= start) return EINVAL;
-               if(end > f->filp_vno->v_size) end = f->filp_vno->v_size;
+       if (offset > 0 && start + offset < start) r = EINVAL;
+       else if (offset < 0 && start + offset > start) r = EINVAL;
+       else {
+               start += offset;
+               if (start < 0) r = EINVAL;
+       }
+       if (r != OK) break;
+
+       if (flock_arg.l_len != 0) {
+               if (start >= f->filp_vno->v_size) r = EINVAL;
+               else if ((end = start + flock_arg.l_len) <= start) r = EINVAL;
+               else if (end > f->filp_vno->v_size) end = f->filp_vno->v_size;
        } else {
                 end = 0;
        }
+       if (r != OK) break;
 
-       r = req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr, start,
-               end);
+       r = req_ftrunc(f->filp_vno->v_fs_e, f->filp_vno->v_inode_nr,start,end);
 
-       if(r == OK && flock_arg.l_len == 0)
+       if (r == OK && flock_arg.l_len == 0)
                f->filp_vno->v_size = start;
 
-       return(r);
+       break;
      }
 
-     default:
-       return(EINVAL);
+    default:
+       r = EINVAL;
   }
-}
 
+  unlock_filp(f);
+  return(r);
+}
 
 /*===========================================================================*
  *                             do_sync                                      *
@@ -261,11 +287,19 @@ PUBLIC int do_fcntl()
 PUBLIC int do_sync()
 {
   struct vmnt *vmp;
-  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) 
-         if (vmp->m_dev != NO_DEV) 
-                  req_sync(vmp->m_fs_e);
+  int r = OK;
+
+  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
+       if (vmp->m_dev != NO_DEV && vmp->m_fs_e != NONE &&
+                vmp->m_root_node != NULL) {
+               if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK)
+                       break;
+               req_sync(vmp->m_fs_e);
+               unlock_vmnt(vmp);
+       }
+  }
 
-  return(OK);
+  return(r);
 }
 
 /*===========================================================================*
@@ -273,31 +307,28 @@ PUBLIC int do_sync()
  *===========================================================================*/
 PUBLIC int do_fsync()
 {
-/* Perform the fsync() system call. For now, don't be unnecessarily smart. */
-
-  do_sync();
-  return(OK);
-}
-
-/*===========================================================================*
- *                             unmount_all                                  *
- *===========================================================================*/
-PRIVATE void unmount_all(void)
-{
-/* Unmount all filesystems.  File systems are mounted on other file systems,
- * so you have to pull off the loose bits repeatedly to get it all undone.
- */
-
-  int i;
-  for (i= 0; i < NR_MNTS; i++) {
-       struct vmnt *vmp;
-
-       /* Unmount at least one. */
-       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
-               if (vmp->m_dev != NO_DEV) 
-                       unmount(vmp->m_dev, NULL);
+/* Perform the fsync() system call. */
+  struct filp *rfilp;
+  struct vmnt *vmp;
+  dev_t dev;
+  int r = OK;
+
+  if ((rfilp = get_filp(m_in.m1_i1, VNODE_READ)) == NULL) return(err_code);
+  dev = rfilp->filp_vno->v_dev;
+  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
+       if (vmp->m_dev != NO_DEV && vmp->m_dev == dev &&
+               vmp->m_fs_e != NONE && vmp->m_root_node != NULL) {
+
+               if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK)
+                       break;
+               req_sync(vmp->m_fs_e);
+               unlock_vmnt(vmp);
        }
   }
+
+  unlock_filp(rfilp);
+
+  return(r);
 }
 
 /*===========================================================================*
@@ -305,32 +336,29 @@ PRIVATE void unmount_all(void)
  *===========================================================================*/
 PUBLIC void pm_reboot()
 {
-  /* Perform the FS side of the reboot call. */
+  /* Perform the VFS side of the reboot call. */
   int i;
+  struct fproc *rfp;
 
   do_sync();
 
-  SANITYCHECK;
-
   /* Do exit processing for all leftover processes and servers,
    * but don't actually exit them (if they were really gone, PM
    * will tell us about it).
    */
-  for (i = 0; i < NR_PROCS; i++)
-       if((m_in.endpt1 = fproc[i].fp_endpoint) != NONE) {
-               /* No FP_EXITING, just free the resources, otherwise
-                * consistency check for fp_endpoint (set to NONE) will
-                * fail if process wants to do something in the (short)
-                * future.
-                */
-               free_proc(&fproc[i], 0);
-       }
-  SANITYCHECK;
+  for (i = 0; i < NR_PROCS; i++) {
+       rfp = &fproc[i];
+       if (rfp->fp_endpoint == NONE) continue;
+
+       /* Don't just free the proc right away, but let it finish what it was
+        * doing first */
+       lock_proc(rfp, 0);
+       free_proc(rfp, 0);
+       unlock_proc(rfp);
+  }
 
+  do_sync();
   unmount_all();
-
-  SANITYCHECK;
-
 }
 
 /*===========================================================================*
@@ -347,8 +375,9 @@ int cpid;   /* Child process id */
  * system uses the same slot numbers as the kernel.  Only PM makes this call.
  */
 
-  register struct fproc *cp;
+  register struct fproc *cp, *pp;
   int i, parentno, childno;
+  mutex_t c_fp_lock;
 
   /* Check up-to-dateness of fproc. */
   okendpt(pproc, &parentno);
@@ -358,17 +387,20 @@ int cpid; /* Child process id */
    * number is correct in fproc, which it won't be.
    */
   childno = _ENDPOINT_P(cproc);
-  if(childno < 0 || childno >= NR_PROCS)
-       panic("FS: bogus child for forking: %d", m_in.child_endpt);
-  if(fproc[childno].fp_pid != PID_FREE)
-       panic("FS: forking on top of in-use child: %d", childno);
+  if (childno < 0 || childno >= NR_PROCS)
+       panic("VFS: bogus child for forking: %d", m_in.child_endpt);
+  if (fproc[childno].fp_pid != PID_FREE)
+       panic("VFS: forking on top of in-use child: %d", childno);
 
   /* Copy the parent's fproc struct to the child. */
+  /* However, the mutex variables belong to a slot and must stay the same. */
+  c_fp_lock = fproc[childno].fp_lock;
   fproc[childno] = fproc[parentno];
+  fproc[childno].fp_lock = c_fp_lock;
 
   /* Increase the counters in the 'filp' table. */
   cp = &fproc[childno];
-  fp = &fproc[parentno];
+  pp = &fproc[parentno];
 
   for (i = 0; i < OPEN_MAX; i++)
        if (cp->fp_filp[i] != NULL) cp->fp_filp[i]->filp_count++;
@@ -377,27 +409,23 @@ int cpid; /* Child process id */
   cp->fp_pid = cpid;
   cp->fp_endpoint = cproc;
 
-  /* A forking process never has an outstanding grant,
-   * as it isn't blocking on i/o.
-   */
-  if(GRANT_VALID(fp->fp_grant)) {
-       printf("vfs: fork: fp (endpoint %d) has grant %d\n", fp->fp_endpoint, fp->fp_grant);
-       panic("fp contains valid grant");
+  /* A forking process never has an outstanding grant, as it isn't blocking on
+   * I/O. */
+  if(GRANT_VALID(pp->fp_grant)) {
+       panic("VFS: fork: pp (endpoint %d) has grant %d\n", pp->fp_endpoint,
+              pp->fp_grant);
   }
   if(GRANT_VALID(cp->fp_grant)) {
-       printf("vfs: fork: cp (endpoint %d) has grant %d\n", cp->fp_endpoint, cp->fp_grant);
-       panic("cp contains valid grant");
+       panic("VFS: fork: cp (endpoint %d) has grant %d\n", cp->fp_endpoint,
+              cp->fp_grant);
   }
 
-  /* A child is not a process leader. */
-  cp->fp_sesldr = 0;
-
-  /* This child has not exec()ced yet. */
-  cp->fp_execced = 0;
+  /* A child is not a process leader, not being revived, etc. */
+  cp->fp_flags = FP_NOFLAGS;
 
   /* Record the fact that both root and working dir have another user. */
-  if(cp->fp_rd) dup_vnode(cp->fp_rd);
-  if(cp->fp_wd) dup_vnode(cp->fp_wd);
+  if (cp->fp_rd) dup_vnode(cp->fp_rd);
+  if (cp->fp_wd) dup_vnode(cp->fp_wd);
 }
 
 /*===========================================================================*
@@ -411,56 +439,46 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
   register struct vnode *vp;
   dev_t dev;
 
- SANITYCHECK;
-
-  fp = exiter;         /* get_filp() needs 'fp' */
-
-  if(fp->fp_endpoint == NONE) {
+  if (exiter->fp_endpoint == NONE)
        panic("free_proc: already free");
-  }
-
-  if (fp_is_blocked(fp)) {
-       SANITYCHECK;
-       unpause(fp->fp_endpoint);
-       SANITYCHECK;
-  }
 
- SANITYCHECK;
+  if (fp_is_blocked(exiter))
+       unpause(exiter->fp_endpoint);
 
   /* Loop on file descriptors, closing any that are open. */
   for (i = 0; i < OPEN_MAX; i++) {
-       (void) close_fd(fp, i);
+       (void) close_fd(exiter, i);
   }
-  
+
+  /* Release root and working directories. */
+  if (exiter->fp_rd) { put_vnode(exiter->fp_rd); exiter->fp_rd = NULL; }
+  if (exiter->fp_wd) { put_vnode(exiter->fp_wd); exiter->fp_wd = NULL; }
+
+  /* The rest of these actions is only done when processes actually exit. */
+  if (!(flags & FP_EXITING)) return;
+
+  exiter->fp_flags |= FP_EXITING;
+
   /* Check if any process is SUSPENDed on this driver.
    * If a driver exits, unmap its entries in the dmap table.
    * (unmapping has to be done after the first step, because the
    * dmap table is used in the first step.)
    */
-  unsuspend_by_endpt(fp->fp_endpoint);
-
-  /* Release root and working directories. */
-  if(fp->fp_rd) { put_vnode(fp->fp_rd); fp->fp_rd = NULL; }
-  if(fp->fp_wd) { put_vnode(fp->fp_wd); fp->fp_wd = NULL; }
+  unsuspend_by_endpt(exiter->fp_endpoint);
+  dmap_unmap_by_endpt(exiter->fp_endpoint);
 
-  /* The rest of these actions is only done when processes actually
-   * exit.
-   */
-  if(!(flags & FP_EXITING)) {
-       SANITYCHECK;
-       return;
-  }
+  worker_stop_by_endpt(exiter->fp_endpoint); /* Unblock waiting threads */
+  vmnt_unmap_by_endpt(exiter->fp_endpoint); /* Invalidate open files if this
+                                            * was an active FS */
 
   /* Invalidate endpoint number for error and sanity checks. */
-  fp->fp_endpoint = NONE;
+  exiter->fp_endpoint = NONE;
 
-  /* If a session leader exits and it has a controlling tty, then revoke 
+  /* If a session leader exits and it has a controlling tty, then revoke
    * access to its controlling tty from all other processes using it.
    */
-  if (fp->fp_sesldr && fp->fp_tty != 0) {
-
-      dev = fp->fp_tty;
-
+  if ((exiter->fp_flags & FP_SESLDR) && exiter->fp_tty != 0) {
+      dev = exiter->fp_tty;
       for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
          if(rfp->fp_pid == PID_FREE) continue;
           if (rfp->fp_tty == dev) rfp->fp_tty = 0;
@@ -471,19 +489,21 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
                vp = rfilp->filp_vno;
                if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
                if ((dev_t) vp->v_sdev != dev) continue;
-
-               (void) dev_close(dev, rfilp-filp);
-               /* Ignore any errors, even SUSPEND. */
+               lock_filp(rfilp, VNODE_READ);
+               (void) dev_close(dev, rfilp-filp); /* Ignore any errors, even
+                                                   * SUSPEND. */
 
                rfilp->filp_mode = FILP_CLOSED;
+               unlock_filp(rfilp);
           }
       }
   }
 
   /* Exit done. Mark slot as free. */
-  fp->fp_pid = PID_FREE;
-
-  SANITYCHECK;
+  exiter->fp_pid = PID_FREE;
+  if (exiter->fp_flags & FP_PENDING)
+       pending--;      /* No longer pending job, not going to do it */
+  exiter->fp_flags = FP_NOFLAGS;
 }
 
 /*===========================================================================*
@@ -492,12 +512,13 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
 PUBLIC void pm_exit(proc)
 int proc;
 {
-  int exitee_p;
 /* Perform the file system portion of the exit(status) system call. */
+  int exitee_p;
 
   /* Nevertheless, pretend that the call came from the user. */
   okendpt(proc, &exitee_p);
-  free_proc(&fproc[exitee_p], FP_EXITING);
+  fp = &fproc[exitee_p];
+  free_proc(fp, FP_EXITING);
 }
 
 /*===========================================================================*
@@ -533,12 +554,12 @@ gid_t *groups;
   okendpt(proc_e, &slot);
   rfp = &fproc[slot];
   if (ngroups * sizeof(gid_t) > sizeof(rfp->fp_sgroups))
-       panic("VFS: pm_setgroups: too much data to copy");
-  if(sys_datacopy(who_e, (vir_bytes) groups, SELF, (vir_bytes) rfp->fp_sgroups,
-                  ngroups * sizeof(gid_t)) == OK) {
+       panic("VFS: pm_setgroups: too much data to copy");
+  if (sys_datacopy(who_e, (vir_bytes) groups, SELF, (vir_bytes) rfp->fp_sgroups,
+                  ngroups * sizeof(gid_t)) == OK) {
        rfp->fp_ngroups = ngroups;
   } else
-       panic("VFS: pm_setgroups: datacopy failed");
+       panic("VFS: pm_setgroups: datacopy failed");
 }
 
 
@@ -550,7 +571,7 @@ int proc_e;
 int euid;
 int ruid;
 {
-  register struct fproc *tfp;
+  struct fproc *tfp;
   int slot;
 
   okendpt(proc_e, &slot);
@@ -567,7 +588,7 @@ PUBLIC int do_svrctl()
 {
   switch (m_in.svrctl_req) {
   /* No control request implemented yet. */
-  default:
+    default:
        return(EINVAL);
   }
 }
@@ -575,44 +596,34 @@ PUBLIC int do_svrctl()
 /*===========================================================================*
  *                             pm_dumpcore                                  *
  *===========================================================================*/
-PUBLIC int pm_dumpcore(proc_e, csig, exe_name)
-int proc_e;
-int csig;
-char *exe_name;
+PUBLIC int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name)
 {
-  int proc_s, r, old_who_e;
-  int traced_proc_e = m_in.PM_TRACED_PROC;
-
-  okendpt(traced_proc_e, &proc_s);
-  fp = &fproc[proc_s];
-
-  /* Open the core file */
-  sprintf(user_fullpath, "%s.%d", CORE_NAME, fproc[proc_s].fp_pid);
-  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE);
-  if (r < 0) {
-       printf("VFS: Cannot open file to dump core\n");
-       return r;
-  }
-
-  old_who_e = who_e;
-  who_e = VFS_PROC_NR;
+  int slot, r, core_fd;
+  struct filp *f;
+  char core_path[PATH_MAX];
+  char proc_name[PROC_NAME_LEN];
 
-  /* Write the core file in ELF format */
-  write_elf_core_file(csig, exe_name);
+  okendpt(proc_e, &slot);
+  fp = &fproc[slot];
 
-  /* Close file */
-  close_fd(fp, r);
+  /* open core file */
+  snprintf(core_path, PATH_MAX, "%s.%d", CORE_NAME, fp->fp_pid);
+  core_fd = common_open(core_path, O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE);
+  if (core_fd < 0) return(core_fd);
 
-  /* Terminate the process */
-  if (traced_proc_e == proc_e)
-       free_proc(&fproc[proc_s], FP_EXITING);
+  /* get process' name */
+  r = sys_datacopy(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name,
+                       PROC_NAME_LEN);
+  if (r != OK) return(r);
+  proc_name[PROC_NAME_LEN - 1] = '\0';
 
-  /* Restore the important variables that have been overwritten */
-  m_in.PM_PROC = proc_e;
-  m_in.PM_TRACED_PROC = traced_proc_e;
-  who_e = old_who_e;
+  if ((f = get_filp(core_fd, VNODE_WRITE)) == NULL) return(EBADF);
+  write_elf_core_file(f, csig, proc_name);
+  unlock_filp(f);
+  (void) close_fd(fp, core_fd);        /* ignore failure, we're exiting anyway */
 
-  return OK;
+  free_proc(fp, FP_EXITING);
+  return(OK);
 }
 
 /*===========================================================================*
@@ -620,39 +631,33 @@ char *exe_name;
  *===========================================================================*/
 PUBLIC void ds_event(void)
 {
-       char key[DS_MAX_KEYLEN];
-       char *blkdrv_prefix = "drv.blk.";
-       char *chrdrv_prefix = "drv.chr.";
-       u32_t value;
-       int type;
-       endpoint_t owner_endpoint;
-       int r, is_blk;
-
-       /* Get the event and the owner from DS. */
-       r = ds_check(key, &type, &owner_endpoint);
-       if(r != OK) {
-               if(r != ENOENT)
-                       printf("vfs: ds_event: ds_check failed: %d\n", r);
-               return;
-       }
-
+  char key[DS_MAX_KEYLEN];
+  char *blkdrv_prefix = "drv.blk.";
+  char *chrdrv_prefix = "drv.chr.";
+  u32_t value;
+  int type, r, is_blk;
+  endpoint_t owner_endpoint;
+
+  /* Get the event and the owner from DS. */
+  while ((r = ds_check(key, &type, &owner_endpoint)) == OK) {
        /* Only check for block and character driver up events. */
        if (!strncmp(key, blkdrv_prefix, strlen(blkdrv_prefix))) {
                is_blk = TRUE;
        } else if (!strncmp(key, chrdrv_prefix, strlen(chrdrv_prefix))) {
                is_blk = FALSE;
        } else {
-               return;         /* neither block nor character driver */
+               continue;
        }
 
-       r = ds_retrieve_u32(key, &value);
-       if(r != OK) {
-               printf("vfs: ds_event: ds_retrieve_u32 failed\n");
+       if ((r = ds_retrieve_u32(key, &value)) != OK) {
+               printf("VFS: ds_event: ds_retrieve_u32 failed\n");
                return;
        }
-       if (value != DS_DRIVER_UP) return;
+       if (value != DS_DRIVER_UP) continue;
 
        /* Perform up. */
        dmap_endpt_up(owner_endpoint, is_blk);
-}
+  }
 
+  if (r != ENOENT) printf("VFS: ds_event: ds_check failed: %d\n", r);
+}
index 118568ef9304035203629dac508a5db1cba1b5fe..4e4666d5a509bee257384d8fbf9a2105b74e05bf 100644 (file)
@@ -1,7 +1,7 @@
 /* This file performs the MOUNT and UMOUNT system calls.
  *
  * The entry points into this file are
- *   do_fslogin:       perform the FSLOGIN system call
+ *   do_fsready:       perform the FS_READY system call
  *   do_mount:         perform the MOUNT system call
  *   do_umount:                perform the UMOUNT system call
  *   unmount:          unmount a file system
 #include <sys/stat.h>
 #include <sys/mount.h>
 #include <dirent.h>
+#include <assert.h>
 #include "file.h"
 #include "fproc.h"
-#include "param.h"
+#include "dmap.h"
 #include <minix/vfsif.h>
 #include "vnode.h"
 #include "vmnt.h"
+#include "path.h"
+#include "param.h"
 
 /* Allow the root to be replaced before the first 'real' mount. */
-PRIVATE int allow_newroot = 1;
+PRIVATE int have_root = 0;
 
 /* Bitmap of in-use "none" pseudo devices. */
 PRIVATE bitchunk_t nonedev[BITMAP_CHUNKS(NR_NONEDEVS)] = { 0 };
@@ -38,49 +41,75 @@ PRIVATE bitchunk_t nonedev[BITMAP_CHUNKS(NR_NONEDEVS)] = { 0 };
 #define alloc_nonedev(dev) SET_BIT(nonedev, minor(dev) - 1)
 #define free_nonedev(dev) UNSET_BIT(nonedev, minor(dev) - 1)
 
-FORWARD _PROTOTYPE( dev_t name_to_dev, (int allow_mountpt)             );
-FORWARD _PROTOTYPE( int mount_fs, (endpoint_t fs_e)                    );
-FORWARD _PROTOTYPE( int is_nonedev, (dev_t dev)                                );
+FORWARD _PROTOTYPE( dev_t name_to_dev, (int allow_mountpt,
+                                       char path[PATH_MAX])            );
 FORWARD _PROTOTYPE( dev_t find_free_nonedev, (void)                    );
+FORWARD _PROTOTYPE( void update_bspec, (dev_t dev, endpoint_t fs_e,
+                                     int send_drv_e)                   );
 
 /*===========================================================================*
  *                             update_bspec                                 *
  *===========================================================================*/
-PRIVATE void update_bspec(dev_t dev, endpoint_t fs_e)
+PRIVATE void update_bspec(dev_t dev, endpoint_t fs_e, int send_drv_e)
 {
 /* Update all block special files for a certain device, to use a new FS endpt
  * to route raw block I/O requests through.
  */
   struct vnode *vp;
+  struct dmap *dp;
+  int r, major;
 
   for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
-       if (vp->v_ref_count > 0 && S_ISBLK(vp->v_mode) && vp->v_sdev == dev)
+       if (vp->v_ref_count > 0 && S_ISBLK(vp->v_mode) && vp->v_sdev == dev) {
                vp->v_bfs_e = fs_e;
+               if (send_drv_e) {
+                       major = major(dev);
+                       if (major < 0 || major >= NR_DEVICES) {
+                               /* Can't update for out-of-range major */
+                               continue;
+                       }
+                       dp = &dmap[major(dev)];
+                       if (dp->dmap_driver == NONE) {
+                               /* Can't update for vanished driver */
+                               printf("VFS: can't send new driver label\n");
+                               continue;
+                       }
+
+                       if ((r = req_newdriver(fs_e, vp->v_sdev,
+                                       dp->dmap_label)) != OK) {
+                               printf("VFS: Failed to send new driver label"
+                                      " for moved block special file to %d\n",
+                                      fs_e);
+                       }
+               }
+       }
 }
 
-
 /*===========================================================================*
- *                              do_fslogin                                   *
+ *                              do_fsready                                   *
  *===========================================================================*/
-PUBLIC int do_fslogin()
+PUBLIC int do_fsready()
 {
   /* deprecated */
   return(SUSPEND);
 }
 
-
 /*===========================================================================*
  *                              do_mount                                     *
  *===========================================================================*/
 PUBLIC int do_mount()
 {
+/* Perform the mount(name, mfile, mount_flags) system call. */
   endpoint_t fs_e;
-  int r, proc_nr;
+  int r, slot, rdonly, nodev;
+  char fullpath[PATH_MAX];
+  char mount_label[LABEL_MAX];
+  dev_t dev;
 
   /* Only the super-user may do MOUNT. */
   if (!super_user) return(EPERM);
-       
-  /* FS process' endpoint number */ 
+
+  /* FS process' endpoint number */
   if (m_in.mount_flags & MS_LABEL16) {
        /* Get the label from the caller, and ask DS for the endpoint. */
        r = sys_datacopy(who_e, (vir_bytes) m_in.fs_label, SELF,
@@ -91,8 +120,6 @@ PUBLIC int do_mount()
 
        r = ds_retrieve_label_endpt(mount_label, &fs_e);
        if (r != OK) return(r);
-
-       if (isokendpt(fs_e, &proc_nr) != OK) return(EINVAL);
   } else {
        /* Legacy support: get the endpoint from the request itself. */
        fs_e = (endpoint_t) m_in.fs_label;
@@ -100,47 +127,18 @@ PUBLIC int do_mount()
   }
 
   /* Sanity check on process number. */
-  if(fs_e <= 0) {
-       printf("VFS: warning: got process number %d for mount call.\n", fs_e);
-       return EINVAL;
-  }
-
-  /* Do the actual job */
-  return mount_fs(fs_e);
-}
-
-
-/*===========================================================================*
- *                              mount                                        *
- *===========================================================================*/
-PRIVATE int mount_fs(endpoint_t fs_e)
-{
-/* Perform the mount(name, mfile, mount_flags) system call. */
-  int rdir, mdir;               /* TRUE iff {root|mount} file is dir */
-  int i, r, found, rdonly, nodev, isroot, replace_root;
-  struct fproc *tfp;
-  struct dmap *dp;
-  dev_t dev;
-  struct vnode *root_node, *vp = NULL, *bspec;
-  struct vmnt *vmp;
-  char *label;
-  struct node_details res;
+  if (isokendpt(fs_e, &slot) != OK) return(EINVAL);
 
-  /* Only the super-user may do MOUNT. */
-  if (!super_user) return(EPERM);
-
-  /* Clear endpoint field */
   /* Should the file system be mounted read-only? */
   rdonly = (m_in.mount_flags & MS_RDONLY);
 
   /* A null string for block special device means don't use a device at all. */
   nodev = (m_in.name1_length == 0);
-
   if (!nodev) {
        /* If 'name' is not for a block special file, return error. */
-       if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK)
+       if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
                return(err_code);
-       if ((dev = name_to_dev(FALSE /*allow_mountpt*/)) == NO_DEV)
+       if ((dev = name_to_dev(FALSE /*allow_mountpt*/, fullpath)) == NO_DEV)
                return(err_code);
   } else {
        /* Find a free pseudo-device as substitute for an actual device. */
@@ -148,124 +146,146 @@ PRIVATE int mount_fs(endpoint_t fs_e)
                return(err_code);
   }
 
-  /* Check whether there is a block special file open which uses the 
-   * same device (partition) */
-  for (bspec = &vnode[0]; bspec < &vnode[NR_VNODES]; ++bspec) {
-       if (bspec->v_ref_count > 0 && bspec->v_sdev == dev) {
-               /* Found, flush and invalidate any blocks for this device. */
-               req_flush(bspec->v_fs_e, dev);
-               break;
+  /* Fetch the name of the mountpoint */
+  if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
+       return(err_code);
+
+  /* Do the actual job */
+  return mount_fs(dev, fullpath, fs_e, rdonly, mount_label);
+}
+
+
+/*===========================================================================*
+ *                              mount_fs                                    *
+ *===========================================================================*/
+PUBLIC int mount_fs(
+dev_t dev,
+char mountpoint[PATH_MAX],
+endpoint_t fs_e,
+int rdonly,
+char mount_label[LABEL_MAX] )
+{
+  int rdir, mdir;               /* TRUE iff {root|mount} file is dir */
+  int i, r = OK, found, isroot, mount_root, con_reqs, slot;
+  struct fproc *tfp, *rfp;
+  struct dmap *dp;
+  struct vnode *root_node, *vp = NULL;
+  struct vmnt *new_vmp, *parent_vmp;
+  char *label;
+  struct node_details res;
+  struct lookup resolve;
+
+  /* Look up block device driver label when dev is not a pseudo-device */
+  label = "";
+  if (!is_nonedev(dev)) {
+       /* Get driver process' endpoint */
+       dp = &dmap[major(dev)];
+       if (dp->dmap_driver == NONE) {
+               printf("VFS: no driver for dev %d\n", dev);
+               return(EINVAL);
        }
+
+       label = dp->dmap_label;
+       assert(strlen(label) > 0);
   }
-  
+
   /* Scan vmnt table to see if dev already mounted. If not, find a free slot.*/
-  found = FALSE; 
-  vmp = NULL;
+  found = FALSE;
   for (i = 0; i < NR_MNTS; ++i) {
-         if (vmnt[i].m_dev == dev) {
-                 vmp = &vmnt[i];
-                 found = TRUE;
-                 break;
-         } else if (!vmp && vmnt[i].m_dev == NO_DEV) {
-                 vmp = &vmnt[i];
-         }
+       if (vmnt[i].m_dev == dev) found = TRUE;
   }
-
-  /* Partition was/is already mounted */
   if (found) {
-       /* It is possible that we have an old root lying around that 
-        * needs to be remounted. This could for example be a boot
-        * ramdisk that has already been replaced by the real root.
-        */
-       if(vmp->m_mounted_on || root_dev == vmp->m_dev) {
-               return(EBUSY);   /* not a root or still mounted */
-       }
-  
-       /* Now get the inode of the file to be mounted on. */
-       if (fetch_name(m_in.name2, m_in.name2_length, M1)!=OK) return(err_code);
-       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
-       if (vp->v_ref_count != 1) {
-               put_vnode(vp);
-               return(EBUSY);
-       }
-
-       /* Tell FS on which vnode it is mounted (glue into mount tree) */
-       if ((r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr)) == OK) {
-               root_node = vmp->m_root_node;
+       return(EBUSY);
+  } else if ((new_vmp = get_free_vmnt()) == NULL) {
+       return(ENOMEM);
+  }
 
-               /* File types of 'vp' and 'root_node' may not conflict. */
-               mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY);/* TRUE iff dir*/
-               rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
-               if(!mdir && rdir) r = EISDIR;
+  if ((r = lock_vmnt(new_vmp, VMNT_EXCL)) != OK) return(r);
+
+  isroot = (strcmp(mountpoint, "/") == 0);
+  mount_root = (isroot && have_root < 2); /* Root can be mounted twice:
+                                          * 1: ramdisk
+                                          * 2: boot disk (e.g., harddisk)
+                                          */
+
+  if (!mount_root) {
+       /* Get vnode of mountpoint */
+       lookup_init(&resolve, mountpoint, PATH_NOFLAGS, &parent_vmp, &vp);
+       resolve.l_vmnt_lock = VMNT_EXCL;
+       resolve.l_vnode_lock = VNODE_WRITE;
+       if ((vp = eat_path(&resolve, fp)) == NULL)
+               r = err_code;
+       else if (vp->v_ref_count == 1) {
+               /*Tell FS on which vnode it is mounted (glue into mount tree)*/
+               r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr);
+       } else
+               r = EBUSY;
+
+       if (vp != NULL) {
+               /* Quickly unlock to allow back calls (from e.g. FUSE) to
+                * relock */
+               unlock_vmnt(parent_vmp);
        }
 
        if (r != OK) {
-               put_vnode(vp);
+               if (vp != NULL) {
+                       unlock_vnode(vp);
+                       put_vnode(vp);
+               }
+               unlock_vmnt(new_vmp);
                return(r);
        }
-
-       /* Nothing else can go wrong.  Perform the mount. */
-       vmp->m_mounted_on = vp;
-       vmp->m_flags = rdonly;
-       strcpy(vmp->m_label, mount_label);
-       allow_newroot = 0;              /* The root is now fixed */
-       if (nodev) alloc_nonedev(dev);  /* Make the allocation final */
-       update_bspec(dev, fs_e);        /* Update open block-special files */
-
-       return(OK);
-  } else if (vmp == NULL) {
-       /* No free slot available, bail out */
-       return(ENOMEM);
   }
 
-  /* Fetch the name of the mountpoint */
-  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) return(err_code);
-  isroot = (strcmp(user_fullpath, "/") == 0);
-  replace_root = (isroot && allow_newroot);
-
-  if(!replace_root) {
-       /* Get vnode of mountpoint */
-       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
-
-       if (vp->v_ref_count != 1) {
+  /* We'll need a vnode for the root inode */
+  if ((root_node = get_free_vnode()) == NULL) {
+       if (vp != NULL) {
+               unlock_vnode(vp);
                put_vnode(vp);
-               return(EBUSY);
        }
+       unlock_vmnt(new_vmp);
+       return(err_code);
+  }
+  lock_vnode(root_node, VNODE_OPCL);
 
-       /* Tell FS on which vnode it is mounted (glue into mount tree) */
-       if ((r = req_mountpoint(vp->v_fs_e, vp->v_inode_nr)) != OK) {
+  /* Record process as a system process */
+  if (isokendpt(fs_e, &slot) != OK) {
+       if (vp != NULL) {
+               unlock_vnode(vp);
                put_vnode(vp);
-               return r;
        }
+       unlock_vnode(root_node);
+       unlock_vmnt(new_vmp);
+       return(EINVAL);
   }
+  rfp = &fproc[slot];
+  rfp->fp_flags |= FP_SYS_PROC;        /* Process is an FS */
 
-  /* We'll need a vnode for the root inode, check whether there is one */
-  if ((root_node = get_free_vnode()) == NULL) {
-       if (vp != NULL) put_vnode(vp);
-       return(ENFILE);
-  }
-
-  label = "";
-  if (!nodev) {
-       /* Get driver process' endpoint */
-       dp = &dmap[(dev >> MAJOR) & BYTE];
-       if (dp->dmap_driver == NONE) {
-               printf("VFS: no driver for dev %x\n", dev);
-               if (vp != NULL) put_vnode(vp);
-               return(EINVAL);
-       }
-
-       label = dp->dmap_label;
-       if (strlen(label) == 0)
-               panic("VFS mount_fs: no label for major: 0x%x", dev >> MAJOR);
-  }
+  /* Store some essential vmnt data first */
+  new_vmp->m_fs_e = fs_e;
+  new_vmp->m_dev = dev;
+  if (rdonly) new_vmp->m_flags |= VMNT_READONLY;
+  else new_vmp->m_flags &= ~VMNT_READONLY;
 
   /* Tell FS which device to mount */
-  if ((r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res)) != OK) {
-       if (vp != NULL) put_vnode(vp);
+  new_vmp->m_flags |= VMNT_MOUNTING;
+  r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res, &con_reqs);
+  new_vmp->m_flags &= ~VMNT_MOUNTING;
+
+  if (r != OK) {
+       new_vmp->m_fs_e = NONE;
+       new_vmp->m_dev = NO_DEV;
+       unlock_vnode(root_node);
+       if (vp != NULL) {
+               unlock_vnode(vp);
+               put_vnode(vp);
+       }
+       unlock_vmnt(new_vmp);
        return(r);
   }
 
+  lock_bsf();
+
   /* Fill in root node's fields */
   root_node->v_fs_e = res.fs_e;
   root_node->v_inode_nr = res.inode_nr;
@@ -276,46 +296,50 @@ PRIVATE int mount_fs(endpoint_t fs_e)
   root_node->v_sdev = NO_DEV;
   root_node->v_fs_count = 1;
   root_node->v_ref_count = 1;
-  
-  /* Fill in max file size and blocksize for the vmnt */
-  vmp->m_fs_e = res.fs_e;
-  vmp->m_dev = dev;
-  vmp->m_flags = rdonly;
-  
+
   /* Root node is indeed on the partition */
-  root_node->v_vmnt = vmp;
-  root_node->v_dev = vmp->m_dev;
-  
-  if(replace_root) {
-       /* Superblock and root node already read. 
+  root_node->v_vmnt = new_vmp;
+  root_node->v_dev = new_vmp->m_dev;
+  if (con_reqs == 0)
+       new_vmp->m_comm.c_max_reqs = 1; /* Default if FS doesn't tell us */
+  else
+       new_vmp->m_comm.c_max_reqs = con_reqs;
+  new_vmp->m_comm.c_cur_reqs = 0;
+
+  if (mount_root) {
+       /* Superblock and root node already read.
         * Nothing else can go wrong. Perform the mount. */
-       vmp->m_root_node = root_node;
-       vmp->m_mounted_on = NULL;
-       strcpy(vmp->m_label, mount_label);
-       if (nodev) alloc_nonedev(dev);
-       update_bspec(dev, fs_e);
+       new_vmp->m_root_node = root_node;
+       new_vmp->m_mounted_on = NULL;
+       strcpy(new_vmp->m_label, mount_label);
+       if (is_nonedev(dev)) alloc_nonedev(dev);
+       update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */);
 
-       root_dev = dev;
+       ROOT_DEV = dev;
        ROOT_FS_E = fs_e;
 
        /* Replace all root and working directories */
-       for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++) {
+       for (i = 0, tfp = fproc; i < NR_PROCS; i++, tfp++) {
                if (tfp->fp_pid == PID_FREE)
                        continue;
 
-#define MAKEROOT(what) {               \
-               put_vnode(what);        \
-               dup_vnode(root_node);   \
-               what = root_node;       \
-       }
+#define                MAKEROOT(what) {                        \
+                       if (what) put_vnode(what);      \
+                       dup_vnode(root_node);           \
+                       what = root_node;               \
+               }
 
-               if(tfp->fp_rd) MAKEROOT(tfp->fp_rd);
-               if(tfp->fp_wd) MAKEROOT(tfp->fp_wd);
+               MAKEROOT(tfp->fp_rd);
+               MAKEROOT(tfp->fp_wd);
        }
 
+       unlock_vnode(root_node);
+       unlock_vmnt(new_vmp);
+       have_root++; /* We have a (new) root */
+       unlock_bsf();
        return(OK);
   }
-  
+
   /* File types may not conflict. */
   mdir = ((vp->v_mode & I_TYPE) == I_DIRECTORY); /*TRUE iff dir*/
   rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
@@ -323,30 +347,66 @@ PRIVATE int mount_fs(endpoint_t fs_e)
 
   /* If error, return the super block and both inodes; release the vmnt. */
   if (r != OK) {
+       unlock_vnode(vp);
+       unlock_vnode(root_node);
+       unlock_vmnt(new_vmp);
        put_vnode(vp);
        put_vnode(root_node);
-       vmp->m_dev = NO_DEV;
+       new_vmp->m_dev = NO_DEV;
+       new_vmp->m_flags = 0;
+       unlock_bsf();
        return(r);
   }
 
   /* Nothing else can go wrong.  Perform the mount. */
-  vmp->m_mounted_on = vp;
-  vmp->m_root_node = root_node;
-  strcpy(vmp->m_label, mount_label);
-  
-  /* The root is now fixed */
-  allow_newroot = 0;
+  new_vmp->m_mounted_on = vp;
+  new_vmp->m_root_node = root_node;
+  strcpy(new_vmp->m_label, mount_label);
 
   /* Allocate the pseudo device that was found, if not using a real device. */
-  if (nodev) alloc_nonedev(dev);
+  if (is_nonedev(dev)) alloc_nonedev(dev);
 
   /* The new FS will handle block I/O requests for its device now. */
-  update_bspec(dev, fs_e);
+  if (!(new_vmp->m_flags & VMNT_FORCEROOTBSF))
+       update_bspec(dev, fs_e, 0 /* Don't send new driver endpoint */);
+
+  unlock_vnode(vp);
+  unlock_vnode(root_node);
+  unlock_vmnt(new_vmp);
+  unlock_bsf();
 
   return(OK);
 }
 
 
+/*===========================================================================*
+ *                             mount_pfs                                    *
+ *===========================================================================*/
+PUBLIC void mount_pfs(void)
+{
+/* Mount the Pipe File Server. It's not really mounted onto the file system,
+   but it's necessary it has a vmnt entry to make locking easier */
+
+  dev_t dev;
+  struct vmnt *vmp;
+  struct fproc *rfp;
+
+  if ((dev = find_free_nonedev()) == NO_DEV)
+       panic("VFS: no nonedev to initialize PFS");
+
+  if ((vmp = get_free_vmnt()) == NULL)
+       panic("VFS: no vmnt to initialize PFS");
+
+  alloc_nonedev(dev);
+
+  vmp->m_dev = dev;
+  vmp->m_fs_e = PFS_PROC_NR;
+  strcpy(vmp->m_label, "pfs");
+
+  rfp = &fproc[_ENDPOINT_P(PFS_PROC_NR)];
+  rfp->fp_flags |= FP_SYS_PROC;        /* PFS is a driver and an FS */
+}
+
 /*===========================================================================*
  *                              do_umount                                    *
  *===========================================================================*/
@@ -356,15 +416,18 @@ PUBLIC int do_umount(void)
   char label[LABEL_MAX];
   dev_t dev;
   int r;
-       
+  char fullpath[PATH_MAX];
+
   /* Only the super-user may do umount. */
   if (!super_user) return(EPERM);
-       
+
   /* If 'name' is not for a block special file or mountpoint, return error. */
-  if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  if((dev = name_to_dev(TRUE /*allow_mountpt*/)) == NO_DEV) return(err_code);
+  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
+       return(err_code);
+  if ((dev = name_to_dev(TRUE /*allow_mountpt*/, fullpath)) == NO_DEV)
+       return(err_code);
 
-  if((r = unmount(dev, label)) != OK) return(r);
+  if ((r = unmount(dev, label)) != OK) return(r);
 
   /* Return the label of the mounted file system, so that the caller
    * can shut down the corresponding server process.
@@ -386,11 +449,10 @@ PUBLIC int unmount(
 {
   struct vnode *vp;
   struct vmnt *vmp_i = NULL, *vmp = NULL;
-  struct dmap *dp;
-  int count, r;
-  
+  int count, locks, r;
+
   /* Find vmnt that is to be unmounted */
-  for(vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) {
+  for (vmp_i = &vmnt[0]; vmp_i < &vmnt[NR_MNTS]; ++vmp_i) {
          if (vmp_i->m_dev == dev) {
                  if(vmp) panic("device mounted more than once: %d", dev);
                  vmp = vmp_i;
@@ -399,15 +461,23 @@ PUBLIC int unmount(
 
   /* Did we find the vmnt (i.e., was dev a mounted device)? */
   if(!vmp) return(EINVAL);
-  
+
+  if ((r = lock_vmnt(vmp, VMNT_EXCL)) != OK) return(r);
+
   /* See if the mounted device is busy.  Only 1 vnode using it should be
    * open -- the root vnode -- and that inode only 1 time. */
-  count = 0;
-  for(vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++)
-         if(vp->v_ref_count > 0 && vp->v_dev == dev) count += vp->v_ref_count;
+  locks = count = 0;
+  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++)
+         if (vp->v_ref_count > 0 && vp->v_dev == dev) {
+               count += vp->v_ref_count;
+               if (is_vnode_locked(vp)) locks++;
+         }
+
+  if (count > 1 || locks > 1 || tll_haspendinglock(&vmp->m_lock)) {
+       unlock_vmnt(vmp);
+       return(EBUSY);    /* can't umount a busy file system */
+  }
 
-  if(count > 1) return(EBUSY);    /* can't umount a busy file system */
-  
   /* Tell FS to drop all inode references for root inode except 1. */
   vnode_clean_refs(vmp->m_root_node);
 
@@ -416,59 +486,69 @@ PUBLIC int unmount(
        vmp->m_mounted_on = NULL;
   }
 
-  /* Tell FS to unmount */
-  if(vmp->m_fs_e <= 0 || vmp->m_fs_e == NONE)
-       panic("unmount: strange fs endpoint: %d", vmp->m_fs_e);
+  vmp->m_comm.c_max_reqs = 1;  /* Force max concurrent reqs to just one, so
+                                * we won't send any messages after the
+                                * unmount request */
 
+  /* Tell FS to unmount */
   if ((r = req_unmount(vmp->m_fs_e)) != OK)              /* Not recoverable. */
-       printf("VFS: ignoring failed umount attempt (%d) fs pid: %d\n", r,
-                                               _ENDPOINT_P(vmp->m_fs_e));
-
-  if (is_nonedev(vmp->m_dev))
-       free_nonedev(vmp->m_dev);
-
-  if (label != NULL)
-       strcpy(label, vmp->m_label);
-  vmp->m_root_node->v_ref_count = 0;
-  vmp->m_root_node->v_fs_count = 0;
-  vmp->m_root_node->v_sdev = NO_DEV;
-  vmp->m_root_node = NULL;
+       printf("VFS: ignoring failed umount attempt FS endpoint: %d (%d)\n",
+              vmp->m_fs_e, r);
+
+  if (is_nonedev(vmp->m_dev)) free_nonedev(vmp->m_dev);
+
+  if (label != NULL) strcpy(label, vmp->m_label);
+
+  if (vmp->m_root_node) {      /* PFS lacks a root node */
+       vmp->m_root_node->v_ref_count = 0;
+       vmp->m_root_node->v_fs_count = 0;
+       vmp->m_root_node->v_sdev = NO_DEV;
+       vmp->m_root_node = NULL;
+  }
   vmp->m_dev = NO_DEV;
   vmp->m_fs_e = NONE;
-       
-  /* Is there a block special file that was handled by that partition? */
-  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
-       if(vp->v_ref_count > 0 && S_ISBLK(vp->v_mode) &&
-                       vp->v_bfs_e == vmp->m_fs_e) {
-
-               /* Get the driver endpoint of the block spec device */
-               dp = &dmap[(dev >> MAJOR) & BYTE];
-               if (dp->dmap_driver == NONE) {
-                       printf("VFS: driver not found for device %d\n", dev);
-                       continue;
-               }
 
-               printf("VFS: umount moving block spec %d to root FS\n", dev);
-               vp->v_bfs_e = ROOT_FS_E;
-                       
-               /* Send the driver label */
-               r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_label);
-               if (r != OK) 
-                       printf("VFS: error sending driver label for"
-                               " moved block spec to %d\n", vp->v_bfs_e);
-                 
-       }
-  }
-  
+  unlock_vmnt(vmp);
+
+  /* The root FS will handle block I/O requests for this device now. */
+  lock_bsf();
+  update_bspec(dev, ROOT_FS_E, 1 /* send new driver endpoint */);
+  unlock_bsf();
+
   return(OK);
 }
 
 
+/*===========================================================================*
+ *                             unmount_all                                  *
+ *===========================================================================*/
+PUBLIC void unmount_all(void)
+{
+/* Unmount all filesystems.  File systems are mounted on other file systems,
+ * so you have to pull off the loose bits repeatedly to get it all undone.
+ */
+
+  int i;
+  struct vmnt *vmp;
+
+  /* Now unmount the rest */
+  for (i = 0; i < NR_MNTS; i++) {
+       /* Unmount at least one. */
+       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
+               if (vmp->m_dev != NO_DEV)
+                       unmount(vmp->m_dev, NULL);
+       }
+  }
+  check_vnode_locks();
+  check_vmnt_locks();
+  check_filp_locks();
+  check_bsf_lock();
+}
+
 /*===========================================================================*
  *                              name_to_dev                                  *
  *===========================================================================*/
-PRIVATE dev_t name_to_dev(int allow_mountpt)
+PRIVATE dev_t name_to_dev(int allow_mountpt, char path[PATH_MAX])
 {
 /* Convert the block special file in 'user_fullpath' to a device number.
  * If the given path is not a block special file, but 'allow_mountpt' is set
@@ -477,21 +557,27 @@ PRIVATE dev_t name_to_dev(int allow_mountpt)
  */
   dev_t dev;
   struct vnode *vp;
-  
+  struct vmnt *vmp;
+  struct lookup resolve;
+
+  lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+
   /* Request lookup */
-  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) {
-       return(NO_DEV);
-  }
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(NO_DEV);
 
   if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL) {
        dev = vp->v_sdev;
   } else if (allow_mountpt && vp->v_vmnt->m_root_node == vp) {
        dev = vp->v_dev;
   } else {
-       err_code = ENOTBLK;
+       err_code = ENOTBLK;
        dev = NO_DEV;
   }
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
   put_vnode(vp);
   return(dev);
 }
@@ -500,7 +586,7 @@ PRIVATE dev_t name_to_dev(int allow_mountpt)
 /*===========================================================================*
  *                              is_nonedev                                  *
  *===========================================================================*/
-PRIVATE int is_nonedev(dev_t dev)
+PUBLIC int is_nonedev(dev_t dev)
 {
 /* Return whether the given device is a "none" pseudo device.
  */
index ae47d048e5c5b61637ed7796cb8743d66bb26733..a3fd9dc24c05b81b06ae60efb4060153ff59aa55 100644 (file)
@@ -8,6 +8,7 @@
  *   do_mkdir: perform the MKDIR system call
  *   do_close: perform the CLOSE system call
  *   do_lseek:  perform the LSEEK system call
+ *   do_llseek: perform the LLSEEK system call
  */
 
 #include "fs.h"
@@ -20,6 +21,8 @@
 #include <minix/u64.h>
 #include "file.h"
 #include "fproc.h"
+#include "scratchpad.h"
+#include "dmap.h"
 #include "lock.h"
 #include "param.h"
 #include <dirent.h>
 #include <minix/vfsif.h>
 #include "vnode.h"
 #include "vmnt.h"
+#include "path.h"
 
 PUBLIC char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
 
-FORWARD _PROTOTYPE( struct vnode *new_node, (int oflags, mode_t bits)          );
-FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
+FORWARD _PROTOTYPE( struct vnode *new_node, (struct lookup *resolve,
+                                            int oflags, mode_t bits)   );
+FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp, mode_t bits,
+                                   int oflags)                         );
 
 
 /*===========================================================================*
@@ -41,9 +47,11 @@ PUBLIC int do_creat()
 {
 /* Perform the creat(name, mode) system call. */
   int r;
+  char fullpath[PATH_MAX];
 
-  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
+  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
+       return(err_code);
+  r = common_open(fullpath, O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
   return(r);
 }
 
@@ -56,17 +64,18 @@ PUBLIC int do_open()
 /* Perform the open(name, flags,...) system call. */
   int create_mode = 0;         /* is really mode_t but this gives problems */
   int r;
+  char fullpath[PATH_MAX];
 
   /* If O_CREAT is set, open has three parameters, otherwise two. */
   if (m_in.mode & O_CREAT) {
-       create_mode = m_in.c_mode;      
-       r = fetch_name(m_in.c_name, m_in.name1_length, M1);
+       create_mode = m_in.c_mode;
+       r = fetch_name(m_in.c_name, m_in.name1_length, M1, fullpath);
   } else {
-       r = fetch_name(m_in.name, m_in.name_length, M3);
+       r = fetch_name(m_in.name, m_in.name_length, M3, fullpath);
   }
 
   if (r != OK) return(err_code); /* name was bad */
-  r = common_open(m_in.mode, create_mode);
+  r = common_open(fullpath, m_in.mode, create_mode);
   return(r);
 }
 
@@ -74,101 +83,143 @@ PUBLIC int do_open()
 /*===========================================================================*
  *                             common_open                                  *
  *===========================================================================*/
-PUBLIC int common_open(register int oflags, mode_t omode)
+PUBLIC int common_open(char path[PATH_MAX], int oflags, mode_t omode)
 {
 /* Common code from do_creat and do_open. */
-  int b, r, exist = TRUE;
+  int b, r, exist = TRUE, major_dev;
   dev_t dev;
   mode_t bits;
-  struct filp *fil_ptr, *filp2;
+  struct filp *filp, *filp2;
   struct vnode *vp;
   struct vmnt *vmp;
   struct dmap *dp;
+  struct lookup resolve;
 
   /* Remap the bottom two bits of oflags. */
   bits = (mode_t) mode_map[oflags & O_ACCMODE];
   if (!bits) return(EINVAL);
 
   /* See if file descriptor and filp slots are available. */
-  if ((r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);
+  if ((r = get_fd(0, bits, &(scratch(fp).file.fd_nr), &filp)) != OK) return(r);
+
+  lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp);
 
   /* If O_CREATE is set, try to make the file. */
   if (oflags & O_CREAT) {
         omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
-       vp = new_node(oflags, omode);
+       vp = new_node(&resolve, oflags, omode);
        r = err_code;
-       if (r == OK) exist = FALSE; /* We just created the file */
-       else if (r != EEXIST) return(r);  /* other error */ 
-       else exist = !(oflags & O_EXCL);  /* file exists, if the O_EXCL
-                                            flag is set this is an error */
+       if (r == OK) exist = FALSE;     /* We just created the file */
+       else if (r != EEXIST) {         /* other error */
+               if (vp) unlock_vnode(vp);
+               unlock_filp(filp);
+               return(r);
+       }
+       else exist = !(oflags & O_EXCL);/* file exists, if the O_EXCL
+                                          flag is set this is an error */
   } else {
        /* Scan path name */
-       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+       resolve.l_vmnt_lock = VMNT_READ;
+       resolve.l_vnode_lock = VNODE_OPCL;
+       if ((vp = eat_path(&resolve, fp)) == NULL) {
+               unlock_filp(filp);
+               return(err_code);
+       }
+
+       if (vmp != NULL) unlock_vmnt(vmp);
   }
 
   /* Claim the file descriptor and filp slot and fill them in. */
-  fp->fp_filp[m_in.fd] = fil_ptr;
-  FD_SET(m_in.fd, &fp->fp_filp_inuse);
-  fil_ptr->filp_count = 1;
-  fil_ptr->filp_vno = vp;
-  fil_ptr->filp_flags = oflags;
+  fp->fp_filp[scratch(fp).file.fd_nr] = filp;
+  FD_SET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse);
+  filp->filp_count = 1;
+  filp->filp_vno = vp;
+  filp->filp_flags = oflags;
 
   /* Only do the normal open code if we didn't just create the file. */
-  if(exist) {
+  if (exist) {
        /* Check protections. */
        if ((r = forbidden(fp, vp, bits)) == OK) {
                /* Opening reg. files, directories, and special files differ */
                switch (vp->v_mode & I_TYPE) {
                   case I_REGULAR:
-                       /* Truncate regular file if O_TRUNC. */
-                       if (oflags & O_TRUNC) {
-                               if ((r = forbidden(fp, vp, W_BIT)) != OK)
-                                       break;
-                               truncate_vnode(vp, 0);
-                       }
-                       break;
+                       /* Truncate regular file if O_TRUNC. */
+                       if (oflags & O_TRUNC) {
+                               if ((r = forbidden(fp, vp, W_BIT)) != OK)
+                                       break;
+                               truncate_vnode(vp, 0);
+                       }
+                       break;
                   case I_DIRECTORY:
-                       /* Directories may be read but not written. */
-                       r = (bits & W_BIT ? EISDIR : OK);
-                       break;
+                       /* Directories may be read but not written. */
+                       r = (bits & W_BIT ? EISDIR : OK);
+                       break;
                   case I_CHAR_SPECIAL:
                        /* Invoke the driver for special processing. */
                        dev = (dev_t) vp->v_sdev;
                        /* TTY needs to know about the O_NOCTTY flag. */
                        r = dev_open(dev, who_e, bits | (oflags & O_NOCTTY));
-                       if (r == SUSPEND) suspend(FP_BLOCKED_ON_DOPEN);
-                       break;
+                       if (r == SUSPEND) suspend(FP_BLOCKED_ON_DOPEN);
+                       else vp = filp->filp_vno; /* Might be updated by
+                                                  * dev_open/clone_opcl */
+                       break;
                   case I_BLOCK_SPECIAL:
+
+                       lock_bsf();
+
                        /* Invoke the driver for special processing. */
                        dev = (dev_t) vp->v_sdev;
                        r = bdev_open(dev, bits);
-                       if (r != OK) break;
+                       if (r != OK) {
+                               unlock_bsf();
+                               break;
+                       }
+
+                       major_dev = major(vp->v_sdev);
+                       dp = &dmap[major_dev];
+                       if (dp->dmap_driver == NONE) {
+                               printf("VFS: block driver disappeared!\n");
+                               unlock_bsf();
+                               r = ENXIO;
+                               break;
+                       }
 
                        /* Check whether the device is mounted or not. If so,
                         * then that FS is responsible for this device.
                         * Otherwise we default to ROOT_FS.
                         */
                        vp->v_bfs_e = ROOT_FS_E; /* By default */
-                       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) 
-                               if (vmp->m_dev == vp->v_sdev) 
+                       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
+                               if (vmp->m_dev == vp->v_sdev &&
+                                   !(vmp->m_flags & VMNT_FORCEROOTBSF)) {
                                        vp->v_bfs_e = vmp->m_fs_e;
+                               }
 
-                       /* Send the driver label to the file system (even when
-                        * known already).
+                       /* Send the driver label to the file system that will
+                        * handle the block I/O requests (even when its label
+                        * and endpoint are known already), but only when it is
+                        * the root file system. Other file systems will
+                        * already have it anyway.
                         */
-                       dp = &dmap[major(vp->v_sdev)];
-                       if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev,
-                                       dp->dmap_label)) != OK) {
+                       if (vp->v_bfs_e != ROOT_FS_E) {
+                               unlock_bsf();
+                               break;
+                       }
+
+                       if (req_newdriver(vp->v_bfs_e, vp->v_sdev,
+                                       dp->dmap_label) != OK) {
                                printf("VFS: error sending driver label\n");
                                bdev_close(dev);
                                r = ENXIO;
                        }
+                       unlock_bsf();
                        break;
 
                   case I_NAMED_PIPE:
                        /* Create a mapped inode on PFS which handles reads
                           and writes to this named pipe. */
-                       r = map_vnode(vp);
+                       tll_upgrade(&vp->v_lock);
+                       r = map_vnode(vp, PFS_PROC_NR);
                        if (r == OK) {
                                vp->v_pipe = I_PIPE;
                                if (vp->v_ref_count == 1) {
@@ -178,7 +229,7 @@ PUBLIC int common_open(register int oflags, mode_t omode)
                                                r = truncate_vnode(vp, 0);
                                }
                                oflags |= O_APPEND;     /* force append mode */
-                               fil_ptr->filp_flags = oflags;
+                               filp->filp_flags = oflags;
                        }
                        if (r == OK) {
                                r = pipe_open(vp, bits, oflags);
@@ -189,10 +240,10 @@ PUBLIC int common_open(register int oflags, mode_t omode)
                                 * file position will be automatically shared.
                                 */
                                b = (bits & R_BIT ? R_BIT : W_BIT);
-                               fil_ptr->filp_count = 0; /* don't find self */
+                               filp->filp_count = 0; /* don't find self */
                                if ((filp2 = find_filp(vp, b)) != NULL) {
                                        /* Co-reader or writer found. Use it.*/
-                                       fp->fp_filp[m_in.fd] = filp2;
+                                       fp->fp_filp[scratch(fp).file.fd_nr] = filp2;
                                        filp2->filp_count++;
                                        filp2->filp_vno = vp;
                                        filp2->filp_flags = oflags;
@@ -204,71 +255,105 @@ PUBLIC int common_open(register int oflags, mode_t omode)
                                         * existing filp entry.  Correct this
                                         * error.
                                         */
+                                       unlock_vnode(vp);
                                        put_vnode(vp);
                                } else {
                                        /* Nobody else found. Restore filp. */
-                                       fil_ptr->filp_count = 1;
+                                       filp->filp_count = 1;
                                }
-                       } 
+                       }
                        break;
                }
        }
   }
 
+  unlock_filp(filp);
+
   /* If error, release inode. */
   if (r != OK) {
-       if (r == SUSPEND) return(r);            /* Oops, just suspended */
-       fp->fp_filp[m_in.fd] = NULL;
-       FD_CLR(m_in.fd, &fp->fp_filp_inuse);
-       fil_ptr->filp_count= 0;
-       put_vnode(vp);     
-       fil_ptr->filp_vno = NULL;
-       return(r);
+       if (r != SUSPEND) {
+               fp->fp_filp[scratch(fp).file.fd_nr] = NULL;
+               FD_CLR(scratch(fp).file.fd_nr, &fp->fp_filp_inuse);
+               filp->filp_count = 0;
+               filp->filp_vno = NULL;
+               put_vnode(vp);
+       }
+  } else {
+       r = scratch(fp).file.fd_nr;
   }
-  
-  return(m_in.fd);
+
+  return(r);
 }
 
 
 /*===========================================================================*
  *                             new_node                                     *
  *===========================================================================*/
-PRIVATE struct vnode *new_node(int oflags, mode_t bits)
+PRIVATE struct vnode *new_node(struct lookup *resolve, int oflags, mode_t bits)
 {
 /* Try to create a new inode and return a pointer to it. If the inode already
    exists, return a pointer to it as well, but set err_code accordingly.
    NULL is returned if the path cannot be resolved up to the last
    directory, or when the inode cannot be created due to permissions or
-   otherwise. */ 
+   otherwise. */
   struct vnode *dirp, *vp;
-  int r, flags;
+  struct vmnt *dir_vmp, *vp_vmp;
+  int r;
   struct node_details res;
+  struct lookup findnode;
+  char *path;
+
+  path = resolve->l_path;      /* For easy access */
+
+  lookup_init(&findnode, path, resolve->l_flags, &dir_vmp, &dirp);
+  findnode.l_vmnt_lock = VMNT_WRITE;
+  findnode.l_vnode_lock = VNODE_WRITE; /* dir node */
 
   /* When O_CREAT and O_EXCL flags are set, the path may not be named by a
    * symbolic link. */
-  flags = PATH_NOFLAGS;
-  if (oflags & O_EXCL) flags |= PATH_RET_SYMLINK;
+  if (oflags & O_EXCL) findnode.l_flags |= PATH_RET_SYMLINK;
 
   /* See if the path can be opened down to the last directory. */
-  if ((dirp = last_dir(fp)) == NULL) return(NULL);
+  if ((dirp = last_dir(&findnode, fp)) == NULL) return(NULL);
 
   /* The final directory is accessible. Get final component of the path. */
-  vp = advance(dirp, flags, fp);
+  lookup_init(&findnode, findnode.l_path, findnode.l_flags, &vp_vmp, &vp);
+  findnode.l_vmnt_lock = VMNT_WRITE;
+  findnode.l_vnode_lock = (oflags & O_TRUNC) ? VNODE_WRITE : VNODE_OPCL;
+  vp = advance(dirp, &findnode, fp);
+  assert(vp_vmp == NULL);      /* Lookup to last dir should have yielded lock
+                                * on vmp or final component does not exist.
+                                * Either way, vp_vmp ought to be not set.
+                                */
 
   /* The combination of a symlink with absolute path followed by a danglink
    * symlink results in a new path that needs to be re-resolved entirely. */
-  if (user_fullpath[0] == '/') return new_node(oflags, bits);
+  if (path[0] == '/') {
+       unlock_vnode(dirp);
+       unlock_vmnt(dir_vmp);
+       put_vnode(dirp);
+       if (vp != NULL) {
+               unlock_vnode(vp);
+               put_vnode(vp);
+       }
+       return new_node(resolve, oflags, bits);
+  }
 
   if (vp == NULL && err_code == ENOENT) {
        /* Last path component does not exist. Make a new directory entry. */
        if ((vp = get_free_vnode()) == NULL) {
-               /* Can't create new vnode: out of vnodes. */
-               put_vnode(dirp);        
+               /* Can't create new entry: out of vnodes. */
+               unlock_vnode(dirp);
+               unlock_vmnt(dir_vmp);
+               put_vnode(dirp);
                return(NULL);
        }
+
+       lock_vnode(vp, VNODE_OPCL);
+
        if ((r = forbidden(fp, dirp, W_BIT|X_BIT)) != OK ||
            (r = req_create(dirp->v_fs_e, dirp->v_inode_nr,bits, fp->fp_effuid,
-                           fp->fp_effgid, user_fullpath, &res)) != OK ) {
+                           fp->fp_effgid, path, &res)) != OK ) {
                /* Can't create inode either due to permissions or some other
                 * problem. In case r is EEXIST, we might be dealing with a
                 * dangling symlink.*/
@@ -276,58 +361,74 @@ PRIVATE struct vnode *new_node(int oflags, mode_t bits)
                        struct vnode *slp, *old_wd;
 
                        /* Resolve path up to symlink */
-                       slp = advance(dirp, PATH_RET_SYMLINK, fp);
+                       findnode.l_flags = PATH_RET_SYMLINK;
+                       findnode.l_vnode_lock = VNODE_READ;
+                       findnode.l_vnode = &slp;
+                       slp = advance(dirp, &findnode, fp);
                        if (slp != NULL) {
                                if (S_ISLNK(slp->v_mode)) {
                                        /* Get contents of link */
 
-                                       int max_linklen;
-                                       max_linklen = sizeof(user_fullpath)-1;
                                        r = req_rdlink(slp->v_fs_e,
                                                       slp->v_inode_nr,
-                                                      VFS_PROC_NR,
-                                                      user_fullpath,
-                                                      max_linklen, 0);
+                                                      VFS_PROC_NR,
+                                                      path,
+                                                      PATH_MAX - 1, 0);
                                        if (r < 0) {
                                                /* Failed to read link */
+                                               unlock_vnode(slp);
+                                               unlock_vnode(dirp);
+                                               unlock_vmnt(dir_vmp);
                                                put_vnode(slp);
                                                put_vnode(dirp);
                                                err_code = r;
                                                return(NULL);
                                        }
-                                       user_fullpath[r] = '\0';/* Term. path*/
-                               } 
+                                       path[r] = '\0'; /* Terminate path */
+                               }
+                               unlock_vnode(slp);
                                put_vnode(slp);
                        }
 
                        /* Try to create the inode the dangling symlink was
                         * pointing to. We have to use dirp as starting point
                         * as there might be multiple successive symlinks
-                        * crossing multiple mountpoints. */
+                        * crossing multiple mountpoints.
+                        * Unlock vnodes and vmnts as we're going to recurse.
+                        */
+                       unlock_vnode(dirp);
+                       unlock_vnode(vp);
+                       unlock_vmnt(dir_vmp);
+
                        old_wd = fp->fp_wd; /* Save orig. working dirp */
                        fp->fp_wd = dirp;
-                       vp = new_node(oflags, bits);
+                       vp = new_node(resolve, oflags, bits);
                        fp->fp_wd = old_wd; /* Restore */
 
                        if (vp != NULL) {
                                put_vnode(dirp);
+                               *(resolve->l_vnode) = vp;
                                return(vp);
                        }
                        r = err_code;
-               } 
+               }
 
-               if (r == EEXIST) 
+               if (r == EEXIST)
                        err_code = EIO; /* Impossible, we have verified that
                                         * the last component doesn't exist and
                                         * is not a dangling symlink. */
                else
                        err_code = r;
 
+               unlock_vnode(dirp);
+               unlock_vnode(vp);
+               unlock_vmnt(dir_vmp);
                put_vnode(dirp);
                return(NULL);
        }
-       
+
        /* Store results and mark vnode in use */
+
        vp->v_fs_e = res.fs_e;
        vp->v_inode_nr = res.inode_nr;
        vp->v_mode = res.fmode;
@@ -340,16 +441,25 @@ PRIVATE struct vnode *new_node(int oflags, mode_t bits)
        vp->v_fs_count = 1;
        vp->v_ref_count = 1;
   } else {
-       /* Either last component exists, or there is some other problem. */
-       if (vp != NULL)
-               r = EEXIST;     /* File exists or a symlink names a file while
-                                * O_EXCL is set. */ 
-       else
+       /* Either last component exists, or there is some other problem. */
+       if (vp != NULL) {
+               r = EEXIST;     /* File exists or a symlink names a file while
+                                * O_EXCL is set. */
+       else
                r = err_code;   /* Other problem. */
   }
 
   err_code = r;
+  /* When dirp equals vp, we shouldn't release the lock as a vp is locked only
+   * once. Releasing the lock would cause the resulting vp not be locked and
+   * cause mayhem later on. */
+  if (dirp != vp) {
+       unlock_vnode(dirp);
+  }
+  unlock_vmnt(dir_vmp);
   put_vnode(dirp);
+
+  *(resolve->l_vnode) = vp;
   return(vp);
 }
 
@@ -357,8 +467,7 @@ PRIVATE struct vnode *new_node(int oflags, mode_t bits)
 /*===========================================================================*
  *                             pipe_open                                    *
  *===========================================================================*/
-PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
-       register int oflags)
+PRIVATE int pipe_open(struct vnode *vp, mode_t bits, int oflags)
 {
 /*  This function is called from common_open. It checks if
  *  there is at least one reader/writer pair for the pipe, if not
@@ -366,15 +475,18 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
  *  processes hanging on the pipe.
  */
 
-  vp->v_pipe = I_PIPE; 
+  vp->v_pipe = I_PIPE;
 
-  if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO);
+  if ((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) return(ENXIO);
 
-  if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NULL) { 
+  /* Find the reader/writer at the other end of the pipe */
+  if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NULL) {
+       /* Not found */
        if (oflags & O_NONBLOCK) {
                if (bits & W_BIT) return(ENXIO);
        } else {
-               suspend(FP_BLOCKED_ON_POPEN);   /* suspend caller */
+               /* Let's wait for the other side to show up */
+               suspend(FP_BLOCKED_ON_POPEN);
                return(SUSPEND);
        }
   } else if (susp_count > 0) { /* revive blocked processes */
@@ -394,32 +506,41 @@ PUBLIC int do_mknod()
   register mode_t bits, mode_bits;
   int r;
   struct vnode *vp;
-  
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_READ;
+
   /* Only the super_user may make nodes other than fifos. */
   mode_bits = (mode_t) m_in.mk_mode;           /* mode of the inode */
-  if(!super_user && (((mode_bits & I_TYPE) != I_NAMED_PIPE) && ((mode_bits & I_TYPE) != I_UNIX_SOCKET))) return(EPERM);
+  if (!super_user && (((mode_bits & I_TYPE) != I_NAMED_PIPE) &&
+      ((mode_bits & I_TYPE) != I_UNIX_SOCKET))) {
+       return(EPERM);
+  }
   bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
 
   /* Open directory that's going to hold the new node. */
-  if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if((vp = last_dir(fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+       return(err_code);
+  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
 
   /* Make sure that the object is a directory */
-  if((vp->v_mode & I_TYPE) != I_DIRECTORY) {
-         put_vnode(vp);
-         return(ENOTDIR);
-  }
-
-  if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
-       r = req_mknod(vp->v_fs_e, vp->v_inode_nr, user_fullpath, fp->fp_effuid,
+  if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
+       r = ENOTDIR;
+  } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
+       r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
                      fp->fp_effgid, bits, m_in.mk_z0);
   }
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
   put_vnode(vp);
   return(r);
 }
 
-
 /*===========================================================================*
  *                             do_mkdir                                     *
  *===========================================================================*/
@@ -429,30 +550,33 @@ PUBLIC int do_mkdir()
   mode_t bits;                 /* mode bits for the new inode */
   int r;
   struct vnode *vp;
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
 
-  if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_READ;
 
+  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+       return(err_code);
   bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
-
-  /* Request lookup */
-  if((vp = last_dir(fp)) == NULL) return(err_code);
+  if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
 
   /* Make sure that the object is a directory */
   if ((vp->v_mode & I_TYPE) != I_DIRECTORY) {
-         put_vnode(vp);
-         return(ENOTDIR);
-  }
-
-  if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
-       r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, user_fullpath, fp->fp_effuid,
+       r = ENOTDIR;
+  } else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
+       r = req_mkdir(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
                      fp->fp_effgid, bits);
   }
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
   put_vnode(vp);
   return(r);
 }
 
-
 /*===========================================================================*
  *                             do_lseek                                     *
  *===========================================================================*/
@@ -460,48 +584,55 @@ PUBLIC int do_lseek()
 {
 /* Perform the lseek(ls_fd, offset, whence) system call. */
   register struct filp *rfilp;
-  int r;
+  int r = OK;
   long offset;
   u64_t pos, newpos;
 
   /* Check to see if the file descriptor is valid. */
-  if ( (rfilp = get_filp(m_in.ls_fd)) == NULL) return(err_code);
+  if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code);
 
   /* No lseek on pipes. */
-  if (rfilp->filp_vno->v_pipe == I_PIPE) return(ESPIPE);
+  if (rfilp->filp_vno->v_pipe == I_PIPE) {
+       unlock_filp(rfilp);
+       return(ESPIPE);
+  }
 
   /* The value of 'whence' determines the start position to use. */
   switch(m_in.whence) {
-      case SEEK_SET: pos = cvu64(0);   break;
-      case SEEK_CUR: pos = rfilp->filp_pos;    break;
-      case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size);    break;
-      default: return(EINVAL);
+    case SEEK_SET: pos = cvu64(0);     break;
+    case SEEK_CUR: pos = rfilp->filp_pos;      break;
+    case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size);      break;
+    default: unlock_filp(rfilp); return(EINVAL);
   }
 
   offset = m_in.offset_lo;
   if (offset >= 0)
-       newpos= add64ul(pos, offset);
+       newpos = add64ul(pos, offset);
   else
-       newpos= sub64ul(pos, -offset);
+       newpos = sub64ul(pos, -offset);
 
   /* Check for overflow. */
-  if (ex64hi(newpos) != 0)
-       return(EINVAL);
-
-  if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
-      r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);
-      if (r != OK) return(r);
-  }
+  if (ex64hi(newpos) != 0) {
+       r = EOVERFLOW;
+  } else if ((off_t) ex64lo(newpos) < 0) { /* no negative file size */
+       r = EOVERFLOW;
+  } else {
+       rfilp->filp_pos = newpos;
 
-  rfilp->filp_pos = newpos;
+       /* insert the new position into the output message */
+       m_out.reply_l1 = ex64lo(newpos);
 
-  /* insert the new position into the output message */
-  m_out.reply_l1 = ex64lo(newpos);
+       if (cmp64(newpos, rfilp->filp_pos) != 0) {
+               /* Inhibit read ahead request */
+               r = req_inhibread(rfilp->filp_vno->v_fs_e,
+                                 rfilp->filp_vno->v_inode_nr);
+       }
+  }
 
-  return(OK);
+  unlock_filp(rfilp);
+  return(r);
 }
 
-
 /*===========================================================================*
  *                             do_llseek                                    *
  *===========================================================================*/
@@ -510,48 +641,57 @@ PUBLIC int do_llseek()
 /* Perform the llseek(ls_fd, offset, whence) system call. */
   register struct filp *rfilp;
   u64_t pos, newpos;
-  int r;
+  int r = OK;
 
   /* Check to see if the file descriptor is valid. */
-  if ( (rfilp = get_filp(m_in.ls_fd)) == NULL) return(err_code);
+  if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code);
 
   /* No lseek on pipes. */
-  if (rfilp->filp_vno->v_pipe == I_PIPE) return(ESPIPE);
+  if (rfilp->filp_vno->v_pipe == I_PIPE) {
+       unlock_filp(rfilp);
+       return(ESPIPE);
+  }
 
   /* The value of 'whence' determines the start position to use. */
   switch(m_in.whence) {
-      case SEEK_SET: pos = cvu64(0);   break;
-      case SEEK_CUR: pos = rfilp->filp_pos;    break;
-      case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size);    break;
-      default: return(EINVAL);
+    case SEEK_SET: pos = cvu64(0);     break;
+    case SEEK_CUR: pos = rfilp->filp_pos;      break;
+    case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size);      break;
+    default: unlock_filp(rfilp); return(EINVAL);
   }
 
   newpos = add64(pos, make64(m_in.offset_lo, m_in.offset_high));
 
   /* Check for overflow. */
-  if (((long)m_in.offset_high > 0) && cmp64(newpos, pos) < 0) 
-      return(EINVAL);
-  if (((long)m_in.offset_high < 0) && cmp64(newpos, pos) > 0) 
-      return(EINVAL);
-
-  if (cmp64(newpos, rfilp->filp_pos) != 0) { /* Inhibit read ahead request */
-      r = req_inhibread(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr);
-      if (r != OK) return(r);
+  if (( (long) m_in.offset_high > 0) && cmp64(newpos, pos) < 0)
+      r = EINVAL;
+  else if (( (long) m_in.offset_high < 0) && cmp64(newpos, pos) > 0)
+      r = EINVAL;
+  else {
+       rfilp->filp_pos = newpos;
+
+       /* insert the new position into the output message */
+       m_out.reply_l1 = ex64lo(newpos);
+       m_out.reply_l2 = ex64hi(newpos);
+
+       if (cmp64(newpos, rfilp->filp_pos) != 0) {
+               /* Inhibit read ahead request */
+               r = req_inhibread(rfilp->filp_vno->v_fs_e,
+                                 rfilp->filp_vno->v_inode_nr);
+       }
   }
 
-  rfilp->filp_pos = newpos;
-  m_out.reply_l1 = ex64lo(newpos);
-  m_out.reply_l2 = ex64hi(newpos);
-  return(OK);
+  unlock_filp(rfilp);
+  return(r);
 }
 
-
 /*===========================================================================*
  *                             do_close                                     *
  *===========================================================================*/
 PUBLIC int do_close()
 {
 /* Perform the close(fd) system call. */
+
   return close_fd(fp, m_in.fd);
 }
 
@@ -570,25 +710,28 @@ int fd_nr;
   int lock_count;
 
   /* First locate the vnode that belongs to the file descriptor. */
-  if ( (rfilp = get_filp2(rfp, fd_nr)) == NULL) return(err_code);
+  if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_OPCL)) == NULL) return(err_code);
   vp = rfilp->filp_vno;
-  close_filp(rfilp);
 
-  FD_CLR(fd_nr, &rfp->fp_cloexec_set);
+  close_filp(rfilp);
   rfp->fp_filp[fd_nr] = NULL;
+  FD_CLR(fd_nr, &rfp->fp_cloexec_set);
   FD_CLR(fd_nr, &rfp->fp_filp_inuse);
 
   /* Check to see if the file is locked.  If so, release all locks. */
-  if (nr_locks == 0) return(OK);
-  lock_count = nr_locks;       /* save count of locks */
-  for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
-       if (flp->lock_type == 0) continue;      /* slot not in use */
-       if (flp->lock_vnode == vp && flp->lock_pid == rfp->fp_pid) {
-               flp->lock_type = 0;
-               nr_locks--;
+  if (nr_locks > 0) {
+       lock_count = nr_locks;  /* save count of locks */
+       for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
+               if (flp->lock_type == 0) continue;      /* slot not in use */
+               if (flp->lock_vnode == vp && flp->lock_pid == rfp->fp_pid) {
+                       flp->lock_type = 0;
+                       nr_locks--;
+               }
        }
+       if (nr_locks < lock_count)
+               lock_revive();  /* one or more locks released */
   }
-  if (nr_locks < lock_count) lock_revive();    /* lock released */
+
   return(OK);
 }
 
@@ -599,4 +742,3 @@ PUBLIC void close_reply()
 {
        /* No need to do anything */
 }
-
index 77a27f830e8d689a347cd51cb7538166c2f765a5..ea05621bb2e701c455642fa85624e5400b224c31 100644 (file)
@@ -1,3 +1,6 @@
+#ifndef __VFS_PARAM_H__
+#define __VFS_PARAM_H__
+
 /* The following names are synonyms for the variables in the input message. */
 #define addr         m1_i3
 #define buffer       m1_p1
@@ -54,3 +57,5 @@
 #define reply_l2      m2_l2
 #define reply_i1      m1_i1
 #define reply_i2      m1_i2
+
+#endif
index 834ba6b2bcf897547a983f4666ba9745bd65aabf..a6945458faeca559152767569a9d6399f4504b5d 100644 (file)
@@ -1,4 +1,4 @@
-/* lookup() is the main routine that controls the path name lookup. It  
+/* lookup() is the main routine that controls the path name lookup. It
  * handles mountpoints and symbolic links. The actual lookup requests
  * are sent through the req_lookup wrapper function.
  */
 #include <sys/stat.h>
 #include <sys/un.h>
 #include <dirent.h>
-#include "fproc.h"
+#include "threads.h"
 #include "vmnt.h"
 #include "vnode.h"
+#include "path.h"
+#include "fproc.h"
 #include "param.h"
 
 /* Set to following define to 1 if you really want to use the POSIX definition
  */
 #define DO_POSIX_PATHNAME_RES  0
 
-FORWARD _PROTOTYPE( int lookup, (struct vnode *dirp, int flags,
+FORWARD _PROTOTYPE( int lookup, (struct vnode *dirp, struct lookup *resolve,
                                 node_details_t *node, struct fproc *rfp));
+FORWARD _PROTOTYPE( int check_perms, (endpoint_t ep, cp_grant_id_t io_gr,
+                                     size_t pathlen)                   );
 
 /*===========================================================================*
  *                             advance                                      *
  *===========================================================================*/
-PUBLIC struct vnode *advance(dirp, flags, rfp)
+PUBLIC struct vnode *advance(dirp, resolve, rfp)
 struct vnode *dirp;
-int flags;
+struct lookup *resolve;
 struct fproc *rfp;
 {
-/* Resolve a pathname (in user_fullpath) starting at dirp to a vnode. */
+/* Resolve a path name starting at dirp to a vnode. */
   int r;
+  int do_downgrade = 1;
   struct vnode *new_vp, *vp;
   struct vmnt *vmp;
   struct node_details res = {0,0,0,0,0,0,0};
+  tll_access_t initial_locktype;
 
   assert(dirp);
+  assert(resolve->l_vnode_lock != TLL_NONE);
+  assert(resolve->l_vmnt_lock != TLL_NONE);
+
+  if (resolve->l_vnode_lock == VNODE_READ)
+       initial_locktype = VNODE_OPCL;
+  else
+       initial_locktype = resolve->l_vnode_lock;
+
+  /* Get a free vnode and lock it */
+  if ((new_vp = get_free_vnode()) == NULL) return(NULL);
+  lock_vnode(new_vp, initial_locktype);
 
-  /* Get a free vnode */
-  if((new_vp = get_free_vnode()) == NULL) return(NULL);
-  
   /* Lookup vnode belonging to the file. */
-  if ((r = lookup(dirp, flags, &res, rfp)) != OK) {
+  if ((r = lookup(dirp, resolve, &res, rfp)) != OK) {
        err_code = r;
+       unlock_vnode(new_vp);
        return(NULL);
   }
-  
-  /* Check whether vnode is already in use or not */
+
+  /* Check whether we already have a vnode for that file */
   if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NULL) {
-         dup_vnode(vp);
-         vp->v_fs_count++;     /* We got a reference from the FS */
-         return(vp);
+       unlock_vnode(new_vp);   /* Don't need this anymore */
+       do_downgrade = (lock_vnode(vp, initial_locktype) != EBUSY);
+
+       /* Unfortunately, by the time we get the lock, another thread might've
+        * rid of the vnode (e.g., find_vnode found the vnode while a
+        * req_putnode was being processed). */
+       if (vp->v_ref_count == 0) { /* vnode vanished! */
+               /* As the lookup before increased the usage counters in the FS,
+                * we can simply set the usage counters to 1 and proceed as
+                * normal, because the putnode resulted in a use count of 1 in
+                * the FS. Other data is still valid, because the vnode was
+                * marked as pending lock, so get_free_vnode hasn't
+                * reinitialized the vnode yet. */
+               vp->v_fs_count = 1;
+               if (vp->v_mapfs_e != NONE) vp->v_mapfs_count = 1;
+       } else {
+               vp->v_fs_count++;       /* We got a reference from the FS */
+       }
+
+  } else {
+       /* Vnode not found, fill in the free vnode's fields */
+
+       new_vp->v_fs_e = res.fs_e;
+       new_vp->v_inode_nr = res.inode_nr;
+       new_vp->v_mode = res.fmode;
+       new_vp->v_size = res.fsize;
+       new_vp->v_uid = res.uid;
+       new_vp->v_gid = res.gid;
+       new_vp->v_sdev = res.dev;
+
+       if( (vmp = find_vmnt(new_vp->v_fs_e)) == NULL)
+                 panic("advance: vmnt not found");
+
+       new_vp->v_vmnt = vmp;
+       new_vp->v_dev = vmp->m_dev;
+       new_vp->v_fs_count = 1;
+
+       vp = new_vp;
   }
 
-  /* Fill in the free vnode's fields */
-  new_vp->v_fs_e = res.fs_e;
-  new_vp->v_inode_nr = res.inode_nr;
-  new_vp->v_mode = res.fmode;
-  new_vp->v_size = res.fsize;
-  new_vp->v_uid = res.uid;
-  new_vp->v_gid = res.gid;
-  new_vp->v_sdev = res.dev;
-  
-  if( (vmp = find_vmnt(new_vp->v_fs_e)) == NULL)
-         panic("VFS advance: vmnt not found");
-
-  new_vp->v_vmnt = vmp; 
-  new_vp->v_dev = vmp->m_dev;
-  new_vp->v_fs_count = 1;
-  new_vp->v_ref_count = 1;
-  
-  return(new_vp);
-}
+  dup_vnode(vp);
+  if (do_downgrade) {
+       /* Only downgrade a lock if we managed to lock it in the first place */
+       *(resolve->l_vnode) = vp;
+
+       if (initial_locktype != resolve->l_vnode_lock)
+               tll_downgrade(&vp->v_lock);
+
+#if LOCK_DEBUG
+       if (resolve->l_vnode_lock == VNODE_READ)
+               fp->fp_vp_rdlocks++;
+#endif
+  }
 
+  return(vp);
+}
 
 /*===========================================================================*
  *                             eat_path                                     *
  *===========================================================================*/
-PUBLIC struct vnode *eat_path(flags, rfp)
-int flags;
+PUBLIC struct vnode *eat_path(resolve, rfp)
+struct lookup *resolve;
 struct fproc *rfp;
 {
-/* Resolve 'user_fullpath' to a vnode. advance does the actual work. */
-  struct vnode *vp;
+/* Resolve path to a vnode. advance does the actual work. */
+  struct vnode *start_dir;
 
-  vp = (user_fullpath[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
-  return advance(vp, flags, rfp);
+  start_dir = (resolve->l_path[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
+  return advance(start_dir, resolve, rfp);
 }
 
-
 /*===========================================================================*
  *                             last_dir                                     *
  *===========================================================================*/
-PUBLIC struct vnode *last_dir(rfp)
+PUBLIC struct vnode *last_dir(resolve, rfp)
+struct lookup *resolve;
 struct fproc *rfp;
 {
-/* Parse a path, 'user_fullpath', as far as the last directory, fetch the vnode
+/* Parse a path, as far as the last directory, fetch the vnode
  * for the last directory into the vnode table, and return a pointer to the
  * vnode. In addition, return the final component of the path in 'string'. If
  * the last directory can't be opened, return NULL and the reason for
  * failure in 'err_code'. We can't parse component by component as that would
  * be too expensive. Alternatively, we cut off the last component of the path,
  * and parse the path up to the penultimate component.
- */  
+ */
 
   size_t len;
   char *cp;
   char dir_entry[NAME_MAX+1];
-  struct vnode *vp, *res;
-  
-  /* Is the path absolute or relative? Initialize 'vp' accordingly. */
-  vp = (user_fullpath[0] == '/' ? rfp->fp_rd : rfp->fp_wd);
+  struct vnode *start_dir, *res_vp, *sym_vp, *loop_start;
+  struct vmnt *sym_vmp = NULL;
+  int r, symloop = 0, ret_on_symlink = 0;
+  struct lookup symlink;
 
-  len = strlen(user_fullpath);
+  *resolve->l_vnode = NULL;
+  *resolve->l_vmp = NULL;
+  loop_start = NULL;
+  sym_vp = NULL;
 
-  /* If path is empty, return ENOENT. */
-  if (len == 0)        {
-       err_code = ENOENT;
-       return(NULL); 
-  }
+  ret_on_symlink = !!(resolve->l_flags & PATH_RET_SYMLINK);
+
+  do {
+       /* Is the path absolute or relative? Initialize 'start_dir'
+        * accordingly. Use loop_start in case we're looping.
+        */
+       if (loop_start != NULL)
+               start_dir = loop_start;
+       else
+               start_dir = (resolve->l_path[0] == '/' ? rfp->fp_rd:rfp->fp_wd);
+
+       len = strlen(resolve->l_path);
+
+       /* If path is empty, return ENOENT. */
+       if (len == 0)   {
+               err_code = ENOENT;
+               res_vp = NULL;
+               break;
+       }
 
 #if !DO_POSIX_PATHNAME_RES
-  /* Remove trailing slashes */
-  while (len > 1 && user_fullpath[len-1] == '/') {
-         len--;
-         user_fullpath[len]= '\0';
-  }
+       /* Remove trailing slashes */
+       while (len > 1 && resolve->l_path[len-1] == '/') {
+               len--;
+               resolve->l_path[len]= '\0';
+       }
 #endif
 
-  cp = strrchr(user_fullpath, '/');
-  if (cp == NULL) {
-         /* Just one entry in the current working directory */
-         dup_vnode(vp);
-         return(vp);
-  } else if (cp[1] == '\0') {
-         /* Path ends in a slash. The directory entry is '.' */
-         strcpy(dir_entry, ".");
-  } else {
-         /* A path name for the directory and a directory entry */
-         strncpy(dir_entry, cp+1, NAME_MAX);
-         cp[1]= '\0';
-         dir_entry[NAME_MAX] = '\0';
+       cp = strrchr(resolve->l_path, '/');
+       if (cp == NULL) {
+               /* Just an entry in the current working directory */
+               struct vmnt *vmp;
+
+               vmp = find_vmnt(start_dir->v_fs_e);
+               if (vmp == NULL) {
+                       r = EIO;
+                       res_vp = NULL;
+                       break;
+               }
+               r = lock_vmnt(vmp, resolve->l_vmnt_lock);
+               if (r == EDEADLK) {
+                       res_vp = NULL;
+                       break;
+               } else if (r == OK)
+                       *resolve->l_vmp = vmp;
+
+               lock_vnode(start_dir, resolve->l_vnode_lock);
+               *resolve->l_vnode = start_dir;
+               dup_vnode(start_dir);
+               if (loop_start != NULL) {
+                       unlock_vnode(loop_start);
+                       put_vnode(loop_start);
+               }
+               return(start_dir);
+       } else if (cp[1] == '\0') {
+               /* Path ends in a slash. The directory entry is '.' */
+               strcpy(dir_entry, ".");
+       } else {
+               /* A path name for the directory and a directory entry */
+               strncpy(dir_entry, cp+1, NAME_MAX);
+               cp[1] = '\0';
+               dir_entry[NAME_MAX] = '\0';
+       }
+
+       /* Remove trailing slashes */
+       while (cp > resolve->l_path && cp[0] == '/') {
+               cp[0]= '\0';
+               cp--;
+       }
+
+       /* Resolve up to and including the last directory of the path. Turn off
+        * PATH_RET_SYMLINK, because we do want to follow the symlink in this
+        * case. That is, the flag is meant for the actual filename of the path,
+        * not the last directory.
+        */
+       resolve->l_flags &= ~PATH_RET_SYMLINK;
+       if ((res_vp = advance(start_dir, resolve, rfp)) == NULL) {
+               break;
+       }
+
+       /* If the directory entry is not a symlink we're done now. If it is a
+        * symlink, then we're not at the last directory, yet. */
+
+       /* Copy the directory entry back to user_fullpath */
+       strncpy(resolve->l_path, dir_entry, NAME_MAX + 1);
+
+       /* Look up the directory entry, but do not follow the symlink when it
+        * is one.
+        */
+       lookup_init(&symlink, resolve->l_path,
+                   resolve->l_flags|PATH_RET_SYMLINK, &sym_vmp, &sym_vp);
+       symlink.l_vnode_lock = VNODE_READ;
+       symlink.l_vmnt_lock = VMNT_READ;
+       sym_vp = advance(res_vp, &symlink, rfp);
+
+       /* Advance caused us to either switch to a different vmnt or we're
+        * still at the same vmnt. The former might've yielded a new vmnt lock,
+        * the latter should not have. Verify. */
+       if (sym_vmp != NULL) {
+               /* We got a vmnt lock, so the endpoints of the vnodes must
+                * differ.
+                */
+               assert(sym_vp->v_fs_e != res_vp->v_fs_e);
+       }
+
+       if (sym_vp != NULL && S_ISLNK(sym_vp->v_mode)) {
+               /* Last component is a symlink, but if we've been asked to not
+                * resolve it, return now.
+                */
+               if (ret_on_symlink) {
+                       break;
+               }
+
+               r = req_rdlink(sym_vp->v_fs_e, sym_vp->v_inode_nr, NONE,
+                               resolve->l_path, PATH_MAX - 1, 1);
+
+               if (r < 0) {
+                       /* Failed to read link */
+                       err_code = r;
+                       unlock_vnode(res_vp);
+                       unlock_vmnt(*resolve->l_vmp);
+                       put_vnode(res_vp);
+                       *resolve->l_vmp = NULL;
+                       *resolve->l_vnode = NULL;
+                       res_vp = NULL;
+                       break;
+               }
+               resolve->l_path[r] = '\0';
+
+               if (strrchr(resolve->l_path, '/') != NULL) {
+                       unlock_vnode(sym_vp);
+                       unlock_vmnt(*resolve->l_vmp);
+                       if (sym_vmp != NULL)
+                               unlock_vmnt(sym_vmp);
+                       *resolve->l_vmp = NULL;
+                       put_vnode(sym_vp);
+                       sym_vp = NULL;
+
+                       symloop++;
+
+                       /* Relative symlinks are relative to res_vp, not cwd */
+                       if (resolve->l_path[0] != '/') {
+                               loop_start = res_vp;
+                       } else {
+                               /* Absolute symlink, forget about res_vp */
+                               unlock_vnode(res_vp);
+                               put_vnode(res_vp);
+                       }
+
+                       continue;
+               }
+       }
+       break;
+  } while (symloop < SYMLOOP_MAX);
+
+  if (symloop >= SYMLOOP_MAX) {
+       err_code = ELOOP;
+       res_vp = NULL;
   }
 
-  /* Remove trailing slashes */
-  while(cp > user_fullpath && cp[0] == '/') {
-         cp[0]= '\0';
-         cp--;
+  if (sym_vp != NULL) {
+       unlock_vnode(sym_vp);
+       if (sym_vmp != NULL) {
+               unlock_vmnt(sym_vmp);
+       }
+       put_vnode(sym_vp);
   }
 
-  res = advance(vp, PATH_NOFLAGS, rfp);
-  if (res == NULL) return(NULL);
+  if (loop_start != NULL) {
+       unlock_vnode(loop_start);
+       put_vnode(loop_start);
+  }
 
   /* Copy the directory entry back to user_fullpath */
-  strncpy(user_fullpath, dir_entry, NAME_MAX);
-  
-  return(res);
+  strncpy(resolve->l_path, dir_entry, NAME_MAX + 1);
+  return(res_vp);
 }
 
-
 /*===========================================================================*
  *                             lookup                                       *
  *===========================================================================*/
-PRIVATE int lookup(start_node, flags, node, rfp)
+PRIVATE int lookup(start_node, resolve, result_node, rfp)
 struct vnode *start_node;
-int flags;
-node_details_t *node;
+struct lookup *resolve;
+node_details_t *result_node;
 struct fproc *rfp;
 {
-/* Resolve a pathname (in user_fullpath) relative to start_node. */
+/* Resolve a path name relative to start_node. */
 
   int r, symloop;
   endpoint_t fs_e;
@@ -190,62 +372,86 @@ struct fproc *rfp;
   uid_t uid;
   gid_t gid;
   struct vnode *dir_vp;
-  struct vmnt *vmp;
+  struct vmnt *vmp, *vmpres;
   struct lookup_res res;
 
+  assert(resolve->l_vmp);
+  assert(resolve->l_vnode);
+
+  *(resolve->l_vmp) = vmpres = NULL; /* No vmnt found nor locked yet */
+
   /* Empty (start) path? */
-  if (user_fullpath[0] == '\0') {
-       node->inode_nr = 0;
+  if (resolve->l_path[0] == '\0') {
+       result_node->inode_nr = 0;
        return(ENOENT);
   }
 
-  if(!rfp->fp_rd || !rfp->fp_wd) {
-       printf("VFS: lookup_rel %d: no rd/wd\n", rfp->fp_endpoint);
+  if (!rfp->fp_rd || !rfp->fp_wd) {
+       printf("VFS: lookup %d: no rd/wd\n", rfp->fp_endpoint);
        return(ENOENT);
   }
 
   fs_e = start_node->v_fs_e;
   dir_ino = start_node->v_inode_nr;
+  vmpres = find_vmnt(fs_e);
+
+  if (vmpres == NULL) return(EIO);     /* mountpoint vanished? */
+
   /* Is the process' root directory on the same partition?,
    * if so, set the chroot directory too. */
   if (rfp->fp_rd->v_dev == rfp->fp_wd->v_dev)
-       root_ino = rfp->fp_rd->v_inode_nr; 
+       root_ino = rfp->fp_rd->v_inode_nr;
   else
        root_ino = 0;
 
   /* Set user and group ids according to the system call */
-  uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid); 
-  gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid); 
+  uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid);
+  gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid);
 
   symloop = 0; /* Number of symlinks seen so far */
 
+  /* Lock vmnt */
+  if ((r = lock_vmnt(vmpres, resolve->l_vmnt_lock)) != OK) {
+       if (r == EBUSY) /* vmnt already locked */
+               vmpres = NULL;
+       else
+               return(r);
+  }
+  *(resolve->l_vmp) = vmpres;
+
   /* Issue the request */
-  r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res, rfp);
+  r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, resolve, &res, rfp);
 
-  if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
+  if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK) {
+       if (vmpres) unlock_vmnt(vmpres);
+       *(resolve->l_vmp) = NULL;
        return(r); /* i.e., an error occured */
+  }
 
-  /* While the response is related to mount control set the 
+  /* While the response is related to mount control set the
    * new requests respectively */
-  while(r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
+  while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
        /* Update user_fullpath to reflect what's left to be parsed. */
        path_off = res.char_processed;
-       path_left_len = strlen(&user_fullpath[path_off]);
-       memmove(user_fullpath, &user_fullpath[path_off], path_left_len);
-       user_fullpath[path_left_len] = '\0'; /* terminate string */ 
+       path_left_len = strlen(&resolve->l_path[path_off]);
+       memmove(resolve->l_path, &resolve->l_path[path_off], path_left_len);
+       resolve->l_path[path_left_len] = '\0'; /* terminate string */
 
        /* Update the current value of the symloop counter */
        symloop += res.symloop;
-       if (symloop > SYMLOOP_MAX)
+       if (symloop > SYMLOOP_MAX) {
+               if (vmpres) unlock_vmnt(vmpres);
+               *(resolve->l_vmp) = NULL;
                return(ELOOP);
+       }
 
        /* Symlink encountered with absolute path */
        if (r == ESYMLINK) {
                dir_vp = rfp->fp_rd;
+               vmp = NULL;
        } else if (r == EENTERMOUNT) {
                /* Entering a new partition */
-               dir_vp = 0;
+               dir_vp = NULL;
                /* Start node is now the mounted partition's root node */
                for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
                        if (vmp->m_dev != NO_DEV && vmp->m_mounted_on) {
@@ -256,22 +462,29 @@ struct fproc *rfp;
                           }
                        }
                }
-               assert(dir_vp);
+               if (dir_vp == NULL) {
+                       printf("VFS: path lookup error; root node not found\n");
+                       if (vmpres) unlock_vmnt(vmpres);
+                       *(resolve->l_vmp) = NULL;
+                       return(EIO);
+               }
        } else {
                /* Climbing up mount */
                /* Find the vmnt that represents the partition on
                 * which we "climb up". */
                if ((vmp = find_vmnt(res.fs_e)) == NULL) {
                        panic("VFS lookup: can't find parent vmnt");
-               }         
+               }
 
                /* Make sure that the child FS does not feed a bogus path
                 * to the parent FS. That is, when we climb up the tree, we
                 * must've encountered ".." in the path, and that is exactly
                 * what we're going to feed to the parent */
-               if(strncmp(user_fullpath, "..", 2) != 0 ||
-                       (user_fullpath[2] != '\0' && user_fullpath[2] != '/')) {
-                       printf("VFS: bogus path: %s\n", user_fullpath);
+               if(strncmp(resolve->l_path, "..", 2) != 0 ||
+                  (resolve->l_path[2] != '\0' && resolve->l_path[2] != '/')) {
+                       printf("VFS: bogus path: %s\n", resolve->l_path);
+                       if (vmpres) unlock_vmnt(vmpres);
+                       *(resolve->l_vmp) = NULL;
                        return(ENOENT);
                }
 
@@ -286,29 +499,67 @@ struct fproc *rfp;
 
        /* Is the process' root directory on the same partition?,
         * if so, set the chroot directory too. */
-       if(dir_vp->v_dev == rfp->fp_rd->v_dev)
-               root_ino = rfp->fp_rd->v_inode_nr; 
+       if (dir_vp->v_dev == rfp->fp_rd->v_dev)
+               root_ino = rfp->fp_rd->v_inode_nr;
        else
                root_ino = 0;
 
-       r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, flags, &res, rfp);
+       /* Unlock a previously locked vmnt if locked and lock new vmnt */
+       if (vmpres) unlock_vmnt(vmpres);
+       vmpres = find_vmnt(fs_e);
+       if (vmpres == NULL) return(EIO);        /* mount point vanished? */
+       if ((r = lock_vmnt(vmpres, resolve->l_vmnt_lock)) != OK) {
+               if (r == EBUSY)
+                       vmpres = NULL;  /* Already locked */
+               else
+                       return(r);
+       }
+       *(resolve->l_vmp) = vmpres;
+
+       r = req_lookup(fs_e, dir_ino, root_ino, uid, gid, resolve, &res, rfp);
 
-       if(r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK)
+       if (r != OK && r != EENTERMOUNT && r != ELEAVEMOUNT && r != ESYMLINK) {
+               if (vmpres) unlock_vmnt(vmpres);
+               *(resolve->l_vmp) = NULL;
                return(r);
+       }
   }
 
   /* Fill in response fields */
-  node->inode_nr = res.inode_nr;
-  node->fmode = res.fmode;
-  node->fsize = res.fsize;
-  node->dev = res.dev;
-  node->fs_e = res.fs_e;
-  node->uid = res.uid;
-  node->gid = res.gid;
-  
+  result_node->inode_nr = res.inode_nr;
+  result_node->fmode = res.fmode;
+  result_node->fsize = res.fsize;
+  result_node->dev = res.dev;
+  result_node->fs_e = res.fs_e;
+  result_node->uid = res.uid;
+  result_node->gid = res.gid;
+
   return(r);
 }
 
+/*===========================================================================*
+ *                             lookup_init                                  *
+ *===========================================================================*/
+PUBLIC void lookup_init(resolve, path, flags, vmp, vp)
+struct lookup *resolve;
+char *path;
+int flags;
+struct vmnt **vmp;
+struct vnode **vp;
+{
+  assert(vmp != NULL);
+  assert(vp != NULL);
+
+  resolve->l_path = path;
+  resolve->l_flags = flags;
+  resolve->l_vmp = vmp;
+  resolve->l_vnode = vp;
+  resolve->l_vmnt_lock = TLL_NONE;
+  resolve->l_vnode_lock = TLL_NONE;
+  *vmp = NULL; /* Initialize lookup result to NULL */
+  *vp = NULL;
+}
+
 /*===========================================================================*
  *                             get_name                                     *
  *===========================================================================*/
@@ -329,8 +580,8 @@ char ename[NAME_MAX + 1];
   }
 
   do {
-       r = req_getdents(dirp->v_fs_e, dirp->v_inode_nr, pos, 
-                                               buf, sizeof(buf), &new_pos, 1);
+       r = req_getdents(dirp->v_fs_e, dirp->v_inode_nr, pos, buf, sizeof(buf),
+                        &new_pos, 1);
 
        if (r == 0) {
                return(ENOENT); /* end of entries -- matching inode !found */
@@ -361,108 +612,143 @@ char ename[NAME_MAX + 1];
 /*===========================================================================*
  *                             canonical_path                               *
  *===========================================================================*/
-PUBLIC int canonical_path(orig_path, canon_path, rfp)
-char *orig_path;
-char *canon_path; /* should have length PATH_MAX */
+PUBLIC int canonical_path(orig_path, rfp)
+char orig_path[PATH_MAX];
 struct fproc *rfp;
 {
+/* Find canonical path of a given path */
   int len = 0;
   int r, symloop = 0;
   struct vnode *dir_vp, *parent_dir;
-  char component[NAME_MAX+1];
-  char link_path[PATH_MAX];
+  struct vmnt *dir_vmp, *parent_vmp;
+  char component[NAME_MAX+1];  /* NAME_MAX does /not/ include '\0' */
+  char temp_path[PATH_MAX];
+  struct lookup resolve;
 
   dir_vp = NULL;
-  orig_path[PATH_MAX - 1] = '\0';
-  strncpy(user_fullpath, orig_path, PATH_MAX);
+  strncpy(temp_path, orig_path, PATH_MAX);
+  temp_path[PATH_MAX - 1] = '\0';
 
+  /* First resolve path to the last directory holding the file */
   do {
-       if (dir_vp) put_vnode(dir_vp);
-
-       /* Resolve to the last directory holding the socket file */
-       if ((dir_vp = last_dir(rfp)) == NULL) {
-               return(err_code);
+       if (dir_vp) {
+               unlock_vnode(dir_vp);
+               unlock_vmnt(dir_vmp);
+               put_vnode(dir_vp);
        }
 
-       /* dir_vp points to dir and user_fullpath now contains only the
+       lookup_init(&resolve, temp_path, PATH_NOFLAGS, &dir_vmp, &dir_vp);
+       resolve.l_vmnt_lock = VMNT_READ;
+       resolve.l_vnode_lock = VNODE_READ;
+       if ((dir_vp = last_dir(&resolve, rfp)) == NULL) return(err_code);
+
+       /* dir_vp points to dir and resolve path now contains only the
         * filename.
         */
-       strcpy(canon_path, user_fullpath); /* Store file name */
+       strncpy(orig_path, temp_path, NAME_MAX);        /* Store file name */
 
        /* check if the file is a symlink, if so resolve it */
-       r = rdlink_direct(canon_path, link_path, rfp);
-       if (r <= 0) {
-               strcpy(user_fullpath, canon_path);
+       r = rdlink_direct(orig_path, temp_path, rfp);
+
+       if (r <= 0)
                break;
-       }
 
        /* encountered a symlink -- loop again */
-       strcpy(user_fullpath, link_path);
-
+       strncpy(orig_path, temp_path, PATH_MAX - 1);
        symloop++;
   } while (symloop < SYMLOOP_MAX);
 
   if (symloop >= SYMLOOP_MAX) {
-       if (dir_vp) put_vnode(dir_vp);
-       return ELOOP;
+       if (dir_vp) {
+               unlock_vnode(dir_vp);
+               unlock_vmnt(dir_vmp);
+               put_vnode(dir_vp);
+       }
+       return(ELOOP);
   }
 
-  while(dir_vp != rfp->fp_rd) {
+  /* We've got the filename and the actual directory holding the file. From
+   * here we start building up the canonical path by climbing up the tree */
+  while (dir_vp != rfp->fp_rd) {
 
-       strcpy(user_fullpath, "..");
+       strcpy(temp_path, "..");
 
        /* check if we're at the root node of the file system */
        if (dir_vp->v_vmnt->m_root_node == dir_vp) {
+               unlock_vnode(dir_vp);
+               unlock_vmnt(dir_vmp);
                put_vnode(dir_vp);
                dir_vp = dir_vp->v_vmnt->m_mounted_on;
+               dir_vmp = dir_vp->v_vmnt;
+               if (lock_vmnt(dir_vmp, VMNT_READ) != OK)
+                       panic("failed to lock vmnt");
+               if (lock_vnode(dir_vp, VNODE_READ) != OK)
+                       panic("failed to lock vnode");
                dup_vnode(dir_vp);
        }
 
-       if ((parent_dir = advance(dir_vp, PATH_NOFLAGS, rfp)) == NULL) {
+       lookup_init(&resolve, temp_path, PATH_NOFLAGS, &parent_vmp,
+                   &parent_dir);
+       resolve.l_vmnt_lock = VMNT_READ;
+       resolve.l_vnode_lock = VNODE_READ;
+
+       if ((parent_dir = advance(dir_vp, &resolve, rfp)) == NULL) {
+               unlock_vnode(dir_vp);
+               unlock_vmnt(dir_vmp);
                put_vnode(dir_vp);
                return(err_code);
        }
 
        /* now we have to retrieve the name of the parent directory */
        if (get_name(parent_dir, dir_vp, component) != OK) {
-               put_vnode(dir_vp);
+               unlock_vnode(parent_dir);
+               unlock_vmnt(parent_vmp);
+               unlock_vnode(dir_vp);
+               unlock_vmnt(dir_vmp);
                put_vnode(parent_dir);
+               put_vnode(dir_vp);
                return(ENOENT);
        }
 
        len += strlen(component) + 1;
        if (len >= PATH_MAX) {
-               /* adding the component to canon_path would exceed PATH_MAX */
-               put_vnode(dir_vp);
+               /* adding the component to orig_path would exceed PATH_MAX */
+               unlock_vnode(parent_dir);
+               unlock_vmnt(parent_vmp);
+               unlock_vnode(dir_vp);
+               unlock_vmnt(dir_vmp);
                put_vnode(parent_dir);
+               put_vnode(dir_vp);
                return(ENOMEM);
        }
 
-       /* store result of component in canon_path */
-
-       /* first make space by moving the contents of canon_path to
-        * the right. Move strlen + 1 bytes to include the terminating '\0'.
+       /* Store result of component in orig_path. First make space by moving
+        * the contents of orig_path to the right. Move strlen + 1 bytes to
+        * include the terminating '\0'. Move to strlen + 1 bytes to reserve
+        * space for the slash.
         */
-       memmove(canon_path+strlen(component)+1, canon_path, 
-                                               strlen(canon_path) + 1);
-
+       memmove(orig_path+strlen(component)+1, orig_path, strlen(orig_path)+1);
        /* Copy component into canon_path */
-       memmove(canon_path, component, strlen(component));
-
+       memmove(orig_path, component, strlen(component));
        /* Put slash into place */
-       canon_path[strlen(component)] = '/';
+       orig_path[strlen(component)] = '/';
 
        /* Store parent_dir result, and continue the loop once more */
+       unlock_vnode(dir_vp);
+       unlock_vmnt(dir_vmp);
        put_vnode(dir_vp);
        dir_vp = parent_dir;
   }
 
+  unlock_vnode(dir_vp);
+  unlock_vmnt(parent_vmp);
+
   put_vnode(dir_vp);
 
   /* add the leading slash */
-  if (strlen(canon_path) >= PATH_MAX) return(ENAMETOOLONG);
-  memmove(canon_path+1, canon_path, strlen(canon_path));
-  canon_path[0] = '/';
+  if (strlen(orig_path) >= PATH_MAX) return(ENAMETOOLONG);
+  memmove(orig_path+1, orig_path, strlen(orig_path));
+  orig_path[0] = '/';
 
   return(OK);
 }
@@ -470,62 +756,50 @@ struct fproc *rfp;
 /*===========================================================================*
  *                             check_perms                                  *
  *===========================================================================*/
-PUBLIC int check_perms(ep, io_gr, pathlen)
+PRIVATE int check_perms(ep, io_gr, pathlen)
 endpoint_t ep;
 cp_grant_id_t io_gr;
-int pathlen;
+size_t pathlen;
 {
-  int r, i;
+  int r, slot;
   struct vnode *vp;
+  struct vmnt *vmp;
   struct fproc *rfp;
-  char orig_path[PATH_MAX];
   char canon_path[PATH_MAX];
+  struct lookup resolve;
 
-  i = _ENDPOINT_P(ep);
-  if (pathlen < UNIX_PATH_MAX || pathlen >= PATH_MAX || i < 0 || i >= NR_PROCS)
-       return EINVAL;
-
-  rfp = &(fproc[i]);
-
-  memset(canon_path, '\0', PATH_MAX);
+  if (isokendpt(ep, &slot) != OK) return(EINVAL);
+  if (pathlen < UNIX_PATH_MAX || pathlen >= PATH_MAX) return(EINVAL);
 
+  rfp = &(fproc[slot]);
   r = sys_safecopyfrom(PFS_PROC_NR, io_gr, (vir_bytes) 0,
-                               (vir_bytes) &user_fullpath, pathlen, D);
-  if (r != OK) {
-       return r;
-  }
-  user_fullpath[pathlen] = '\0';
-
-  /* save path from pfs before permissions checking modifies it */
-  memcpy(orig_path, user_fullpath, PATH_MAX);
+                               (vir_bytes) canon_path, pathlen, D);
+  if (r != OK) return(r);
+  canon_path[pathlen] = '\0';
 
-  /* get the canonical path to the socket file */
-  r = canonical_path(orig_path, canon_path, rfp);
-  if (r != OK) {
-       return r;
-  }
+  /* Turn path into canonical path to the socket file */
+  if ((r = canonical_path(canon_path, rfp)) != OK)
+       return(r);
 
-  if (strlen(canon_path) >= pathlen) {
-       return ENAMETOOLONG;
-  }
+  if (strlen(canon_path) >= pathlen) return(ENAMETOOLONG);
 
   /* copy canon_path back to PFS */
-  r = sys_safecopyto(PFS_PROC_NR, (cp_grant_id_t) io_gr, (vir_bytes) 0, 
-                               (vir_bytes) canon_path, strlen(canon_path)+1,
-                               D);
-  if (r != OK) {
-       return r;
-  }
+  r = sys_safecopyto(PFS_PROC_NR, (cp_grant_id_t) io_gr, (vir_bytes) 0,
+                               (vir_bytes) canon_path, pathlen, D);
+  if (r != OK) return(r);
 
-  /* reload user_fullpath for permissions checking */
-  memcpy(user_fullpath, orig_path, PATH_MAX);
-  if ((vp = eat_path(PATH_NOFLAGS, rfp)) == NULL) {
-       return(err_code);
-  }
+  /* Now do permissions checking */
+  lookup_init(&resolve, canon_path, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+  if ((vp = eat_path(&resolve, rfp)) == NULL) return(err_code);
 
   /* check permissions */
   r = forbidden(rfp, vp, (R_BIT | W_BIT));
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
+
   put_vnode(vp);
   return(r);
 }
@@ -536,5 +810,5 @@ int pathlen;
 PUBLIC int do_check_perms(void)
 {
   return check_perms(m_in.USER_ENDPT, (cp_grant_id_t) m_in.IO_GRANT,
-       m_in.COUNT);
+                    (size_t) m_in.COUNT);
 }
similarity index 100%
rename from servers/avfs/path.h
rename to servers/vfs/path.h
index c5183b33790b3513f2a1a8b25863f377250ccf5d..0a6d6f49d528136026d2fabc15ee3b5672fc3288 100644 (file)
@@ -27,6 +27,8 @@
 #include <sys/time.h>
 #include "file.h"
 #include "fproc.h"
+#include "scratchpad.h"
+#include "dmap.h"
 #include "param.h"
 #include "select.h"
 #include <minix/vfsif.h>
@@ -46,21 +48,34 @@ PUBLIC int do_pipe()
   struct filp *fil_ptr0, *fil_ptr1;
   int fil_des[2];              /* reply goes here */
   struct vnode *vp;
+  struct vmnt *vmp;
   struct node_details res;
 
+  /* Get a lock on PFS */
+  if ((vmp = find_vmnt(PFS_PROC_NR)) == NULL) panic("PFS gone");
+  if ((r = lock_vmnt(vmp, VMNT_WRITE)) != OK) return(r);
+
   /* See if a free vnode is available */
-  if ( (vp = get_free_vnode()) == NULL) return(err_code);
+  if ((vp = get_free_vnode()) == NULL) return(err_code);
+  lock_vnode(vp, VNODE_OPCL);
 
   /* Acquire two file descriptors. */
   rfp = fp;
-  if ((r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r);
+  if ((r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) {
+       unlock_vnode(vp);
+       unlock_vmnt(vmp);
+       return(r);
+  }
   rfp->fp_filp[fil_des[0]] = fil_ptr0;
   FD_SET(fil_des[0], &rfp->fp_filp_inuse);
-  fil_ptr0->filp_count = 1;
+  fil_ptr0->filp_count = 1;            /* mark filp in use */
   if ((r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
        rfp->fp_filp[fil_des[0]] = NULL;
        FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
-       fil_ptr0->filp_count = 0;
+       fil_ptr0->filp_count = 0;       /* mark filp free */
+       unlock_filp(fil_ptr0);
+       unlock_vnode(vp);
+       unlock_vmnt(vmp);
        return(r);
   }
   rfp->fp_filp[fil_des[1]] = fil_ptr1;
@@ -78,14 +93,18 @@ PUBLIC int do_pipe()
        rfp->fp_filp[fil_des[1]] = NULL;
        FD_CLR(fil_des[1], &rfp->fp_filp_inuse);
        fil_ptr1->filp_count = 0;
+       unlock_filp(fil_ptr1);
+       unlock_filp(fil_ptr0);
+       unlock_vnode(vp);
+       unlock_vmnt(vmp);
        return(r);
   }
 
   /* Fill in vnode */
   vp->v_fs_e = res.fs_e;
   vp->v_mapfs_e = res.fs_e;
-  vp->v_inode_nr = res.inode_nr; 
-  vp->v_mapinode_nr = res.inode_nr; 
+  vp->v_inode_nr = res.inode_nr;
+  vp->v_mapinode_nr = res.inode_nr;
   vp->v_mode = res.fmode;
   vp->v_pipe = I_PIPE;
   vp->v_pipe_rd_pos= 0;
@@ -94,7 +113,7 @@ PUBLIC int do_pipe()
   vp->v_mapfs_count = 1;
   vp->v_ref_count = 1;
   vp->v_size = 0;
-  vp->v_vmnt = NULL; 
+  vp->v_vmnt = NULL;
   vp->v_dev = NO_DEV;
 
   /* Fill in filp objects */
@@ -107,6 +126,9 @@ PUBLIC int do_pipe()
   m_out.reply_i1 = fil_des[0];
   m_out.reply_i2 = fil_des[1];
 
+  unlock_filps(fil_ptr0, fil_ptr1);
+  unlock_vmnt(vmp);
+
   return(OK);
 }
 
@@ -114,28 +136,41 @@ PUBLIC int do_pipe()
 /*===========================================================================*
  *                             map_vnode                                    *
  *===========================================================================*/
-PUBLIC int map_vnode(vp)
+PUBLIC int map_vnode(vp, map_to_fs_e)
 struct vnode *vp;
+endpoint_t map_to_fs_e;
 {
   int r;
+  struct vmnt *vmp;
   struct node_details res;
 
-  if(vp->v_mapfs_e != 0) return(OK);   /* Already mapped; nothing to do. */
+  if(vp->v_mapfs_e != NONE) return(OK);        /* Already mapped; nothing to do. */
+
+  if ((vmp = find_vmnt(map_to_fs_e)) == NULL)
+       panic("Can't map to unknown endpoint");
+  if ((r = lock_vmnt(vmp, VMNT_WRITE)) != OK) {
+       if (r == EBUSY)
+               vmp = NULL;     /* Already locked, do not unlock */
+       else
+               return(r);
+
+  }
 
-  /* Create a temporary mapping of this inode to PipeFS. Read and write
-   * operations on data will be handled by PipeFS. The rest by the 'original'
+  /* Create a temporary mapping of this inode to another FS. Read and write
+   * operations on data will be handled by that FS. The rest by the 'original'
    * FS that holds the inode. */
-  if ((r = req_newnode(PFS_PROC_NR, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE,
+  if ((r = req_newnode(map_to_fs_e, fp->fp_effuid, fp->fp_effgid, I_NAMED_PIPE,
                       vp->v_dev, &res)) == OK) {
        vp->v_mapfs_e = res.fs_e;
-       vp->v_mapinode_nr = res.inode_nr; 
+       vp->v_mapinode_nr = res.inode_nr;
        vp->v_mapfs_count = 1;
   }
 
+  if (vmp) unlock_vmnt(vmp);
+
   return(r);
 }
 
-
 /*===========================================================================*
  *                             pipe_check                                   *
  *===========================================================================*/
@@ -165,11 +200,11 @@ int notouch;                      /* check only */
                /* Process is reading from an empty pipe. */
                if (find_filp(vp, W_BIT) != NULL) {
                        /* Writer exists */
-                       if (oflags & O_NONBLOCK) 
+                       if (oflags & O_NONBLOCK)
                                r = EAGAIN;
-                       else 
+                       else
                                r = SUSPEND;
-                       
+
                        /* If need be, activate sleeping writers. */
                        if (susp_count > 0)
                                release(vp, WRITE, susp_count);
@@ -250,37 +285,25 @@ PUBLIC void suspend(int why)
  */
 
 #if DO_SANITYCHECKS
-  if (why == FP_BLOCKED_ON_PIPE)
-       panic("suspend: called for FP_BLOCKED_ON_PIPE");
-
   if(fp_is_blocked(fp))
        panic("suspend: called for suspended process");
-  
+
   if(why == FP_BLOCKED_ON_NONE)
        panic("suspend: called for FP_BLOCKED_ON_NONE");
 #endif
 
-  if (why == FP_BLOCKED_ON_POPEN)
-         /* #procs susp'ed on pipe*/
-         susp_count++;
+  if (why == FP_BLOCKED_ON_POPEN || why == FP_BLOCKED_ON_PIPE)
+       /* #procs susp'ed on pipe*/
+       susp_count++;
 
   fp->fp_blocked_on = why;
   assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant));
-  fp->fp_block_fd = m_in.fd;
   fp->fp_block_callnr = call_nr;
-  fp->fp_flags &= ~SUSP_REOPEN;                        /* Clear this flag. The caller
+  fp->fp_flags &= ~FP_SUSP_REOPEN;             /* Clear this flag. The caller
                                                 * can set it when needed.
                                                 */
-  if (why == FP_BLOCKED_ON_LOCK) {
-       fp->fp_buffer = (char *) m_in.name1;    /* third arg to fcntl() */
-       fp->fp_nbytes = m_in.request;           /* second arg to fcntl() */
-  } else {
-       fp->fp_buffer = m_in.buffer;            /* for reads and writes */
-       fp->fp_nbytes = m_in.nbytes;
-  }
 }
 
-
 /*===========================================================================*
  *                             wait_for                                     *
  *===========================================================================*/
@@ -296,30 +319,23 @@ PUBLIC void wait_for(endpoint_t who)
 /*===========================================================================*
  *                             pipe_suspend                                         *
  *===========================================================================*/
-PUBLIC void pipe_suspend(rw_flag, fd_nr, buf, size)
-int rw_flag;
-int fd_nr;
+PUBLIC void pipe_suspend(filp, buf, size)
+struct filp *filp;
 char *buf;
 size_t size;
 {
 /* Take measures to suspend the processing of the present system call.
  * Store the parameters to be used upon resuming in the process table.
- * (Actually they are not used when a process is waiting for an I/O device,
- * but they are needed for pipes, and it is not worth making the distinction.)
- * The SUSPEND pseudo error should be returned after calling suspend().
  */
 #if DO_SANITYCHECKS
   if(fp_is_blocked(fp))
        panic("pipe_suspend: called for suspended process");
 #endif
 
-  susp_count++;                                        /* #procs susp'ed on pipe*/
-  fp->fp_blocked_on = FP_BLOCKED_ON_PIPE;
-  assert(!GRANT_VALID(fp->fp_grant));
-  fp->fp_block_fd = fd_nr;
-  fp->fp_block_callnr = ((rw_flag == READING) ? READ : WRITE);
-  fp->fp_buffer = buf;         
-  fp->fp_nbytes = size;
+  scratch(fp).file.filp = filp;
+  scratch(fp).io.io_buffer = buf;
+  scratch(fp).io.io_nbytes = size;
+  suspend(FP_BLOCKED_ON_PIPE);
 }
 
 
@@ -334,8 +350,8 @@ PUBLIC void unsuspend_by_endpt(endpoint_t proc_e)
   struct fproc *rp;
 
   for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) {
-       if (rp->fp_pid == PID_FREE) continue;
-       if (rp->fp_blocked_on == FP_BLOCKED_ON_OTHER && rp->fp_task == proc_e) 
+       if (rp->fp_pid == PID_FREE) continue;
+       if (rp->fp_blocked_on == FP_BLOCKED_ON_OTHER && rp->fp_task == proc_e)
                revive(rp->fp_endpoint, EAGAIN);
   }
 
@@ -349,42 +365,63 @@ PUBLIC void unsuspend_by_endpt(endpoint_t proc_e)
 /*===========================================================================*
  *                             release                                      *
  *===========================================================================*/
-PUBLIC void release(vp, call_nr, count)
+PUBLIC void release(vp, op, count)
 register struct vnode *vp;     /* inode of pipe */
-int call_nr;                   /* READ, WRITE, OPEN or CREAT */
+int op;                                /* READ, WRITE, OPEN or CREAT */
 int count;                     /* max number of processes to release */
 {
-/* Check to see if any process is hanging on the pipe whose inode is in 'ip'.
- * If one is, and it was trying to perform the call indicated by 'call_nr',
- * release it.
+/* Check to see if any process is hanging on vnode 'vp'. If one is, and it
+ * was trying to perform the call indicated by 'call_nr', release it.
  */
 
   register struct fproc *rp;
   struct filp *f;
+  int selop;
 
   /* Trying to perform the call also includes SELECTing on it with that
    * operation.
    */
-  if (call_nr == READ || call_nr == WRITE) {
-         int op;
-         if (call_nr == READ)
-               op = SEL_RD;
-         else
-               op = SEL_WR;
-         for(f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-               if (f->filp_count < 1 || !(f->filp_pipe_select_ops & op) ||
-                  f->filp_vno != vp)
-                       continue;
-                select_callback(f, op);
-               f->filp_pipe_select_ops &= ~op;
-       }
+  if (op == READ || op == WRITE) {
+       if (op == READ)
+               selop = SEL_RD;
+       else
+               selop = SEL_WR;
+
+       for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
+               if (f->filp_count < 1 || !(f->filp_pipe_select_ops & selop) ||
+                   f->filp_vno != vp)
+                       continue;
+               select_callback(f, selop);
+               f->filp_pipe_select_ops &= ~selop;
+       }
   }
 
   /* Search the proc table. */
   for (rp = &fproc[0]; rp < &fproc[NR_PROCS] && count > 0; rp++) {
        if (rp->fp_pid != PID_FREE && fp_is_blocked(rp) &&
-           rp->fp_revived == NOT_REVIVING && rp->fp_block_callnr == call_nr &&
-           rp->fp_filp[rp->fp_block_fd]->filp_vno == vp) {
+           !(rp->fp_flags & FP_REVIVED) && rp->fp_block_callnr == op) {
+               /* Find the vnode. Depending on the reason the process was
+                * suspended, there are different ways of finding it.
+                */
+
+               if (rp->fp_blocked_on == FP_BLOCKED_ON_POPEN ||
+                   rp->fp_blocked_on == FP_BLOCKED_ON_DOPEN ||
+                   rp->fp_blocked_on == FP_BLOCKED_ON_LOCK ||
+                   rp->fp_blocked_on == FP_BLOCKED_ON_OTHER) {
+                       if (!FD_ISSET(scratch(rp).file.fd_nr,
+                                                       &rp->fp_filp_inuse))
+                               continue;
+                       if (rp->fp_filp[scratch(rp).file.fd_nr]->filp_vno != vp)
+                               continue;
+               } else if (rp->fp_blocked_on == FP_BLOCKED_ON_PIPE) {
+                       if (scratch(rp).file.filp == NULL)
+                               continue;
+                       if (scratch(rp).file.filp->filp_vno != vp)
+                               continue;
+               } else
+                       continue;
+
+               /* We found the vnode. Revive process. */
                revive(rp->fp_endpoint, 0);
                susp_count--;   /* keep track of who is suspended */
                if(susp_count < 0)
@@ -407,61 +444,66 @@ int returned;                     /* if hanging on task, how many bytes read */
  */
   register struct fproc *rfp;
   int blocked_on;
-  int fd_nr, proc_nr;
+  int fd_nr, slot;
   struct filp *fil_ptr;
 
-  if(isokendpt(proc_nr_e, &proc_nr) != OK) return;
+  if (proc_nr_e == NONE || isokendpt(proc_nr_e, &slot) != OK) return;
 
-  rfp = &fproc[proc_nr];
-  if (!fp_is_blocked(rfp) || rfp->fp_revived == REVIVING) return;
+  rfp = &fproc[slot];
+  if (!fp_is_blocked(rfp) || (rfp->fp_flags & FP_REVIVED)) return;
 
   /* The 'reviving' flag only applies to pipes.  Processes waiting for TTY get
    * a message right away.  The revival process is different for TTY and pipes.
    * For select and TTY revival, the work is already done, for pipes it is not:
-   *  the proc must be restarted so it can try again.
+   * the proc must be restarted so it can try again.
    */
   blocked_on = rfp->fp_blocked_on;
+  fd_nr = scratch(rfp).file.fd_nr;
   if (blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_LOCK) {
        /* Revive a process suspended on a pipe or lock. */
-       rfp->fp_revived = REVIVING;
+       rfp->fp_flags |= FP_REVIVED;
        reviving++;             /* process was waiting on pipe or lock */
   } else if (blocked_on == FP_BLOCKED_ON_DOPEN) {
        rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
-       fd_nr = rfp->fp_block_fd;
+       scratch(rfp).file.fd_nr = 0;
        if (returned < 0) {
                fil_ptr = rfp->fp_filp[fd_nr];
+               lock_filp(fil_ptr, VNODE_OPCL);
                rfp->fp_filp[fd_nr] = NULL;
                FD_CLR(fd_nr, &rfp->fp_filp_inuse);
                if (fil_ptr->filp_count != 1) {
-                       panic("revive: bad count in filp: %d",
+                       panic("VFS: revive: bad count in filp: %d",
                                fil_ptr->filp_count);
                }
                fil_ptr->filp_count = 0;
-               put_vnode(fil_ptr->filp_vno);     
+               unlock_filp(fil_ptr);
+               put_vnode(fil_ptr->filp_vno);
                fil_ptr->filp_vno = NULL;
                reply(proc_nr_e, returned);
-       } else
+       } else {
                reply(proc_nr_e, fd_nr);
+       }
   } else {
        rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
+       scratch(rfp).file.fd_nr = 0;
        if (blocked_on == FP_BLOCKED_ON_POPEN) {
                /* process blocked in open or create */
-               reply(proc_nr_e, rfp->fp_block_fd);
+               reply(proc_nr_e, fd_nr);
        } else if (blocked_on == FP_BLOCKED_ON_SELECT) {
                reply(proc_nr_e, returned);
        } else {
-               /* Revive a process suspended on TTY or other device. 
+               /* Revive a process suspended on TTY or other device.
                 * Pretend it wants only what there is.
                 */
-               rfp->fp_nbytes = returned; 
+               scratch(rfp).io.io_nbytes = returned;
                /* If a grant has been issued by FS for this I/O, revoke
                 * it again now that I/O is done.
                 */
-               if(GRANT_VALID(rfp->fp_grant)) {
+               if (GRANT_VALID(rfp->fp_grant)) {
                        if(cpf_revoke(rfp->fp_grant)) {
-                               panic("FS: revoke failed for grant: %d",
+                               panic("VFS: revoke failed for grant: %d",
                                        rfp->fp_grant);
-                       } 
+                       }
                        rfp->fp_grant = GRANT_INVALID;
                }
                reply(proc_nr_e, returned);     /* unblock the process */
@@ -473,31 +515,30 @@ int returned;                     /* if hanging on task, how many bytes read */
 /*===========================================================================*
  *                             unpause                                      *
  *===========================================================================*/
-PUBLIC void unpause(proc_nr_e)
-int proc_nr_e;
+PUBLIC void unpause(endpoint_t proc_e)
 {
 /* A signal has been sent to a user who is paused on the file system.
  * Abort the system call with the EINTR error message.
  */
 
-  register struct fproc *rfp;
-  int proc_nr_p, blocked_on, fild, status = EINTR;
+  register struct fproc *rfp, *org_fp;
+  int slot, blocked_on, fild, status = EINTR, major_dev, minor_dev;
   struct filp *f;
   dev_t dev;
   message mess;
   int wasreviving = 0;
 
-  if(isokendpt(proc_nr_e, &proc_nr_p) != OK) {
-       printf("VFS: ignoring unpause for bogus endpoint %d\n", proc_nr_e);
+  if (isokendpt(proc_e, &slot) != OK) {
+       printf("VFS: ignoring unpause for bogus endpoint %d\n", proc_e);
        return;
   }
 
-  rfp = &fproc[proc_nr_p];
+  rfp = &fproc[slot];
   if (!fp_is_blocked(rfp)) return;
   blocked_on = rfp->fp_blocked_on;
 
-  if (rfp->fp_revived == REVIVING) {
-       rfp->fp_revived = NOT_REVIVING;
+  if (rfp->fp_flags & FP_REVIVED) {
+       rfp->fp_flags &= ~FP_REVIVED;
        reviving--;
        wasreviving = 1;
   }
@@ -510,126 +551,69 @@ int proc_nr_e;
                break;
 
        case FP_BLOCKED_ON_SELECT:/* process blocking on select() */
-               select_forget(proc_nr_e);
+               select_forget(proc_e);
                break;
 
-       case FP_BLOCKED_ON_POPEN:               /* process trying to open a fifo */
+       case FP_BLOCKED_ON_POPEN:       /* process trying to open a fifo */
                break;
 
        case FP_BLOCKED_ON_DOPEN:/* process trying to open a device */
                /* Don't cancel OPEN. Just wait until the open completes. */
-               return; 
+               return;
 
-       case FP_BLOCKED_ON_OTHER:               /* process trying to do device I/O (e.g. tty)*/
-               if (rfp->fp_flags & SUSP_REOPEN) {
+       case FP_BLOCKED_ON_OTHER:/* process trying to do device I/O (e.g. tty)*/
+               if (rfp->fp_flags & FP_SUSP_REOPEN) {
                        /* Process is suspended while waiting for a reopen.
                         * Just reply EINTR.
                         */
-                       rfp->fp_flags &= ~SUSP_REOPEN;
+                       rfp->fp_flags &= ~FP_SUSP_REOPEN;
                        status = EINTR;
                        break;
                }
-               
-               fild = rfp->fp_block_fd;
+
+               fild = scratch(rfp).file.fd_nr;
                if (fild < 0 || fild >= OPEN_MAX)
-                       panic("unpause err 2");
+                       panic("file descriptor out-of-range");
                f = rfp->fp_filp[fild];
                dev = (dev_t) f->filp_vno->v_sdev;      /* device hung on */
-               mess.TTY_LINE = (dev >> MINOR) & BYTE;
+               major_dev = major(dev);
+               minor_dev = minor(dev);
+               mess.TTY_LINE = minor_dev;
                mess.USER_ENDPT = rfp->fp_ioproc;
                mess.IO_GRANT = (char *) rfp->fp_grant;
 
                /* Tell kernel R or W. Mode is from current call, not open. */
                mess.COUNT = rfp->fp_block_callnr == READ ? R_BIT : W_BIT;
                mess.m_type = CANCEL;
+
+               org_fp = fp;
                fp = rfp;       /* hack - ctty_io uses fp */
-               (*dmap[(dev >> MAJOR) & BYTE].dmap_io)(rfp->fp_task, &mess);
+               (*dmap[major_dev].dmap_io)(rfp->fp_task, &mess);
+               fp = org_fp;
                status = mess.REP_STATUS;
                if (status == SUSPEND)
                        return;         /* Process will be revived at a
                                         * later time.
                                         */
 
-               if(status == EAGAIN) status = EINTR;
-               if(GRANT_VALID(rfp->fp_grant)) {
-                       if(cpf_revoke(rfp->fp_grant)) {
-                               panic("FS: revoke failed for grant (cancel): %d",
-                                       rfp->fp_grant);
-                       } 
+               if (status == EAGAIN) status = EINTR;
+               if (GRANT_VALID(rfp->fp_grant)) {
+                       (void) cpf_revoke(rfp->fp_grant);
                        rfp->fp_grant = GRANT_INVALID;
                }
                break;
        default :
-               panic("FS: unknown value: %d", blocked_on);
+               panic("VFS: unknown block reason: %d", blocked_on);
   }
 
   rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
 
-  if ((blocked_on == FP_BLOCKED_ON_PIPE ||
-                       blocked_on == FP_BLOCKED_ON_POPEN) &&
-                       !wasreviving) {
+  if ((blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_POPEN)&&
+       !wasreviving) {
        susp_count--;
   }
 
-  reply(proc_nr_e, status);    /* signal interrupted call */
-}
-
-
-/*===========================================================================*
- *                             select_request_pipe                          *
- *===========================================================================*/
-PUBLIC int select_request_pipe(struct filp *f, int *ops, int block)
-{
-       int orig_ops, r = 0, err;
-       orig_ops = *ops;
-       if ((*ops & (SEL_RD|SEL_ERR))) {
-               if ((err = pipe_check(f->filp_vno, READING, 0,
-                       1, f->filp_pos, 1)) != SUSPEND)
-                       r |= SEL_RD;
-               if (err < 0 && err != SUSPEND)
-                       r |= SEL_ERR;
-               if(err == SUSPEND && f->filp_mode & W_BIT) {
-                        /* A "meaningless" read select, therefore ready
-                           for reading and no error set. */
-                       r |= SEL_RD; 
-                       r &= ~SEL_ERR;
-                }
-       }
-
-       if ((*ops & (SEL_WR|SEL_ERR))) {
-               if ((err = pipe_check(f->filp_vno, WRITING, 0,
-                       1, f->filp_pos, 1)) != SUSPEND)
-                       r |= SEL_WR;
-               if (err < 0 && err != SUSPEND)
-                       r |= SEL_ERR;
-               if(err == SUSPEND && f->filp_mode & R_BIT) {
-                        /* A "meaningless" write select, therefore ready
-                           for reading and no error set. */
-                       r |= SEL_WR; 
-                       r &= ~SEL_ERR;
-                }
-       }
-
-       /* Some options we collected might not be requested. */
-       *ops = r & orig_ops;
-
-       if (!*ops && block) {
-               f->filp_pipe_select_ops |= orig_ops;
-       }
-
-       return(SEL_OK);
-}
-
-
-/*===========================================================================*
- *                             select_match_pipe                            *
- *===========================================================================*/
-PUBLIC int select_match_pipe(struct filp *f)
-{
-       /* recognize either pipe or named pipe (FIFO) */
-       if (f && f->filp_vno && (f->filp_vno->v_mode & I_NAMED_PIPE))
-               return 1;
-       return 0;
+  reply(proc_e, status);       /* signal interrupted call */
 }
 
 #if DO_SANITYCHECKS
@@ -638,24 +622,24 @@ PUBLIC int select_match_pipe(struct filp *f)
  *===========================================================================*/
 PUBLIC int check_pipe(void)
 {
-       struct fproc *rfp;
-       int mycount = 0;
-        for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-                if (rfp->fp_pid == PID_FREE)
-                        continue;
-               if(rfp->fp_revived != REVIVING &&
-                               (rfp->fp_blocked_on == FP_BLOCKED_ON_PIPE ||
-                                rfp->fp_blocked_on == FP_BLOCKED_ON_POPEN)) {
-                       mycount++;
-               }
-        }
-
-       if(mycount != susp_count) {
-               printf("check_pipe: mycount %d susp_count %d\n",
-                       mycount, susp_count);
-               return 0;
+/* Integrity check; verify that susp_count equals what the fproc table thinks
+ * is suspended on a pipe */
+  struct fproc *rfp;
+  int count = 0;
+  for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+       if (rfp->fp_pid == PID_FREE) continue;
+       if ( !(rfp->fp_flags & FP_REVIVED) &&
+           (rfp->fp_blocked_on == FP_BLOCKED_ON_PIPE ||
+            rfp->fp_blocked_on == FP_BLOCKED_ON_POPEN)) {
+               count++;
        }
+  }
+
+  if (count != susp_count) {
+       printf("check_pipe: count %d susp_count %d\n", count, susp_count);
+       return(0);
+  }
 
-       return 1;
+  return(l);
 }
 #endif
index 958cfe8ac9de1a05ccaa60b0e4da86535d5d4ecb..04325c61499ba6a54e0055092ec085170e9d2eef 100644 (file)
@@ -13,6 +13,7 @@
 #include <minix/callnr.h>
 #include "file.h"
 #include "fproc.h"
+#include "path.h"
 #include "param.h"
 #include <minix/vfsif.h>
 #include "vnode.h"
@@ -27,19 +28,30 @@ PUBLIC int do_chmod()
 
   struct filp *flp;
   struct vnode *vp;
+  struct vmnt *vmp;
   int r;
   mode_t new_mode;
-    
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  flp = NULL;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_WRITE;
+
   if (call_nr == CHMOD) {
-       /* Temporarily open the file */
-       if(fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-       if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+       /* Temporarily open the file */
+       if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
+               return(err_code);
+       if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
   } else {     /* call_nr == FCHMOD */
        /* File is already opened; get a pointer to vnode from filp. */
-       if (!(flp = get_filp(m_in.fd))) return(err_code);
+       if ((flp = get_filp(m_in.fd, VNODE_WRITE)) == NULL)
+               return(err_code);
        vp = flp->filp_vno;
        dup_vnode(vp);
-  } 
+  }
 
   /* Only the owner or the super_user may change the mode of a file.
    * No one may change the mode of a file on a read-only file system.
@@ -49,21 +61,26 @@ PUBLIC int do_chmod()
   else
        r = read_only(vp);
 
-  /* If error, return inode. */
-  if (r != OK) {
-       put_vnode(vp);
-       return(r);
-  }
+  if (r == OK) {
+       /* Now make the change. Clear setgid bit if file is not in caller's
+        * group */
+       if (fp->fp_effuid != SU_UID && vp->v_gid != fp->fp_effgid)
+               m_in.mode &= ~I_SET_GID_BIT;
 
-  /* Now make the change. Clear setgid bit if file is not in caller's grp */
-  if (fp->fp_effuid != SU_UID && vp->v_gid != fp->fp_effgid) 
-         m_in.mode &= ~I_SET_GID_BIT;
+       r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode);
+       if (r == OK)
+               vp->v_mode = new_mode;
+  }
 
-  if ((r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode)) == OK)
-       vp->v_mode = new_mode;
+  if (call_nr == CHMOD) {
+       unlock_vnode(vp);
+       unlock_vmnt(vmp);
+  } else {     /* FCHMOD */
+       unlock_filp(flp);
+  }
 
   put_vnode(vp);
-  return(OK);
+  return(r);
 }
 
 
@@ -72,23 +89,35 @@ PUBLIC int do_chmod()
  *===========================================================================*/
 PUBLIC int do_chown()
 {
-/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */
+/* Perform the chown(path, owner, group) and fchmod(fd, owner, group) system
+ * calls. */
   struct filp *flp;
   struct vnode *vp;
+  struct vmnt *vmp;
   int r;
   uid_t uid;
   gid_t gid;
   mode_t new_mode;
-  
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  flp = NULL;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_WRITE;
+
   if (call_nr == CHOWN) {
        /* Temporarily open the file. */
-      if(fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-      if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+       if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+               return(err_code);
+       if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
   } else {     /* call_nr == FCHOWN */
-       /* File is already opened; get a pointer to the vnode from filp. */
-      if (!(flp = get_filp(m_in.fd))) return(err_code);
-      vp = flp->filp_vno;
-      dup_vnode(vp);
+       /* File is already opened; get a pointer to the vnode from filp. */
+       if ((flp = get_filp(m_in.fd, VNODE_WRITE)) == NULL)
+               return(err_code);
+       vp = flp->filp_vno;
+       dup_vnode(vp);
   }
 
   r = read_only(vp);
@@ -98,7 +127,7 @@ PUBLIC int do_chown()
           a regular user. */
        if (fp->fp_effuid != SU_UID) {
                /* Regular users can only change groups of their own files. */
-               if (vp->v_uid != fp->fp_effuid) r = EPERM;      
+               if (vp->v_uid != fp->fp_effuid) r = EPERM;
                if (vp->v_uid != m_in.owner) r = EPERM; /* no giving away */
                if (fp->fp_effgid != m_in.group) r = EPERM;
        }
@@ -113,17 +142,23 @@ PUBLIC int do_chown()
                r = EINVAL;
        else if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, uid, gid,
                                &new_mode)) == OK) {
-               vp->v_uid = uid;
+               vp->v_uid = uid;
                vp->v_gid = gid;
                vp->v_mode = new_mode;
        }
   }
 
+  if (call_nr == CHOWN) {
+       unlock_vnode(vp);
+       unlock_vmnt(vmp);
+  } else {     /* FCHOWN */
+       unlock_filp(flp);
+  }
+
   put_vnode(vp);
   return(r);
 }
 
-
 /*===========================================================================*
  *                             do_umask                                     *
  *===========================================================================*/
@@ -146,16 +181,28 @@ PUBLIC int do_access()
 /* Perform the access(name, mode) system call. */
   int r;
   struct vnode *vp;
-    
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+
   /* First check to see if the mode is correct. */
   if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
        return(EINVAL);
 
   /* Temporarily open the file. */
-  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
+       return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
 
   r = forbidden(fp, vp, m_in.mode);
+
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
+
   put_vnode(vp);
   return(r);
 }
@@ -211,7 +258,7 @@ PUBLIC int forbidden(struct fproc *rfp, struct vnode *vp, mode_t access_desired)
    */
   if (r == OK)
        if (access_desired & W_BIT)
-               r = read_only(vp);
+               r = read_only(vp);
 
   return(r);
 }
@@ -225,10 +272,5 @@ struct vnode *vp;          /* ptr to inode whose file sys is to be cked */
 /* Check to see if the file system on which the inode 'ip' resides is mounted
  * read only.  If so, return EROFS, else return OK.
  */
-  register struct vmnt *mp;
-
-  mp = vp->v_vmnt;
-  return(mp->m_flags ? EROFS : OK);
+  return((vp->v_vmnt->m_flags & VMNT_READONLY) ? EROFS : OK);
 }
-
-
index 3c933df04b4b24ae9f9593b64a4242b0180ed25f..432ef3a521d2f8f910353e0ecbcd82bc1ad52637 100644 (file)
@@ -1,32 +1,46 @@
+#ifndef __VFS_PROTO_H__
+#define __VFS_PROTO_H__
+
 /* Function prototypes. */
 
 #include "timers.h"
 #include "request.h"
+#include "tll.h"
+#include "threads.h"
 #include <minix/rs.h>
 
 /* Structs used in prototypes must be declared as such first. */
-struct filp;           
+struct filp;
 struct fproc;
 struct vmnt;
 struct vnode;
+struct lookup;
+struct worker_thread;
+struct job;
 
 typedef struct filp * filp_id_t;
 
+/* comm.c */
+_PROTOTYPE(void fs_cancel, (struct vmnt *vmp)                          );
+_PROTOTYPE(int fs_sendrec, (endpoint_t fs_e, message *reqm)            );
+_PROTOTYPE(void fs_sendmore, (struct vmnt *vmp)                                );
+_PROTOTYPE(void send_work, (void)                                      );
+
 /* device.c */
-_PROTOTYPE( int dev_open, (dev_t dev, int proc, int flags)             );
+_PROTOTYPE( int dev_open, (dev_t dev, endpoint_t proc_e, int flags)    );
 _PROTOTYPE( int dev_reopen, (dev_t dev, int filp_no, int flags)                );
 _PROTOTYPE( int dev_close, (dev_t dev, int filp_no)                    );
-_PROTOTYPE( int bdev_open, (dev_t dev, int flags)                      );
+_PROTOTYPE( int bdev_open, (dev_t dev, int access)                     );
 _PROTOTYPE( int bdev_close, (dev_t dev)                                        );
-_PROTOTYPE( int dev_io, (int op, dev_t dev, int proc, void *buf,
-               u64_t pos, int bytes, int flags, int suspend_reopen)    );
-_PROTOTYPE( int gen_opcl, (int op, dev_t dev, int proc, int flags)     );
-_PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr)               );
+_PROTOTYPE( int dev_io, (int op, dev_t dev, endpoint_t proc_e, void *buf,
+               u64_t pos, size_t bytes, int flags, int suspend_reopen) );
+_PROTOTYPE( int gen_opcl, (int op, dev_t dev, endpoint_t task_nr, int flags));
+_PROTOTYPE( int gen_io, (endpoint_t driver_e, message *mess_ptr)               );
 _PROTOTYPE( int asyn_io, (int task_nr, message *mess_ptr)              );
 _PROTOTYPE( int no_dev, (int op, dev_t dev, int proc, int flags)       );
 _PROTOTYPE( int no_dev_io, (int, message *)                            );
-_PROTOTYPE( int tty_opcl, (int op, dev_t dev, int proc, int flags)     );
-_PROTOTYPE( int ctty_opcl, (int op, dev_t dev, int proc, int flags)    );
+_PROTOTYPE( int tty_opcl, (int op, dev_t dev, endpoint_t proc, int flags));
+_PROTOTYPE( int ctty_opcl, (int op, dev_t dev, endpoint_t proc, int flags));
 _PROTOTYPE( int clone_opcl, (int op, dev_t dev, int proc, int flags)   );
 _PROTOTYPE( int ctty_io, (int task_nr, message *mess_ptr)              );
 _PROTOTYPE( int do_ioctl, (void)                                       );
@@ -34,33 +48,53 @@ _PROTOTYPE( void pm_setsid, (int proc_e)                            );
 _PROTOTYPE( void dev_status, (message *)                               );
 _PROTOTYPE( void bdev_up, (int major)                                  );
 _PROTOTYPE( void cdev_up, (int major)                                  );
-_PROTOTYPE( endpoint_t suspended_ep, (endpoint_t driver,
-                                               cp_grant_id_t g)        );
+_PROTOTYPE( endpoint_t find_suspended_ep, (endpoint_t driver,
+                                          cp_grant_id_t g)             );
 _PROTOTYPE( void reopen_reply, (void)                                  );
+_PROTOTYPE( void open_reply, (void)                                    );
 
 /* dmap.c */
-_PROTOTYPE( void build_dmap, (void)                                    );
 _PROTOTYPE( int do_mapdriver, (void)                                   );
+_PROTOTYPE( void init_dmap, (void)                                     );
 _PROTOTYPE( int dmap_driver_match, (endpoint_t proc, int major)                );
 _PROTOTYPE( void dmap_endpt_up, (int proc_nr, int is_blk)              );
 _PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr)                    );
 _PROTOTYPE( struct dmap *get_dmap, (endpoint_t proc_e)                 );
+_PROTOTYPE( int do_mapdriver, (void)                                   );
+_PROTOTYPE( int map_service, (struct rprocpub *rpub)                   );
+_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr)                    );
+_PROTOTYPE( struct dmap *get_dmap, (endpoint_t proc_e)                 );
 _PROTOTYPE( int map_driver, (const char *label, int major, endpoint_t proc_nr,
        int dev_style, int flags)                                       );
 _PROTOTYPE( int map_service, (struct rprocpub *rpub)                   );
 
+/* elf_core_dump.c */
+_PROTOTYPE( void write_elf_core_file, (struct filp *f, int csig,
+                                      char *exe_name)                  );
+
 /* exec.c */
 _PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
                          char *frame, vir_bytes frame_len, vir_bytes *pc));
+#define check_bsf_lock() do {                                          \
+       assert(mutex_trylock(&bsf_lock) == 0);                          \
+       unlock_bsf();                                                   \
+                       } while(0)
 
 /* filedes.c */
+_PROTOTYPE( void check_filp_locks, (void)                              );
+_PROTOTYPE( void check_filp_locks_by_me, (void)                                );
+_PROTOTYPE( void init_filps, (void)                                    );
 _PROTOTYPE( struct filp *find_filp, (struct vnode *vp, mode_t bits)    );
-_PROTOTYPE( int get_fd, (int start, mode_t bits, int *k, 
+_PROTOTYPE( int get_fd, (int start, mode_t bits, int *k,
             struct filp **fpt)                                         );
-_PROTOTYPE( struct filp *get_filp, (int fild)                          );
-_PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild)      );
-_PROTOTYPE( int invalidate, (struct filp *)                            );
-_PROTOTYPE( filp_id_t verify_fd, (endpoint_t ep, int fd)               );
+_PROTOTYPE( struct filp *get_filp, (int fild, tll_access_t locktype)                           );
+_PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild,
+                                       tll_access_t locktype)          );
+_PROTOTYPE( void lock_filp, (struct filp *filp, tll_access_t locktype) );
+_PROTOTYPE( void unlock_filp, (struct filp *filp)                      );
+_PROTOTYPE( void unlock_filps, (struct filp *filp1, struct filp *filp2)        );
+_PROTOTYPE( int invalidate_filp, (struct filp *)                       );
+_PROTOTYPE( void invalidate_filp_by_endpt, (endpoint_t proc_e)         );
 _PROTOTYPE( int do_verify_fd, (void)                                   );
 _PROTOTYPE( int set_filp, (filp_id_t sfilp)                            );
 _PROTOTYPE( int do_set_filp, (void)                                    );
@@ -74,7 +108,6 @@ _PROTOTYPE( void close_filp, (struct filp *fp)                               );
 
 /* fscall.c */
 _PROTOTYPE( void nested_fs_call, (message *m)                          );
-_PROTOTYPE( void nested_dev_call, (message *m)                         );
 
 /* link.c */
 _PROTOTYPE( int do_link, (void)                                                );
@@ -93,6 +126,9 @@ _PROTOTYPE( void lock_revive, (void)                                 );
 /* main.c */
 _PROTOTYPE( int main, (void)                                           );
 _PROTOTYPE( void reply, (int whom, int result)                         );
+_PROTOTYPE( void lock_proc, (struct fproc *rfp, int force_lock)                );
+_PROTOTYPE( void unlock_proc, (struct fproc *rfp)                      );
+_PROTOTYPE( void *do_dummy, (void *arg)                                        );
 
 /* misc.c */
 _PROTOTYPE( int do_dup, (void)                                         );
@@ -107,54 +143,62 @@ _PROTOTYPE( int do_fsync, (void)                                  );
 _PROTOTYPE( void pm_reboot, (void)                                     );
 _PROTOTYPE( int do_svrctl, (void)                                      );
 _PROTOTYPE( int do_getsysinfo, (void)                                  );
-_PROTOTYPE( int pm_dumpcore, (int proc_e, int sig, char *exe_name)      );
+_PROTOTYPE( int pm_dumpcore, (endpoint_t proc_e, int sig,
+                               vir_bytes exe_name)                     );
 _PROTOTYPE( void ds_event, (void)                                      );
 
 /* mount.c */
-_PROTOTYPE( int do_fslogin, (void)                                      );
+_PROTOTYPE( int do_fsready, (void)                                      );
 _PROTOTYPE( int do_mount, (void)                                       );
 _PROTOTYPE( int do_umount, (void)                                      );
+_PROTOTYPE( int is_nonedev, (dev_t dev)                                        );
+_PROTOTYPE( void mount_pfs, (void)                                     );
+_PROTOTYPE( int mount_fs, (dev_t dev, char fullpath[PATH_MAX+1],
+                                  endpoint_t fs_e, int rdonly,
+                                  char mount_label[LABEL_MAX])         );
 _PROTOTYPE( int unmount, (dev_t dev, char *label)                      );
+_PROTOTYPE( void unmount_all, (void)                                   );
 
 /* open.c */
 _PROTOTYPE( int do_close, (void)                                       );
 _PROTOTYPE( int close_fd, (struct fproc *rfp, int fd_nr)               );
 _PROTOTYPE( void close_reply, (void)                                   );
+_PROTOTYPE( int common_open, (char path[PATH_MAX], int oflags,
+                               mode_t omode)                           );
 _PROTOTYPE( int do_creat, (void)                                       );
 _PROTOTYPE( int do_lseek, (void)                                       );
 _PROTOTYPE( int do_llseek, (void)                                      );
 _PROTOTYPE( int do_mknod, (void)                                       );
 _PROTOTYPE( int do_mkdir, (void)                                       );
 _PROTOTYPE( int do_open, (void)                                                );
-_PROTOTYPE( int common_open, (register int oflags, mode_t omode)       );
 _PROTOTYPE( int do_slink, (void)                                        );
 _PROTOTYPE( int do_vm_open, (void)                                     );
 _PROTOTYPE( int do_vm_close, (void)                                    );
 
 /* path.c */
-_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, int flags,
-                                               struct fproc *rfp)      );
-_PROTOTYPE( struct vnode *eat_path, (int flags, struct fproc *rfp)     );
-_PROTOTYPE( struct vnode *last_dir, (struct fproc *rfp)                        );
+_PROTOTYPE( struct vnode *advance, (struct vnode *dirp, struct lookup *resolve,
+                                   struct fproc *rfp)                  );
+_PROTOTYPE( struct vnode *eat_path, (struct lookup *resolve,
+                                    struct fproc *rfp)                 );
+_PROTOTYPE( struct vnode *last_dir, (struct lookup *resolve,
+                                    struct fproc *rfp)                 );
+_PROTOTYPE( void lookup_init, (struct lookup *resolve, char *path, int flags,
+                              struct vmnt **vmp, struct vnode **vp)    );
 _PROTOTYPE( int get_name, (struct vnode *dirp, struct vnode *entry,
                                                        char *_name)    );
-_PROTOTYPE( int canonical_path, (char *orig_path, char *canon_path,
-                                               struct fproc *rfp)      );
-_PROTOTYPE( int check_perms, (endpoint_t ep, cp_grant_id_t gid,
-                                                       int strlen)     );
+_PROTOTYPE( int canonical_path, (char *orig_path, struct fproc *rfp)   );
 _PROTOTYPE( int do_check_perms, (void)                                 );
 
 /* pipe.c */
 _PROTOTYPE( int do_pipe, (void)                                                );
-_PROTOTYPE( int map_vnode, (struct vnode *vp)                          );
+_PROTOTYPE( int map_vnode, (struct vnode *vp, endpoint_t fs_e)         );
 _PROTOTYPE( void unpause, (int proc_nr_e)                              );
 _PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag,
              int oflags, int bytes, u64_t position, int notouch)       );
 _PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count)   );
 _PROTOTYPE( void revive, (int proc_nr, int bytes)                      );
 _PROTOTYPE( void suspend, (int task)                                   );
-_PROTOTYPE( void pipe_suspend, (int rw_flag, int fd_nr, char *buf,
-                                                       size_t size)    );
+_PROTOTYPE( void pipe_suspend, (struct filp *rfilp, char *buf, size_t size));
 _PROTOTYPE( void unsuspend_by_endpt, (endpoint_t)                      );
 _PROTOTYPE( void wait_for, (endpoint_t)                                        );
 #if DO_SANITYCHECKS
@@ -173,9 +217,13 @@ _PROTOTYPE( int read_only, (struct vnode *vp)                              );
 /* read.c */
 _PROTOTYPE( int do_read, (void)                                                );
 _PROTOTYPE( int do_getdents, (void)                                    );
-_PROTOTYPE( int read_write, (int rw_flag)                              );
-_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr,
-               int fd_nr, struct filp *f, char *buf, size_t req_size)  );
+_PROTOTYPE( void lock_bsf, (void)                                      );
+_PROTOTYPE( void unlock_bsf, (void)                                    );
+_PROTOTYPE( int do_read_write, (int rw_flag)                           );
+_PROTOTYPE( int read_write, (int rw_flag, struct filp *f, char *buffer,
+                            size_t nbytes, endpoint_t for_e)                           );
+_PROTOTYPE( int rw_pipe, (int rw_flag, endpoint_t usr, struct filp *f,
+                        char *buf, size_t req_size)    );
 
 /* request.c */
 _PROTOTYPE( int req_breadwrite, (endpoint_t fs_e, endpoint_t user_e,
@@ -187,7 +235,7 @@ _PROTOTYPE( int req_chmod, (int fs_e, ino_t inode_nr, mode_t rmode,
 _PROTOTYPE( int req_chown, (endpoint_t fs_e, ino_t inode_nr,
        uid_t newuid, gid_t newgid, mode_t *new_modep)  );
 _PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode,
-               uid_t uid, gid_t gid, char *path, node_details_t *res)  ); 
+               uid_t uid, gid_t gid, char *path, node_details_t *res)  );
 _PROTOTYPE( int req_flush, (endpoint_t fs_e, dev_t dev)                        );
 _PROTOTYPE( int req_fstatfs, (int fs_e, int who_e, char *buf)          );
 _PROTOTYPE( int req_statvfs, (int fs_e, int who_e, char *buf)          );
@@ -200,7 +248,7 @@ _PROTOTYPE( int req_inhibread, (endpoint_t fs_e, ino_t inode_nr)    );
 _PROTOTYPE( int req_link, (endpoint_t fs_e, ino_t link_parent,
                                        char *lastc, ino_t linked_file) );
 _PROTOTYPE( int req_lookup, (endpoint_t fs_e, ino_t dir_ino, ino_t root_ino,
-                            uid_t uid, gid_t gid, int flags,
+                            uid_t uid, gid_t gid, struct lookup *resolve,
                             lookup_res_t *res, struct fproc *rfp)      );
 _PROTOTYPE( int req_mkdir, (endpoint_t fs_e, ino_t inode_nr,
        char *lastc, uid_t uid, gid_t gid, mode_t dmode)                );
@@ -213,16 +261,17 @@ _PROTOTYPE( int req_newnode, (endpoint_t fs_e, uid_t uid,
                                dev_t dev, struct node_details *res)    );
 _PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count)     );
 _PROTOTYPE( int req_rdlink, (endpoint_t fs_e, ino_t inode_nr,
-                               endpoint_t who_e, char *buf, size_t len, 
+                               endpoint_t who_e, char *buf, size_t len,
                                int direct)                             );
 _PROTOTYPE( int req_readsuper, (endpoint_t fs_e, char *driver_name,
                                dev_t dev, int readonly, int isroot,
-                               struct node_details *res_nodep)         );
+                               struct node_details *res_nodep,
+                               int *con_reqs)                          );
 _PROTOTYPE( int req_readwrite, (endpoint_t fs_e, ino_t inode_nr,
                                u64_t pos, int rw_flag,
                                endpoint_t user_e, char *user_addr,
                                unsigned int num_of_bytes, u64_t *new_posp,
-                               unsigned int *cum_iop)                                  ); 
+                               unsigned int *cum_iop)                  );
 _PROTOTYPE( int req_rename, (endpoint_t fs_e, ino_t old_dir,
                        char *old_name, ino_t new_dir, char *new_name)  );
 _PROTOTYPE( int req_rmdir, (endpoint_t fs_e, ino_t inode_nr,
@@ -238,7 +287,7 @@ _PROTOTYPE( int req_unlink, (endpoint_t fs_e, ino_t inode_nr,
 _PROTOTYPE( int req_unmount, (endpoint_t fs_e)                          );
 _PROTOTYPE( int req_utime, (endpoint_t fs_e, ino_t inode_nr,
                                        time_t actime, time_t modtime)  );
-_PROTOTYPE( int req_newdriver, (endpoint_t fs_e, dev_t dev, 
+_PROTOTYPE( int req_newdriver, (endpoint_t fs_e, dev_t dev,
             char *label)                                               );
 
 /* stadir.c */
@@ -250,17 +299,28 @@ _PROTOTYPE( int do_stat, (void)                                           );
 _PROTOTYPE( int do_fstatfs, (void)                                     );
 _PROTOTYPE( int do_statvfs, (void)                                     );
 _PROTOTYPE( int do_fstatvfs, (void)                                    );
-_PROTOTYPE( int do_rdlink, (void)                                      );
-_PROTOTYPE( int do_lstat, (void)                                       );
+_PROTOTYPE( int do_rdlink, (void)                                      );
+_PROTOTYPE( int do_lstat, (void)                                       );
 
 /* time.c */
 _PROTOTYPE( int do_utime, (void)                                       );
 
+/* tll.c */
+_PROTOTYPE( void tll_downgrade, (tll_t *tllp)                          );
+_PROTOTYPE( int tll_haspendinglock, (tll_t *tllp)                      );
+_PROTOTYPE( void tll_init, (tll_t *tllp)                               );
+_PROTOTYPE( int tll_islocked, (tll_t *tllp)                            );
+_PROTOTYPE( int tll_lock, (tll_t *tllp, tll_access_t locktype)         );
+_PROTOTYPE( int tll_locked_by_me, (tll_t *tllp)                                );
+_PROTOTYPE( void tll_lockstat, (tll_t *tllp)                           );
+_PROTOTYPE( int tll_unlock, (tll_t *tllp)                              );
+_PROTOTYPE( void tll_upgrade, (tll_t *tllp)                            );
+
 /* utility.c */
 _PROTOTYPE( time_t clock_time, (void)                                  );
 _PROTOTYPE( unsigned conv2, (int norm, int w)                          );
 _PROTOTYPE( long conv4, (int norm, long x)                             );
-_PROTOTYPE( int fetch_name, (char *path, int len, int flag)            );
+_PROTOTYPE( int fetch_name, (char *path, int len, int flag, char *dest)                );
 _PROTOTYPE( int no_sys, (void)                                         );
 _PROTOTYPE( int isokendpt_f, (char *f, int l, endpoint_t e, int *p, int ft));
 _PROTOTYPE( int in_group, (struct fproc *rfp, gid_t grp)               );
@@ -269,14 +329,27 @@ _PROTOTYPE( int in_group, (struct fproc *rfp, gid_t grp)          );
 #define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0)
 
 /* vmnt.c */
-_PROTOTYPE( struct vmnt *get_free_vmnt, (short *index)                  );
-_PROTOTYPE( struct vmnt *find_vmnt, (int fs_e)                          );
+_PROTOTYPE( void check_vmnt_locks, (void)                              );
+_PROTOTYPE( void check_vmnt_locks_by_me, (struct fproc *rfp)           );
+_PROTOTYPE( struct vmnt *get_free_vmnt, (void)                         );
+_PROTOTYPE( struct vmnt *find_vmnt, (endpoint_t fs_e)                  );
+_PROTOTYPE( struct vmnt *get_locked_vmnt, (struct fproc *rfp)          );
+_PROTOTYPE( void init_vmnts, (void)                                    );
+_PROTOTYPE( int lock_vmnt, (struct vmnt *vp, tll_access_t locktype)    );
+_PROTOTYPE( void unlock_vmnt, (struct vmnt *vp)                                );
+_PROTOTYPE( void vmnt_unmap_by_endpt, (endpoint_t proc_e)              );
 
 /* vnode.c */
+_PROTOTYPE( void check_vnode_locks, (void)                             );
+_PROTOTYPE( void check_vnode_locks_by_me, (struct fproc *rfp)          );
 _PROTOTYPE( struct vnode *get_free_vnode, (void)                       );
 _PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb)              );
+_PROTOTYPE( void init_vnodes, (void)                                   );
+_PROTOTYPE( int is_vnode_locked, (struct vnode *vp)                    );
+_PROTOTYPE( int lock_vnode, (struct vnode *vp, tll_access_t locktype)  );
+_PROTOTYPE( void unlock_vnode, (struct vnode *vp)                      );
 _PROTOTYPE( void dup_vnode, (struct vnode *vp)                          );
-_PROTOTYPE( void put_vnode, (struct vnode *vp)                          );
+_PROTOTYPE( void put_vnode, (struct vnode *vp)                         );
 _PROTOTYPE( void vnode_clean_refs, (struct vnode *vp)                   );
 #if DO_SANITYCHECKS
 _PROTOTYPE( int check_vrefs, (void)                    );
@@ -301,5 +374,17 @@ _PROTOTYPE( void select_reply2, (endpoint_t driver_e, int minor, int status));
 _PROTOTYPE( void select_timeout_check, (timer_t *)                     );
 _PROTOTYPE( void select_unsuspend_by_endpt, (endpoint_t proc)          );
 
-/* elf_core_dump.c */
-_PROTOTYPE( void write_elf_core_file, (int csig, char *exe_name)       );
+/* worker.c */
+_PROTOTYPE( int worker_available, (void)                               );
+_PROTOTYPE( struct worker_thread *worker_get, (thread_t worker_tid)    );
+_PROTOTYPE( struct job *worker_getjob, (thread_t worker_tid)           );
+_PROTOTYPE( void worker_init, (struct worker_thread *worker)           );
+_PROTOTYPE( struct worker_thread *worker_self, (void)                  );
+_PROTOTYPE( void worker_signal, (struct worker_thread *worker)         );
+_PROTOTYPE( void worker_start, (void *(*func)(void *arg))              );
+_PROTOTYPE( void worker_stop, (struct worker_thread *worker)           );
+_PROTOTYPE( void worker_stop_by_endpt, (endpoint_t proc_e)             );
+_PROTOTYPE( void worker_wait, (void)                                   );
+_PROTOTYPE( void sys_worker_start, (void *(*func)(void *arg))          );
+_PROTOTYPE( void dl_worker_start, (void *(*func)(void *arg))           );
+#endif
index 06bf6dcf27c99b73c86a954b7bea74f6336af243..13df38ae0f4e5e278a6fe2e2bc902b54e2b13091 100644 (file)
@@ -17,6 +17,7 @@
 #include <minix/u64.h>
 #include "file.h"
 #include "fproc.h"
+#include "scratchpad.h"
 #include "param.h"
 #include <dirent.h>
 #include <assert.h>
  *===========================================================================*/
 PUBLIC int do_read()
 {
-  return(read_write(READING));
+  return(do_read_write(READING));
 }
 
 
 /*===========================================================================*
- *                             read_write                                   *
+ *                             lock_bsf                                     *
  *===========================================================================*/
-PUBLIC int read_write(rw_flag)
+PUBLIC void lock_bsf(void)
+{
+  message org_m_in;
+  struct fproc *org_fp;
+  struct worker_thread *org_self;
+
+  if (mutex_trylock(&bsf_lock) == 0)
+       return;
+
+  org_m_in = m_in;
+  org_fp = fp;
+  org_self = self;
+
+  if (mutex_lock(&bsf_lock) != 0)
+       panic("unable to lock block special file lock");
+
+  m_in = org_m_in;
+  fp = org_fp;
+  self = org_self;
+}
+
+/*===========================================================================*
+ *                             unlock_bsf                                   *
+ *===========================================================================*/
+PUBLIC void unlock_bsf(void)
+{
+  if (mutex_unlock(&bsf_lock) != 0)
+       panic("failed to unlock block special file lock");
+}
+
+/*===========================================================================*
+ *                             do_read_write                                *
+ *===========================================================================*/
+PUBLIC int do_read_write(rw_flag)
 int rw_flag;                   /* READING or WRITING */
 {
 /* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
-  register struct filp *f;
-  register struct vnode *vp;
-  u64_t position, res_pos, new_pos;
-  unsigned int cum_io, cum_io_incr, res_cum_io;
-  int op, oflags, r, block_spec, char_spec;
-  int regular;
-  mode_t mode_word;
+  struct filp *f;
+  tll_access_t locktype;
+  int r;
+
+  scratch(fp).file.fd_nr = m_in.fd;
+  scratch(fp).io.io_buffer = m_in.buffer;
+  scratch(fp).io.io_nbytes = (size_t) m_in.nbytes;
 
-  /* If the file descriptor is valid, get the vnode, size and mode. */
-  if (m_in.nbytes < 0) return(EINVAL);
-  if ((f = get_filp(m_in.fd)) == NULL) return(err_code);
+  locktype = (rw_flag == READING) ? VNODE_READ : VNODE_WRITE;
+  if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
+       return(err_code);
   if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
+       unlock_filp(f);
        return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
   }
-  if (m_in.nbytes == 0)
+  if (scratch(fp).io.io_nbytes == 0) {
+       unlock_filp(f);
        return(0);      /* so char special files need not check for 0*/
+  }
+
+  r = read_write(rw_flag, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes,
+                who_e);
+
+  unlock_filp(f);
+  return(r);
+}
+
+/*===========================================================================*
+ *                             read_write                                   *
+ *===========================================================================*/
+PUBLIC int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
+                     endpoint_t for_e)
+{
+  register struct vnode *vp;
+  u64_t position, res_pos, new_pos;
+  unsigned int cum_io, cum_io_incr, res_cum_io;
+  int op, oflags, r, block_spec, char_spec, regular;
+  mode_t mode_word;
 
   position = f->filp_pos;
   oflags = f->filp_flags;
@@ -64,11 +120,14 @@ int rw_flag;                       /* READING or WRITING */
   r = OK;
   cum_io = 0;
 
+  if (size > SSIZE_MAX) return(EINVAL);
+
   if (vp->v_pipe == I_PIPE) {
        if (fp->fp_cum_io_partial != 0) {
-               panic("read_write: fp_cum_io_partial not clear");
+               panic("VFS: read_write: fp_cum_io_partial not clear");
        }
-       return rw_pipe(rw_flag, who_e, m_in.fd, f, m_in.buffer, m_in.nbytes);
+       r = rw_pipe(rw_flag, for_e, f, buf, size);
+       return(r);
   }
 
   op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
@@ -77,12 +136,12 @@ int rw_flag;                       /* READING or WRITING */
 
   if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
        if (vp->v_sdev == NO_DEV)
-               panic("read_write tries to read from character device NO_DEV");
+               panic("VFS: read_write tries to access char dev NO_DEV");
   }
 
   if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) {
        if (vp->v_sdev == NO_DEV)
-               panic("read_write tries to read from block device NO_DEV");
+               panic("VFS: read_write tries to access block dev NO_DEV");
   }
 
   if (char_spec) {                     /* Character special files. */
@@ -92,7 +151,7 @@ int rw_flag;                 /* READING or WRITING */
        suspend_reopen = (f->filp_state != FS_NORMAL);
        dev = (dev_t) vp->v_sdev;
 
-       r = dev_io(op, dev, who_e, m_in.buffer, position, m_in.nbytes, oflags,
+       r = dev_io(op, dev, for_e, buf, position, size, oflags,
                   suspend_reopen);
        if (r >= 0) {
                cum_io = r;
@@ -100,12 +159,16 @@ int rw_flag;                      /* READING or WRITING */
                r = OK;
        }
   } else if (block_spec) {             /* Block special files. */
-       r = req_breadwrite(vp->v_bfs_e, who_e, vp->v_sdev, position,
-               m_in.nbytes, m_in.buffer, rw_flag, &res_pos, &res_cum_io);
+       lock_bsf();
+
+       r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position, size,
+                          buf, rw_flag, &res_pos, &res_cum_io);
        if (r == OK) {
                position = res_pos;
                cum_io += res_cum_io;
        }
+
+       unlock_bsf();
   } else {                             /* Regular files */
        if (rw_flag == WRITING && block_spec == 0) {
                /* Check for O_APPEND flag. */
@@ -113,8 +176,8 @@ int rw_flag;                        /* READING or WRITING */
        }
 
        /* Issue request */
-       r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, who_e,
-                         m_in.buffer, m_in.nbytes, &new_pos, &cum_io_incr);
+       r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, for_e,
+                         buf, size, &new_pos, &cum_io_incr);
 
        if (r >= 0) {
                if (ex64hi(new_pos))
@@ -138,40 +201,40 @@ int rw_flag;                      /* READING or WRITING */
   }
 
   f->filp_pos = position;
+
   if (r == OK) return(cum_io);
   return(r);
 }
 
-
 /*===========================================================================*
  *                             do_getdents                                  *
  *===========================================================================*/
 PUBLIC int do_getdents()
 {
 /* Perform the getdents(fd, buf, size) system call. */
-  int r;
+  int r = OK;
   u64_t new_pos;
   register struct filp *rfilp;
 
   /* Is the file descriptor valid? */
-  if ( (rfilp = get_filp(m_in.fd)) == NULL) {
-         return(err_code);
-  }
-  
+  if ( (rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
+
   if (!(rfilp->filp_mode & R_BIT))
-       return(EBADF);
+       r = EBADF;
+  else if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY)
+       r = EBADF;
 
-  if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY)
-       return(EBADF);
+  if (r == OK) {
+       if (ex64hi(rfilp->filp_pos) != 0)
+               panic("do_getdents: can't handle large offsets");
+
+       r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
+                        rfilp->filp_pos, m_in.buffer, m_in.nbytes,&new_pos,0);
 
-  if (ex64hi(rfilp->filp_pos) != 0)
-       panic("do_getdents: should handle large offsets");
-       
-  r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr, 
-                  rfilp->filp_pos, m_in.buffer, m_in.nbytes, &new_pos, 0);
+       if (r > 0) rfilp->filp_pos = new_pos;
+  }
 
-  if (r > 0)
-       rfilp->filp_pos = new_pos;
+  unlock_filp(rfilp);
   return(r);
 }
 
@@ -179,10 +242,9 @@ PUBLIC int do_getdents()
 /*===========================================================================*
  *                             rw_pipe                                      *
  *===========================================================================*/
-PUBLIC int rw_pipe(rw_flag, usr_e, fd_nr, f, buf, req_size)
+PUBLIC int rw_pipe(rw_flag, usr_e, f, buf, req_size)
 int rw_flag;                   /* READING or WRITING */
 endpoint_t usr_e;
-int fd_nr;
 struct filp *f;
 char *buf;
 size_t req_size;
@@ -192,17 +254,21 @@ size_t req_size;
   struct vnode *vp;
   u64_t position, new_pos;
 
+  /* Must make sure we're operating on locked filp and vnode */
+  assert(tll_islocked(&f->filp_vno->v_lock));
+  assert(mutex_trylock(&f->filp_lock) == -EDEADLK);
+
   oflags = f->filp_flags;
   vp = f->filp_vno;
   position = cvu64((rw_flag == READING) ? vp->v_pipe_rd_pos :
-       vp->v_pipe_wr_pos);
+                                                       vp->v_pipe_wr_pos);
   /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
-  cum_io = fp->fp_cum_io_partial; 
+  cum_io = fp->fp_cum_io_partial;
 
   r = pipe_check(vp, rw_flag, oflags, req_size, position, 0);
   if (r <= 0) {
-       if (r == SUSPEND) pipe_suspend(rw_flag, fd_nr, buf, req_size);
-       return(r);
+       if (r == SUSPEND) pipe_suspend(f, buf, req_size);
+       return(r);
   }
 
   size = r;
@@ -210,7 +276,7 @@ size_t req_size;
 
   /* Truncate read request at size. */
   if((rw_flag == READING) &&
-       cmp64ul(add64ul(position, size), vp->v_size) > 0) {
+       cmp64ul(add64ul(position, size), vp->v_size) > 0) {
        /* Position always should fit in an off_t (LONG_MAX). */
        off_t pos32;
 
@@ -221,7 +287,7 @@ size_t req_size;
        size = vp->v_size - pos32;
   }
 
-  if (vp->v_mapfs_e == 0) 
+  if (vp->v_mapfs_e == 0)
        panic("unmapped pipe");
 
   r = req_readwrite(vp->v_mapfs_e, vp->v_mapinode_nr, position, rw_flag, usr_e,
@@ -236,7 +302,7 @@ size_t req_size;
        buf += cum_io_incr;
        req_size -= cum_io_incr;
   }
-  
+
   /* On write, update file size and access time. */
   if (rw_flag == WRITING) {
        if (cmp64ul(position, vp->v_size) > 0) {
@@ -269,7 +335,7 @@ size_t req_size;
                         * non-atomic
                         */
                        fp->fp_cum_io_partial = cum_io;
-                       pipe_suspend(rw_flag, fd_nr, buf, req_size);
+                       pipe_suspend(f, buf, req_size);
                        return(SUSPEND);
                }
        }
@@ -279,4 +345,3 @@ size_t req_size;
 
   return(r);
 }
-
index 137c338ef26bd8f8988cd9e38ba57d425383c57b..be230da77cf19a928c9ca16e3ee60d3cc299f215 100644 (file)
 #include "fproc.h"
 #include "vmnt.h"
 #include "vnode.h"
+#include "path.h"
 #include "param.h"
 
-FORWARD _PROTOTYPE(int fs_sendrec_f, (char *file, int line, endpoint_t fs_e,
-                                     message *reqm)                    );
-
-#define fs_sendrec(e, m) fs_sendrec_f(__FILE__, __LINE__, (e), (m))
-
 
 /*===========================================================================*
  *                     req_breadwrite                                       *
@@ -94,7 +90,7 @@ PUBLIC int req_chmod(
 
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
-  
+
   /* Copy back actual mode. */
   *new_modep = m.RES_MODE;
 
@@ -151,7 +147,7 @@ PUBLIC int req_create(
   message m;
 
   if (path[0] == '/')
-       panic("req_create: filename starts with '/'");
+       panic("req_create: filename starts with '/'");
 
   len = strlen(path) + 1;
   grant_id = cpf_grant_direct(fs_e, (vir_bytes) path, len, CPF_READ);
@@ -180,7 +176,7 @@ PUBLIC int req_create(
   res->uid     = m.RES_UID;
   res->gid     = m.RES_GID;
   res->dev     = m.RES_DEV;
-  
+
   return(OK);
 }
 
@@ -195,7 +191,7 @@ PUBLIC int req_flush(endpoint_t fs_e, dev_t dev)
   /* Fill in request message */
   m.m_type = REQ_FLUSH;
   m.REQ_DEV = dev;
-    
+
   /* Send/rec request */
   return fs_sendrec(fs_e, &m);
 }
@@ -204,15 +200,15 @@ PUBLIC int req_flush(endpoint_t fs_e, dev_t dev)
 /*===========================================================================*
  *                             req_fstatfs                                  *
  *===========================================================================*/
-PUBLIC int req_fstatfs(int fs_e, int who_e, char *buf)
+PUBLIC int req_fstatfs(int fs_e, int proc_e, char *buf)
 {
   int r;
   cp_grant_id_t grant_id;
   message m;
 
-  grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, sizeof(struct statfs),
+  grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, sizeof(struct statfs),
                        CPF_WRITE);
-  if(grant_id == -1) 
+  if(grant_id == -1)
          panic("req_fstatfs: cpf_grant_magic failed");
 
   /* Fill in request message */
@@ -230,15 +226,15 @@ PUBLIC int req_fstatfs(int fs_e, int who_e, char *buf)
 /*===========================================================================*
  *                             req_statvfs                                  *
  *===========================================================================*/
-PUBLIC int req_statvfs(int fs_e, int who_e, char *buf)
+PUBLIC int req_statvfs(int fs_e, int proc_e, char *buf)
 {
   int r;
   cp_grant_id_t grant_id;
   message m;
 
-  grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, sizeof(struct statvfs),
+  grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, sizeof(struct statvfs),
                        CPF_WRITE);
-  if(grant_id == -1) 
+  if(grant_id == -1)
          panic("req_statvfs: cpf_grant_magic failed");
 
   /* Fill in request message */
@@ -267,7 +263,7 @@ PUBLIC int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end)
   m.REQ_TRC_START_HI = 0;      /* Not used for now, so clear it. */
   m.REQ_TRC_END_LO = end;
   m.REQ_TRC_END_HI = 0;                /* Not used for now, so clear it. */
-  
+
   /* Send/rec request */
   return fs_sendrec(fs_e, &m);
 }
@@ -299,7 +295,7 @@ PUBLIC int req_getdents(
   }
 
   if (grant_id < 0)
-       panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
+       panic("req_getdents: cpf_grant_direct/cpf_grant_magic failed: %d",
                                                                grant_id);
 
   m.m_type = REQ_GETDENTS;
@@ -308,10 +304,10 @@ PUBLIC int req_getdents(
   m.REQ_MEM_SIZE = size;
   m.REQ_SEEK_POS_LO = ex64lo(pos);
   m.REQ_SEEK_POS_HI = 0;       /* Not used for now, so clear it. */
-  
+
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
-  
+
   if (r == OK) {
          *new_pos = cvul64(m.RES_SEEK_POS_LO);
          r = m.RES_NBYTES;
@@ -330,7 +326,7 @@ PUBLIC int req_inhibread(endpoint_t fs_e, ino_t inode_nr)
   /* Fill in request message */
   m.m_type = REQ_INHIBREAD;
   m.REQ_INODE_NR = inode_nr;
-  
+
   /* Send/rec request */
   return fs_sendrec(fs_e, &m);
 }
@@ -365,10 +361,10 @@ PUBLIC int req_link(
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
-  
+
   return(r);
 }
-    
+
 
 /*===========================================================================*
  *                             req_lookup                                   *
@@ -379,7 +375,7 @@ PUBLIC int req_lookup(
   ino_t root_ino,
   uid_t uid,
   gid_t gid,
-  int flags,
+  struct lookup *resolve,
   lookup_res_t *res,
   struct fproc *rfp
 )
@@ -389,31 +385,33 @@ PUBLIC int req_lookup(
   cp_grant_id_t grant_id=0, grant_id2=0;
   message m;
   vfs_ucred_t credentials;
+  int flags;
 
-  grant_id = cpf_grant_direct(fs_e, (vir_bytes) user_fullpath,
-                             sizeof(user_fullpath), CPF_READ | CPF_WRITE);
+  grant_id = cpf_grant_direct(fs_e, (vir_bytes) resolve->l_path, PATH_MAX,
+                             CPF_READ | CPF_WRITE);
   if(grant_id == -1)
          panic("req_lookup: cpf_grant_direct failed");
 
-  len = strlen(user_fullpath) + 1;
+  flags = resolve->l_flags;
+  len = strlen(resolve->l_path) + 1;
 
   m.m_type             = REQ_LOOKUP;
   m.REQ_GRANT          = grant_id;
   m.REQ_PATH_LEN       = len;
-  m.REQ_PATH_SIZE      = sizeof(user_fullpath);
+  m.REQ_PATH_SIZE      = PATH_MAX + 1;
   m.REQ_DIR_INO        = dir_ino;
   m.REQ_ROOT_INO       = root_ino;
 
   if(rfp->fp_ngroups > 0) { /* Is the process member of multiple groups? */
-       /* In that case the FS has to copy the uid/gid credentials */
-       int i;
+       /* In that case the FS has to copy the uid/gid credentials */
+       int i;
 
-       /* Set credentials */
-       credentials.vu_uid = rfp->fp_effuid;
-       credentials.vu_gid = rfp->fp_effgid;
-       credentials.vu_ngroups = rfp->fp_ngroups;
-       for (i = 0; i < rfp->fp_ngroups; i++) 
-               credentials.vu_sgroups[i] = rfp->fp_sgroups[i];
+       /* Set credentials */
+       credentials.vu_uid = rfp->fp_effuid;
+       credentials.vu_gid = rfp->fp_effgid;
+       credentials.vu_ngroups = rfp->fp_ngroups;
+       for (i = 0; i < rfp->fp_ngroups; i++)
+               credentials.vu_sgroups[i] = rfp->fp_sgroups[i];
 
        grant_id2 = cpf_grant_direct(fs_e, (vir_bytes) &credentials,
                                     sizeof(credentials), CPF_READ);
@@ -422,9 +420,9 @@ PUBLIC int req_lookup(
 
        m.REQ_GRANT2    = grant_id2;
        m.REQ_UCRED_SIZE= sizeof(credentials);
-       flags           |= PATH_GET_UCRED;
+       flags           |= PATH_GET_UCRED;
   } else {
-       /* When there's only one gid, we can send it directly */
+       /* When there's only one gid, we can send it directly */
        m.REQ_UID       = uid;
        m.REQ_GID       = gid;
        flags           &= ~PATH_GET_UCRED;
@@ -435,7 +433,7 @@ PUBLIC int req_lookup(
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
-  if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2); 
+  if(rfp->fp_ngroups > 0) cpf_revoke(grant_id2);
 
   /* Fill in response according to the return value */
   res->fs_e = m.m_source;
@@ -465,7 +463,7 @@ PUBLIC int req_lookup(
   default:
          break;
   }
-  
+
   return(r);
 }
 
@@ -486,7 +484,7 @@ PUBLIC int req_mkdir(
   cp_grant_id_t grant_id;
   size_t len;
   message m;
-  
+
   len = strlen(lastc) + 1;
   grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
   if(grant_id == -1)
@@ -526,7 +524,7 @@ PUBLIC int req_mknod(
   size_t len;
   cp_grant_id_t grant_id;
   message m;
-  
+
   len = strlen(lastc) + 1;
   grant_id = cpf_grant_direct(fs_e, (vir_bytes)lastc, len, CPF_READ);
   if(grant_id == -1)
@@ -541,11 +539,11 @@ PUBLIC int req_mknod(
   m.REQ_GID = gid;
   m.REQ_GRANT = grant_id;
   m.REQ_PATH_LEN = len;
-  
+
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
-  
+
   return(r);
 }
 
@@ -661,10 +659,10 @@ int count;
 /*===========================================================================*
  *                             req_rdlink                                   *
  *===========================================================================*/
-PUBLIC int req_rdlink(fs_e, inode_nr, who_e, buf, len, direct)
+PUBLIC int req_rdlink(fs_e, inode_nr, proc_e, buf, len, direct)
 endpoint_t fs_e;
 ino_t inode_nr;
-endpoint_t who_e;
+endpoint_t proc_e;
 char *buf;
 size_t len;
 int direct; /* set to 1 to use direct grants instead of magic grants */
@@ -676,7 +674,7 @@ int direct; /* set to 1 to use direct grants instead of magic grants */
   if (direct) {
        grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, len, CPF_WRITE);
   } else {
-       grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf, len,
+       grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, len,
                                                                CPF_WRITE);
   }
   if(grant_id == -1)
@@ -687,7 +685,7 @@ int direct; /* set to 1 to use direct grants instead of magic grants */
   m.REQ_INODE_NR = inode_nr;
   m.REQ_GRANT = grant_id;
   m.REQ_MEM_SIZE = len;
-  
+
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
@@ -707,14 +705,15 @@ PUBLIC int req_readsuper(
   dev_t dev,
   int readonly,
   int isroot,
-  struct node_details *res_nodep
+  struct node_details *res_nodep,
+  int *con_reqs
 )
 {
   int r;
   cp_grant_id_t grant_id;
   size_t len;
   message m;
-  
+
   len = strlen(label)+1;
   grant_id = cpf_grant_direct(fs_e, (vir_bytes) label, len, CPF_READ);
   if (grant_id == -1)
@@ -724,11 +723,11 @@ PUBLIC int req_readsuper(
   m.m_type = REQ_READSUPER;
   m.REQ_FLAGS = 0;
   if(readonly) m.REQ_FLAGS |= REQ_RDONLY;
-  if(isroot)   m.REQ_FLAGS |= REQ_ISROOT;   
+  if(isroot)   m.REQ_FLAGS |= REQ_ISROOT;
   m.REQ_GRANT = grant_id;
   m.REQ_DEV = dev;
   m.REQ_PATH_LEN = len;
-  
+
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
@@ -741,6 +740,7 @@ PUBLIC int req_readsuper(
        res_nodep->fsize = m.RES_FILE_SIZE_LO;
        res_nodep->uid = m.RES_UID;
        res_nodep->gid = m.RES_GID;
+       *con_reqs = m.RES_CONREQS;
   }
 
   return(r);
@@ -770,7 +770,7 @@ unsigned int *cum_iop;
          panic("req_readwrite: pos too large");
 
   grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes,
-                            (rw_flag==READING ? CPF_WRITE:CPF_READ));
+                            (rw_flag==READING ? CPF_WRITE:CPF_READ));
   if (grant_id == -1)
          panic("req_readwrite: cpf_grant_magic failed");
 
@@ -781,7 +781,7 @@ unsigned int *cum_iop;
   m.REQ_SEEK_POS_LO = ex64lo(pos);
   m.REQ_SEEK_POS_HI = 0;       /* Not used for now, so clear it. */
   m.REQ_NBYTES = num_of_bytes;
-  
+
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
@@ -791,7 +791,7 @@ unsigned int *cum_iop;
        *new_posp = cvul64(m.RES_SEEK_POS_LO);
        *cum_iop = m.RES_NBYTES;
   }
-  
+
   return(r);
 }
 
@@ -829,7 +829,7 @@ char *new_name;
   m.REQ_REN_LEN_OLD = len_old;
   m.REQ_REN_GRANT_NEW = gid_new;
   m.REQ_REN_LEN_NEW = len_new;
-  
+
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(gid_old);
@@ -851,7 +851,7 @@ char *lastc;
   cp_grant_id_t grant_id;
   size_t len;
   message m;
-  
+
   len = strlen(lastc) + 1;
   grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
   if(grant_id == -1)
@@ -878,7 +878,7 @@ PUBLIC int req_slink(
   endpoint_t fs_e,
   ino_t inode_nr,
   char *lastc,
-  endpoint_t who_e,
+  endpoint_t proc_e,
   char *path_addr,
   unsigned short path_length,
   uid_t uid,
@@ -895,7 +895,7 @@ PUBLIC int req_slink(
   if(gid_name == -1)
          panic("req_slink: cpf_grant_direct failed");
 
-  gid_buf = cpf_grant_magic(fs_e, who_e, (vir_bytes) path_addr, path_length,
+  gid_buf = cpf_grant_magic(fs_e, proc_e, (vir_bytes) path_addr, path_length,
                            CPF_READ);
   if(gid_buf == -1) {
          cpf_revoke(gid_name);
@@ -924,10 +924,10 @@ PUBLIC int req_slink(
 /*===========================================================================*
  *                             req_stat                                     *
  *===========================================================================*/
-PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos, stat_version)
+PUBLIC int req_stat(fs_e, inode_nr, proc_e, buf, pos, stat_version)
 int fs_e;
 ino_t inode_nr;
-int who_e;
+int proc_e;
 char *buf;
 int pos;
 int stat_version;
@@ -940,9 +940,9 @@ int stat_version;
 
   if (pos != 0 || stat_version != 0)
          grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb,
-                                     sizeof(struct stat), CPF_WRITE);
+                                     sizeof(struct stat), CPF_WRITE);
   else
-         grant_id = cpf_grant_magic(fs_e, who_e, (vir_bytes) buf,
+         grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf,
                                sizeof(struct stat), CPF_WRITE);
 
   if (grant_id < 0)
@@ -963,7 +963,7 @@ int stat_version;
   if (pos != 0)
        sb.st_size -= pos;
   if (stat_version == 0) {
-       r = sys_vircopy(SELF, D, (vir_bytes) &sb, who_e, D, (vir_bytes) buf, 
+       r = sys_vircopy(SELF, D, (vir_bytes) &sb, proc_e, D, (vir_bytes) buf,
                        sizeof(struct stat));
        return(r);
   }
@@ -971,7 +971,7 @@ int stat_version;
   /* User needs old struct stat.
    * Just 1 prev version at this moment */
   assert(stat_version == 1);
+
 /* XXX until that st_Xtime macroses used, we have to undefine them,
  * because of minix_prev_stat
  */
@@ -1000,9 +1000,9 @@ int stat_version;
   old_sb.st_ctime = sb.st_ctime;
 #endif
 
-  r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, who_e, D, (vir_bytes) buf, 
+  r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, proc_e, D, (vir_bytes) buf,
                  sizeof(struct minix_prev_stat));
-  
+
   return(r);
 }
 
@@ -1011,13 +1011,13 @@ int stat_version;
  *                             req_sync                                     *
  *===========================================================================*/
 PUBLIC int req_sync(fs_e)
-endpoint_t fs_e; 
+endpoint_t fs_e;
 {
   message m;
 
   /* Fill in request message */
   m.m_type = REQ_SYNC;
-  
+
   /* Send/rec request */
   return fs_sendrec(fs_e, &m);
 }
@@ -1035,7 +1035,7 @@ char *lastc;
   size_t len;
   int r;
   message m;
-  
+
   len = strlen(lastc) + 1;
   grant_id = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
   if(grant_id == -1)
@@ -1050,7 +1050,7 @@ char *lastc;
   /* Send/rec request */
   r = fs_sendrec(fs_e, &m);
   cpf_revoke(grant_id);
-  
+
   return(r);
 }
 
@@ -1059,13 +1059,13 @@ char *lastc;
  *                             req_unmount                                  *
  *===========================================================================*/
 PUBLIC int req_unmount(fs_e)
-endpoint_t fs_e; 
+endpoint_t fs_e;
 {
   message m;
 
   /* Fill in request message */
   m.m_type = REQ_UNMOUNT;
-    
+
   /* Send/rec request */
   return fs_sendrec(fs_e, &m);
 }
@@ -1087,62 +1087,7 @@ time_t modtime;
   m.REQ_INODE_NR = inode_nr;
   m.REQ_ACTIME = actime;
   m.REQ_MODTIME = modtime;
-  
+
   /* Send/rec request */
   return fs_sendrec(fs_e, &m);
 }
-
-
-/*===========================================================================*
- *                             fs_sendrec                                   *
- *===========================================================================*/
-PRIVATE int fs_sendrec_f(char *file, int line, endpoint_t fs_e, message *reqm)
-{
-/* This is the low level function that sends requests to FS processes.
- * It also handles driver recovery mechanism and reissuing the
- * request which failed due to a dead driver.
- */
-  int r;
-  message origm;
-
-  if(fs_e <= 0 || fs_e == NONE)
-       panic("talking to bogus endpoint: %d", fs_e);
-
-  /* Make a copy of the request so that we can load it back in
-   * case of a dead driver */
-  origm = *reqm;
-
-  /* In response to the request we sent, some file systems may send back their
-   * own VFS request, instead of a reply. VFS currently offers limited support
-   * for this. As long as the FS keeps sending requests, we process them and
-   * send back a reply. We break out of the loop as soon as the FS sends a
-   * reply to the original request.
-   *
-   * There is no form of locking or whatever on global data structures, so it
-   * is quite easy to mess things up; hence, 'limited' support. A future async
-   * VFS will solve this problem for good.
-   */
-  for (;;) {
-       /* Do the actual send, receive */
-       if (OK != (r = sendrec(fs_e, reqm))) {
-               printf("VFS:fs_sendrec:%s:%d: error sending message. "
-                      "FS_e: %d req_nr: %d err: %d\n", file, line, fs_e,
-                      reqm->m_type, r);
-               util_stacktrace();
-               return(r);
-       }
-
-       /* If the type field is 0 (OK) or negative (E*), this is a reply. If it
-        * contains a positive nonzero value, this is a request.
-        */
-       if (reqm->m_type <= 0)
-               break; /* Reply */
-
-       /* Request */
-       nested_fs_call(reqm);
-  }
-
-  /* Return message type */
-  return(reqm->m_type);
-}
-
index 0ec8aab30e12f3975e23601ec1c24a403e10c463..74f612bf9a1cde38a23b868ee208d6c70e9ee134 100644 (file)
@@ -1,3 +1,5 @@
+#ifndef __VFS_REQUEST_H__
+#define __VFS_REQUEST_H__
 
 /* Low level request messages are built and sent by wrapper functions.
  * This file contains the request and response structures for accessing
 
 /* Structure for response that contains inode details */
 typedef struct node_details {
-       endpoint_t fs_e;
-       ino_t inode_nr;
-       mode_t fmode;
-       off_t fsize;
-       uid_t uid;
-       gid_t gid;
-
-       /* For char/block special files */
-       dev_t dev;
+  endpoint_t fs_e;
+  ino_t inode_nr;
+  mode_t fmode;
+  off_t fsize;
+  uid_t uid;
+  gid_t gid;
+
+  /* For char/block special files */
+  dev_t dev;
 } node_details_t;
 
 /* Structure for a lookup response */
 typedef struct lookup_res {
-       endpoint_t fs_e;
-       ino_t inode_nr;
-       mode_t fmode;
-       off_t fsize;
-       uid_t uid;
-       gid_t gid;
-       /* For char/block special files */
-       dev_t dev;
-       
-       /* Fields used for handling mount point and symbolic links */
-       int char_processed;
-       unsigned char symloop;
+  endpoint_t fs_e;
+  ino_t inode_nr;
+  mode_t fmode;
+  off_t fsize;
+  uid_t uid;
+  gid_t gid;
+  /* For char/block special files */
+  dev_t dev;
+
+  /* Fields used for handling mount point and symbolic links */
+  int char_processed;
+  unsigned char symloop;
 } lookup_res_t;
 
 
-/* Structure for REQ_ request */
+#endif
index ae9a8ded0d03840855021abc973f6bf7bad52e34..90e23ab0608f6ed304d417b96b645718eeb060bc 100644 (file)
@@ -2,7 +2,7 @@
  *
  * The entry points into this file are
  *   do_select:               perform the SELECT system call
- *   select_callback:  notify select system of possible fd operation 
+ *   select_callback:  notify select system of possible fd operation
  *   select_unsuspend_by_endpt: cancel a blocking select on exiting driver
  */
 
@@ -51,6 +51,7 @@ FORWARD _PROTOTYPE(void ops2tab, (int ops, int fd, struct selectentry *e));
 FORWARD _PROTOTYPE(int is_regular_file, (struct filp *f)               );
 FORWARD _PROTOTYPE(int is_pipe, (struct filp *f)                       );
 FORWARD _PROTOTYPE(int is_supported_major, (struct filp *f)                    );
+FORWARD _PROTOTYPE(void select_lock_filp, (struct filp *f, int ops)    );
 FORWARD _PROTOTYPE(int select_request_async, (struct filp *f, int *ops,
                                               int block)               );
 FORWARD _PROTOTYPE(int select_request_file, (struct filp *f, int *ops,
@@ -69,9 +70,9 @@ FORWARD _PROTOTYPE(int tab2ops, (int fd, struct selectentry *e)               );
 FORWARD _PROTOTYPE(void wipe_select, (struct selectentry *s)           );
 
 PRIVATE struct fdtype {
-       int (*select_request)(struct filp *, int *ops, int block);      
+       int (*select_request)(struct filp *, int *ops, int block);
        int (*type_match)(struct filp *f);
-} fdtypes[] = { 
+} fdtypes[] = {
        { select_request_major, is_supported_major },
        { select_request_file, is_regular_file },
        { select_request_pipe, is_pipe },
@@ -93,9 +94,9 @@ PUBLIC int do_select(void)
 /* Implement the select(nfds, readfds, writefds, errorfds, timeout) system
  * call. First we copy the arguments and verify their sanity. Then we check
  * whether there are file descriptors that satisfy the select call right of the
- * bat. If so, or if there are no ready file descriptors but the process 
+ * bat. If so, or if there are no ready file descriptors but the process
  * requested to return immediately, we return the result. Otherwise we set a
- * timeout and wait for either the file descriptors to become ready or the 
+ * timeout and wait for either the file descriptors to become ready or the
  * timer to go off. If no timeout value was provided, we wait indefinitely. */
 
   int r, nfds, do_timeout = 0, fd, s;
@@ -121,11 +122,11 @@ PUBLIC int do_select(void)
   se->vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS;
 
   /* Copy fdsets from the process */
-  if ((r = copy_fdsets(se, nfds, FROM_PROC)) != OK) return(r); 
+  if ((r = copy_fdsets(se, nfds, FROM_PROC)) != OK) return(r);
 
   /* Did the process set a timeout value? If so, retrieve it. */
   if (m_in.SEL_TIMEOUT != NULL) {
-       do_timeout = 1;
+       do_timeout = 1;
        r = sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_TIMEOUT, SELF, D,
                        (vir_bytes) &timeout, sizeof(timeout));
        if (r != OK) return(r);
@@ -136,20 +137,20 @@ PUBLIC int do_select(void)
        return(EINVAL);
 
   /* If there is no timeout, we block forever. Otherwise, we block up to the
-   * specified time interval.  
+   * specified time interval.
    */
   if (!do_timeout)     /* No timeout value set */
        se->block = 1;
   else if (do_timeout && (timeout.tv_sec > 0 || timeout.tv_usec > 0))
-       se->block = 1;
+       se->block = 1;
   else                 /* timeout set as (0,0) - this effects a poll */
-       se->block = 0;  
+       se->block = 0;
   se->expiry = 0;      /* no timer set (yet) */
 
   /* Verify that file descriptors are okay to select on */
   for (fd = 0; fd < nfds; fd++) {
-       struct filp *f;
-       int type, ops;
+       struct filp *f;
+       int type, ops;
 
        /* Because the select() interface implicitly includes file descriptors
         * you might not want to select on, we have to figure out whether we're
@@ -157,20 +158,19 @@ PUBLIC int do_select(void)
         * inherited from the parent proc and file descriptors that have been
         * close()d, but had a lower fd than one in the current set.
         */
-       if (!(ops = tab2ops(fd, se))) 
+       if (!(ops = tab2ops(fd, se)))
                continue; /* No operations set; nothing to do for this fd */
 
        /* Get filp belonging to this fd */
-       f = se->filps[fd] = get_filp(fd);
+       f = se->filps[fd] = get_filp(fd, VNODE_READ);
        if (f == NULL) {
-               if (err_code == EBADF) 
+               if (err_code == EBADF)
                        r = err_code;
                else /* File descriptor is 'ready' to return EIO */
                        r = EINTR;
 
                return(r);
-       } else if (f->filp_vno == NULL) 
-               return(EBADF);
+       }
 
        /* Check file types. According to POSIX 2008:
         * "The pselect() and select() functions shall support regular files,
@@ -194,7 +194,8 @@ PUBLIC int do_select(void)
                        break;
                }
        }
-       if (se->type[fd] == -1) /* Type not found */
+       unlock_filp(f);
+       if (se->type[fd] == -1) /* Type not found */
                return(EBADF);
   }
 
@@ -202,30 +203,34 @@ PUBLIC int do_select(void)
   for (fd = 0; fd < nfds; fd++) {
        int ops, r;
        struct filp *f;
-       
+
        /* Again, check for involuntarily selected fd's */
-       if (!(ops = tab2ops(fd, se))) 
+       if (!(ops = tab2ops(fd, se)))
                continue; /* No operations set; nothing to do for this fd */
 
-       /* Test filp for select operations if not already done so. e.g., 
+       /* Test filp for select operations if not already done so. e.g.,
         * processes sharing a filp and both doing a select on that filp. */
        f = se->filps[fd];
+       select_lock_filp(f, f->filp_select_ops | ops);
        if ((f->filp_select_ops & ops) != ops) {
                int wantops;
 
                wantops = (f->filp_select_ops |= ops);
                r = do_select_request(se, fd, &wantops);
+               unlock_filp(f);
                if (r != SEL_OK) {
                        if (r == SEL_DEFERRED) continue;
                        else break; /* Error or bogus return code; abort */
                }
-               
+
                /* The select request above might have turned on/off some
                 * operations because they were 'ready' or not meaningful.
                 * Either way, we might have a result and we need to store them
                 * in the select table entry. */
                if (wantops & ops) ops2tab(wantops, fd, se);
-       } 
+       } else {
+               unlock_filp(f);
+       }
   }
 
   if ((se->nreadyfds > 0 || !se->block) && !is_deferred(se)) {
@@ -243,7 +248,7 @@ PUBLIC int do_select(void)
 
        return(se->nreadyfds);
   }
+
   /* Convert timeval to ticks and set the timer. If it fails, undo
    * all, return error.
    */
@@ -322,9 +327,9 @@ PRIVATE int is_supported_major(struct filp *f)
   if (!(f && f->filp_vno)) return(FALSE);
   if ((f->filp_vno->v_mode & I_TYPE) != I_CHAR_SPECIAL) return(FALSE);
 
-  for (m = 0; m < SEL_MAJORS; m++) 
-       if (major(f->filp_vno->v_sdev) == select_majors[m]) 
-               return(TRUE);
+  for (m = 0; m < SEL_MAJORS; m++)
+       if (major(f->filp_vno->v_sdev) == select_majors[m])
+               return(TRUE);
 
   return(FALSE);
 }
@@ -381,7 +386,7 @@ PRIVATE int select_request_async(struct filp *f, int *ops, int block)
   if (r < 0 && r != SUSPEND)
        return(SEL_ERROR);
 
-  if (r != SUSPEND) 
+  if (r != SUSPEND)
        panic("select_request_asynch: expected SUSPEND got: %d", r);
 
   dp->dmap_sel_filp = f;
@@ -393,7 +398,8 @@ PRIVATE int select_request_async(struct filp *f, int *ops, int block)
 /*===========================================================================*
  *                             select_request_file                          *
  *===========================================================================*/
-PRIVATE int select_request_file(struct filp *f, int *ops, int block)
+PRIVATE int select_request_file(struct filp *UNUSED(f), int *UNUSED(ops),
+  int UNUSED(block))
 {
   /* Files are always ready, so output *ops is input *ops */
   return(SEL_OK);
@@ -409,10 +415,11 @@ PRIVATE int select_request_major(struct filp *f, int *ops, int block)
   major = major(f->filp_vno->v_sdev);
   if (major < 0 || major >= NR_DEVICES) return(SEL_ERROR);
 
-  if (dmap[major].dmap_style == STYLE_DEVA)
-       r = select_request_async(f, ops, block);
+  if (dmap[major].dmap_style == STYLE_DEVA ||
+      dmap[major].dmap_style == STYLE_CLONE_A)
+       r = select_request_async(f, ops, block);
   else
-       r = select_request_sync(f, ops, block);
+       r = select_request_sync(f, ops, block);
 
   return(r);
 }
@@ -453,7 +460,7 @@ PRIVATE int select_request_pipe(struct filp *f, int *ops, int block)
        if (err == SUSPEND && !(f->filp_mode & R_BIT)) {
                /* A "meaningless" read select, therefore ready
                 * for reading and no error set. */
-               r |= SEL_RD; 
+               r |= SEL_RD;
                r &= ~SEL_ERR;
        }
   }
@@ -468,7 +475,7 @@ PRIVATE int select_request_pipe(struct filp *f, int *ops, int block)
        if (err == SUSPEND && !(f->filp_mode & W_BIT)) {
                /* A "meaningless" write select, therefore ready
                    for writing and no error set. */
-               r |= SEL_WR; 
+               r |= SEL_WR;
                r &= ~SEL_ERR;
        }
   }
@@ -491,8 +498,8 @@ PRIVATE int tab2ops(int fd, struct selectentry *e)
   if (FD_ISSET(fd, &e->readfds))  ops |= SEL_RD;
   if (FD_ISSET(fd, &e->writefds)) ops |= SEL_WR;
   if (FD_ISSET(fd, &e->errorfds)) ops |= SEL_ERR;
-  return(ops); 
+
+  return(ops);
 }
 
 
@@ -586,9 +593,6 @@ PRIVATE void select_cancel_all(struct selectentry *se)
   int fd;
   struct filp *f;
 
-  /* Always await results of asynchronous requests */
-  assert(!is_deferred(se));
-
   for (fd = 0; fd < se->nfds; fd++) {
        if ((f = se->filps[fd]) == NULL) continue;
        se->filps[fd] = NULL;
@@ -596,7 +600,7 @@ PRIVATE void select_cancel_all(struct selectentry *se)
   }
 
   if (se->expiry > 0) {
-       cancel_timer(&se->timer); 
+       cancel_timer(&se->timer);
        se->expiry = 0;
   }
 
@@ -613,14 +617,19 @@ PRIVATE void select_cancel_filp(struct filp *f)
   assert(f);
   assert(f->filp_selectors >= 0);
   if (f->filp_selectors == 0) return;
+  if (f->filp_count == 0) return;
+
+  select_lock_filp(f, f->filp_select_ops);
 
   f->filp_selectors--;
-  if (f->filp_selectors == 0) { 
+  if (f->filp_selectors == 0) {
        /* No one selecting on this filp anymore, forget about select state */
        f->filp_select_ops = 0;
        f->filp_select_flags = 0;
        f->filp_pipe_select_ops = 0;
   }
+
+  unlock_filp(f);
 }
 
 /*===========================================================================*
@@ -633,13 +642,14 @@ PRIVATE void select_return(struct selectentry *se)
   assert(!is_deferred(se));    /* Not done yet, first wait for async reply */
 
   select_cancel_all(se);
-  r1 = copy_fdsets(se, se->nfds, TO_PROC); 
+
+  r1 = copy_fdsets(se, se->nfds, TO_PROC);
   if (r1 != OK)
-       r = r1;
+       r = r1;
   else if (se->error != OK)
-       r = se->error;
+       r = se->error;
   else
-       r = se->nreadyfds;
+       r = se->nreadyfds;
 
   revive(se->req_endpt, r);
 }
@@ -670,7 +680,7 @@ PUBLIC void init_select(void)
  *===========================================================================*/
 PUBLIC void select_forget(endpoint_t proc_e)
 {
-/* Something has happened (e.g. signal delivered that interrupts select()). 
+/* Something has happened (e.g. signal delivered that interrupts select()).
  * Totally forget about the select(). */
 
   int slot;
@@ -678,7 +688,7 @@ PUBLIC void select_forget(endpoint_t proc_e)
 
   for (slot = 0; slot < MAXSELECTS; slot++) {
        se = &selecttab[slot];
-       if (se->requestor != NULL && se->req_endpt == proc_e) 
+       if (se->requestor != NULL && se->req_endpt == proc_e)
                break;
   }
 
@@ -700,9 +710,10 @@ PUBLIC void select_timeout_check(timer_t *timer)
 
   s = tmr_arg(timer)->ta_int;
   if (s < 0 || s >= MAXSELECTS) return;        /* Entry does not exist */
-  
-  se = &selecttab[s]; 
+
+  se = &selecttab[s];
   if (se->requestor == NULL) return;
+  fp = se->requestor;
   if (se->expiry <= 0) return; /* Strange, did we even ask for a timeout? */
   se->expiry = 0;
   if (is_deferred(se)) return; /* Wait for initial replies to DEV_SELECT */
@@ -722,12 +733,17 @@ PUBLIC void select_unsuspend_by_endpt(endpoint_t proc_e)
   struct filp *f;
 
   for (s = 0; s < MAXSELECTS; s++) {
-       int wakehim = 0;
-       se = &selecttab[s];
+       int wakehim = 0;
+       se = &selecttab[s];
        if (se->requestor == NULL) continue;
-         
+       if (se->requestor->fp_endpoint == proc_e) {
+               assert(se->requestor->fp_flags & FP_EXITING);
+               select_cancel_all(se);
+               continue;
+       }
+
        for (fd = 0; fd < se->nfds; fd++) {
-               if ((f = se->filps[fd]) == NULL || f->filp_vno == NULL) 
+               if ((f = se->filps[fd]) == NULL || f->filp_vno == NULL)
                        continue;
 
                major = major(f->filp_vno->v_sdev);
@@ -744,7 +760,6 @@ PUBLIC void select_unsuspend_by_endpt(endpoint_t proc_e)
   }
 }
 
-
 /*===========================================================================*
  *                             select_reply1                                *
  *===========================================================================*/
@@ -762,11 +777,8 @@ int status;
   struct vnode *vp;
 
   /* Figure out which device is replying */
-  if ((dp = get_dmap(driver_e)) == NULL) {
-       printf("VFS (%s:%d): endpoint %d is not a known driver endpoint\n",
-               __FILE__, __LINE__, driver_e);
-       return;
-  }
+  if ((dp = get_dmap(driver_e)) == NULL) return;
+
   major = dp-dmap;
   dev = makedev(major, minor);
 
@@ -792,31 +804,50 @@ int status;
   }
 
   /* No longer waiting for a reply from this device */
-  f->filp_select_flags &= ~FSF_BUSY;
   dp->dmap_sel_filp = NULL;
 
-  /* The select call is done now, except when 
-   * - another process started a select on the same filp with possibly a
-   *   different set of operations.
-   * - a process does a select on the same filp but using different file
-   *   descriptors.
-   * - the select has a timeout. Upon receiving this reply the operations might
-   *   not be ready yet, so we want to wait for that to ultimately happen.
-   *   Therefore we need to keep remembering what the operations are. */
-  if (!(f->filp_select_flags & (FSF_UPDATE|FSF_BLOCKED)))
-       f->filp_select_ops = 0;         /* done selecting */
-  else if (!(f->filp_select_flags & FSF_UPDATE)) 
-       f->filp_select_ops &= ~status;  /* there may be operations pending */
-
-  /* Tell filp owners about result unless we need to wait longer */
-  if (!(status == 0 && (f->filp_select_flags & FSF_BLOCKED))) {
-       if (status > 0) {       /* operations ready */
-               if (status & SEL_RD) f->filp_select_flags &= ~FSF_RD_BLOCK;
-               if (status & SEL_WR) f->filp_select_flags &= ~FSF_WR_BLOCK;
-               if (status & SEL_ERR) f->filp_select_flags &= ~FSF_ERR_BLOCK;
-       } else if (status < 0)  /* error */
-               f->filp_select_flags &= ~FSF_BLOCKED; /* No longer blocking */
-       filp_status(f, status); /* Tell filp owners about the results */
+  /* Process select result only if requestor is still around. That is, the
+   * corresponding filp is still in use.
+   */
+  if (f->filp_count >= 1) {
+       select_lock_filp(f, f->filp_select_ops);
+       f->filp_select_flags &= ~FSF_BUSY;
+
+       /* The select call is done now, except when
+        * - another process started a select on the same filp with possibly a
+        *   different set of operations.
+        * - a process does a select on the same filp but using different file
+        *   descriptors.
+        * - the select has a timeout. Upon receiving this reply the operations
+        *   might not be ready yet, so we want to wait for that to ultimately
+        *   happen.
+        *   Therefore we need to keep remembering what the operations are.
+        */
+       if (!(f->filp_select_flags & (FSF_UPDATE|FSF_BLOCKED)))
+               f->filp_select_ops = 0;         /* done selecting */
+       else if (!(f->filp_select_flags & FSF_UPDATE))
+               /* there may be operations pending */
+               f->filp_select_ops &= ~status;
+
+       /* Tell filp owners about result unless we need to wait longer */
+       if (!(status == 0 && (f->filp_select_flags & FSF_BLOCKED))) {
+               if (status > 0) {       /* operations ready */
+                       if (status & SEL_RD)
+                               f->filp_select_flags &= ~FSF_RD_BLOCK;
+                       if (status & SEL_WR)
+                               f->filp_select_flags &= ~FSF_WR_BLOCK;
+                       if (status & SEL_ERR)
+                               f->filp_select_flags &= ~FSF_ERR_BLOCK;
+               } else if (status < 0) { /* error */
+                       /* Always unblock upon error */
+                       f->filp_select_flags &= ~FSF_BLOCKED;
+               }
+
+               unlock_filp(f);
+               filp_status(f, status); /* Tell filp owners about the results */
+       } else {
+               unlock_filp(f);
+       }
   }
 
   select_restart_filps();
@@ -841,9 +872,9 @@ int status;
   struct selectentry *se;
 
   if (status == 0) {
-       printf("VFS (%s:%d): weird status (%d) to report\n", 
-               __FILE__, __LINE__, status);
-       return;
+       printf("VFS (%s:%d): weird status (%d) to report\n",
+               __FILE__, __LINE__, status);
+       return;
   }
 
   /* Figure out which device is replying */
@@ -857,19 +888,21 @@ int status;
 
   /* Find all file descriptors selecting for this device */
   for (slot = 0; slot < MAXSELECTS; slot++) {
-       se = &selecttab[slot];
+       se = &selecttab[slot];
        if (se->requestor == NULL) continue;    /* empty slot */
-                                        
+
        for (fd = 0; fd < se->nfds; fd++) {
                if ((f = se->filps[fd]) == NULL) continue;
                if ((vp = f->filp_vno) == NULL) continue;
                if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
                if (vp->v_sdev != dev) continue;
+
+               select_lock_filp(f, f->filp_select_ops);
                if (status > 0) {       /* Operations ready */
                        /* Clear the replied bits from the request
                         * mask unless FSF_UPDATE is set.
                         */
-                       if (!(f->filp_select_flags & FSF_UPDATE)) 
+                       if (!(f->filp_select_flags & FSF_UPDATE))
                                f->filp_select_ops &= ~status;
                        if (status & SEL_RD)
                                f->filp_select_flags &= ~FSF_RD_BLOCK;
@@ -880,10 +913,10 @@ int status;
 
                        ops2tab(status, fd, se);
                } else {
-                       f->filp_select_flags &= ~FSF_BLOCKED; 
+                       f->filp_select_flags &= ~FSF_BLOCKED;
                        ops2tab(SEL_RD|SEL_WR|SEL_ERR, fd, se);
                }
-
+               unlock_filp(f);
                if (se->nreadyfds > 0) restart_proc(se);
        }
   }
@@ -910,7 +943,7 @@ PRIVATE void select_restart_filps()
        if (!is_deferred(se)) continue;
 
        /* Find filps that are not waiting for a reply, but have an updated
-        * status (i.e., another select on the same filp with possibly a 
+        * status (i.e., another select on the same filp with possibly a
         * different set of operations is to be done), and thus requires the
         * select request to be sent again).
         */
@@ -922,11 +955,12 @@ PRIVATE void select_restart_filps()
                if (!(f->filp_select_flags & FSF_UPDATE)) /* Must be in  */
                        continue;                         /* 'update' state */
 
-               vp = f->filp_vno;
-               assert(vp != NULL);
-               assert((vp->v_mode & I_TYPE) == I_CHAR_SPECIAL); 
                wantops = ops = f->filp_select_ops;
+               select_lock_filp(f, ops);
+               vp = f->filp_vno;
+               assert((vp->v_mode & I_TYPE) == I_CHAR_SPECIAL);
                r = do_select_request(se, fd, &wantops);
+               unlock_filp(f);
                if (r != SEL_OK) {
                        if (r == SEL_DEFERRED) continue;
                        else break; /* Error or bogus return code; abort */
@@ -946,17 +980,16 @@ int *ops;
 {
 /* Perform actual select request for file descriptor fd */
 
-  int r, type, block;
+  int r, type;
   struct filp *f;
 
   type = se->type[fd];
-  block = se->block;
   f = se->filps[fd];
-  r = fdtypes[type].select_request(f, ops, block);
+  r = fdtypes[type].select_request(f, ops, se->block);
   if (r != SEL_OK && r != SEL_DEFERRED) {
        se->error = EINTR;
        se->block = 0;  /* Stop blocking to return asap */
-       select_cancel_all(se);
+       if (!is_deferred(se)) select_cancel_all(se);
   }
 
   return(r);
@@ -981,7 +1014,7 @@ int status;
                if (se->filps[fd] != f) continue;
                if (status < 0)
                        ops2tab(SEL_RD|SEL_WR|SEL_ERR, fd, se);
-               else 
+               else
                        ops2tab(status, fd, se);
                restart_proc(se);
        }
@@ -997,7 +1030,7 @@ struct selectentry *se;
 /* Tell process about select results (if any) unless there are still results
  * pending. */
 
-  if ((se->nreadyfds > 0 || !se->block) && !is_deferred(se)) 
+  if ((se->nreadyfds > 0 || !se->block) && !is_deferred(se))
        select_return(se);
 }
 
@@ -1009,7 +1042,8 @@ PRIVATE void wipe_select(struct selectentry *se)
   se->nfds = 0;
   se->nreadyfds = 0;
   se->error = OK;
-  memset(se->filps, 0, sizeof(se->filps)); 
+  se->block = 0;
+  memset(se->filps, 0, sizeof(se->filps));
 
   FD_ZERO(&se->readfds);
   FD_ZERO(&se->writefds);
@@ -1019,3 +1053,19 @@ PRIVATE void wipe_select(struct selectentry *se)
   FD_ZERO(&se->ready_errorfds);
 }
 
+/*===========================================================================*
+ *                             select_lock_filp                                     *
+ *===========================================================================*/
+PRIVATE void select_lock_filp(struct filp *f, int ops)
+{
+/* Lock a filp and vnode based on which operations are requested */
+  tll_access_t locktype;;
+
+  locktype = VNODE_READ; /* By default */
+
+  if (ops & (SEL_WR|SEL_ERR))
+       /* Selecting for error or writing requires exclusive access */
+       locktype = VNODE_WRITE;
+
+  lock_filp(f, locktype);
+}
index 4f5d760194564830f5ca02bfd3bbc94b7661ec37..5215b1a9078f0fb1a66fc6d373e2683672a46613 100644 (file)
@@ -1,5 +1,5 @@
-#ifndef _FS_SELECT_H
-#define _FS_SELECT_H 1
+#ifndef __VFS_SELECT_H__
+#define __VFS_SELECT_H__
 
 /* return codes for select_request_* and select_cancel_* */
 #define SEL_OK         0       /* ready */
@@ -7,4 +7,3 @@
 #define SEL_DEFERRED   2       /* request is sent to driver */
 
 #endif
-
index 8f8da30595073b02768a90fb166ffdfd13fe9929..bc49bf9c4ba526f73bc30f01dc4815213287001e 100644 (file)
@@ -20,6 +20,7 @@
 #include <string.h>
 #include "file.h"
 #include "fproc.h"
+#include "path.h"
 #include "param.h"
 #include <minix/vfsif.h>
 #include <minix/callnr.h>
@@ -29,7 +30,6 @@
 FORWARD _PROTOTYPE( int change, (struct vnode **iip, char *name_ptr, int len));
 FORWARD _PROTOTYPE( int change_into, (struct vnode **iip, struct vnode *vp));
 
-
 /*===========================================================================*
  *                             do_fchdir                                    *
  *===========================================================================*/
@@ -37,14 +37,15 @@ PUBLIC int do_fchdir()
 {
   /* Change directory on already-opened fd. */
   struct filp *rfilp;
+  int r;
 
   /* Is the file descriptor valid? */
-  if ((rfilp = get_filp(m_in.fd)) == NULL) return(err_code);
-  dup_vnode(rfilp->filp_vno);  /* Change into expects a reference. */
-  return change_into(&fp->fp_wd, rfilp->filp_vno);
+  if ((rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
+  r = change_into(&fp->fp_wd, rfilp->filp_vno);
+  unlock_filp(rfilp);
+  return(r);
 }
 
-
 /*===========================================================================*
  *                             do_chdir                                     *
  *===========================================================================*/
@@ -55,7 +56,6 @@ PUBLIC int do_chdir()
   return change(&fp->fp_wd, m_in.name, m_in.name_length);
 }
 
-
 /*===========================================================================*
  *                             do_chroot                                    *
  *===========================================================================*/
@@ -67,7 +67,6 @@ PUBLIC int do_chroot()
   return change(&fp->fp_rd, m_in.name, m_in.name_length);
 }
 
-
 /*===========================================================================*
  *                             change                                       *
  *===========================================================================*/
@@ -78,14 +77,25 @@ int len;                    /* length of the directory name string */
 {
 /* Do the actual work for chdir() and chroot(). */
   struct vnode *vp;
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+  int r;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
 
   /* Try to open the directory */
-  if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
-  return change_into(iip, vp);
+  if (fetch_name(name_ptr, len, M3, fullpath) != OK) return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
+  r = change_into(iip, vp);
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
+  put_vnode(vp);
+  return(r);
 }
 
-
 /*===========================================================================*
  *                             change_into                                  *
  *===========================================================================*/
@@ -95,25 +105,22 @@ struct vnode *vp;          /* this is what the inode has to become */
 {
   int r;
 
+  if (*iip == vp) return(OK);  /* Nothing to do */
+
   /* It must be a directory and also be searchable */
   if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
-       r = ENOTDIR;
+       r = ENOTDIR;
   else
        r = forbidden(fp, vp, X_BIT);   /* Check if dir is searchable*/
-
-  /* If error, return vnode */
-  if (r != OK) {
-       put_vnode(vp);
-       return(r);
-  }
+  if (r != OK) return(r);
 
   /* Everything is OK.  Make the change. */
   put_vnode(*iip);             /* release the old directory */
+  dup_vnode(vp);
   *iip = vp;                   /* acquire the new one */
   return(OK);
 }
 
-
 /*===========================================================================*
  *                             do_stat                                      *
  *===========================================================================*/
@@ -122,20 +129,30 @@ PUBLIC int do_stat()
 /* Perform the stat(name, buf) system call. */
   int r;
   struct vnode *vp;
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
   int old_stat = 0;
 
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+
   if (call_nr == PREV_STAT)
        old_stat = 1;
 
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+       return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
   r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat);
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
+
   put_vnode(vp);
   return r;
 }
 
-
 /*===========================================================================*
  *                             do_fstat                                     *
  *===========================================================================*/
@@ -143,6 +160,7 @@ PUBLIC int do_fstat()
 {
 /* Perform the fstat(fd, buf) system call. */
   register struct filp *rfilp;
+  int r;
   int pipe_pos = 0;
   int old_stat = 0;
 
@@ -150,21 +168,24 @@ PUBLIC int do_fstat()
        old_stat = 1;
 
   /* Is the file descriptor valid? */
-  if ((rfilp = get_filp(m_in.fd)) == NULL) return(err_code);
-  
+  if ((rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
+
   /* If we read from a pipe, send position too */
   if (rfilp->filp_vno->v_pipe == I_PIPE) {
-       if (rfilp->filp_mode & R_BIT) 
+       if (rfilp->filp_mode & R_BIT)
                if (ex64hi(rfilp->filp_pos) != 0) {
                        panic("do_fstat: bad position in pipe");
                }
        pipe_pos = ex64lo(rfilp->filp_pos);
   }
 
-  return req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
-                 who_e, m_in.buffer, pipe_pos, old_stat);
-}
+  r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
+              who_e, m_in.buffer, pipe_pos, old_stat);
 
+  unlock_filp(rfilp);
+
+  return(r);
+}
 
 /*===========================================================================*
  *                             do_fstatfs                                   *
@@ -173,11 +194,16 @@ PUBLIC int do_fstatfs()
 {
 /* Perform the fstatfs(fd, buf) system call. */
   struct filp *rfilp;
+  int r;
 
   /* Is the file descriptor valid? */
-  if( (rfilp = get_filp(m_in.fd)) == NULL) return(err_code);
+  if( (rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
+
+  r = req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, m_in.buffer);
 
-  return req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, m_in.buffer);
+  unlock_filp(rfilp);
+
+  return(r);
 }
 
 /*===========================================================================*
@@ -188,16 +214,26 @@ PUBLIC int do_statvfs()
 /* Perform the stat(name, buf) system call. */
   int r;
   struct vnode *vp;
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
 
-  if (fetch_name(m_in.STATVFS_NAME, m_in.STATVFS_LEN, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.STATVFS_NAME, m_in.STATVFS_LEN, M1, fullpath) != OK)
+       return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
   r = req_statvfs(vp->v_fs_e, who_e, m_in.STATVFS_BUF);
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
+
   put_vnode(vp);
   return r;
 }
 
-
 /*===========================================================================*
  *                             do_fstatvfs                                  *
  *===========================================================================*/
@@ -205,13 +241,18 @@ PUBLIC int do_fstatvfs()
 {
 /* Perform the fstat(fd, buf) system call. */
   register struct filp *rfilp;
+  int r;
 
   /* Is the file descriptor valid? */
-  if ((rfilp = get_filp(m_in.FSTATVFS_FD)) == NULL) return(err_code);
-  
-  return req_statvfs(rfilp->filp_vno->v_fs_e, who_e, m_in.FSTATVFS_BUF);
-}
+  if ((rfilp = get_filp(m_in.FSTATVFS_FD, VNODE_READ)) == NULL)
+       return(err_code);
+
+  r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, m_in.FSTATVFS_BUF);
 
+  unlock_filp(rfilp);
+
+  return(r);
+}
 
 /*===========================================================================*
  *                             do_lstat                                             *
@@ -220,18 +261,27 @@ PUBLIC int do_lstat()
 {
 /* Perform the lstat(name, buf) system call. */
   struct vnode *vp;
+  struct vmnt *vmp;
   int r;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
   int old_stat = 0;
 
+  lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_READ;
+  resolve.l_vnode_lock = VNODE_READ;
+
   if (call_nr == PREV_LSTAT)
        old_stat = 1;
+  if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+       return(err_code);
 
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_RET_SYMLINK, fp)) == NULL) return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
   r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat);
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
+
   put_vnode(vp);
   return(r);
 }
-
-
index 5b59ca9b5f4ec68e64fcb5f143dba52755e7e468..4429e3192b7eddc1324bfeb8089ca79c601c54e7 100644 (file)
 #include "file.h"
 #include "fproc.h"
 #include "lock.h"
+#include "scratchpad.h"
 #include "vnode.h"
 #include "vmnt.h"
 
-
 PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        no_sys,         /*  0 = unused  */
        no_sys,         /*  1 = (exit)  */
@@ -46,11 +46,11 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        do_fstat,       /* 28 = fstat (prev)*/
        no_sys,         /* 29 = pause   */
        do_utime,       /* 30 = utime   */
-       no_sys,         /* 31 = unused  */
-       no_sys,         /* 32 = unused  */
+       no_sys,         /* 31 = (stty)  */
+       no_sys,         /* 32 = (gtty)  */
        do_access,      /* 33 = access  */
-       no_sys,         /* 34 = unused  */
-       no_sys,         /* 35 = unused  */
+       no_sys,         /* 34 = (nice)  */
+       no_sys,         /* 35 = (ftime) */
        do_sync,        /* 36 = sync    */
        no_sys,         /* 37 = kill    */
        do_rename,      /* 38 = rename  */
@@ -59,7 +59,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        do_dup,         /* 41 = dup     */
        do_pipe,        /* 42 = pipe    */
        no_sys,         /* 43 = times   */
-       no_sys,         /* 44 = unused  */
+       no_sys,         /* 44 = (prof)  */
        do_slink,       /* 45 = symlink */
        no_sys,         /* 46 = (setgid)*/
        no_sys,         /* 47 = getgid  */
@@ -71,8 +71,8 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        do_lstat,       /* 53 = lstat   */
        do_ioctl,       /* 54 = ioctl   */
        do_fcntl,       /* 55 = fcntl   */
-       no_sys,         /* 56 = unused  */
-       do_fslogin,     /* 57 = FS proc login */
+       no_sys,         /* 56 = (mpx)   */
+       do_fsready,     /* 57 = FS proc ready */
        no_sys,         /* 58 = unused  */
        no_sys,         /* 59 = (execve)*/
        do_umask,       /* 60 = umask   */
@@ -137,7 +137,7 @@ PUBLIC _PROTOTYPE (int (*pfs_call_vec[]), (void) ) = {
 
        no_sys,         /* 0 */
        do_check_perms, /* 1 */
-       do_verify_fd,   /* 2 */ 
+       do_verify_fd,   /* 2 */
        do_set_filp,    /* 3 */
        do_copy_filp,   /* 4 */
        do_put_filp,    /* 5 */
similarity index 100%
rename from servers/avfs/threads.h
rename to servers/vfs/threads.h
index 491adeb5d176f001e0ef382cfa38bff63140471c..29b84e320e4681cc3a32296b4b62c3062de0e985 100644 (file)
@@ -9,6 +9,7 @@
 #include <minix/com.h>
 #include "file.h"
 #include "fproc.h"
+#include "path.h"
 #include "param.h"
 #include "vnode.h"
 #include <minix/vfsif.h>
@@ -24,21 +25,28 @@ PUBLIC int do_utime()
   int r;
   time_t actime, modtime;
   struct vnode *vp;
-  
+  struct vmnt *vmp;
+  char fullpath[PATH_MAX];
+  struct lookup resolve;
+
+  lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+  resolve.l_vmnt_lock = VMNT_WRITE;
+  resolve.l_vnode_lock = VNODE_READ;
+
   /* Adjust for case of 'timep' being NULL;
    * utime_strlen then holds the actual size: strlen(name)+1 */
   len = m_in.utime_length;
-  if(len == 0) len = m_in.utime_strlen;
+  if (len == 0) len = m_in.utime_strlen;
 
   /* Temporarily open the file */
-  if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code);
-  if ((vp = eat_path(PATH_NOFLAGS, fp)) == NULL) return(err_code);
+  if (fetch_name(m_in.utime_file, len, M1, fullpath) != OK) return(err_code);
+  if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
 
-  /* Only the owner of a file or the super user can change its name. */  
+  /* Only the owner of a file or the super user can change its name. */
   r = OK;
   if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM;
   if (m_in.utime_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT);
-  if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */ 
+  if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */
   if (r == OK) {
        /* Issue request */
        if(m_in.utime_length == 0) {
@@ -50,7 +58,9 @@ PUBLIC int do_utime()
        r = req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime);
   }
 
+  unlock_vnode(vp);
+  unlock_vmnt(vmp);
+
   put_vnode(vp);
   return(r);
 }
-
similarity index 100%
rename from servers/avfs/tll.c
rename to servers/vfs/tll.c
similarity index 100%
rename from servers/avfs/tll.h
rename to servers/vfs/tll.h
index 79227fb52b32ccf8795a3a99432fb5f69e860ca0..71922d84a336c9965dcc5f43fe21a4721f535d0d 100644 (file)
 /*===========================================================================*
  *                             fetch_name                                   *
  *===========================================================================*/
-PUBLIC int fetch_name(path, len, flag)
+PUBLIC int fetch_name(path, len, flag, dest)
 char *path;                    /* pointer to the path in user space */
 int len;                       /* path length, including 0 byte */
 int flag;                      /* M3 means path may be in message */
+char *dest;                    /* pointer to where path is to be stored */
 {
 /* Go get path and put it in 'user_fullpath'.
  * If 'flag' = M3 and 'len' <= M3_STRING, the path is present in 'message'.
@@ -42,9 +43,6 @@ int flag;                     /* M3 means path may be in message */
        return(EGENERIC);
   }
 
-  if (len > sizeof(user_fullpath))
-       panic("fetch_name: len too much for user_fullpath: %d", len);
-
   /* Check name length for validity. */
   if (len <= 0) {
        err_code = EINVAL;
@@ -53,7 +51,7 @@ int flag;                     /* M3 means path may be in message */
 
   if (flag == M3 && len <= M3_STRING) {
        /* Just copy the path from the message to 'user_fullpath'. */
-       rpu = &user_fullpath[0];
+       rpu = &dest[0];
        rpm = m_in.pathname;            /* contained in input message */
        count = len;
        do { *rpu++ = *rpm++; } while (--count);
@@ -61,12 +59,12 @@ int flag;                   /* M3 means path may be in message */
   } else {
        /* String is not contained in the message.  Get it from user space. */
        r = sys_datacopy(who_e, (vir_bytes) path,
-               VFS_PROC_NR, (vir_bytes) user_fullpath, (phys_bytes) len);
+               VFS_PROC_NR, (vir_bytes) dest, (phys_bytes) len);
   }
 
-  if (user_fullpath[len - 1] != '\0') {
-       err_code = ENAMETOOLONG;
-       return(EGENERIC);
+  if (dest[len - 1] != '\0') {
+       err_code = ENAMETOOLONG;
+       return(EGENERIC);
   }
 
   return(r);
@@ -91,20 +89,20 @@ PUBLIC int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc, int
   int failed = 0;
   endpoint_t ke;
   *proc = _ENDPOINT_P(endpoint);
-  if(endpoint == NONE) {
-       printf("vfs:%s:%d: endpoint is NONE\n", file, line);
+  if (endpoint == NONE) {
+       printf("VFS %s:%d: endpoint is NONE\n", file, line);
        failed = 1;
-  } else if(*proc < 0 || *proc >= NR_PROCS) {
-       printf("vfs:%s:%d: proc (%d) from endpoint (%d) out of range\n",
+  } else if (*proc < 0 || *proc >= NR_PROCS) {
+       printf("VFS %s:%d: proc (%d) from endpoint (%d) out of range\n",
                file, line, *proc, endpoint);
        failed = 1;
-  } else if((ke=fproc[*proc].fp_endpoint) != endpoint) {
+  } else if ((ke = fproc[*proc].fp_endpoint) != endpoint) {
        if(ke == NONE) {
-               printf("vfs:%s:%d: endpoint (%d) points to NONE slot (%d)\n",
-                       file, line, endpoint, *proc);
+               printf("VFS %s:%d: endpoint (%d) points to NONE slot (%d)\n",
+                       file, line, endpoint, *proc);
                assert(fproc[*proc].fp_pid == PID_FREE);
-       } else {
-               printf("vfs:%s:%d: proc (%d) from endpoint (%d) doesn't match "
+       } else {
+               printf("VFS %s:%d: proc (%d) from endpoint (%d) doesn't match "
                        "known endpoint (%d)\n", file, line, *proc, endpoint,
                        fproc[*proc].fp_endpoint);
                assert(fproc[*proc].fp_pid != PID_FREE);
@@ -147,12 +145,9 @@ PUBLIC int in_group(struct fproc *rfp, gid_t grp)
 {
   int i;
 
-  for (i = 0; i < rfp->fp_ngroups; i++) {
-       if (rfp->fp_sgroups[i] == grp) {
+  for (i = 0; i < rfp->fp_ngroups; i++)
+       if (rfp->fp_sgroups[i] == grp)
                return(OK);
-       }
-  }
 
   return(EINVAL);
 }
-
index 842abc1cc5768bad3610920c316b63972da1758a..bb3dc0746705a4f1ad746eaa4108ca55ae9ade91 100644 (file)
  */
 
 #include "fs.h"
+#include "threads.h"
 #include "vmnt.h"
+#include <assert.h>
+#include "fproc.h"
 
+FORWARD _PROTOTYPE( int is_vmnt_locked, (struct vmnt *vmp)             );
+FORWARD _PROTOTYPE( void clear_vmnt, (struct vmnt *vmp)                        );
+
+/* Is vmp pointer reasonable? */
+#define SANEVMP(v) ((((v) >= &vmnt[0] && (v) < &vmnt[NR_MNTS])))
+#define BADVMP(v, f, l) printf("%s:%d: bad vmp %p\n", f, l, v)
+/* vp check that panics */
+#define ASSERTVMP(v) if(!SANEVMP(v)) { \
+       BADVMP(v, __FILE__, __LINE__); panic("bad vmp"); }
+
+#if LOCK_DEBUG
+/*===========================================================================*
+ *                             check_vmnt_locks_by_me                       *
+ *===========================================================================*/
+PUBLIC void check_vmnt_locks_by_me(struct fproc *rfp)
+{
+/* Check whether this thread still has locks held on vmnts */
+  struct vmnt *vmp;
+
+  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
+       if (tll_locked_by_me(&vmp->m_lock))
+               panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n",
+                     mthread_self(), vmp, call_nr);
+  }
+
+  if (rfp->fp_vmnt_rdlocks != 0)
+       panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n",
+             mthread_self(), rfp->fp_vmnt_rdlocks, call_nr);
+}
+#endif
+
+/*===========================================================================*
+ *                             check_vmnt_locks                             *
+ *===========================================================================*/
+PUBLIC void check_vmnt_locks()
+{
+  struct vmnt *vmp;
+  int count = 0;
+
+  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++)
+       if (is_vmnt_locked(vmp)) {
+               count++;
+               printf("vmnt %p is %s, fs_e=%d dev=%d\n", vmp, (tll_islocked(&vmp->m_lock) ? "locked":"pending locked"), vmp->m_fs_e, vmp->m_dev);
+       }
+
+  if (count) panic("%d locked vmnts\n", count);
+#if 0
+  printf("check_vmnt_locks OK\n");
+#endif
+}
+
+/*===========================================================================*
+ *                             clear_vmnt                                   *
+ *===========================================================================*/
+PRIVATE void clear_vmnt(struct vmnt *vmp)
+{
+/* Reset vmp to initial parameters */
+  ASSERTVMP(vmp);
+
+  vmp->m_fs_e = NONE;
+  vmp->m_dev = NO_DEV;
+  vmp->m_flags = 0;
+  vmp->m_mounted_on = NULL;
+  vmp->m_root_node = NULL;
+  vmp->m_label[0] = '\0';
+  vmp->m_comm.c_max_reqs = 1;
+  vmp->m_comm.c_cur_reqs = 0;
+  vmp->m_comm.c_req_queue = NULL;
+}
 
 /*===========================================================================*
  *                             get_free_vmnt                                *
  *===========================================================================*/
-PUBLIC struct vmnt *get_free_vmnt(short *index)
+PUBLIC struct vmnt *get_free_vmnt(void)
 {
   struct vmnt *vp;
-  *index = 0;
-  for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp, ++(*index)) 
+
+  for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
       if (vp->m_dev == NO_DEV) return(vp);
 
   return(NULL);
 }
 
-
 /*===========================================================================*
  *                             find_vmnt                                    *
  *===========================================================================*/
-PUBLIC struct vmnt *find_vmnt(int fs_e) 
+PUBLIC struct vmnt *find_vmnt(endpoint_t fs_e)
 {
+/* Find the vmnt belonging to an FS with endpoint 'fs_e' iff it's in use */
   struct vmnt *vp;
-  for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) 
-      if (vp->m_fs_e == fs_e) return(vp);
+
+  for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
+       if (vp->m_fs_e == fs_e && vp->m_dev != NO_DEV)
+               return(vp);
 
   return(NULL);
 }
 
+/*===========================================================================*
+ *                             init_vmnts                                   *
+ *===========================================================================*/
+PUBLIC void init_vmnts(void)
+{
+/* Initialize vmnt table */
+  struct vmnt *vmp;
 
+  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
+       clear_vmnt(vmp);
+       tll_init(&vmp->m_lock);
+  }
+}
+
+/*===========================================================================*
+ *                             is_vmnt_locked                               *
+ *===========================================================================*/
+PRIVATE int is_vmnt_locked(struct vmnt *vmp)
+{
+  ASSERTVMP(vmp);
+  return(tll_islocked(&vmp->m_lock) || tll_haspendinglock(&vmp->m_lock));
+}
+
+/*===========================================================================*
+ *                             lock_vmnt                                    *
+ *===========================================================================*/
+PUBLIC int lock_vmnt(struct vmnt *vmp, tll_access_t locktype)
+{
+  int r;
+  tll_access_t initial_locktype;
+
+  ASSERTVMP(vmp);
+
+  initial_locktype = (locktype == VMNT_EXCL) ? VMNT_WRITE : locktype;
+
+  if (vmp->m_fs_e == who_e) return(EDEADLK);
+
+  r = tll_lock(&vmp->m_lock, initial_locktype);
+
+  if (r == EBUSY) return(r);
+
+  if (initial_locktype != locktype) {
+       tll_upgrade(&vmp->m_lock);
+  }
+
+#if LOCK_DEBUG
+  if (locktype == VMNT_READ)
+       fp->fp_vmnt_rdlocks++;
+#endif
+
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             vmnt_unmap_by_endpoint                       *
+ *===========================================================================*/
+PUBLIC void vmnt_unmap_by_endpt(endpoint_t proc_e)
+{
+  struct vmnt *vmp;
+
+  if ((vmp = find_vmnt(proc_e)) != NULL) {
+       fs_cancel(vmp);
+       invalidate_filp_by_endpt(proc_e);
+       if (vmp->m_mounted_on) {
+               /* Only put mount point when it was actually used as mount
+                * point. That is, the mount was succesful. */
+               put_vnode(vmp->m_mounted_on);
+       }
+       clear_vmnt(vmp);
+  }
+}
+
+/*===========================================================================*
+ *                             unlock_vmnt                                  *
+ *===========================================================================*/
+PUBLIC void unlock_vmnt(struct vmnt *vmp)
+{
+  ASSERTVMP(vmp);
+
+#if LOCK_DEBUG
+  /* Decrease read-only lock counter when not locked as VMNT_WRITE or
+   * VMNT_EXCL */
+  if (!tll_locked_by_me(&vmp->m_lock))
+       fp->fp_vmnt_rdlocks--;
+#endif
+
+  tll_unlock(&vmp->m_lock);
+
+#if LOCK_DEBUG
+  assert(!tll_locked_by_me(&vmp->m_lock));
+#endif
+
+}
index 390d93e677751a5ba8495db20b74cbe6c13b545f..14d00b3ab377e6133831608f337888e49e003566 100644 (file)
@@ -1,11 +1,26 @@
-
+#ifndef __VFS_VMNT_H__
+#define __VFS_VMNT_H__
 
 EXTERN struct vmnt {
-  int m_fs_e;                   /* FS process' kernel endpoint */
-  dev_t m_dev;                  /* device number */
-  int m_flags;                  /* mount flags */
-  struct vnode *m_mounted_on;   /* vnode on which the partition is mounted */
-  struct vnode *m_root_node;    /* root vnode */
+  int m_fs_e;                  /* FS process' kernel endpoint */
+  tll_t m_lock;
+  comm_t m_comm;
+  dev_t m_dev;                 /* device number */
+  unsigned int m_flags;                /* mount flags */
+  struct vnode *m_mounted_on;  /* vnode on which the partition is mounted */
+  struct vnode *m_root_node;   /* root vnode */
   char m_label[LABEL_MAX];     /* label of the file system process */
 } vmnt[NR_MNTS];
 
+/* vmnt flags */
+#define VMNT_READONLY          01      /* Device mounted readonly */
+#define VMNT_CALLBACK          02      /* FS did back call */
+#define VMNT_MOUNTING          04      /* Device is being mounted */
+#define VMNT_FORCEROOTBSF      010     /* Force usage of none-device */
+
+/* vmnt lock types mapping */
+#define VMNT_READ TLL_READ
+#define VMNT_WRITE TLL_READSER
+#define VMNT_EXCL TLL_WRITE
+
+#endif
index 9e1a9e03a443a3a9a83a7b43cb5853414a938483..ad854f7320a6f97c4094d00255b97104fb9de209 100644 (file)
@@ -1,19 +1,21 @@
 /* This file contains the routines related to vnodes.
  * The entry points are:
- *      
+ *
  *  get_vnode - increase counter and get details of an inode
  *  get_free_vnode - get a pointer to a free vnode obj
- *  find_vnode - find a vnode according to the FS endpoint and the inode num.  
+ *  find_vnode - find a vnode according to the FS endpoint and the inode num.
  *  dup_vnode - duplicate vnode (i.e. increase counter)
- *  put_vnode - drop vnode (i.e. decrease counter)  
+ *  put_vnode - drop vnode (i.e. decrease counter)
  */
 
 #include "fs.h"
+#include "threads.h"
 #include "vnode.h"
 #include "vmnt.h"
 #include "fproc.h"
 #include "file.h"
 #include <minix/vfsif.h>
+#include <assert.h>
 
 /* Is vnode pointer reasonable? */
 #if NDEBUG
        BADVP(v, __FILE__, __LINE__); panic("bad vp"); }
 #endif
 
+#if LOCK_DEBUG
+/*===========================================================================*
+ *                             check_vnode_locks_by_me                      *
+ *===========================================================================*/
+PUBLIC void check_vnode_locks_by_me(struct fproc *rfp)
+{
+/* Check whether this thread still has locks held on vnodes */
+  struct vnode *vp;
+
+  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
+       if (tll_locked_by_me(&vp->v_lock)) {
+               panic("Thread %d still holds vnode lock on vp %x call_nr=%d\n",
+                     mthread_self(), vp, call_nr);
+       }
+  }
+
+  if (rfp->fp_vp_rdlocks != 0)
+       panic("Thread %d still holds read locks on a vnode (%d) call_nr=%d\n",
+             mthread_self(), rfp->fp_vp_rdlocks, call_nr);
+}
+#endif
+
+/*===========================================================================*
+ *                             check_vnode_locks                            *
+ *===========================================================================*/
+PUBLIC void check_vnode_locks()
+{
+  struct vnode *vp;
+  int count = 0;
+
+  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++)
+       if (is_vnode_locked(vp)) {
+               count++;
+       }
+
+  if (count) panic("%d locked vnodes\n", count);
+#if 0
+  printf("check_vnode_locks OK\n");
+#endif
+}
+
 /*===========================================================================*
  *                             get_free_vnode                               *
  *===========================================================================*/
@@ -45,16 +88,17 @@ PUBLIC struct vnode *get_free_vnode()
   struct vnode *vp;
 
   for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) {
-       if (vp->v_ref_count == 0) {
+       if (vp->v_ref_count == 0 && !is_vnode_locked(vp)) {
                vp->v_pipe = NO_PIPE;
                vp->v_uid  = -1;
                vp->v_gid  = -1;
                vp->v_sdev = NO_DEV;
-               vp->v_mapfs_e = 0;
+               vp->v_mapfs_e = NONE;
+               vp->v_mapfs_count = 0;
                vp->v_mapinode_nr = 0;
                return(vp);
        }
-  } 
+  }
 
   err_code = ENFILE;
   return(NULL);
@@ -64,19 +108,110 @@ PUBLIC struct vnode *get_free_vnode()
 /*===========================================================================*
  *                             find_vnode                                   *
  *===========================================================================*/
-PUBLIC struct vnode *find_vnode(int fs_e, int numb)
+PUBLIC struct vnode *find_vnode(int fs_e, int ino)
 {
 /* Find a specified (FS endpoint and inode number) vnode in the
  * vnode table */
   struct vnode *vp;
 
   for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
-       if (vp->v_ref_count > 0 && vp->v_inode_nr == numb && vp->v_fs_e == fs_e)
+       if (vp->v_ref_count > 0 && vp->v_inode_nr == ino && vp->v_fs_e == fs_e)
                return(vp);
-  
+
   return(NULL);
 }
 
+/*===========================================================================*
+ *                             is_vnode_locked                              *
+ *===========================================================================*/
+PUBLIC int is_vnode_locked(struct vnode *vp)
+{
+/* Find out whether a thread holds a lock on this vnode or is trying to obtain
+ * a lock. */
+  ASSERTVP(vp);
+
+  return(tll_islocked(&vp->v_lock) || tll_haspendinglock(&vp->v_lock));
+}
+
+/*===========================================================================*
+ *                             init_vnodes                                  *
+ *===========================================================================*/
+PUBLIC void init_vnodes(void)
+{
+  struct vnode *vp;
+
+  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp) {
+       vp->v_fs_e = NONE;
+       vp->v_mapfs_e = NONE;
+       vp->v_inode_nr = 0;
+       vp->v_ref_count = 0;
+       vp->v_fs_count = 0;
+       vp->v_mapfs_count = 0;
+       tll_init(&vp->v_lock);
+  }
+}
+
+/*===========================================================================*
+ *                             lock_vnode                                   *
+ *===========================================================================*/
+PUBLIC int lock_vnode(struct vnode *vp, tll_access_t locktype)
+{
+  int r;
+
+  ASSERTVP(vp);
+
+  r = tll_lock(&vp->v_lock, locktype);
+
+#if LOCK_DEBUG
+  if (locktype == VNODE_READ) {
+       fp->fp_vp_rdlocks++;
+  }
+#endif
+
+  if (r == EBUSY) return(r);
+  return(OK);
+}
+
+/*===========================================================================*
+ *                             unlock_vnode                                 *
+ *===========================================================================*/
+PUBLIC void unlock_vnode(struct vnode *vp)
+{
+#if LOCK_DEBUG
+  int i;
+  register struct vnode *rvp;
+  struct worker_thread *w;
+#endif
+  ASSERTVP(vp);
+
+#if LOCK_DEBUG
+  /* Decrease read-only lock counter when not locked as VNODE_OPCL or
+   * VNODE_WRITE */
+  if (!tll_locked_by_me(&vp->v_lock)) {
+       fp->fp_vp_rdlocks--;
+  }
+
+  for (i = 0; i < NR_VNODES; i++) {
+       rvp = &vnode[i];
+
+       w = rvp->v_lock.t_write;
+       assert(w != self);
+       while (w && w->w_next != NULL) {
+               w = w->w_next;
+               assert(w != self);
+       }
+
+       w = rvp->v_lock.t_serial;
+       assert(w != self);
+       while (w && w->w_next != NULL) {
+               w = w->w_next;
+               assert(w != self);
+       }
+  }
+#endif
+
+  tll_unlock(&vp->v_lock);
+}
 
 /*===========================================================================*
  *                             dup_vnode                                    *
@@ -96,7 +231,7 @@ PUBLIC void dup_vnode(struct vnode *vp)
  *===========================================================================*/
 PUBLIC void put_vnode(struct vnode *vp)
 {
-/* Decrease vnode's usage counter and decrease inode's usage counter in the 
+/* Decrease vnode's usage counter and decrease inode's usage counter in the
  * corresponding FS process. Decreasing the fs_count each time we decrease the
  * ref count would lead to poor performance. Instead, only decrease fs_count
  * when the ref count hits zero. However, this could lead to fs_count to wrap.
@@ -104,45 +239,55 @@ PUBLIC void put_vnode(struct vnode *vp)
  * We maintain fs_count as a sanity check to make sure VFS and the FS are in
  * sync.
  */
+  int r, lock_vp;
+
   ASSERTVP(vp);
 
+  /* Lock vnode. It's quite possible this thread already has a lock on this
+   * vnode. That's no problem, because the reference counter will not decrease
+   * to zero in that case. However, if the counter does decrease to zero *and*
+   * is already locked, we have a consistency problem somewhere. */
+  lock_vp = lock_vnode(vp, VNODE_OPCL);
+
   if (vp->v_ref_count > 1) {
        /* Decrease counter */
        vp->v_ref_count--;
-       if (vp->v_fs_count > 256) 
+       if (vp->v_fs_count > 256)
                vnode_clean_refs(vp);
-
+       if (lock_vp != EBUSY) unlock_vnode(vp);
        return;
   }
 
-  /* A vnode that's not in use can't be put. */
-  if (vp->v_ref_count <= 0) {
-       printf("put_vnode: bad v_ref_count %d\n", vp->v_ref_count);
-       panic("put_vnode failed");
-  }
+  /* If we already had a lock, there is a consistency problem */
+  assert(lock_vp != EBUSY);
+  tll_upgrade(&vp->v_lock);    /* Make sure nobody else accesses this vnode */
+
+  /* A vnode that's not in use can't be put back. */
+  if (vp->v_ref_count <= 0)
+       panic("put_vnode failed: bad v_ref_count %d\n", vp->v_ref_count);
 
   /* fs_count should indicate that the file is in use. */
-  if (vp->v_fs_count <= 0) {
-       printf("put_vnode: bad v_fs_count %d\n", vp->v_fs_count);
-       panic("put_vnode failed");
-  }
+  if (vp->v_fs_count <= 0)
+       panic("put_vnode failed: bad v_fs_count %d\n", vp->v_fs_count);
 
   /* Tell FS we don't need this inode to be open anymore. */
-  req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count); 
+  r = req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count);
 
-  /* This inode could've been mapped. If so, tell PFS to close it as well. */
-  if(vp->v_mapfs_e != 0  && vp->v_mapinode_nr != vp->v_inode_nr &&
-     vp->v_mapfs_e != vp->v_fs_e) {
-       req_putnode(vp->v_mapfs_e, vp->v_mapinode_nr, vp->v_mapfs_count); 
+  if (r != OK) {
+       printf("VFS: putnode failed: %d\n", r);
+       util_stacktrace();
   }
 
+  /* This inode could've been mapped. If so, tell mapped FS to close it as
+   * well. If mapped onto same FS, this putnode is not needed. */
+  if (vp->v_mapfs_e != NONE && vp->v_mapfs_e != vp->v_fs_e)
+       req_putnode(vp->v_mapfs_e, vp->v_mapinode_nr, vp->v_mapfs_count);
+
   vp->v_fs_count = 0;
   vp->v_ref_count = 0;
-  vp->v_pipe = NO_PIPE;
-  vp->v_sdev = NO_DEV;
-  vp->v_mapfs_e = 0;
-  vp->v_mapinode_nr = 0;
   vp->v_mapfs_count = 0;
+
+  unlock_vnode(vp);
 }
 
 
@@ -187,7 +332,7 @@ PUBLIC int check_vrefs()
                        continue;
                if(rfp->fp_rd) REFVP(rfp->fp_rd);
                 if(rfp->fp_wd) REFVP(rfp->fp_wd);
-       }
+       }
 
        /* Count references from filedescriptors */
        for (f = &filp[0]; f < &filp[NR_FILPS]; f++)
index 9ce588d7ef3ed05e8d1383357774b966b14fd835..babb6aab4e9216300998f49a0e89fed245d21089 100644 (file)
@@ -1,4 +1,5 @@
-
+#ifndef __VFS_VNODE_H__
+#define __VFS_VNODE_H__
 
 EXTERN struct vnode {
   endpoint_t v_fs_e;            /* FS process' endpoint number */
@@ -20,10 +21,11 @@ EXTERN struct vnode {
   off_t v_pipe_wr_pos;
   endpoint_t v_bfs_e;          /* endpoint number for the FS proces in case
                                   of a block special file */
-  dev_t v_dev;                  /* device number on which the corresponding 
+  dev_t v_dev;                  /* device number on which the corresponding
                                    inode resides */
   dev_t v_sdev;                 /* device number for special files */
   struct vmnt *v_vmnt;          /* vmnt object of the partition */
+  tll_t v_lock;                        /* three-level-lock */
 } vnode[NR_VNODES];
 
 
@@ -31,3 +33,8 @@ EXTERN struct vnode {
 #define NO_PIPE            0   /* i_pipe is NO_PIPE if inode is not a pipe */
 #define I_PIPE             1   /* i_pipe is I_PIPE if inode is a pipe */
 
+/* vnode lock types mapping */
+#define VNODE_READ TLL_READ
+#define VNODE_OPCL TLL_READSER
+#define VNODE_WRITE TLL_WRITE
+#endif
similarity index 100%
rename from servers/avfs/worker.c
rename to servers/vfs/worker.c
index 6682ed2e79a4483c357512ef4e66e9f5dff5997f..a3e9d636ee90d678bb5e5da223870574673a5ca4 100644 (file)
@@ -7,7 +7,6 @@
 
 #include "fs.h"
 #include "file.h"
-#include "fproc.h"
 
 
 /*===========================================================================*
@@ -16,6 +15,5 @@
 PUBLIC int do_write()
 {
 /* Perform the write(fd, buffer, nbytes) system call. */
-  return(read_write(WRITING));
+  return(do_read_write(WRITING));
 }
-
index fdcc62e387ca213a3a9e6c5928d53aedb32f3836..8022426e6b1e8e04112818cad75da26ba8fb82ac 100644 (file)
@@ -12,8 +12,6 @@ SMP_FLAGS += -DCONFIG_MAX_CPUS=${CONFIG_MAX_CPUS}
 
 CPPFLAGS+= ${SMP_FLAGS}
 
-BUILDAVFS?= "no"
-
 MAKECONF?=     /etc/make.conf
 .-include "${MAKECONF}"
 
index 0e387adefd098b9e6cad72e61e7f32e3534c106a..f2f6ad193da45de25a6253ac65cfc1fd220557c7 100644 (file)
@@ -9,13 +9,6 @@ MDEC=  /usr/mdec
 GEN_FILES=     *.bak image kernel *.iso *.iso.gz cdfdimage rootimage src
 
 # Specify the programs that are part of the system image.
-.if ${BUILDAVFS} == "yes"
-VFS= avfs
-PFS= apfs
-.else
-VFS= vfs
-PFS= pfs
-.endif
 KERNEL= kernel
 # PROGRAMS are in the order they should be loaded by boot
 PROGRAMS= \
@@ -23,13 +16,13 @@ PROGRAMS= \
        ../servers/rs/rs \
        ../servers/pm/pm \
        ../servers/sched/sched \
-       ../servers/${VFS}/vfs \
+       ../servers/vfs/vfs \
        ../drivers/memory/memory \
        ../drivers/log/log \
        ../drivers/tty/tty \
        ../servers/mfs/mfs \
        ../servers/vm/vm \
-       ../servers/${PFS}/pfs \
+       ../servers/pfs/pfs \
        ../servers/init/init
 
 usage: