]> Zhao Yanbai Git Server - minix.git/commitdiff
VFS cleanup (mostly open).
authorPhilip Homburg <philip@cs.vu.nl>
Fri, 5 Jan 2007 16:36:55 +0000 (16:36 +0000)
committerPhilip Homburg <philip@cs.vu.nl>
Fri, 5 Jan 2007 16:36:55 +0000 (16:36 +0000)
25 files changed:
include/minix/vfsif.h
servers/mfs/inode.c
servers/mfs/main.c
servers/mfs/open.c
servers/mfs/path.c
servers/mfs/proto.h
servers/mfs/stadir.c
servers/mfs/table.c
servers/vfs/device.c
servers/vfs/exec.c
servers/vfs/link.c
servers/vfs/main.c
servers/vfs/misc.c
servers/vfs/mount.c
servers/vfs/open.c
servers/vfs/path.c
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/stadir.c
servers/vfs/vnode.c
servers/vfs/vnode.h

index 5409f0d30565d2aed5ba1ef4c00ff1553f445515..b3a52d1aae0e18c541324890715e2f2042e4d5f3 100644 (file)
 #define REQ_FLAGS                m6_l3
 #define REQ_DEV                  m6_l3
 #define REQ_WHO_E                m6_l3
+#define REQ_GRANT                m6_l3
 #define REQ_USER_ADDR            m6_p2
 #define REQ_LENGTH               m6_l3
 #define REQ_SYMLOOP              m6_c2
+#define REQ_COUNT               m6_l2
 
 #define REQ_NEW_UID              m6_s3
 #define REQ_NEW_GID              m6_c2
@@ -75,7 +77,6 @@
 #define RES_MODE                 m6_s1
 #define RES_FILE_SIZE            m6_l2
 #define RES_DEV                  m6_l3
-#define RES_POS                  m6_l3
 #define RES_INODE_INDEX          m6_s2
 #define RES_NLINKS               m6_s3
 #define RES_SYMLOOP              m6_c1
 #define REQ_WRITE                6
 #define REQ_CLONE_OPCL           7
 #define REQ_FTRUNC               8
-
 #define REQ_CHOWN                9
 #define REQ_CHMOD                10
 #define REQ_ACCESS               11
 #define REQ_MKDIR                13
 #define REQ_INHIBREAD            14
 #define REQ_STAT                 15
-#define REQ_FSTAT                16
+
+#define REQ_CREATE              16
+
 #define REQ_UNLINK               17
 #define REQ_RMDIR                18
 #define REQ_UTIME                19
-#define REQ_FSTATFS              20
-#define REQ_LSTAT                21      /* NO POINT !!! */
-#define REQ_GETDIR               22
+
+#define REQ_FSTATFS              21
 
 #define REQ_LINK                 25
 
 #define ELEAVEMOUNT              302
 #define ESYMLINK                 303
 
-
-
-
-
-
-
-
-
index a98fc9671d8be976c5ebe536525e453b3e465232..a18ffbe742b47b73b26f7b39e3185c23ecb66cc7 100644 (file)
@@ -27,6 +27,7 @@ FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
                                                int direction, int norm));
 FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
                                                int direction, int norm));
+FORWARD _PROTOTYPE( void put_inode2, (struct inode *rip, int count));
 
 
 /*===========================================================================*
@@ -37,6 +38,7 @@ PUBLIC int fs_putnode()
 /* Find the inode specified by the request message and decrease its counter.
  */
   struct inode *rip;
+  int count;
   
   /* Sanity check for the direct index */
   if (fs_m_in.REQ_INODE_INDEX >= 0 && 
@@ -50,10 +52,27 @@ PUBLIC int fs_putnode()
   }
 
   if (!rip)
+  {
       printf("FSput_inode: inode #%d dev: %d couldn't be put, req_nr: %d\n", 
             fs_m_in.REQ_INODE_NR, fs_dev, req_nr);
+       panic(__FILE__, "fs_putnode failed", NO_NUM);
+  }
+
+  count= fs_m_in.REQ_COUNT;
+  if (count <= 0)
+  {
+       printf("put_inode: bad value for count: %d\n", count);
+       panic(__FILE__, "fs_putnode failed", NO_NUM);
+       return EINVAL;
+  }
+  if (count > rip->i_count)
+  {
+       printf("put_inode: count too high: %d > %d\n", count, rip->i_count);
+       panic(__FILE__, "fs_putnode failed", NO_NUM);
+       return EINVAL;
+  }
 
-  put_inode(rip);
+  put_inode2(rip, count);
   return OK;
 }
 
@@ -80,6 +99,8 @@ PUBLIC int fs_getnode()
   fs_m_out.RES_MODE = rip->i_mode;
   fs_m_out.RES_FILE_SIZE = rip->i_size;
   fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0];
+  fs_m_out.RES_UID = rip->i_uid;
+  fs_m_out.RES_GID = rip->i_gid;
 
   return OK;
 }
@@ -183,6 +204,10 @@ int numb;                  /* inode number (ANSI: may not be unshort) */
   rip->i_count = 1;
   if (dev != NO_DEV) rw_inode(rip, READING);   /* get inode from disk */
   rip->i_update = 0;           /* all the times are initially up-to-date */
+  if ((rip->i_mode & I_TYPE) == I_NAMED_PIPE)
+       rip->i_pipe = I_PIPE;
+  else
+       rip->i_pipe = NO_PIPE;
 
   /* Add to hash */
   addhash_inode(rip);
@@ -240,7 +265,52 @@ register struct inode *rip;        /* pointer to inode to be released */
                if (rip->i_pipe == I_PIPE) truncate_inode(rip, 0);
        }
         rip->i_mount = NO_MOUNT;
-       rip->i_pipe = NO_PIPE;  /* should always be cleared */
+       if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
+
+       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);
+       }
+  }
+}
+
+
+/*===========================================================================*
+ *                             put_inode2                                   *
+ *===========================================================================*/
+PRIVATE void put_inode2(rip, count)
+register struct inode *rip;    /* pointer to inode to be released */
+int count;
+{
+/* 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 < count)
+       panic(__FILE__, "put_inode2: bad value for count", count);
+  rip->i_count -= 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 */
+               rip->i_dirt = DIRTY;
+               free_inode(rip->i_dev, rip->i_num);
+       } 
+        else {
+               if (rip->i_pipe == I_PIPE)
+                       truncate_inode(rip, 0);
+       }
+        rip->i_mount = NO_MOUNT;
        if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
 
        if (rip->i_nlinks == 0) {
index 9a61e637a9429c9ebbf4ac7eb75104d18b59fb79..7fdcab630044d3c611e62c999d437f5300887a5a 100644 (file)
@@ -180,7 +180,7 @@ PRIVATE void cch_check(void)
   for (i = 0; i < NR_INODES; ++i) {
          if (inode[i].i_count != cch[i] &&
                req_nr != REQ_OPEN && req_nr != REQ_GETNODE &&
-               req_nr != REQ_PUTNODE && req_nr != REQ_GETDIR &&
+               req_nr != REQ_PUTNODE &&
                req_nr != REQ_CLONE_OPCL && req_nr != REQ_READSUPER &&
                req_nr != REQ_MOUNTPOINT && req_nr != REQ_UNMOUNT &&
                req_nr != REQ_PIPE && req_nr != REQ_SYNC && 
index 9e040c1ee4d48a404783b1baa141f347a4fb7b6e..77e92c3f907cb5cf5c54494ccc209f3cccf624c0 100644 (file)
@@ -15,7 +15,7 @@
 
 PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
 FORWARD _PROTOTYPE( struct inode *new_node, (struct inode *ldirp, 
-       char *string, mode_t bits, zone_t z0, int opaque, char *parsed));
+       char *string, mode_t bits, zone_t z0));
 
 
 /*===========================================================================*
@@ -61,7 +61,7 @@ printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E);
          }
 
          /* Create a new inode by calling new_node(). */
-         rip = new_node(ldirp, lastc, omode, NO_ZONE, oflags&O_EXCL, NULL);
+         rip = new_node(ldirp, lastc, omode, NO_ZONE);
          r = err_code;
          if (r == OK) exist = FALSE;      /* we just created the file */
          else if (r != EEXIST) {
@@ -113,11 +113,6 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E);
                         
                    case I_NAMED_PIPE:
                        rip->i_pipe = I_PIPE;
-                        b = (bits & R_BIT ? R_BIT : W_BIT);
-                        if (b == R_BIT)
-                            fs_m_out.RES_POS = rip->i_zone[V2_NR_DZONES+0];
-                        else
-                            fs_m_out.RES_POS = rip->i_zone[V2_NR_DZONES+1];
                         break;
                }
        }
@@ -148,6 +143,66 @@ printf("MFS(%d) get_inode by open() failed\n", SELF_E);
   return OK;
 }
 
+/*===========================================================================*
+ *                             fs_create                                    *
+ *===========================================================================*/
+PUBLIC int fs_create()
+{
+  int r, b;
+  struct inode *ldirp;
+  struct inode *rip;
+  mode_t omode;
+  char lastc[NAME_MAX];
+  
+  /* Read request message */
+  omode = fs_m_in.REQ_MODE;
+  
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Try to make the file. */ 
+
+  /* Copy the last component */
+  err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, 
+       SELF, (vir_bytes) lastc, (phys_bytes) fs_m_in.REQ_PATH_LEN);
+
+  if (err_code != OK) return err_code;
+
+  /* Get last directory inode */
+  if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E);
+         return ENOENT;
+  }
+
+  /* Create a new inode by calling new_node(). */
+  rip = new_node(ldirp, lastc, omode, NO_ZONE);
+  r = err_code;
+
+  /* If error, release inode. */
+  if (r != OK) {
+        put_inode(ldirp);
+       put_inode(rip);
+       return(r);
+  }
+
+  /* Reply message */
+  fs_m_out.m_source = rip->i_dev;  /* filled with FS endpoint by the system */
+  fs_m_out.RES_INODE_NR = rip->i_num;
+  fs_m_out.RES_MODE = rip->i_mode;
+  fs_m_out.RES_FILE_SIZE = rip->i_size;
+  fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode);
+
+  /* This values are needed for the execution */
+  fs_m_out.RES_UID = rip->i_uid;
+  fs_m_out.RES_GID = rip->i_gid;
+  if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime;
+
+  /* Drop parent dir */
+  put_inode(ldirp);
+  
+  return OK;
+}
+
 /*===========================================================================*
  *                             fs_mknod                                     *
  *===========================================================================*/
@@ -172,8 +227,7 @@ printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E);
   }
   
   /* Try to create the new node */
-  ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV, 
-          TRUE, NULL);
+  ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV);
 
   put_inode(ip);
   put_inode(ldirp);
@@ -208,7 +262,7 @@ printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E);
   }
   
   /* Next make the inode. If that fails, return error code. */
