]> Zhao Yanbai Git Server - minix.git/commitdiff
Add PFS (missing in previous commit)
authorThomas Veerman <thomas@minix3.org>
Sun, 20 Dec 2009 20:41:50 +0000 (20:41 +0000)
committerThomas Veerman <thomas@minix3.org>
Sun, 20 Dec 2009 20:41:50 +0000 (20:41 +0000)
21 files changed:
servers/pfs/Makefile [new file with mode: 0644]
servers/pfs/buf.h [new file with mode: 0644]
servers/pfs/buffer.c [new file with mode: 0644]
servers/pfs/const.h [new file with mode: 0644]
servers/pfs/drivers.h [new file with mode: 0644]
servers/pfs/fs.h [new file with mode: 0644]
servers/pfs/glo.h [new file with mode: 0644]
servers/pfs/inc.h [new file with mode: 0644]
servers/pfs/inode.c [new file with mode: 0644]
servers/pfs/inode.h [new file with mode: 0644]
servers/pfs/link.c [new file with mode: 0644]
servers/pfs/main.c [new file with mode: 0644]
servers/pfs/misc.c [new file with mode: 0644]
servers/pfs/open.c [new file with mode: 0644]
servers/pfs/proto.h [new file with mode: 0644]
servers/pfs/read.c [new file with mode: 0644]
servers/pfs/stadir.c [new file with mode: 0644]
servers/pfs/super.c [new file with mode: 0644]
servers/pfs/table.c [new file with mode: 0644]
servers/pfs/type.h [new file with mode: 0644]
servers/pfs/utility.c [new file with mode: 0644]