-  rip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0, TRUE, NULL);
+  rip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0);
 
   if (rip == NIL_INODE || err_code == EEXIST) {
        put_inode(rip);         /* can't make dir: it already exists */
@@ -275,7 +329,7 @@ PUBLIC int fs_slink()
   
   /* Create the inode for the symlink. */
   sip = new_node(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
-                 (zone_t) 0, TRUE, NULL);
+                 (zone_t) 0);
 
   /* Allocate a disk block for the contents of the symlink.
    * Copy contents of symlink (the name pointed to) into first disk block.
@@ -325,7 +379,7 @@ PUBLIC int fs_slink()
  *                             new_node                                     *
  *===========================================================================*/
 PRIVATE struct inode *new_node(struct inode *ldirp,
-       char *string, mode_t bits, zone_t z0, int opaque, char *parsed)
+       char *string, mode_t bits, zone_t z0)
 {
 /* New_node() is called by fs_open(), fs_mknod(), and fs_mkdir().  
  * In all cases it allocates a new inode, makes a directory entry for it in
@@ -341,11 +395,6 @@ PRIVATE struct inode *new_node(struct inode *ldirp,
   register struct inode *rip;
   register int r;
 
-  /*
-  *ldirp = parse_path(path, string, opaque ? LAST_DIR : LAST_DIR_EATSYM);       
-  if (*ldirp == NIL_INODE) return(NIL_INODE);
-  */
-  
   /* Get final component of the path. */
   rip = advance(&ldirp, string);
 
@@ -391,11 +440,6 @@ PRIVATE struct inode *new_node(struct inode *ldirp,
                r = err_code;
   }
 
-  if(parsed) { /* Give the caller the parsed string if requested. */
-       strncpy(parsed, string, NAME_MAX-1);
-       parsed[NAME_MAX-1] = '\0';
-  }
-
   /* The caller has to return the directory inode (*ldirp).  */
   err_code = r;
   return(rip);
index ab0b80cefb180a228f175ce07d6fb63ab968d4fe..5c6f37e3761e8d1db171680e9d6359a5ce5a9987 100644 (file)
@@ -36,7 +36,7 @@ PUBLIC int lookup()
 {
   char string[NAME_MAX];
   struct inode *rip;
-  int s_error;
+  int s_error, flags;
 
   string[0] = '\0';
   
@@ -48,13 +48,16 @@ PUBLIC int lookup()
 
   caller_uid = fs_m_in.REQ_UID;
   caller_gid = fs_m_in.REQ_GID;
+  flags = fs_m_in.REQ_FLAGS;
+
+  /* Clear RES_OFFSET for ENOENT */
+  fs_m_out.RES_OFFSET= 0;
 
   /* Lookup inode */
-  rip = parse_path(user_path, string, fs_m_in.REQ_FLAGS);
+  rip = parse_path(user_path, string, flags);
   
   /* Copy back the last name if it is required */
-  if ((fs_m_in.REQ_FLAGS & LAST_DIR || fs_m_in.REQ_FLAGS & LAST_DIR_EATSYM)
-                 && err_code != ENAMETOOLONG) {
+  if (err_code != OK || (flags & PATH_PENULTIMATE)) {
        s_error = sys_datacopy(SELF_E, (vir_bytes) string, FS_PROC_NR, 
               (vir_bytes) fs_m_in.REQ_USER_ADDR, (phys_bytes) 
               MIN(strlen(string)+1, NAME_MAX));
@@ -63,7 +66,11 @@ PUBLIC int lookup()
 
   /* Error or mount point encountered */
   if (rip == NIL_INODE)
-      return err_code;
+  {
+       if (err_code != EENTERMOUNT)
+               fs_m_out.RES_INODE_NR = 0;              /* signal no inode */
+       return err_code;
+  }
 
   fs_m_out.RES_INODE_NR = rip->i_num;
   fs_m_out.RES_MODE = rip->i_mode;
@@ -77,7 +84,7 @@ PUBLIC int lookup()
   /* Drop inode (path parse increased the counter) */
   put_inode(rip);
 
-  return OK;
+  return err_code;
 }
 
 
@@ -107,6 +114,7 @@ int action;                    /* action on last part of path */
         printf("FS: couldn't find starting inode req_nr: %d %s\n", req_nr,
                        user_path);
         err_code = ENOENT;
+printf("%s, %d\n", __FILE__, __LINE__);
         return NIL_INODE;
   }
 
@@ -116,6 +124,7 @@ int action;                    /* action on last part of path */
                          == NIL_INODE) {
                  printf("FS: couldn't find chroot inode\n");
                  err_code = ENOENT;
+printf("%s, %d\n", __FILE__, __LINE__);
                  return NIL_INODE;
          }
   }
@@ -135,6 +144,7 @@ int action;                    /* action on last part of path */
   /* Note: empty (start) path is checked in the VFS process */
   if (rip->i_nlinks == 0/* || *path == '\0'*/) {
        err_code = ENOENT;
+printf("%s, %d\n", __FILE__, __LINE__);
        return(NIL_INODE);
   }
 
@@ -148,7 +158,11 @@ int action;                    /* action on last part of path */
   if (rip->i_mount == I_MOUNT && rip->i_num != ROOT_INODE) {
        dir_ip = rip;
        rip = advance(&dir_ip, "..");
-       if (rip == NIL_INODE) return rip;
+       if (rip == NIL_INODE)
+       {
+printf("%s, %d\n", __FILE__, __LINE__);
+               return NIL_INODE;
+       }
        put_inode(rip);         /* advance() increased the counter */
   }
 
@@ -166,8 +180,10 @@ int action;                    /* action on last part of path */
   /* Scan the path component by component. */
   while (TRUE) {
        /* Extract one component. */
+       fs_m_out.RES_OFFSET = path_processed;   /* For ENOENT */
        if ( (new_name = get_name(path, string)) == (char*) 0) {
                put_inode(rip); /* bad path in user space */
+printf("%s, %d\n", __FILE__, __LINE__);
                return(NIL_INODE);
        }
        if (*new_name == '\0' && (action & PATH_PENULTIMATE)) {
@@ -177,6 +193,7 @@ int action;                    /* action on last part of path */
                        /* last file of path prefix is not a directory */
                        put_inode(rip);
                        err_code = ENOTDIR;                     
+printf("%s, %d\n", __FILE__, __LINE__);
                        return(NIL_INODE);
                }
         }
@@ -194,9 +211,17 @@ int action;                    /* action on last part of path */
 
        if (rip == NIL_INODE) {
                if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0)
+               {
+printf("%s, %d\n", __FILE__, __LINE__);
                        return(dir_ip);
+               }
+               else if (err_code == ENOENT)
+               {
+                       return(dir_ip);
+               }
                else {
                        put_inode(dir_ip);
+printf("%s, %d\n", __FILE__, __LINE__);
                        return(NIL_INODE);
                }
        }
@@ -211,6 +236,7 @@ int action;                    /* action on last part of path */
                        if (ltraverse(rip, user_path, new_name) != OK) {
                            put_inode(dir_ip);
                            err_code = ENOENT;
+printf("%s, %d\n", __FILE__, __LINE__);
                            return NIL_INODE;
                        }
 
@@ -218,6 +244,7 @@ int action;                    /* action on last part of path */
                        if (++symloop > SYMLOOP) {
                            put_inode(dir_ip);
                            err_code = ELOOP;
+printf("%s, %d\n", __FILE__, __LINE__);
                            return NIL_INODE;
                        }
 
@@ -250,6 +277,7 @@ int action;                    /* action on last part of path */
        /* Either last name reached or symbolic link is opaque */
        if ((action & PATH_NONSYMBOLIC) != 0) {
                put_inode(rip);
+printf("%s, %d\n", __FILE__, __LINE__);
                return(dir_ip);
        } else {
                put_inode(dir_ip);
index e8aef47d91079f4387c4c83fc224b1947b6e81d7..54f07198533c27ac3dbd7b36fc1ae17162ea7a6b 100644 (file)
@@ -24,12 +24,10 @@ int fs_mknod(void);
 int fs_mkdir(void);
 int fs_inhibread(void);
 int fs_stat(void);
-int fs_fstat(void);
+int fs_create(void);
 int fs_unlink(void);
 int fs_utime(void);
 int fs_fstatfs(void);
-int fs_lstat(void);
-int fs_getdir(void);
 int fs_link(void);
 int fs_lookup_rn_old(void);
 int fs_lookup_rn_new(void);
index 6b7d7cb1a6966451fada14f916880550a4222a58..720ee04608b20b2b8607d5b4e8e145c3ffeb245f 100644 (file)
 
 
 FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int pipe_pos,
-                       char *user_addr, int who_e)                     );
+                       int who_e, cp_grant_id_t gid)                   );
 
 
-/*===========================================================================*
- *                             fs_getdir                                    *
- *===========================================================================*/
-PUBLIC int fs_getdir()
-{
-  register int r;
-  register struct inode *rip;
-
-  struct inodelist *rlp;
-
-  caller_uid = fs_m_in.REQ_UID;
-  caller_gid = fs_m_in.REQ_GID;
-  
-  /* Try to open the new directory. */
-  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
-printf("MFS(%d) get_inode by fs_getdir() failed\n", SELF_E);
-        return(EINVAL);
-  }
-  
-  r = forbidden(rip, X_BIT);   /* check if dir is searchable */
-
-  /* If error, return inode. */
-  if (r != OK) {
-       put_inode(rip);
-       return(r);
-  }
-  
-  /* If OK send back inode details */
-  fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */
-  fs_m_out.RES_INODE_NR = rip->i_num;
-  fs_m_out.RES_MODE = rip->i_mode;
-  fs_m_out.RES_FILE_SIZE = rip->i_size;
-
-/*
-printf("MFS(%d): ", SELF_E);
-for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp) {
-       int elements = 0;
-       LIST_FOREACH(rip, rlp, i_hash) elements++;
-       printf("%d ", elements);
-}
-printf("\n");
-*/
-       
-  return OK;  
-}
-
-/*===========================================================================*
- *                             fs_stat                                      *
- *===========================================================================*/
-PUBLIC int fs_stat()
-{
-  register struct inode *rip;
-  register int r;
-  
-  /* Both stat() and fstat() use the same routine to do the real work.  That
-   * routine expects an inode, so acquire it temporarily.
-   */
-  caller_uid = fs_m_in.REQ_UID;
-  caller_gid = fs_m_in.REQ_GID;
-  
-  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
-printf("MFS(%d) get_inode by fs_stat() failed\n", SELF_E);
-        return(EINVAL);
-  }
-  
-  r = stat_inode(rip, 0, fs_m_in.REQ_USER_ADDR, fs_m_in.REQ_WHO_E);
-  put_inode(rip);              /* release the inode */
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             fs_fstat                                     *
- *===========================================================================*/
-PUBLIC int fs_fstat()
-{
-  int r;   
-  struct inode *rip;
-
-  /* Both stat() and fstat() use the same routine to do the real work.  That
-   * routine expects an inode, so acquire it temporarily.
-   */
-  if ((rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR))
-          == NIL_INODE) {
-      printf("FSfstat: couldn't find inode %d\n", fs_m_in.REQ_FD_INODE_NR);
-      return EINVAL;
-  }
-  
-  r = stat_inode(rip, fs_m_in.REQ_FD_POS, fs_m_in.REQ_FD_USER_ADDR, 
-          fs_m_in.REQ_FD_WHO_E);
-
-  return r;
-}
-
 /*===========================================================================*
  *                             stat_inode                                   *
  *===========================================================================*/
-PRIVATE int stat_inode(rip, pipe_pos, user_addr, who_e)
+PRIVATE int stat_inode(rip, pipe_pos, who_e, gid)
 register struct inode *rip;    /* pointer to inode to stat */
 int pipe_pos;                  /* position in a pipe, supplied by fstat() */
-char *user_addr;               /* user space address where stat buf goes */
-int who_e;                      /* kernel endpoint of the caller */
+int who_e;                     /* Caller endpoint */
+cp_grant_id_t gid;             /* grant for the stat buf */
 {
 /* Common code for stat and fstat system calls. */
 
@@ -153,14 +59,13 @@ int who_e;                      /* kernel endpoint of the caller */
   statbuf.st_ctime = rip->i_ctime;
 
   /* Copy the struct to user space. */
-  r = sys_datacopy(SELF, (vir_bytes) &statbuf,
-               who_e, (vir_bytes) user_addr, (phys_bytes) sizeof(statbuf));
+  r = sys_safecopyto(who_e, gid, 0, (vir_bytes) &statbuf,
+               (phys_bytes) sizeof(statbuf), D);
   
   return(r);
 }
 
 
-
 /*===========================================================================*
  *                             fs_fstatfs                                   *
  *===========================================================================*/
@@ -169,7 +74,7 @@ PUBLIC int fs_fstatfs()
   struct statfs st;
   struct inode *rip;
   int r;
-  
+
   if ((rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR))
           == NIL_INODE) {
       printf("FSfstatfs: couldn't find inode %d\n", fs_m_in.REQ_FD_INODE_NR);
@@ -179,28 +84,26 @@ PUBLIC int fs_fstatfs()
   st.f_bsize = rip->i_sp->s_block_size;
   
   /* Copy the struct to user space. */
-  r = sys_datacopy(SELF, (vir_bytes) &st, fs_m_in.REQ_FD_WHO_E, 
-          (vir_bytes) fs_m_in.REQ_FD_USER_ADDR, (phys_bytes) sizeof(st));
+  r = sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0,
+       (vir_bytes) &st, (phys_bytes) sizeof(st), D);
   
   return(r);
 }
 
 /*===========================================================================*
- *                             fs_lstat                                     *
+ *                             fs_stat                                      *
  *===========================================================================*/
-PUBLIC int fs_lstat()
+PUBLIC int fs_stat()
 {
   register int r;              /* return value */
   register struct inode *rip;  /* target inode */
-  caller_uid = fs_m_in.REQ_UID;
-  caller_gid = fs_m_in.REQ_GID;
 
   if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
-printf("MFS(%d) get_inode by fs_lstat() failed\n", SELF_E);
+printf("MFS(%d) get_inode by fs_stat() failed\n", SELF_E);
         return(EINVAL);
   }
   
-  r = stat_inode(rip, 0, fs_m_in.REQ_USER_ADDR, fs_m_in.REQ_WHO_E);
+  r = stat_inode(rip, 0, fs_m_in.m_source, fs_m_in.REQ_GRANT);
   put_inode(rip);              /* release the inode */
   return(r);
 }
index a86739fb9e74ca21bf80f54cbaf81218b2a8c679..9a5a8f2437ed5e82f2a41c18680c448f4de233fe 100644 (file)
@@ -31,14 +31,13 @@ PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = {
         fs_mkdir,           /* 13  */
         fs_inhibread,       /* 14  */       /* for lseek() */
         fs_stat,            /* 15  */
-        fs_fstat,           /* 16  */
+        fs_create,          /* 16  */
         fs_unlink,          /* 17  */       /* unlink() */
         fs_unlink,          /* 18  */       /* rmdir() */
         fs_utime,           /* 19  */
-        fs_fstatfs,         /* 20  */
-        fs_lstat,           /* 21  */
-        fs_getdir,          /* 22  */       /* chdir(), chroot() */
-
+        no_sys,             /* 20  */
+        fs_fstatfs,         /* 21  */
+        no_sys,             /* 22  */
         no_sys,             /* 23  */
         no_sys,             /* 24  */    
         fs_link,            /* 25  */
index efe4441e6f276950c9d7f8c9d381020ecfd5d3e9..51d31e168ae703791b6703576aad96355a740572 100644 (file)
@@ -654,7 +654,7 @@ PUBLIC int do_ioctl()
        && (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
   dev = (dev_t) vp->v_sdev;
 
-  return(dev_io(DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0), 
+  return (dev_io(DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0), 
        m_in.REQUEST, f->filp_flags));
 }
 
@@ -837,7 +837,7 @@ int flags;                  /* mode bits and flags */
                 vp = fp->fp_filp[m_in.fd]->filp_vno;
                
                 put_vnode(vp);
-               if ((vp = get_free_vnode()) == NIL_VNODE) {
+               if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
                        printf("VFSclone_opcl: failed to get a free vnode..\n");
                        vp = fp->fp_filp[m_in.fd]->filp_vno;
                }
@@ -852,7 +852,8 @@ int flags;                  /* mode bits and flags */
                 vp->v_inode_nr = res.inode_nr;
                 vp->v_mode = res.fmode; 
                 vp->v_sdev = dev;
-                vp->v_count = 1;
+                vp->v_fs_count = 1;
+                vp->v_ref_count = 1;
                fp->fp_filp[m_in.fd]->filp_vno = vp;
        }
        dev_mess.REP_STATUS = OK;
index 0cfc72dc42b08a8830ebc4734427f460b26e78be..6c32cf6d2af9bcba25dd06f8f07edcc4b7ddc953 100644 (file)
@@ -79,20 +79,16 @@ vir_bytes frame_len;
     uid_t new_uid;
     gid_t new_gid;
     struct fproc *rfp;
-    struct vnode vn;
-    struct vmnt *vmp;
+    struct vnode *vp;
     time_t v_ctime;
-    uid_t v_uid;
-    gid_t v_gid;
     char *cp;
+    struct stat sb;
     char progname[PROC_NAME_LEN];
     static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */
 
     /* Request and response structures */
     struct lookup_req lookup_req;
-    struct access_req access_req;
-    struct open_req open_req;
-    struct node_details res;
+    struct node_details Xres;
     
     okendpt(proc_e, &proc_s);
     rfp= fp= &fproc[proc_s];
@@ -105,6 +101,7 @@ vir_bytes frame_len;
     if (r != OK)
     {
         printf("pm_exec: fetch_name failed\n");
+printf("return at %s, %d\n", __FILE__, __LINE__);
         return(r);     /* file name not in user data segment */
     }
 
@@ -112,6 +109,7 @@ vir_bytes frame_len;
     if (frame_len > ARG_MAX)
     {
         printf("pm_exec: bad frame_len\n");
+printf("return at %s, %d\n", __FILE__, __LINE__);
         return(ENOMEM);        /* stack too big */
     }
     r = sys_datacopy(proc_e, (vir_bytes) frame,
@@ -120,6 +118,7 @@ vir_bytes frame_len;
     if (r != OK)
     {
         printf("pm_exec: sys_datacopy failed\n");
+printf("return at %s, %d\n", __FILE__, __LINE__);
         return(r);     
     }
 
@@ -142,70 +141,48 @@ vir_bytes frame_len;
         lookup_req.flags = EAT_PATH;
         
         /* Request lookup */
-        if ((r = lookup(&lookup_req, &res)) != OK) return r;
+        if ((r = lookup_vp(&lookup_req, &vp)) != OK)
+       {
+               put_vnode(vp);
+               return r;
+       }
         
-        if ((res.fmode & I_TYPE) != I_REGULAR) {
+        if ((vp->v_mode & I_TYPE) != I_REGULAR) {
+printf("put_vnode at %s, %d\n", __FILE__, __LINE__);
+           put_vnode(vp);
+printf("return at %s, %d\n", __FILE__, __LINE__);
             return ENOEXEC;
         }
-        else {
-            /* Fill in request fields */
-            access_req.fs_e = res.fs_e;
-            access_req.amode = X_BIT;
-            access_req.inode_nr = res.inode_nr;
-           access_req.uid = fp->fp_effuid;
-           access_req.gid = fp->fp_effgid;
-
-            
-           /* Issue request */
-           if ((r = req_access(&access_req)) != OK) {
-                printf("VFSexec: access failed for %s\n", progname);
-               return r;
-           }
-        }
 
-        /* Open request. */
-        open_req.inode_nr = res.inode_nr;
-        open_req.fs_e = res.fs_e;
-        open_req.oflags = 0;
-        open_req.omode = 0;
-        open_req.lastc = NULL;
-        open_req.uid = 0;
-        open_req.gid = 0;
-        
-        /* Issue request */
-        if ((r = req_open(&open_req, &res)) != OK) {
-            printf("VFSexec: open failed\n");          
+       /* Check access. */
+       if ((r = forbidden(vp, X_BIT)) != OK)
+       {
+printf("put_vnode at %s, %d\n", __FILE__, __LINE__);
+           put_vnode(vp);
+printf("return at %s, %d\n", __FILE__, __LINE__);
            return r;
        }
 
-        /* Use the vnode to store file details */
-        vn.v_inode_nr = res.inode_nr;
-        vn.v_mode = res.fmode;
-        vn.v_index = res.inode_index;
-        vn.v_size = res.fsize;
-        vn.v_fs_e = res.fs_e;
-        vn.v_count = 1;
-        if ( (vmp = find_vmnt(vn.v_fs_e)) == NIL_VMNT)
-            printf("VFS: vmnt not found by exec()");
-      
-        vn.v_dev = vmp->m_dev;
-        vn.v_vmnt = vmp;
-        
-        v_ctime = res.ctime;
-        v_uid = res.uid;
-        v_gid = res.gid;
+       /* Get ctime */
+       r= req_stat(vp->v_fs_e, vp->v_inode_nr, FS_PROC_NR, (char *)&sb, 0);
+       if (r != OK)
+       {
+           put_vnode(vp);
+           return r;
+       }
+        v_ctime = sb.st_ctime;
         
         if (round == 0)
         {
             /* Deal with setuid/setgid executables */
-            if (vn.v_mode & I_SET_UID_BIT)
-                new_uid = v_uid;
-            if (vn.v_mode & I_SET_GID_BIT)
-                new_gid = v_gid;
+            if (vp->v_mode & I_SET_UID_BIT)
+                new_uid = vp->v_uid;
+            if (vp->v_mode & I_SET_GID_BIT)
+                new_gid = vp->v_gid;
         }
 
         /* Read the file header and extract the segment sizes. */
-        r = read_header(&vn, &sep_id, &text_bytes, &data_bytes, &bss_bytes, 
+        r = read_header(vp, &sep_id, &text_bytes, &data_bytes, &bss_bytes, 
                 &tot_bytes, &pc, &hdrlen);
         if (r != ESCRIPT || round != 0)
             break;
@@ -215,14 +192,17 @@ vir_bytes frame_len;
         if (r != OK)
         {
             printf("pm_exec: 2nd fetch_name failed\n");
-            put_vnode(&vn);
+printf("put_vnode at %s, %d\n", __FILE__, __LINE__);
+            put_vnode(vp);
+printf("return at %s, %d\n", __FILE__, __LINE__);
             return(r); /* strange */
         }
-        r= patch_stack(&vn, mbuf, &frame_len);
-        put_vnode(&vn);
+        r= patch_stack(vp, mbuf, &frame_len);
+        put_vnode(vp);
         if (r != OK)
         {
             printf("pm_exec: patch stack\n");
+printf("return at %s, %d\n", __FILE__, __LINE__);
             return r;
         }
     }
@@ -230,16 +210,20 @@ vir_bytes frame_len;
     if (r != OK)
     {
         printf("pm_exec: returning ENOEXEC, r = %d\n", r);
+       printf("pm_exec: progname = '%s'\n", progname);
+        put_vnode(vp);
         return ENOEXEC;
     }
 
     r= exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes,
-            frame_len, sep_id, vn.v_dev, vn.v_inode_nr, v_ctime, 
+            frame_len, sep_id, vp->v_dev, vp->v_inode_nr, v_ctime, 
             progname, new_uid, new_gid, &stack_top, &load_text, &allow_setuid);
     if (r != OK)
     {
         printf("pm_exec: exec_newmap failed: %d\n", r);
-        put_vnode(&vn);
+printf("put_vnode at %s, %d\n", __FILE__, __LINE__);
+        put_vnode(vp);
+printf("return at %s, %d\n", __FILE__, __LINE__);
         return r;
     }
 
@@ -255,15 +239,19 @@ vir_bytes frame_len;
 
     /* Read in text and data segments. */
     if (load_text) {
-        r= read_seg(&vn, off, proc_e, T, text_bytes);
+        r= read_seg(vp, off, proc_e, T, text_bytes);
     }
     off += text_bytes;
     if (r == OK)
-        r= read_seg(&vn, off, proc_e, D, data_bytes);
+        r= read_seg(vp, off, proc_e, D, data_bytes);
 
-    put_vnode(&vn);
+    put_vnode(vp);
 
-    if (r != OK) return r;
+    if (r != OK)
+    {
+printf("return at %s, %d\n", __FILE__, __LINE__);
+       return r;
+    }
 
     clo_exec(rfp);
 
index c616869701aa5b8781c0eb0db776b3b15e25e250..69c471bdbdf0a9cc8e23fa48381ea59df52f6dae 100644 (file)
@@ -270,6 +270,8 @@ PUBLIC int do_truncate()
   struct lookup_req lookup_req;
   struct node_details res;
   int r;
+
+  printf("in do_truncate\n");
   
   if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code;
   
@@ -309,25 +311,39 @@ PUBLIC int do_truncate()
 PUBLIC int do_ftruncate()
 {
 /* As with do_truncate(), truncate_inode() does the actual work. */
-  int r;
   struct filp *rfilp;
-  struct ftrunc_req req;
   
   if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP)
         return err_code;
-  if ( (rfilp->filp_vno->v_mode & I_TYPE) != I_REGULAR)
+  return truncate_vn(rfilp->filp_vno, m_in.m2_l1);
+}
+
+
+/*===========================================================================*
+ *                             truncate_vn                                  *
+ *===========================================================================*/
+PUBLIC int truncate_vn(vp, newsize)
+struct vnode *vp;
+off_t newsize;
+{
+  int r;
+  struct ftrunc_req req;
+
+  if ( (vp->v_mode & I_TYPE) != I_REGULAR &&
+       (vp->v_mode & I_TYPE) != I_NAMED_PIPE) {
        return EINVAL;
+  }
         
   /* Fill in FS request */
-  req.fs_e = rfilp->filp_vno->v_fs_e; 
-  req.inode_nr = rfilp->filp_vno->v_inode_nr;
-  req.start = m_in.m2_l1;
+  req.fs_e = vp->v_fs_e; 
+  req.inode_nr = vp->v_inode_nr;
+  req.start = newsize;
   req.end = 0;     /* Indicate trunc in fs_freesp_trunc */
 
   /* Issue request */
   if ((r = req_ftrunc(&req)) != OK) return r;
          
-  rfilp->filp_vno->v_size = m_in.m2_l1;
+  vp->v_size = newsize;
   return OK;
 }
 
index f7dac46df945fc28c324e999794fbf9744d31c73..bfd62da0f92e8b2693df945c805bd5a3022ddb06 100644 (file)
@@ -57,7 +57,6 @@ PUBLIC int main()
 
   fs_init();
 
-
   /* This is the main loop that gets work, processes it, and sends replies. */
   while (TRUE) {
        get_work();             /* sets who and call_nr */
@@ -86,6 +85,14 @@ PUBLIC int main()
                        /* Device notifies us of an event. */
                        dev_status(&m_in);
                }
+#if 0
+               if (!check_vrefs())
+               {
+                       printf("after call %d from %d/%d\n",
+                               call_nr, who_p, who_e);
+                       panic(__FILE__, "check_vrefs failed at line", __LINE__);
+               }
+#endif
                continue;
        }
 