diff --git a/servers/pfs/Makefile b/servers/pfs/Makefile
new file mode 100644 (file)
index 0000000..1af893e
--- /dev/null
@@ -0,0 +1,36 @@
+# Makefile for Pipe File System (PFS)
+SERVER = pfs
+NR_BUFS=256 
+BS=4096
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+h = $i/minix
+
+# programs, flags, etc.
+CC =   exec cc
+CFLAGS = -I$i $(EXTRA_OPTS) $(CPROFILE) -DNR_BUFS=$(NR_BUFS)
+LDFLAGS = -i
+LIBS =  -lsys 
+
+OBJ =   open.o table.o inode.o main.o super.o link.o \
+        buffer.o read.o misc.o utility.o stadir.o
+
+# build local binary 
+install all build:     $(SERVER)
+$(SERVER):     $(OBJ)
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+
+# clean up local files
+clean:
+       rm -f $(SERVER) *.o *.bak 
+
+depend: 
+       mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
+
diff --git a/servers/pfs/buf.h b/servers/pfs/buf.h
new file mode 100644 (file)
index 0000000..1434626
--- /dev/null
@@ -0,0 +1,26 @@
+/* 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. */
+
+#define NIL_BUF ((struct buf *) 0)     /* indicates absence of a buffer */
+
+#define BUFHASH(b) ((b) % NR_BUFS)
+
+EXTERN struct buf *front;      /* points to least recently used free block */
+EXTERN struct buf *rear;       /* points to most recently used free block */
+EXTERN int bufs_in_use;                /* # bufs currently in use (not on free list)*/
+
diff --git a/servers/pfs/buffer.c b/servers/pfs/buffer.c
new file mode 100644 (file)
index 0000000..e49b159
--- /dev/null
@@ -0,0 +1,112 @@
+#include "fs.h"
+#include "buf.h"
+#include "inode.h"
+#include <sys/types.h>
+#include <stdlib.h>
+#include <alloca.h>
+#include <string.h>
+
+
+/*===========================================================================*
+ *                              buf_pool                                     *
+ *===========================================================================*/
+PUBLIC void buf_pool(void)
+{
+/* Initialize the buffer pool. */
+
+  front = NIL_BUF;
+  rear = NIL_BUF;
+}
+
+
+
+/*===========================================================================*
+ *                             get_block                                    *
+ *===========================================================================*/
+PUBLIC struct buf *get_block(dev, inum)
+Dev_t dev;
+ino_t inum;
+{
+  struct buf *bp;
+
+  bp = front;
+  while(bp != NIL_BUF) {
+       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                                    *
+ *===========================================================================*/
+PUBLIC struct buf *new_block(dev, inum)
+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(NIL_BUF); 
+  }
+  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 == NIL_BUF) {      /* Empty list? */
+       front = bp;
+       bp->b_prev = NIL_BUF;
+  } else {
+       rear->b_next = bp;
+       bp->b_prev = rear;
+  }
+  bp->b_next = NIL_BUF;
+  rear = bp;
+
+  return(bp);
+}
+
+
+/*===========================================================================*
+ *                             put_block                                    *
+ *===========================================================================*/
+PUBLIC void put_block(dev, inum)
+dev_t dev;
+ino_t inum;
+{
+  struct buf *bp;
+
+  bp = get_block(dev, inum);
+  if (bp == NIL_BUF) 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 == NIL_BUF)
+       front = bp->b_next;
+  else
+       bp->b_prev->b_next = bp->b_next;
+
+  if (bp->b_next == NIL_BUF)
+       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/pfs/const.h b/servers/pfs/const.h
new file mode 100644 (file)
index 0000000..97387cb
--- /dev/null
@@ -0,0 +1,98 @@
+/* Tables sizes */
+#define V1_NR_DZONES       7   /* # direct zone numbers in a V1 inode */
+#define V1_NR_TZONES       9   /* total # zone numbers in a V1 inode */
+#define V2_NR_DZONES       7   /* # direct zone numbers in a V2 inode */
+#define V2_NR_TZONES      10   /* total # zone numbers in a V2 inode */
+
+#define NR_INODES        256   /* # slots in "in core" inode table */
+#define GETDENTS_BUFSIZ  257
+
+#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)
+#define INODE_MAP_SIZE    INODE_HASH_LOG2
+
+
+/* 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))
+
+/* File system types. */
+#define SUPER_MAGIC   0x137F   /* magic number contained in super-block */
+#define SUPER_REV     0x7F13   /* magic # when 68000 disk read on PC or vv */
+#define SUPER_V2      0x2468   /* magic # for V2 file systems */
+#define SUPER_V2_REV  0x6824   /* V2 magic written on PC, read on 68K or vv */
+#define SUPER_V3      0x4d5a   /* magic # for V3 file systems */
+
+#define V1                1    /* version number of V1 file systems */ 
+#define V2                2    /* version number of V2 file systems */ 
+#define V3                3    /* version number of V3 file systems */ 
+
+/* Miscellaneous constants */
+#define SU_UID          ((uid_t) 0)    /* super_user's uid_t */
+#define SERVERS_UID ((uid_t) 11) /* who may do FSSIGNON */
+#define SYS_UID  ((uid_t) 0)   /* uid_t for processes MM and INIT */
+#define SYS_GID  ((gid_t) 0)   /* gid_t for processes MM and INIT */
+#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 */
+
+/* write_map() args */
+#define WMAP_FREE      (1 << 0)
+
+#define IGN_PERM       0
+#define CHK_PERM       1
+
+#define CLEAN              0   /* disk and memory copies identical */
+#define DIRTY              1   /* disk and memory copies differ */
+#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 BYTE_SWAP          0   /* tells conv2/conv4 to swap bytes */
+
+#define END_OF_FILE   (-104)   /* eof detected */
+
+#define ROOT_INODE         1           /* inode number for root directory */
+#define BOOT_BLOCK  ((block_t) 0)      /* block number of boot block */
+#define SUPER_BLOCK_BYTES (1024)       /* bytes offset */
+#define START_BLOCK    2               /* first block of FS (not counting SB) */
+
+#define DIR_ENTRY_SIZE       usizeof (struct direct)  /* # bytes/dir entry   */
+#define NR_DIR_ENTRIES(b)   ((b)/DIR_ENTRY_SIZE)  /* # dir entries/blk   */
+#define SUPER_SIZE      usizeof (struct super_block)  /* super_block size    */
+#define PIPE_SIZE(b)          (V1_NR_DZONES*(b))  /* pipe size in bytes  */
+
+#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)
+
+/* Derived sizes pertaining to the V1 file system. */
+#define V1_ZONE_NUM_SIZE           usizeof (zone1_t)  /* # bytes in V1 zone  */
+#define V1_INODE_SIZE             usizeof (d1_inode)  /* bytes in V1 dsk ino */
+
+/* # zones/indir block */
+#define V1_INDIRECTS (_STATIC_BLOCK_SIZE/V1_ZONE_NUM_SIZE)  
+
+/* # V1 dsk inodes/blk */
+#define V1_INODES_PER_BLOCK (_STATIC_BLOCK_SIZE/V1_INODE_SIZE)
+
+/* Derived sizes pertaining to the V2 file system. */
+#define V2_ZONE_NUM_SIZE            usizeof (zone_t)  /* # bytes in V2 zone  */
+#define V2_INODE_SIZE             usizeof (d2_inode)  /* bytes in V2 dsk ino */
+#define V2_INDIRECTS(b)   ((b)/V2_ZONE_NUM_SIZE)  /* # zones/indir block */
+#define V2_INODES_PER_BLOCK(b) ((b)/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
+
+#define PFS_MIN(a,b) pfs_min_f(__FILE__,__LINE__,(a), (b))
+#define PFS_NUL(str,l,m) pfs_nul_f(__FILE__,__LINE__,(str), (l), (m))
+
+/* Args to dev_bio/dev_io */ 
+#define PFS_DEV_READ    10001
+#define PFS_DEV_WRITE   10002 
+#define PFS_DEV_SCATTER 10003
+#define PFS_DEV_GATHER  10004
+
diff --git a/servers/pfs/drivers.h b/servers/pfs/drivers.h
new file mode 100644 (file)
index 0000000..2f41fdd
--- /dev/null
@@ -0,0 +1,9 @@
+
+/* Driver endpoints for major devices. Only the block devices
+ * are mapped here, it's a subset of the mapping in the VFS */
+
+EXTERN struct driver_endpoints {
+    endpoint_t driver_e;
+} driver_endpoints[NR_DEVICES];
+
+
diff --git a/servers/pfs/fs.h b/servers/pfs/fs.h
new file mode 100644 (file)
index 0000000..b7b3706
--- /dev/null
@@ -0,0 +1,27 @@
+/* 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 */
+
+#define VERBOSE                   0    /* show messages during initialization? */
+
+/* The following are so basic, all the *.c files get them automatically. */
+#include <minix/config.h>      /* MUST be first */
+#include <ansi.h>              /* MUST be second */
+#include <sys/types.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/dmap.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"
diff --git a/servers/pfs/glo.h b/servers/pfs/glo.h
new file mode 100644 (file)
index 0000000..2023310
--- /dev/null
@@ -0,0 +1,27 @@
+/* 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 int cch[NR_INODES];
+
+extern _PROTOTYPE (int (*fs_call_vec[]), (void) ); /* fs call table */
+
+EXTERN message fs_m_in;
+EXTERN message fs_m_out;
+
+EXTERN uid_t caller_uid;
+EXTERN gid_t caller_gid;
+EXTERN int req_nr;
+EXTERN int SELF_E;
+EXTERN int exitsignaled;
+EXTERN int busy;
+
+/* Inode map. */
+EXTERN bitchunk_t inodemap[FS_BITMAP_CHUNKS(NR_INODES)]; 
diff --git a/servers/pfs/inc.h b/servers/pfs/inc.h
new file mode 100644 (file)
index 0000000..9f22b60
--- /dev/null
@@ -0,0 +1,31 @@
+
+#define _SYSTEM            1    /* get OK and negative error codes */
+#define _MINIX             1   /* tell headers to include MINIX stuff */
+
+#define VERBOSE                   0    /* display diagnostics */
+
+#include <ansi.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <minix/callnr.h>
+#include <minix/config.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/pfs/inode.c b/servers/pfs/inode.c
new file mode 100644 (file)
index 0000000..3248441
--- /dev/null
@@ -0,0 +1,352 @@
+/* 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
+ *   dup_inode:           indicate that someone else is using an inode table entry
+ *   find_inode:   retrieve pointer to inode in inode cache
+ *
+ */
+
+#include "fs.h"
+#include "buf.h"
+#include "inode.h"
+#include <minix/vfsif.h>
+
+FORWARD _PROTOTYPE( int addhash_inode, (struct inode *node)            ); 
+FORWARD _PROTOTYPE( int unhash_inode, (struct inode *node)             );
+
+
+/*===========================================================================*
+ *                             fs_putnode                                   *
+ *===========================================================================*/
+PUBLIC int fs_putnode()
+{
+/* 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(fs_m_in.REQ_INODE_NR);
+
+  if(!rip) {
+         printf("%s:%d put_inode: inode #%d dev: %d not found\n", __FILE__,
+                __LINE__, fs_m_in.REQ_INODE_NR, fs_m_in.REQ_DEV);
+         panic(__FILE__, "fs_putnode failed", NO_NUM);
+  }
+
+  count = fs_m_in.REQ_COUNT;
+  if (count <= 0) {
+       printf("%s:%d put_inode: bad value for count: %d\n", __FILE__,
+              __LINE__, count);
+       panic(__FILE__, "fs_putnode failed", NO_NUM);
+  } else if(count > rip->i_count) {
+       printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__,
+              __LINE__, count, rip->i_count);
+       panic(__FILE__, "fs_putnode failed", NO_NUM);
+  }
+
+  /* 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 = 0;
+      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 int addhash_inode(struct inode *node) 
+{
+  int hashi = node->i_num & INODE_HASH_MASK;
+  
+  /* insert into hash table */
+  LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash);
+  return(OK);
+}
+
+
+/*===========================================================================*
+ *                             unhash_inode                                 *
+ *===========================================================================*/
+PRIVATE int unhash_inode(struct inode *node) 
+{
+  /* remove from hash table */
+  LIST_REMOVE(node, i_hash);
+  return(OK);
+}
+
+
+/*===========================================================================*
+ *                             get_inode                                    *
+ *===========================================================================*/
+PUBLIC struct inode *get_inode(dev, numb)
+dev_t dev;                     /* device on which inode resides */
+int numb;                      /* inode number (ANSI: may not be unshort) */
+{
+/* 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, *xp;
+  int hashi;
+
+  hashi = 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(NIL_INODE);
+  }
+  rip = TAILQ_FIRST(&unused_inodes);
+
+  /* If not free unhash it */
+  if (rip->i_num != 0) 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)
+int numb;                      /* inode number (ANSI: may not be unshort) */
+{
+/* Find the inode specified by the inode and device number.
+ */
+  struct inode *rip;
+  int hashi;
+
+  hashi = 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(NIL_INODE);
+}
+
+
+/*===========================================================================*
+ *                             put_inode                                    *
+ *===========================================================================*/
+PUBLIC void put_inode(rip)
+register 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 == NIL_INODE) return;        /* checking here is easier than in caller */
+
+  if (rip->i_count < 1)
+       panic(__FILE__, "put_inode: i_count already below 1", rip->i_count);
+
+  if (--rip->i_count == 0) {   /* i_count == 0 means no one is using it now */
+       if (rip->i_nlinks == 0) {
+               /* i_nlinks == 0 means 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, 0);
+       }
+
+       if (rip->i_nlinks == 0) {
+               /* free, put at the front of the LRU list */
+               unhash_inode(rip);
+               rip->i_num = 0;
+               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;
+  int major, minor;
+  bit_t b;
+  ino_t i_num;
+
+  b = alloc_bit();
+  if (b == NO_BIT) {
+       err_code = ENOSPC;
+       printf("PipeFS is out of inodes\n");
+       return(NIL_INODE);
+  }
+  i_num = (ino_t) b;
+  
+
+  /* Try to acquire a slot in the inode table. */
+  if ((rip = get_inode(dev, i_num)) == NIL_INODE) {
+       /* 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 = 0;              /* 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)
+register 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.
+ */
+
+  register int i;
+
+  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 <= 0 || rip->i_num >= NR_INODES) return;
+  b = rip->i_num;
+  free_bit(b);
+}
+
+
+/*===========================================================================*
+ *                             dup_inode                                    *
+ *===========================================================================*/
+PUBLIC void dup_inode(ip)
+struct inode *ip;              /* The inode to be duplicated. */
+{
+/* This routine is a simplified form of get_inode() for the case where
+ * the inode pointer is already known.
+ */
+
+  ip->i_count++;
+}
+
+
+/*===========================================================================*
+ *                             update_times                                 *
+ *===========================================================================*/
+PUBLIC void update_times(rip)
+register 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/pfs/inode.h b/servers/pfs/inode.h
new file mode 100644 (file)
index 0000000..40805fb
--- /dev/null
@@ -0,0 +1,35 @@
+/* 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 */
+  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];
+
+#define NIL_INODE (struct inode *) 0   /* indicates absence of inode slot */
+
diff --git a/servers/pfs/link.c b/servers/pfs/link.c
new file mode 100644 (file)
index 0000000..12c8285
--- /dev/null
@@ -0,0 +1,57 @@
+#include "fs.h"
+#include <sys/stat.h>
+#include <string.h>
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include "buf.h"
+#include "inode.h"
+#include <minix/vfsif.h>
+
+/*===========================================================================*
+ *                             fs_ftrunc                                    *
+ *===========================================================================*/
+PUBLIC int fs_ftrunc(void)
+{
+  struct inode *rip;
+  off_t start, end;
+  int r;
+  ino_t inumb;
+  
+  inumb = fs_m_in.REQ_INODE_NR;
+
+  if( (rip = find_inode(inumb)) == NIL_INODE) 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.
+ */
+  int scale;
+
+  /* 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/pfs/main.c b/servers/pfs/main.c
new file mode 100644 (file)
index 0000000..f57220d
--- /dev/null
@@ -0,0 +1,137 @@
+#include "fs.h"
+#include <assert.h>
+#include <minix/dmap.h>
+#include <minix/endpoint.h>
+#include <minix/vfsif.h>
+#include "buf.h"
+#include "inode.h"
+#include "drivers.h"
+
+FORWARD _PROTOTYPE(void init_server, (void)                            );
+FORWARD _PROTOTYPE(void get_work, (message *m_in)                      );
+
+/*===========================================================================*
+ *                             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 error, ind;
+  message m;
+
+  /* Initialize the server, then go to work. */
+  init_server();       
+
+  while(!exitsignaled || busy) {
+       endpoint_t src;
+
+       /* Wait for request message. */
+       get_work(&fs_m_in);
+       
+       src = fs_m_in.m_source;
+       error = OK;
+       caller_uid = -1;        /* To trap errors */
+       caller_gid = -1;
+
+       if (src == PM_PROC_NR) continue; /* Exit signal */
+       assert(src == VFS_PROC_NR); /* Otherwise this must be VFS talking */
+       req_nr = fs_m_in.m_type;
+       if (req_nr < VFS_BASE) {
+               fs_m_in.m_type += VFS_BASE;
+               req_nr = fs_m_in.m_type;
+       }
+       ind = req_nr - VFS_BASE;
+
+       if (ind < 0 || ind >= NREQS) {
+               printf("mfs: bad request %d\n", req_nr); 
+               printf("ind = %d\n", ind);
+               error = EINVAL; 
+       } else {
+               error = (*fs_call_vec[ind])();
+       }
+
+       fs_m_out.m_type = error; 
+       reply(src, &fs_m_out);
+      
+  }
+  return(OK);
+}
+
+
+/*===========================================================================*
+ *                             init_server                                  *
+ *===========================================================================*/
+PRIVATE void init_server(void)
+{
+  int i;
+
+  /* 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;
+       cch[i] = 0;
+  }
+       
+  init_inode_cache();
+
+  /* Init driver mapping */
+  for (i = 0; i < NR_DEVICES; ++i) 
+       driver_endpoints[i].driver_e = NONE;
+       
+  SELF_E = getprocnr();
+  buf_pool();
+}
+
+
+/*===========================================================================*
+ *                             get_work                                     *
+ *===========================================================================*/
+PRIVATE void get_work(m_in)
+message *m_in;                         /* pointer to message */
+{
+  int r, srcok = 0;
+  endpoint_t src;
+
+  do {
+       if ((r = receive(ANY, m_in)) != OK)     /* wait for message */
+               panic("PFS","receive failed", r);
+       src = fs_m_in.m_source;
+
+       if (src != VFS_PROC_NR) {
+               if(src == PM_PROC_NR) {
+                       if(is_notify(fs_m_in.m_type)) {
+                               exitsignaled = 1; /* Normal exit request. */
+                               srcok = 1;      
+                       } else
+                               printf("PFS: unexpected message from PM\n");
+               } else
+                       printf("PFS: unexpected source %d\n", src);
+       } else if(src == VFS_PROC_NR) {
+               srcok = 1;              /* Normal FS request. */
+       } else
+               printf("PFS: unexpected source %d\n", src);
+  } while(!srcok);
+
+   assert( src == VFS_PROC_NR || 
+         (src == PM_PROC_NR && is_notify(fs_m_in.m_type))
+        );
+}
+
+
+/*===========================================================================*
+ *                             reply                                        *
+ *===========================================================================*/
+PUBLIC void reply(who, m_out)
+int 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/pfs/misc.c b/servers/pfs/misc.c
new file mode 100644 (file)
index 0000000..efb0245
--- /dev/null
@@ -0,0 +1,18 @@
+#include "fs.h"
+#include <fcntl.h>
+#include <minix/vfsif.h>
+#include "buf.h"
+#include "inode.h"
+
+
+/*===========================================================================*
+ *                             fs_sync                                      *
+ *===========================================================================*/
+PUBLIC int fs_sync()
+{
+/* Perform the sync() system call.  No-op on this FS. */
+
+  return(OK);          /* sync() can't fail */
+}
+
+
diff --git a/servers/pfs/open.c b/servers/pfs/open.c
new file mode 100644 (file)
index 0000000..3902624
--- /dev/null
@@ -0,0 +1,48 @@
+#include "fs.h"
+#include <sys/stat.h>
+#include <unistd.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "buf.h"
+#include "inode.h"
+#include <minix/vfsif.h>
+
+
+/*===========================================================================*
+ *                             fs_newnode                                   *
+ *===========================================================================*/
+PUBLIC int fs_newnode()
+{
+  register int r = OK;
+  mode_t bits;
+  struct inode *rip;
+  dev_t dev;
+
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  bits = fs_m_in.REQ_MODE;
+  dev = fs_m_in.REQ_DEV;
+
+  /* Try to allocate the inode */
+  if( (rip = alloc_inode(dev, bits) ) == NIL_INODE) return(err_code);
+
+  if (bits & S_IFMT != S_IFIFO) {
+               r = EIO; /* We only support pipes */
+  } else if ((get_block(dev, rip->i_num)) == NIL_BUF)
+               r = EIO; 
+
+  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/pfs/proto.h b/servers/pfs/proto.h
new file mode 100644 (file)
index 0000000..0c4ede0
--- /dev/null
@@ -0,0 +1,56 @@
+/* Function prototypes. */
+
+/* Structs used in prototypes must be declared as such first. */
+struct buf;
+struct filp;           
+struct inode;
+
+/* buffer.c */
+_PROTOTYPE( struct buf *get_block, (Dev_t dev, ino_t inum)             );
+_PROTOTYPE( struct buf *new_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, (int numb)                       );
+_PROTOTYPE( void free_inode, (struct inode *rip)                       );
+_PROTOTYPE( int fs_putnode, (void)                                     );
+_PROTOTYPE( void init_inode_cache, (void)                              );
+_PROTOTYPE( struct inode *get_inode, (Dev_t dev, int 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, (void)                                      );
+_PROTOTYPE( int truncate_inode, (struct inode *rip, off_t newsize)                             );
+
+
+/* main.c */
+_PROTOTYPE( void reply, (int who, message *m_out)                      );
+
+/* misc.c */
+_PROTOTYPE( int fs_sync, (void)                                                );
+
+/* open.c */
+_PROTOTYPE( int fs_newnode, (void)                                     );
+
+/* read.c */
+_PROTOTYPE( int fs_readwrite, (void)                                   );
+_PROTOTYPE( block_t read_map, (struct inode *rip, off_t pos)           );
+_PROTOTYPE( int read_write, (int rw_flag)                              );
+
+/* utility.c */
+_PROTOTYPE( time_t clock_time, (void)                                  );
+_PROTOTYPE( int no_sys, (void)                                         );
+
+/* stadir.c */
+_PROTOTYPE( int fs_stat, (void)                                                );
+
+/* super.c */
+_PROTOTYPE( bit_t alloc_bit, (void)                                    );
+_PROTOTYPE( void free_bit, (bit_t bit_returned)                                );
diff --git a/servers/pfs/read.c b/servers/pfs/read.c
new file mode 100644 (file)
index 0000000..54bd1f9
--- /dev/null
@@ -0,0 +1,92 @@
+#include "fs.h"
+#include "buf.h"
+#include <minix/com.h>
+#include <string.h>
+#include <minix/u64.h>
+#include "inode.h"
+
+
+/*===========================================================================*
+ *                             fs_readwrite                                 *
+ *===========================================================================*/
+PUBLIC int fs_readwrite(void)
+{
+  int r, rw_flag;
+  block_t b;
+  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 = fs_m_in.REQ_INODE_NR;
+  rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
+#if 0  
+  printf("PFS: going to %s inode %d\n", (rw_flag == READING? "read from": "write to"), inumb);
+#endif
+
+  /* Find the inode referred */
+  if ((rip = find_inode(inumb)) == NIL_INODE) 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 = fs_m_in.REQ_GRANT;
+  position = fs_m_in.REQ_SEEK_POS_LO;
+  nrbytes = (unsigned) fs_m_in.REQ_NBYTES;
+  
+  if (rw_flag == WRITING) {
+         /* Check in advance to see if file will grow too big. */
+         if (position > PIPE_BUF - nrbytes) return(EFBIG);
+  }
+
+  /* Mark inode in use */
+  if ((get_inode(rip->i_dev, rip->i_num)) == NIL_INODE) return(err_code);
+  if ((bp = get_block(rip->i_dev, rip->i_num)) == NIL_BUF) return(err_code);
+
+  if (rw_flag == READING) {
+       /* Copy a chunk from the block buffer to user space. */
+       r = sys_safecopyto(FS_PROC_NR, gid, 0,
+               (vir_bytes) (bp->b_data+position), (phys_bytes) nrbytes, D);
+  } else {
+       /* Copy a chunk from user space to the block buffer. */
+       r = sys_safecopyfrom(FS_PROC_NR, gid, 0,
+               (vir_bytes) (bp->b_data+position), (phys_bytes) nrbytes, D);
+  }
+
+  if (r == OK) {
+       position += 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 = cum_io;
+  put_inode(rip);
+  put_block(rip->i_dev, rip->i_num);
+
+  return(r);
+}
+
diff --git a/servers/pfs/stadir.c b/servers/pfs/stadir.c
new file mode 100644 (file)
index 0000000..500d0f8
--- /dev/null
@@ -0,0 +1,60 @@
+#include "fs.h"
+#include "inode.h"
+#include <sys/stat.h>
+
+FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int who_e,
+                                    cp_grant_id_t gid)                 );
+
+
+/*===========================================================================*
+ *                             stat_inode                                   *
+ *===========================================================================*/
+PRIVATE int stat_inode(rip, who_e, gid)
+register struct inode *rip;    /* pointer to inode to stat */
+int who_e;                     /* Caller endpoint */
+cp_grant_id_t gid;             /* grant for the stat buf */
+{
+/* Common code for stat and fstat system calls. */
+
+  struct stat statbuf;
+  int r, s;
+
+  /* Update the atime, ctime, and mtime fields in the inode, if need be. */
+  if (rip->i_update) update_times(rip);
+
+  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 = rip->i_gid;
+  statbuf.st_rdev = (dev_t) 0;
+  statbuf.st_size = rip->i_size;
+  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;
+
+  /* Copy the struct to user space. */
+  r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf,
+               (phys_bytes) sizeof(statbuf), D);
+  
+  return(r);
+}
+
+
+/*===========================================================================*
+ *                             fs_stat                                      *
+ *===========================================================================*/
+PUBLIC int fs_stat()
+{
+  register int r;              /* return value */
+  register struct inode *rip;  /* target inode */
+
+  if( (rip = find_inode(fs_m_in.REQ_INODE_NR)) == NIL_INODE) return(EINVAL);
+  get_inode(rip->i_dev, rip->i_num);   /* mark inode in use */  
+  r = stat_inode(rip, fs_m_in.m_source, fs_m_in.REQ_GRANT);
+  put_inode(rip);                      /* release the inode */
+  return(r);
+}
+
diff --git a/servers/pfs/super.c b/servers/pfs/super.c
new file mode 100644 (file)
index 0000000..845af9f
--- /dev/null
@@ -0,0 +1,80 @@
+/* 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 <string.h>
+#include <minix/com.h>
+#include <minix/u64.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;
+  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 = (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 = bit_returned / FS_BITCHUNK_BITS;
+  bit = bit_returned % FS_BITCHUNK_BITS;
+
+  /* Unset bit */
+  k = &inodemap[word];
+  mask = 1 << bit;
+  *k &= ~mask;
+
+  busy--; /* One inode less in use. */
+}
+
+
diff --git a/servers/pfs/table.c b/servers/pfs/table.c
new file mode 100644 (file)
index 0000000..ddc269f
--- /dev/null
@@ -0,0 +1,49 @@
+
+/* 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 "inode.h"
+#include "buf.h"
+#include "drivers.h"
+
+PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = {
+        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  */
+        no_sys,             /* 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  */
+};
+
diff --git a/servers/pfs/type.h b/servers/pfs/type.h
new file mode 100644 (file)
index 0000000..693aecf
--- /dev/null
@@ -0,0 +1,16 @@
+
+struct buf {
+  /* Data portion of the buffer. */
+  union fsdata_u *bp;
+
+  /* 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 */
+  struct buf *b_hash;           /* used to link bufs on hash chains */
+  block_t b_blocknr;            /* block number of its (minor) device */
+  dev_t b_dev;                  /* major | minor device where block resides */
+  char b_dirt;                  /* CLEAN or DIRTY */
+  char b_count;                 /* number of users of this buffer */
+  int b_bytes;                  /* Number of bytes allocated in bp */
+};
+
diff --git a/servers/pfs/utility.c b/servers/pfs/utility.c
new file mode 100644 (file)
index 0000000..2956a0c
--- /dev/null
@@ -0,0 +1,33 @@
+#include "fs.h"
+
+
+/*===========================================================================*
+ *                             no_sys                                       *
+ *===========================================================================*/
+PUBLIC int no_sys()
+{
+/* Somebody has used an illegal system call number */
+  printf("no_sys: invalid call %d\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, boottime;
+
+  if ((r = getuptime2(&uptime,&boottime)) != OK)
+               panic(__FILE__,"clock_time: getuptme2 failed", r);
+  
+  return( (time_t) (boottime + (uptime/sys_hz())));
+}
+