@@ -119,6 +126,13 @@ PUBLIC int main()
                if (error != SUSPEND) { reply(who_e, error); }
                
        }
+#if 0
+       if (!check_vrefs())
+       {
+               printf("after call %d from %d/%d\n", call_nr, who_p, who_e);
+               panic(__FILE__, "check_vrefs failed at line", __LINE__);
+       }
+#endif
   }
   return(OK);                          /* shouldn't come here */
 }
@@ -261,8 +275,8 @@ PRIVATE void fs_init()
        FD_ZERO(&(rfp->fp_filp_inuse));
        if (rfp->fp_pid != PID_FREE) {
                 
-                rfp->fp_rd = get_vnode(ROOT_FS_E, ROOT_INODE);
-                rfp->fp_wd = get_vnode(ROOT_FS_E, ROOT_INODE);
+                rfp->fp_rd = get_vnode_x(ROOT_FS_E, ROOT_INODE);
+                rfp->fp_wd = get_vnode_x(ROOT_FS_E, ROOT_INODE);
                
        } else  rfp->fp_endpoint = NONE;
   }
@@ -308,7 +322,7 @@ PRIVATE void init_root()
   vmp = &vmnt[0];
  
   /* We'll need a vnode for the root inode, check whether there is one */
-  if ((root_node = get_free_vnode()) == NIL_VNODE) {
+  if ((root_node = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
        panic(__FILE__,"Cannot get free vnode", r);
   }
   
@@ -344,7 +358,8 @@ PRIVATE void init_root()
   root_node->v_mode = sres.fmode;
   root_node->v_size = sres.fsize;
   root_node->v_sdev = NO_DEV;
-  root_node->v_count = 1;
+  root_node->v_fs_count = 0;   /* Is this correct? */
+  root_node->v_ref_count = 1;
 
   /* Fill in max file size and blocksize for the vmnt */
   vmp->m_fs_e = sres.fs_e;
@@ -360,6 +375,7 @@ PRIVATE void init_root()
 
   /* Root directory is mounted on itself */
   vmp->m_mounted_on = root_node;
+  root_node->v_ref_count++;
   vmp->m_root_node = root_node;
 }
 
index 87729f0aeba88053a4c63f8961668f61669d4dd5..f839004d07df6bec4502334d9ea64e48d5bc091f 100644 (file)
@@ -326,7 +326,8 @@ PUBLIC void pm_reboot()
   put_vnode(vmnt[0].m_mounted_on);
   vmnt[0].m_mounted_on = &vdummy;
   vmnt[0].m_root_node = &vdummy;
-  vdummy.v_count = 1;
+  vdummy.v_fs_count = 0;       /* Is this right? */
+  vdummy.v_ref_count = 1;
 
   /* 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.
index 8d26a958c1e72b480e4b8fae207b405916434c73..769926ea3cf05d545a87b262c9fc2ad0b6fd29e7 100644 (file)
@@ -110,6 +110,7 @@ PRIVATE int mount_fs(endpoint_t fs_e)
   struct readsuper_req sreq;
   struct readsuper_res sres;
   struct lookup_req lookup_req;
+  node_req_t node_req;
   
   /* Only the super-user may do MOUNT. */
   if (!super_user) return(EPERM);
@@ -131,13 +132,13 @@ PRIVATE int mount_fs(endpoint_t fs_e)
   if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
   
   /* Get free vnode for the mountpoint */
-  if ((mounted_on = get_free_vnode()) == NIL_VNODE) {
+  if ((mounted_on = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
         printf("VFSmount: not free vnode available\n");
         return ENFILE;
   }
   
   /* Mark it as used so that we won't find the same for the root_node */
-  mounted_on->v_count = 1;
+  mounted_on->v_ref_count = 1;
   
   /* Convert name to device number */
   if ((dev = name_to_dev()) == NO_DEV) return(err_code);
@@ -145,7 +146,7 @@ PRIVATE int mount_fs(endpoint_t fs_e)
   /* 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_count > 0 && bspec->v_sdev == dev) {
+      if (bspec->v_ref_count > 0 && bspec->v_sdev == dev) {
           /* Found, sync the buffer cache */
           req_sync(bspec->v_fs_e);          
           break;
@@ -187,7 +188,7 @@ PRIVATE int mount_fs(endpoint_t fs_e)
            * vnodes are different or if the root of FS is equal two the
            * root of the filesystem we found, we found a filesystem that
            * is in use. */
-          mounted_on->v_count = 0;
+          mounted_on->v_ref_count = 0;
           return EBUSY;   /* already mounted */
       }
 
@@ -221,7 +222,8 @@ PRIVATE int mount_fs(endpoint_t fs_e)
       mounted_on->v_mode = res.fmode;
       mounted_on->v_size = res.fsize;
       mounted_on->v_sdev = NO_DEV;
-      mounted_on->v_count = 1;
+      mounted_on->v_fs_count = 1;
+      mounted_on->v_ref_count = 1;
 
       /* Find the vmnt for the vnode */
       if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT)
@@ -257,13 +259,13 @@ PRIVATE int mount_fs(endpoint_t fs_e)
   }
 
   /* We'll need a vnode for the root inode, check whether there is one */
-  if ((root_node = get_free_vnode()) == NIL_VNODE) {
+  if ((root_node = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
         printf("VFSmount: no free vnode available\n");
         return ENFILE;
   }
   
   /* Set it back to zero so that if st goes wrong it won't be kept in use */
-  mounted_on->v_count = 0;
+  mounted_on->v_ref_count = 0;
   
   /* Fetch the name of the mountpoint */
   if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
@@ -300,13 +302,28 @@ PRIVATE int mount_fs(endpoint_t fs_e)
       return r;
   }
 
+  /* Fill in request message fields.*/
+  node_req.fs_e = sres.fs_e;
+  node_req.inode_nr = sres.inode_nr;
+
+  /* Issue request */
+  if ((r = req_getnode(&node_req, &res)) != OK)
+  {
+       printf("mount: req_getnode failed: %d\n", r);
+        dev_close(dev);
+       return r;
+  }
+  
   /* Fill in root node's fields */
-  root_node->v_fs_e = sres.fs_e;
-  root_node->v_inode_nr = sres.inode_nr;
-  root_node->v_mode = sres.fmode;
-  root_node->v_size = sres.fsize;
+  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_count = 1;
+  root_node->v_fs_count = 2;
+  root_node->v_ref_count = 1;
 
   /* Fill in max file size and blocksize for the vmnt */
   vmp->m_fs_e = sres.fs_e;
@@ -326,6 +343,7 @@ PRIVATE int mount_fs(endpoint_t fs_e)
       /* Superblock and root node already read. 
        * Nothing else can go wrong. Perform the mount. */
       vmp->m_root_node = root_node;
+      root_node->v_ref_count++;
       vmp->m_mounted_on = root_node;
       root_dev = dev;
       ROOT_FS_E = fs_e;
@@ -380,7 +398,8 @@ PRIVATE int mount_fs(endpoint_t fs_e)
   mounted_on->v_mode = res.fmode;
   mounted_on->v_size = res.fsize;
   mounted_on->v_sdev = NO_DEV;
-  mounted_on->v_count = 1;
+  mounted_on->v_fs_count = 1;
+  mounted_on->v_ref_count = 1;
 
   /* Find the vmnt for the vnode */
   if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT)
@@ -464,8 +483,8 @@ Dev_t dev;
    */
   count = 0;
   for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
-      if (vp->v_count > 0 && vp->v_dev == dev) {
-          count += vp->v_count;
+      if (vp->v_ref_count > 0 && vp->v_dev == dev) {
+          count += vp->v_ref_count;
       }
   }
 
@@ -474,6 +493,8 @@ Dev_t dev;
       return(EBUSY);    /* can't umount a busy file system */
   }
 
+  vnode_clean_refs(vmp->m_root_node);
+
   /* Request FS the unmount */
   if ((r = req_unmount(vmp->m_fs_e)) != OK) return r;
 
@@ -509,10 +530,10 @@ Dev_t dev;
   /* Root device is mounted on itself */
   if (vmp->m_root_node != vmp->m_mounted_on) {
       put_vnode(vmp->m_mounted_on);
-      vmp->m_root_node->v_count = 0;
+      vmp->m_root_node->v_ref_count = 0;
   }
   else {
-      vmp->m_mounted_on->v_count--;
+      vmp->m_mounted_on->v_fs_count--;
   }
 
   fs_e = vmp->m_fs_e;
index 1489e5c9694ab1069624661fe0d20e94b5919b83..d05233c07af02534ce5be331c0ece05b690b1226 100644 (file)
@@ -34,7 +34,8 @@
 #define offset_lo      m2_l1
 #define offset_high    m2_l2
  
-
+FORWARD _PROTOTYPE( int x_open, (int bits, int oflags, int omode,
+                       char *lastc, struct vnode **vpp)                );
 FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode)                );
 FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
 
@@ -89,13 +90,13 @@ PRIVATE int common_open(register int oflags, mode_t omode)
   struct filp *fil_ptr, *filp2;
   struct vnode *vp, *vp2;
   struct vmnt *vmp;
-  char lastc[NAME_MAX];
+  char Xlastc[NAME_MAX];
+  char *pathrem;
   int m;
 
   /* Request and response structures */
-  struct lookup_req lookup_req;
-  struct open_req req;
-  struct node_details res;
+  struct lookup_req Xlookup_req;
+  struct open_req Xreq;
 
   /* Remap the bottom two bits of oflags. */
   m = oflags & O_ACCMODE;
@@ -109,26 +110,74 @@ PRIVATE int common_open(register int oflags, mode_t omode)
   /* See if file descriptor and filp slots are available. */
   if ((r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);
 
-  /* See if a free vnode is available */
-  if ((vp = get_free_vnode()) == NIL_VNODE) {
-      printf("VFS: no vnode available!\n");
-      return err_code;
-  }
-
   /* If O_CREATE, set umask */ 
   if (oflags & O_CREAT) {
         omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
   }
 
+  vp= NULL;
+
+#if 0
+  printf("common_open: for '%s'\n", user_fullpath);
+#endif
+
   /* Fill in lookup request fields */
-  lookup_req.path = user_fullpath;
-  lookup_req.lastc = lastc;
-  lookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR : 
+  Xlookup_req.path = user_fullpath;
+  Xlookup_req.lastc = Xlastc;
+  Xlookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR : 
               LAST_DIR_EATSYM) : EAT_PATH;
+  Xlookup_req.flags = ((oflags & (O_CREAT|O_EXCL)) == (O_CREAT|O_EXCL)) ?
+       LAST_DIR : EAT_PATH;
+  Xlastc[0]= '\0';     /* Clear lastc, it will be filled with the part of the
+                        * path that cannot be resolved.
+                        */
   
   /* Request lookup */
-  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  r = Xlookup_vp(&Xlookup_req, &vp, &pathrem);
+
+  if (r == OK && ((oflags & (O_CREAT|O_EXCL)) != (O_CREAT|O_EXCL)))
+  {
+       /* Clear lastc */
+       Xlastc[0]= '\0';
+  }
 
+  /* Hide ENOENT for O_CREAT */
+  if (r == ENOENT && (oflags & O_CREAT))
+  {
+       if (pathrem == NULL)
+               panic(__FILE__, "no pathrem", NO_NUM);
+       if (strchr(pathrem, '/') == 0)
+               r= OK;
+       else
+       {
+               printf("common_open: / in pathrem");
+       }
+  }
+
+  if (r != OK)
+  {
+       if (vp)
+       {
+               put_vnode(vp);
+               vp= NULL;
+       }
+       return r;
+  }
+
+  if (!vp) panic(__FILE__, "common_open: no vp", NO_NUM);
+
+  r= x_open(bits, oflags, omode, Xlastc, &vp);
+  if (r != OK)
+  {
+       if (vp)
+       {
+               put_vnode(vp);
+               vp= NULL;
+       }
+       return r;
+  }
+
+#if 0
   /* Lookup was okay, fill in request fields for 
    * the actual open request. */
   req.inode_nr = res.inode_nr;
@@ -145,8 +194,9 @@ PRIVATE int common_open(register int oflags, mode_t omode)
   /* Check whether the vnode is already in use */
   if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
       vp = vp2;
-      vp->v_size = res.fsize;; /* In case of trunc... */
-      vp->v_count++;
+      vp->v_size = res.fsize; /* In case of trunc... */
+      vp->v_ref_count++;
+      vp->v_fs_count++;
   }
   /* Otherwise use the free one */
   else {
@@ -157,12 +207,16 @@ PRIVATE int common_open(register int oflags, mode_t omode)
       vp->v_dev = vmp->m_dev;
       vp->v_inode_nr = res.inode_nr;
       vp->v_mode = res.fmode;
+      vp->v_uid = res.uid;
+      vp->v_gid = res.gid;
       vp->v_size = res.fsize;
       vp->v_sdev = res.dev; 
-      vp->v_count = 1;
+      vp->v_fs_count = 1;
+      vp->v_ref_count = 1;
       vp->v_vmnt = vmp; 
       vp->v_index = res.inode_index;
   }
+#endif
 
   /* Claim the file descriptor and filp slot and fill them in. */
   fp->fp_filp[m_in.fd] = fil_ptr;
@@ -171,6 +225,7 @@ PRIVATE int common_open(register int oflags, mode_t omode)
   fil_ptr->filp_flags = oflags;
   fil_ptr->filp_vno = vp;
   
+  vp->v_isfifo= FALSE;
   switch (vp->v_mode & I_TYPE) {
       case I_CHAR_SPECIAL:
           /* Invoke the driver for special processing. */
@@ -180,6 +235,8 @@ PRIVATE int common_open(register int oflags, mode_t omode)
       case I_BLOCK_SPECIAL:
           /* Invoke the driver for special processing. */
           r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE));
+         if (r != OK)
+               panic(__FILE__, "common_open: dev_open failed", r);
           
           /* Check whether the device is mounted or not */
           found = 0;
@@ -219,7 +276,10 @@ PRIVATE int common_open(register int oflags, mode_t omode)
           break;
 
       case I_NAMED_PIPE:
+         printf("common_open: setting I_PIPE, inode %d on dev 0x%x\n",
+               vp->v_inode_nr, vp->v_dev);
          vp->v_pipe = I_PIPE;
+               vp->v_isfifo= TRUE;
           oflags |= O_APPEND;  /* force append mode */
           fil_ptr->filp_flags = oflags;
           r = pipe_open(vp, bits, oflags);
@@ -269,6 +329,126 @@ PRIVATE int common_open(register int oflags, mode_t omode)
   return(m_in.fd);
 }
 
+/*===========================================================================*
+ *                             x_open                                       *
+ *===========================================================================*/
+PRIVATE int x_open(bits, oflags, omode, lastc, vpp)
+mode_t bits;
+int oflags;
+mode_t omode;
+char *lastc;
+struct vnode **vpp;
+{
+  int r, b, exist = TRUE;
+  struct vnode *vp, *dvp, *tmp_vp;
+  struct vmnt *vmp;
+  struct node_details res;
+
+  /* If O_CREATE is set, try to make the file. */ 
+  if ((oflags & O_CREAT) && lastc[0] != '\0') {
+       dvp= *vpp;      /* Parent directory */
+
+       /* See if a free vnode is available */
+       if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
+               printf("VFS x_open: no free vnode available\n");
+               return EINVAL;
+       }
+
+       r= req_create(dvp->v_fs_e, dvp->v_inode_nr, omode, fp->fp_effuid,
+               fp->fp_effgid, lastc, &res);
+       if (r != OK)
+               return r;
+       exist = FALSE;
+
+       /* Check whether vnode is already in use or not */
+       if ((tmp_vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
+               vp= tmp_vp;
+               vp->v_ref_count++;
+               vp->v_fs_count++;
+       }
+       else
+       {
+               /* Fill in the free vnode's fields */
+               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;
+
+               if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
+               panic(__FILE__, "lookup_vp: vmnt not found", NO_NUM);
+
+               vp->v_vmnt = vmp; 
+               vp->v_dev = vmp->m_dev;
+               vp->v_fs_count = 1;
+               vp->v_ref_count = 1;
+       }
+
+       /* Release dvp */
+       put_vnode(dvp);
+
+       /* Update *vpp */
+       *vpp= vp;
+  } 
+  else {
+       vp= *vpp;
+  }
+
+  /* Only do the normal open code if we didn't just create the file. */
+  if (!exist)
+       return OK;
+
+  /* Check protections. */
+  if ((r = forbidden(vp, bits)) != OK)
+       return r;
+
+  /* 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(vp, W_BIT)) !=OK) break;
+               truncate_vn(vp, 0);
+       }
+       break;
+
+  case I_DIRECTORY: 
+       /* Directories may be read but not written. */
+       r = (bits & W_BIT ? EISDIR : OK);
+       break;
+
+  case I_CHAR_SPECIAL:
+  case I_BLOCK_SPECIAL:
+       if (vp->v_sdev == (dev_t)-1)
+               panic(__FILE__, "x_open: bad special", NO_NUM);
+       break;
+
+  case I_NAMED_PIPE:
+       printf("x_open (fifo): reference count %d, fd %d\n",
+               vp->v_ref_count, vp->v_fs_count);
+       if (vp->v_ref_count == 1)
+       {
+               printf("x_open (fifo): first reference, size %u\n",
+                       vp->v_size);
+               if (vp->v_size != 0)
+               {
+                       printf("x_open (fifo): clearing\n");
+                       r= truncate_vn(vp, 0);
+                       if (r != OK)
+                       {
+                               printf(
+                               "x_open (fifo): truncate_vn failed: %d\n",
+                                       r);
+                       }
+               }
+       }
+       break;
+  }
+
+  return(r);
+}
 
 
 /*===========================================================================*
@@ -283,6 +463,8 @@ PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
  *  processes hanging on the pipe.
  */
 
+         printf("pipe_open: setting I_PIPE, inode %d on dev 0x%x\n",
+               vp->v_inode_nr, vp->v_dev);
   vp->v_pipe = I_PIPE; 
 
   if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) {
@@ -551,7 +733,7 @@ int fd_nr;
 
   /* If a write has been done, the inode is already marked as DIRTY. */
   if (--rfilp->filp_count == 0) {
-       if (vp->v_pipe == I_PIPE && vp->v_count > 1) {
+       if (vp->v_pipe == I_PIPE && vp->v_ref_count > 1) {
                /* Save the file position in the v-node in case needed later.
                 * The read and write positions are saved separately.  
                 */
index 86e060829f5eb755a122d71b175f0c73d5ceb4aa..fa6051f97c025cf635808a5c50f8ea46a2ca0c9b 100644 (file)
@@ -21,6 +21,8 @@
 #include "vnode.h"
 #include "param.h"
 
+FORWARD _PROTOTYPE( int Xlookup, (lookup_req_t *lookup_req,
+                               node_details_t *node, char **pathrem)   );
 
 /*===========================================================================*
  *                             lookup                                       *
@@ -104,6 +106,8 @@ node_details_t *node;
           }
           if (!start_node) {
               printf("VFSlookup: mounted partition couldn't be found\n");
+             printf("VFSlookup: res.inode_nr = %d, res.fs_e = %d\n",
+               res.inode_nr, res.fs_e);
               return ENOENT;
           }
 
@@ -138,15 +142,300 @@ node_details_t *node;
       r = req_lookup(&req, &res);
   }
 
-  /* If success, fill in response fields */
-  if (OK == r) {
-      node->inode_nr = res.inode_nr;
-      node->fmode = res.fmode;
-      node->fsize = res.fsize;
-      node->dev = res.dev;
-      node->fs_e = res.fs_e;
+  /* 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;
+  
+  return r;
+}
+
+
+/*===========================================================================*
+ *                             Xlookup                                      *
+ *===========================================================================*/
+PRIVATE int Xlookup(lookup_req, node, pathrem)
+lookup_req_t *lookup_req;
+node_details_t *node;
+char **pathrem;
+{
+  struct vmnt *vmp;
+  struct vnode *start_node;
+  struct lookup_res res;
+  int r, symloop = 0;
+  int cum_path_processed = 0;
+
+  /* Make a copy of the request so that the original values will be kept */ 
+  struct lookup_req req = *lookup_req; 
+  char *fullpath = lookup_req->path;
+
+  /* Clear pathrem */
+  *pathrem= NULL;
+
+  /* Empty (start) path? */
+  if (fullpath[0] == '\0') {
+      return ENOENT;
+  }
+
+  /* Set user and group ids according to the system call */
+  req.uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid); 
+  req.gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid); 
+
+  /* Set the starting directories inode number and FS endpoint */
+  start_node = (fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
+  req.start_dir = start_node->v_inode_nr;
+  req.fs_e = start_node->v_fs_e;
+
+  /* Is the process' root directory on the same partition?,
+   * if so, set the chroot directory too. */
+  if (fp->fp_rd->v_dev == fp->fp_wd->v_dev)
+      req.root_dir = fp->fp_rd->v_inode_nr; 
+  else
+      req.root_dir = 0;
+
+  req.symloop = symloop;
+
+  /* Issue the request */
+  r = req_lookup(&req, &res);
+
+  /* While the response is related to mount control set the 
+   * new requests respectively */
+  while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
+      
+      /* If a symlink was encountered during the lookup the 
+       * new path has been copied back and the number of characters 
+       * processed has been started over. */
+      if (r == ESYMLINK || res.symloop > symloop) {
+          /* The link's content is copied back to the user_fullpath
+           * array. Use it as the path argument from now on... */
+          fullpath = user_fullpath;
+          cum_path_processed = res.char_processed;
+      }
+      else {
+          /* Otherwise, cumulate the characters already processsed from 
+           * the path */
+          cum_path_processed += res.char_processed;
+      }
+
+      /* Remember the current value of the symloop counter */
+      symloop = res.symloop;
+
+      /* Symlink encountered with absolute path */
+      if (r == ESYMLINK) {
+          start_node = fp->fp_rd;
+      }
+      /* Entering a new partition */
+      else if (r == EENTERMOUNT) {
+          start_node = 0;
+          /* Start node is now the mounted partition's root node */
+          for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
+              if (vmp->m_mounted_on->v_inode_nr == res.inode_nr
+                      && vmp->m_mounted_on->v_fs_e == res.fs_e) {
+                  start_node = vmp->m_root_node;
+                  break;
+              }
+          }
+          if (!start_node) {
+              printf("VFSlookup: mounted partition couldn't be found\n");
+             printf("VFSlookup: res.inode_nr = %d, res.fs_e = %d\n",
+               res.inode_nr, res.fs_e);
+              return ENOENT;
+          }
+
+      }
+      /* Climbing up mount */
+      else {
+          /* Find the vmnt that represents the partition on
+           * which we "climb up". */
+          if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) {
+              printf("VFS: couldn't find vmnt during the climbup!\n");
+              return ENOENT;
+          }      
+          /* Start node is the vnode on which the partition is
+           * mounted */
+          start_node = vmp->m_mounted_on;
+      }
+      /* Fill in the request fields */
+      req.start_dir = start_node->v_inode_nr;
+      req.fs_e = start_node->v_fs_e;
+
+      /* Is the process' root directory on the same partition?*/
+      if (start_node->v_dev == fp->fp_rd->v_dev)
+          req.root_dir = fp->fp_rd->v_inode_nr;
+      else
+          req.root_dir = 0;
+
+      /* Fill in the current path name */
+      req.path = &fullpath[cum_path_processed];
+      req.symloop = symloop;
+      
+      /* Issue the request */
+      r = req_lookup(&req, &res);
   }
+
+  if (r == ENOENT)
+  {
+        cum_path_processed += res.char_processed;
+       *pathrem= &fullpath[cum_path_processed];
+  }
+
+  /* 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;
   
   return r;
 }
 
+
+/*===========================================================================*
+ *                             lookup_vp                                    *
+ *===========================================================================*/
+PUBLIC int lookup_vp(lookup_req, vpp)
+lookup_req_t *lookup_req;
+struct vnode **vpp;
+{
+  int r, lookup_res;
+  struct vnode *vp;
+  struct vmnt *vmp;
+  node_req_t node_req;
+  struct node_details res;
+
+  lookup_res = lookup(lookup_req, &res);
+
+  if (res.inode_nr == 0)
+  {
+       printf("lookup_vp: lookup returned no inode\n");
+       printf("lookup_res = %d, last = '%s'\n",
+               lookup_res, lookup_req->lastc);
+       *vpp= NULL;
+       return lookup_res;
+  }
+
+  /* Check whether vnode is already in use or not */
+  if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
+        vp->v_ref_count++;
+       *vpp= vp;
+       return lookup_res;
+  }
+
+  /* See if free vnode is available */
+  if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
+      printf("VFS lookup_vp: no free vnode available\n");
+      *vpp= NULL;
+      return EINVAL;
+  }
+
+  /* Fill in request message fields.*/
+  node_req.fs_e = res.fs_e;
+  node_req.inode_nr = res.inode_nr;
+
+  /* Issue request */
+  if ((r = req_getnode(&node_req, &res)) != OK)
+  {
+       printf("lookup_vp: req_getnode failed: %d\n", r);
+       *vpp= NULL;
+       return r;
+  }
+  
+  /* Fill in the free vnode's fields */
+  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;
+
+  if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
+       panic(__FILE__, "lookup_vp: vmnt not found", NO_NUM);
+
+  vp->v_vmnt = vmp; 
+  vp->v_dev = vmp->m_dev;
+  vp->v_fs_count = 1;
+  vp->v_ref_count = 1;
+
+  *vpp= vp;
+  return lookup_res;
+}
+
+/*===========================================================================*
+ *                             Xlookup_vp                                   *
+ *===========================================================================*/
+PUBLIC int Xlookup_vp(lookup_req, vpp, pathrem)
+lookup_req_t *lookup_req;
+struct vnode **vpp;
+char **pathrem;
+{
+  int r, lookup_res;
+  struct vnode *vp;
+  struct vmnt *vmp;
+  node_req_t node_req;
+  struct node_details res;
+
+  lookup_res = Xlookup(lookup_req, &res, pathrem);
+
+  if (res.inode_nr == 0)
+  {
+       printf("Xlookup_vp: lookup returned no inode\n");
+       printf("lookup_res = %d, last = '%s'\n",
+               lookup_res, lookup_req->lastc);
+       *vpp= NULL;
+       return lookup_res;
+  }
+
+  /* Check whether vnode is already in use or not */
+  if ((vp = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
+        vp->v_ref_count++;
+       *vpp= vp;
+       return lookup_res;
+  }
+
+  /* See if free vnode is available */
+  if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
+      printf("VFS Xlookup_vp: no free vnode available\n");
+      *vpp= NULL;
+      return EINVAL;
+  }
+
+  /* Fill in request message fields.*/
+  node_req.fs_e = res.fs_e;
+  node_req.inode_nr = res.inode_nr;
+
+  /* Issue request */
+  if ((r = req_getnode(&node_req, &res)) != OK)
+  {
+       printf("Xlookup_vp: req_getnode failed: %d\n", r);
+       *vpp= NULL;
+       return r;
+  }
+  
+  /* Fill in the free vnode's fields */
+  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;
+
+  if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
+       panic(__FILE__, "Xlookup_vp: vmnt not found", NO_NUM);
+
+  vp->v_vmnt = vmp; 
+  vp->v_dev = vmp->m_dev;
+  vp->v_fs_count = 1;
+  vp->v_ref_count = 1;
+
+  *vpp= vp;
+  return lookup_res;
+}
+
index af327dc518d370da36a84aecc718556fcd4f9d08..0dddab50b172b17e1afb139159a0387afd00ff17 100644 (file)
@@ -59,7 +59,7 @@ PUBLIC int do_pipe()
   struct node_details res;
 
   /* See if a free vnode is available */
-  if ( (vp = get_free_vnode()) == NIL_VNODE) {
+  if ( (vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
       printf("VFS: no vnode available!\n");
       return err_code;
   }
@@ -105,7 +105,8 @@ PUBLIC int do_pipe()
   vp->v_mode = res.fmode;
   vp->v_index = res.inode_index;
   vp->v_pipe = I_PIPE;
-  vp->v_count = 2;              /* Double usage */
+  vp->v_fs_count = 2;           /* Double usage */
+  vp->v_ref_count = 2;          /* Double usage */
   vp->v_size = 0;
 
   if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) {
index 35173a7add85c736c01ca302503ddec0ad357681..093bc2200eb2808868e2229462797bd64941af51 100644 (file)
@@ -163,3 +163,76 @@ PUBLIC int do_access()
   return req_access(&req);
 }
 
+
+/*===========================================================================*
+ *                             forbidden                                    *
+ *===========================================================================*/
+PUBLIC int forbidden(struct vnode *vp, mode_t access_desired)
+{
+/* Given a pointer to an inode, 'rip', 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 struct super_block *sp;
+  register mode_t bits, perm_bits;
+  int r, shift, type;
+
+  if (vp->v_uid == (uid_t)-1 || vp->v_gid == (gid_t)-1)
+  {
+       printf("forbidden: bad uid/gid in vnode\n");
+       printf("forbidden: last allocated at %s, %d\n", vp->v_file, vp->v_line);
+       return EACCES;
+  }
+
+  /* Isolate the relevant rwx bits from the mode. */
+  bits = vp->v_mode;
+  if (fp->fp_effuid == 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 (fp->fp_effuid == vp->v_uid) shift = 6;      /* owner */
+       else if (fp->fp_effgid == vp->v_gid ) shift = 3;        /* group */
+       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.
+ */
+  register struct vmnt *mp;
+
+  mp = vp->v_vmnt;
+  return(mp->m_flags ? EROFS : OK);
+}
+
+
index c886cea90e2a04157f2bbd98a3c6492a04157f90..67aaf73ac6f8e53172d3c0bf2aa320460a3de296 100644 (file)
@@ -58,6 +58,7 @@ _PROTOTYPE( int do_unlink, (void)                                     );
 _PROTOTYPE( int do_rename, (void)                                      );
 _PROTOTYPE( int do_truncate, (void)                                    );
 _PROTOTYPE( int do_ftruncate, (void)                                   );
+_PROTOTYPE( int truncate_vn, (struct vnode *vp, off_t newsize)         );
 
 /* lock.c */
 _PROTOTYPE( int lock_op, (struct filp *f, int req)                     );
@@ -100,6 +101,9 @@ _PROTOTYPE( int do_slink, (void)                                        );
 
 /* path.c */
 _PROTOTYPE( int lookup, (lookup_req_t *request, node_details_t *node)   );
+_PROTOTYPE( int lookup_vp, (lookup_req_t *request, struct vnode **vpp) );
+_PROTOTYPE( int Xlookup_vp, (lookup_req_t *request, struct vnode **vpp,
+                                                       char **pathrem) );
 
 /* pipe.c */
 _PROTOTYPE( int do_pipe, (void)                                                );
@@ -120,6 +124,8 @@ _PROTOTYPE( int do_access, (void)                                   );
 _PROTOTYPE( int do_chmod, (void)                                       );
 _PROTOTYPE( int do_chown, (void)                                       );
 _PROTOTYPE( int do_umask, (void)                                       );
+_PROTOTYPE( int forbidden, (struct vnode *vp, mode_t access_desired)   );
+_PROTOTYPE( int read_only, (struct vnode *vp)                          );
 
 /* read.c */
 _PROTOTYPE( int do_read, (void)                                                );
@@ -129,8 +135,10 @@ _PROTOTYPE( int read_write, (int rw_flag)                          );
 /* request.c */
 _PROTOTYPE( int fs_sendrec, (endpoint_t fs_e, message *reqm)            );
 _PROTOTYPE( int req_getnode, (node_req_t *req, node_details_t *res)     );
-_PROTOTYPE( int req_putnode, (node_req_t *req)                          );
+_PROTOTYPE( int req_putnode, (int fs_e, ino_t inode_nr, int count)     );
 _PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res)        ); 
+_PROTOTYPE( int req_create, (int fs_e, ino_t inode_nr, int omode,
+               int uid, int gid, char *path, node_details_t *res)      ); 
 _PROTOTYPE( int req_readwrite, (readwrite_req_t *req, 
             readwrite_res_t *res)                                       );
 _PROTOTYPE( int req_pipe, (pipe_req_t *req, node_details_t *res)        );
@@ -143,15 +151,15 @@ _PROTOTYPE( int req_access, (access_req_t *req)                         );
 _PROTOTYPE( int req_mknod, (mknod_req_t *req)                           );
 _PROTOTYPE( int req_mkdir, (mkdir_req_t *req)                           );
 _PROTOTYPE( int req_inhibread, (node_req_t *req)                        );
-_PROTOTYPE( int req_stat, (stat_req_t *req)                             );
-_PROTOTYPE( int req_fstat, (stat_req_t *req)                            );
-_PROTOTYPE( int req_fstatfs, (stat_req_t *req)                          );
+_PROTOTYPE( int req_stat, (int fs_e, ino_t inode_nr, int who_e,
+                                               char *buf, int pos)     );
+_PROTOTYPE( int req_fstatfs, (int fs_e, ino_t inode_nr, int who_e,
+                                                       char *buf)      );
 _PROTOTYPE( int req_unlink, (unlink_req_t *req)                         );
 _PROTOTYPE( int req_rmdir, (unlink_req_t *req)                          );
 _PROTOTYPE( int req_utime, (utime_req_t *req)                           );
 _PROTOTYPE( int req_stime, (endpoint_t fs_e, time_t boottime)           );
 _PROTOTYPE( int req_sync, (endpoint_t fs_e)                             );
-_PROTOTYPE( int req_getdir, (getdir_req_t *req, node_details_t *res)    );
 _PROTOTYPE( int req_link, (link_req_t *req)                             );
 _PROTOTYPE( int req_slink, (slink_req_t *req)                           );
 _PROTOTYPE( int req_rdlink, (rdlink_req_t *req)                         );
@@ -202,11 +210,17 @@ _PROTOTYPE( struct vmnt *get_free_vmnt, (short *index)                  );
 _PROTOTYPE( struct vmnt *find_vmnt, (int fs_e)                          );
 
 /* vnode.c */
-_PROTOTYPE( struct vnode *get_free_vnode, (void)                        );
+_PROTOTYPE( struct vnode *get_free_vnode, (char *file, int line)       );
 _PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb)              );
 _PROTOTYPE( void dup_vnode, (struct vnode *vp)                          );
 _PROTOTYPE( void put_vnode, (struct vnode *vp)                          );
+_PROTOTYPE( void vnode_clean_refs, (struct vnode *vp)                   );
 _PROTOTYPE( struct vnode *get_vnode, (int fs_e, int inode_nr)           );
+_PROTOTYPE( struct vnode *get_vnode_x, (int fs_e, int inode_nr)                );
+#if 0
+_PROTOTYPE( void mark_vn, (struct vnode *vp, char *file, int line)     );
+_PROTOTYPE( int check_vrefs, (void)                                    );
+#endif
 
 /* write.c */
 _PROTOTYPE( int do_write, (void)                                       );
index 3f755cfebd9b470e7bf8123cfe6ac7ec18e457d8..d142d33dd1d41a7485f0a46055aee9d1794f2b67 100644 (file)
@@ -192,6 +192,13 @@ int rw_flag;                       /* READING or WRITING */
       req.user_addr = m_in.buffer;
       req.inode_index = vp->v_index;
 
+      if (vp->v_isfifo)
+      {
+       printf("read_write: %s for FIFO @ %u size %u\n",
+               (rw_flag == READING) ? "read" : "write",
+               ex64lo(position), m_in.nbytes);
+      }
+
       /* Issue request */
       r = req_readwrite(&req, &res);
 
index 28d850f110e544f7c94d767d5b7206ff1e64fd8e..b41ea8746b520494ca118bae5a846c88c9a4559c 100644 (file)
@@ -12,6 +12,8 @@
 
 #include "fs.h"
 #include <string.h>
+#include <sys/stat.h>
+#include <sys/statfs.h>
 #include <minix/callnr.h>
 #include <minix/com.h>
 #include <minix/keymap.h>
@@ -50,6 +52,8 @@ node_details_t *res;
     res->fmode = m.RES_MODE;
     res->fsize = m.RES_FILE_SIZE;
     res->dev = m.RES_DEV;
+    res->uid = m.RES_UID;
+    res->gid = m.RES_GID;
 
     return OK;
 }
@@ -58,17 +62,20 @@ node_details_t *res;
 /*===========================================================================*
  *                             req_putnode                                  *
  *===========================================================================*/
-PUBLIC int req_putnode(req)
-node_req_t *req; 
+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 = req->inode_nr;
+    m.REQ_INODE_NR = inode_nr;
+    m.REQ_COUNT = count;
 
     /* Send/rec request */
-    return fs_sendrec(req->fs_e, &m);
+    return fs_sendrec(fs_e, &m);
 }
 
 /*===========================================================================*
@@ -110,6 +117,49 @@ node_details_t *res;
 }
 
 
+/*===========================================================================*
+ *                             req_create                                   *
+ *===========================================================================*/
+int req_create(fs_e, inode_nr, omode, uid, gid, path, res)
+int fs_e;
+ino_t inode_nr;
+int omode;
+uid_t uid;
+gid_t gid;
+char *path;
+node_details_t *res; 
+{
+    int r;
+    message m;
+
+    /* 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_PATH = path;
+    m.REQ_PATH_LEN = strlen(path) + 1;
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(fs_e, &m)) != 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;
+    res->dev = m.RES_DEV;
+    res->inode_index = m.RES_INODE_INDEX;
+    /* For exec */
+    res->uid = m.RES_UID;
+    res->gid = m.RES_GID;
+    res->ctime = m.RES_CTIME;
+
+    return OK;
+}
+
+
 /*===========================================================================*
  *                             req_readwrite                                *
  *===========================================================================*/
@@ -351,60 +401,81 @@ node_req_t *req;
 /*===========================================================================*
  *                             req_stat                                     *
  *===========================================================================*/
-PUBLIC int req_stat(req)
-stat_req_t *req;
+PUBLIC int req_stat(fs_e, inode_nr, who_e, buf, pos)
+int fs_e;
+ino_t inode_nr;
+int who_e;
+char *buf;
+int pos;
 {
-    message m;
+  cp_grant_id_t gid;
+  int r;
+  message m;
+  struct stat sb;
+
+  if (pos != 0)
+  {
+       gid= cpf_grant_direct(fs_e, (vir_bytes)&sb, sizeof(struct stat),
+               CPF_WRITE);
+  }
+  else
+  {
+       gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct stat),
+               CPF_WRITE);
+  }
+  if (gid < 0)
+       return gid;
 
-    /* Fill in request message */
-    m.m_type = REQ_STAT;
-    m.REQ_INODE_NR = req->inode_nr;
-    m.REQ_UID = req->uid;
-    m.REQ_GID = req->gid;
-    m.REQ_WHO_E = req->who_e;
-    m.REQ_USER_ADDR = req->buf;
+  /* Fill in request message */
+  m.m_type = REQ_STAT;
+  m.REQ_INODE_NR = inode_nr;
+  m.REQ_GRANT = gid;
 
-    /* Send/rec request */
-    return fs_sendrec(req->fs_e, &m);
-}
+  /* Send/rec request */
+  r= fs_sendrec(fs_e, &m);
 
+  cpf_revoke(gid);
 
-/*===========================================================================*
- *                             req_fstat                                    *
- *===========================================================================*/
-PUBLIC int req_fstat(req)
-stat_req_t *req;
-{
-    message m;
-
-    /* Fill in request message */
-    m.m_type = REQ_FSTAT;
-    m.REQ_FD_INODE_NR = req->inode_nr;
-    m.REQ_FD_WHO_E = req->who_e;
-    m.REQ_FD_USER_ADDR = req->buf;
-    m.REQ_FD_POS = req->pos;
+  if (r == OK && pos != 0)
+  {
+       sb.st_size -= pos;
+       r= sys_vircopy(SELF, D, (vir_bytes)&sb, who_e, D, (vir_bytes)buf, 
+               sizeof(struct stat));
+  }
 
-    /* Send/rec request */
-    return fs_sendrec(req->fs_e, &m);
+  return r;
 }
 
 
 /*===========================================================================*
  *                             req_fstatfs                                  *
  *===========================================================================*/
-PUBLIC int req_fstatfs(req)
-stat_req_t *req;
+PUBLIC int req_fstatfs(fs_e, inode_nr, who_e, buf)
+int fs_e;
+ino_t inode_nr;
+int who_e;
+char *buf;
 {
-    message m;
+  int r;
+  cp_grant_id_t gid;
+  message m;
 
-    /* Fill in request message */
-    m.m_type = REQ_FSTATFS;
-    m.REQ_FD_INODE_NR = req->inode_nr;
-    m.REQ_FD_WHO_E = req->who_e;
-    m.REQ_FD_USER_ADDR = req->buf;
+  gid= cpf_grant_magic(fs_e, who_e, (vir_bytes)buf, sizeof(struct statfs),
+               CPF_WRITE);
+  if (gid < 0)
+       return gid;
 
-    /* Send/rec request */
-    return fs_sendrec(req->fs_e, &m);
+  /* Fill in request message */
+  m.m_type = REQ_FSTATFS;
+  m.REQ_INODE_NR = inode_nr;
+  m.REQ_GRANT = gid;
+
+  /* Send/rec request */
+  r= fs_sendrec(fs_e, &m);
+
+  cpf_revoke(gid);
+
+  return r;
 }
 
 
@@ -505,35 +576,6 @@ endpoint_t fs_e;
 }
 
 
-/*===========================================================================*
- *                             req_getdir                                   *
- *===========================================================================*/
-PUBLIC int req_getdir(req, res)
-getdir_req_t *req; 
-node_details_t *res;
-{
-    int r;
-    message m;
-
-    /* Fill in request message */
-    m.m_type = REQ_GETDIR;
-    m.REQ_INODE_NR = req->inode_nr;
-    m.REQ_UID = req->uid;
-    m.REQ_GID = req->gid;
-
-    /* Send/rec request */
-    if ((r = fs_sendrec(req->fs_e, &m)) != 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;
-
-    return OK;
-}
-
-
 /*===========================================================================*
  *                             req_link                                     *
  *===========================================================================*/
@@ -787,10 +829,14 @@ lookup_res_t *res;
     res->fs_e = m.m_source;
     switch (r) {
         case OK:
+       default:
             res->inode_nr = m.RES_INODE_NR;
             res->fmode = m.RES_MODE;
             res->fsize = m.RES_FILE_SIZE;
             res->dev = m.RES_DEV;
+           res->uid= m.RES_UID;
+           res->gid= m.RES_GID;
+            res->char_processed = m.RES_OFFSET;                /* For ENOENT */
             break;
         case EENTERMOUNT:
             res->inode_nr = m.RES_INODE_NR;
index a41a278f531f6fe90d1483f916836c34f5e4163e..ca65ac016bd4659980cc763f7cb8ac9b09419e13 100644 (file)
@@ -142,17 +142,6 @@ typedef struct mkdir_req {
 } mkdir_req_t;
 
 
-/* Structure for REQ_STAT, REQ_FSTAT, REQ_FSTATFS requests */
-typedef struct stat_req {
-        int fs_e;
-        ino_t inode_nr;
-        uid_t uid;
-        gid_t gid;
-        int who_e;
-        char *buf;
-        int pos;
-} stat_req_t;
-
 /* Structure for REQ_UNLINK request */
 typedef struct unlink_req {
         int fs_e;
@@ -174,15 +163,6 @@ typedef struct utime_req {
 } utime_req_t;
 
 
-/* Structure for REQ_GETDIR request */
-typedef struct getdir_req {
-       endpoint_t fs_e;
-       ino_t inode_nr;
-        uid_t uid;
-        gid_t gid;
-} getdir_req_t;
-
-
 /* Structure for REQ_LINK request */
 typedef struct link_req {
        endpoint_t fs_e;
@@ -294,6 +274,8 @@ typedef struct lookup_res {
        ino_t inode_nr;
        mode_t fmode;
        off_t fsize;
+       uid_t uid;
+       gid_t gid;
        /* For char/block special files */
        dev_t dev;
        
index 40889a3bfd7da5c9e09af731395958de2f976421..2b90d2a818db994a24e6915bb8b839f0f296d063 100644 (file)
@@ -37,8 +37,6 @@ PUBLIC int do_fchdir()
 {
   /* Change directory on already-opened fd. */
   struct filp *rfilp;
-  struct getdir_req req;
-  struct node_details res;
   int r;
 
   /* Is the file descriptor valid? */
@@ -48,17 +46,11 @@ PUBLIC int do_fchdir()
   if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY)
       return ENOTDIR;
   
-  /* Fill in request message fields.*/
-  req.fs_e = rfilp->filp_vno->v_fs_e;
-  req.inode_nr = rfilp->filp_vno->v_inode_nr;
-  req.uid = fp->fp_effuid;
-  req.gid = fp->fp_effgid;
-  
   /* Issue request and handle error */
-  if ((r = req_getdir(&req, &res)) != OK) return r;
+  r = forbidden(rfilp->filp_vno, X_BIT);
+  if (r != OK) return r;
   
-  /* GETDIR increased the counter in the FS proc */
-  rfilp->filp_vno->v_count++;
+  rfilp->filp_vno->v_ref_count++;      /* change_into expects a reference  */
   
   return change_into(&fp->fp_wd, rfilp->filp_vno);
 }
@@ -129,63 +121,27 @@ 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, *vp2;
-  struct vmnt *vmp;
-  struct getdir_req req;
-  struct node_details res;
+  struct vnode *vp;
   struct lookup_req lookup_req;
   int r;
 
   if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
   
-  /* See if free vnode is available */
-  if ((vp = get_free_vnode()) == NIL_VNODE) {
-      printf("VFSchange: no free vnode available\n");
-      return EINVAL;
-  }
-
   /* Fill in lookup request fields */
   lookup_req.path = user_fullpath;
   lookup_req.lastc = NULL;
   lookup_req.flags = EAT_PATH;
         
   /* Request lookup */
-  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  if ((r = lookup_vp(&lookup_req, &vp)) != OK) return r;
 
   /* Is it a dir? */
-  if ((res.fmode & I_TYPE) != I_DIRECTORY)
+  if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
+  {
+      put_vnode(vp);
       return ENOTDIR;
-  
-  /* Fill in request message fields.*/
-  req.fs_e = res.fs_e;
-  req.inode_nr = res.inode_nr;
-  req.uid = fp->fp_effuid;
-  req.gid = fp->fp_effgid;
-  /* Issue request */
-  if ((r = req_getdir(&req, &res)) != OK) return r;
-  
-  /* Check whether vnode is already in use or not */
-  if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) 
-          != NIL_VNODE) {
-        vp2->v_count++;
-        vp = vp2;
-  }
-  else {
-        /* Fill in the free vnode's fields */
-        vp->v_fs_e = res.fs_e;
-        vp->v_inode_nr = res.inode_nr;
-        vp->v_mode = res.fmode;
-        vp->v_size = res.fsize;
-
-          if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
-              printf("VFSchange: vmnt not found");
-
-        vp->v_vmnt = vmp; 
-        vp->v_dev = vmp->m_dev;
-        vp->v_count = 1;
   }
-
+  
   return change_into(iip, vp);
 }
 
@@ -211,7 +167,6 @@ struct vnode *vp;           /* this is what the inode has to become */
 PUBLIC int do_stat()
 {
 /* Perform the stat(name, buf) system call. */
-  struct stat_req req;
   struct node_details res;
   struct lookup_req lookup_req;
   int r;
@@ -226,16 +181,8 @@ PUBLIC int do_stat()
   /* Request lookup */
   if ((r = lookup(&lookup_req, &res)) != OK) return r;
 
-  /* Fill in request message fields.*/
-  req.fs_e = res.fs_e;
-  req.who_e = who_e;
-  req.buf = m_in.name2;
-  req.inode_nr = res.inode_nr;
-  req.uid = fp->fp_effuid;
-  req.gid = fp->fp_effgid;
-  
   /* Issue request */
-  return req_stat(&req);
+  return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0);
 }
 
 
@@ -248,7 +195,6 @@ PUBLIC int do_fstat()
 /* Perform the fstat(fd, buf) system call. */
   register struct filp *rfilp;
   int pipe_pos = 0;
-  struct stat_req req;
 
   /* Is the file descriptor valid? */
   if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) {
@@ -256,6 +202,7 @@ PUBLIC int do_fstat()
   }
   
   /* If we read from a pipe, send position too */
+  pipe_pos= 0;
   if (rfilp->filp_vno->v_pipe == I_PIPE) {
        if (rfilp->filp_mode & R_BIT) 
                if (ex64hi(rfilp->filp_pos) != 0)
@@ -266,15 +213,9 @@ PUBLIC int do_fstat()
                pipe_pos = ex64lo(rfilp->filp_pos);
   }
 
-  /* Fill in request message */
-  req.fs_e = rfilp->filp_vno->v_fs_e;
-  req.inode_nr = rfilp->filp_vno->v_inode_nr;
-  req.pos = pipe_pos;
-  req.who_e = who_e;
-  req.buf = m_in.buffer;
-
   /* Issue request */
-  return req_fstat(&req);
+  return req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
+       who_e, m_in.buffer, pipe_pos);
 }
 
 
@@ -286,19 +227,13 @@ PUBLIC int do_fstatfs()
 {
   /* Perform the fstatfs(fd, buf) system call. */
   register struct filp *rfilp;
-  struct stat_req req;
 
   /* Is the file descriptor valid? */
   if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
 
-  /* Send FS request */
-  req.fs_e = rfilp->filp_vno->v_fs_e;
-  req.inode_nr = rfilp->filp_vno->v_inode_nr;
-  req.who_e = who_e;
-  req.buf = m_in.buffer;
-  
   /* Issue request */
-  return req_fstatfs(&req);
+  return req_fstatfs(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
+       who_e, m_in.buffer);
 }
 
 
@@ -309,7 +244,6 @@ PUBLIC int do_fstatfs()
 PUBLIC int do_lstat()
 {
 /* Perform the lstat(name, buf) system call. */
-  struct stat_req req;
   struct node_details res;
   struct lookup_req lookup_req;
   int r;
@@ -324,16 +258,8 @@ PUBLIC int do_lstat()
   /* Request lookup */
   if ((r = lookup(&lookup_req, &res)) != OK) return r;
 
-  /* Fill in request message fields.*/
-  req.fs_e = res.fs_e;
-  req.who_e = who_e;
-  req.buf = m_in.name2;
-  req.inode_nr = res.inode_nr;
-  req.uid = fp->fp_effuid;
-  req.gid = fp->fp_effgid;
-  
   /* Issue request */
-  return req_stat(&req);
+  return req_stat(res.fs_e, res.inode_nr, who_e, m_in.name2, 0);
 }
 
 
index 0646bc4c740208b834cd7200582475bb4b0d5b49..a283d4c4117d99aa865e5f2d1fbde30179544aee 100644 (file)
@@ -14,6 +14,9 @@
 #include "vnode.h"
 #include "vmnt.h"
 
+#include "fproc.h"
+#include "file.h"
+
 #include <minix/vfsif.h>
 
 /*===========================================================================*
@@ -30,9 +33,13 @@ PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr)
   /* Request & response structures */
   struct node_req req;
   struct node_details res;
+
+  /* XXX remove this when debugging is complete */
+  if (find_vnode(fs_e, inode_nr) != NULL)
+       panic(__FILE__, "get_vnode: vnode already present", NO_NUM);
   
   /* Check whether a free vnode is avaliable */
-  if ((vp = get_free_vnode()) == NIL_VNODE) {
+  if ((vp = get_free_vnode(__FILE__, __LINE__)) == NIL_VNODE) {
         printf("VFSget_vnode: no vnode available\n");
         return NIL_VNODE;
   }
@@ -60,22 +67,61 @@ PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr)
   
   vp->v_vmnt = vmp; 
   vp->v_dev = vmp->m_dev;
-  vp->v_count = 1;
+  vp->v_fs_count = 1;
+  vp->v_ref_count = 1;
   
   return vp; 
 }
 
 
+/*===========================================================================*
+ *                             get_vnode                                    *
+ *===========================================================================*/
+PUBLIC struct vnode *get_vnode_x(int fs_e, int inode_nr)
+{
+/* get_vnode() is called to get the details of the specified inode.
+ * Note that inode's usage counter in the FS is supposed to be incremented.
+ */
+  struct vnode *vp, *vp2;
+  struct vmnt *vmp;
+
+  /* Request & response structures */
+  struct node_req req;
+  struct node_details res;
+
+  vp= find_vnode(fs_e, inode_nr);
+  if (vp)
+  {
+       vp->v_ref_count++;
+       return vp;
+  }
+
+  return get_vnode(fs_e, inode_nr);
+}
+
+
 /*===========================================================================*
  *                             get_free_vnode                               *
  *===========================================================================*/
-PUBLIC struct vnode *get_free_vnode()
+PUBLIC struct vnode *get_free_vnode(file, line)
+char *file;
+int line;
 {
 /* Find a free vnode slot in the vnode table */    
   struct vnode *vp;
 
   for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
-      if (vp->v_count == 0) return vp;
+       if (vp->v_ref_count == 0)
+       {
+               vp->v_pipe= NO_PIPE;
+               vp->v_uid= -1;
+               vp->v_gid= -1;
+               vp->v_sdev= -1;
+               vp->v_file= file;
+               vp->v_line= line;
+               return vp;
+       }
+
   
   err_code = ENFILE;
   return NIL_VNODE;
@@ -91,7 +137,7 @@ PUBLIC struct vnode *find_vnode(int fs_e, int numb)
   struct vnode *vp;
 
   for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
-      if (vp->v_count > 0 && vp->v_inode_nr == numb
+      if (vp->v_ref_count > 0 && vp->v_inode_nr == numb
               && vp->v_fs_e == fs_e) return vp;
   
   return NIL_VNODE;
@@ -106,23 +152,12 @@ PUBLIC void dup_vnode(struct vnode *vp)
 /* dup_vnode() is called to increment the vnode and therefore the
  * referred inode's counter.
  */
-  struct node_req req;
-  struct node_details res;
-  
   if (vp == NIL_VNODE) {
       printf("VFSdup_vnode NIL_VNODE\n");
       return;
   }
 
-  /* Fill req struct */
-  req.inode_nr = vp->v_inode_nr;
-  req.fs_e = vp->v_fs_e;
-
-  /* Send request to FS */
-  if (req_getnode(&req, &res) != OK)
-        printf("VFSdup_vnode Warning: inode doesn't exist\n"); 
-  else
-        vp->v_count++;
+  vp->v_ref_count++;
 }
 
 
@@ -134,28 +169,176 @@ PUBLIC void put_vnode(struct vnode *vp)
 /* Decrease vnode's usage counter and decrease inode's usage counter in the 
  * corresponding FS process.
  */
-  struct node_req req;
-  
   if (vp == NIL_VNODE) {
         /*printf("VFSput_vnode NIL_VNODE\n");*/
         return;
   }
 
-  /* Fill in request fields */
-  req.fs_e = vp->v_fs_e;
-  req.inode_nr = vp->v_inode_nr;
+  if (vp < &vnode[0] || vp >= &vnode[NR_VNODES])
+  {
+       printf("put_vnode: &vnode[0] = %p, &vnode[NR_VNODES] = %p, vp = %p\n",
+               &vnode[0], &vnode[NR_VNODES], vp);
+       panic(__FILE__, "put_vnode: bad vnode pointer", NO_NUM);
+  }
 
-  /* Send request */
-  if (req_putnode(&req) == OK) {
-      /* Decrease counter */
-      if (--vp->v_count == 0) {
-          vp->v_pipe = NO_PIPE;
-          vp->v_sdev = NO_DEV;
-          vp->v_index = 0;
-      }
+  if (vp->v_ref_count > 1)
+  {
+       /* Decrease counter */
+       vp->v_ref_count--;
+       if (vp->v_fs_count > 256)
+               vnode_clean_refs(vp);
+       return;
+  }
+
+  if (vp->v_ref_count <= 0)
+  {
+       printf("put_vnode: bad v_ref_count %d\n", vp->v_ref_count);
+       panic(__FILE__, "put_vnode failed", NO_NUM);
+  }
+  if (vp->v_fs_count <= 0)
+  {
+       printf("put_vnode: bad v_fs_count %d\n", vp->v_fs_count);
+       panic(__FILE__, "put_vnode failed", NO_NUM);
   }
-  else 
+
+  /* Send request */
+  if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count) != OK)
       printf("VFSput_vnode Warning: inode doesn't exist\n"); 
+
+  vp->v_fs_count= 0;
+  vp->v_ref_count= 0;
+  vp->v_pipe = NO_PIPE;
+  vp->v_sdev = NO_DEV;
+  vp->v_index = 0;
 }
 
 
+/*===========================================================================*
+ *                             vnode_clean_refs                             *
+ *===========================================================================*/
+PUBLIC void vnode_clean_refs(struct vnode *vp)
+{
+/* Tell the underlying FS to drop all reference but one. */
+  if (vp == NIL_VNODE) {
+        return;
+  }
+
+  if (vp->v_fs_count <= 1)
+       return; /* Nothing to do */
+  printf("vnode_clean_refs: dropping some references at FS\n");
+  if (req_putnode(vp->v_fs_e, vp->v_inode_nr, vp->v_fs_count-1) != OK)
+       printf("vnode_clean_refs: req_putnode failed\n"); 
+  vp->v_fs_count= 1;
+}
+
+
+#if 0
+/*===========================================================================*
+ *                             mark_vn                                      *
+ *===========================================================================*/
+PUBLIC void mark_vn(vp, file, line)
+struct vnode *vp;
+char *file;
+int line;
+{
+       if (!vp)
+               return;
+       vp->v_file= file;
+       vp->v_line= line;
+}
+
+
+/*===========================================================================*
+ *                             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;
+               vp= rfp->fp_rd;
+               if (vp < &vnode[0] || vp >= &vnode[NR_VNODES])
+                       panic(__FILE__, "check_vrefs: bad vnode", NO_NUM);
+               vp->v_ref_check++;
+                
+                vp= rfp->fp_wd;
+               if (vp < &vnode[0] || vp >= &vnode[NR_VNODES])
+                       panic(__FILE__, "check_vrefs: bad vnode", NO_NUM);
+               vp->v_ref_check++;
+
+       }
+
+       /* Count references from filedescriptors */
+       for (f = &filp[0]; f < &filp[NR_FILPS]; f++)
+       {
+               if (f->filp_count == 0)
+                       continue;
+               vp= f->filp_vno;
+               if (vp < &vnode[0] || vp >= &vnode[NR_VNODES])
+                       panic(__FILE__, "check_vrefs: bad vnode", NO_NUM);
+               vp->v_ref_check++;
+       }
+
+       /* Count references to mount points */
+       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
+       {
+               if (vmp->m_dev == NO_DEV)
+                       continue;
+               vp= vmp->m_mounted_on;
+               if (vp < &vnode[0] || vp >= &vnode[NR_VNODES])
+                       panic(__FILE__, "check_vrefs: bad vnode", NO_NUM);
+               vp->v_ref_check++;
+
+               vp= vmp->m_root_node;
+               if (vp < &vnode[0] || vp >= &vnode[NR_VNODES])
+                       panic(__FILE__, "check_vrefs: bad vnode", NO_NUM);
+               vp->v_ref_check++;
+       }
+
+       /* 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
index afd8565fb6b9ed29e6a5a12dd2968675007a9a79..6cc1eec0c6068ccbdb325bba121dbb034bc94006 100644 (file)
@@ -4,8 +4,12 @@ EXTERN struct vnode {
   endpoint_t v_fs_e;            /* FS process' endpoint number */
   ino_t v_inode_nr;            /* inode number on its (minor) device */
   mode_t v_mode;               /* file type, protection, etc. */
+  uid_t v_uid;
+  gid_t v_gid;
   off_t v_size;                        /* current file size in bytes */
-  int v_count;                 /* # times vnode used; 0 means slot is free */
+  int v_ref_count;             /* # times vnode used; 0 means slot is free */
+  int v_fs_count;              /* # reference at the underlying FS */
+  int v_ref_check;             /* for consistency checks */
   char v_pipe;                 /* set to I_PIPE if pipe */
   off_t v_pipe_rd_pos;
   off_t v_pipe_wr_pos;
@@ -19,6 +23,11 @@ EXTERN struct vnode {
   int v_blocksize;              /* block size of the filesys */
   unsigned short v_index;       /* inode's index in the FS inode table */
   struct vmnt *v_vmnt;          /* vmnt object of the partition */
+
+  /* For debugging */
+  char *v_file;
+  int v_line;
+  int v_isfifo;        
 } vnode[NR_VNODES];
 
 #define NIL_VNODE (struct vnode *) 0   /* indicates absence of vnode slot */