]> Zhao Yanbai Git Server - minix.git/commitdiff
ext2: use libfsdriver 51/2751/3
authorDavid van Moolenbroek <david@minix3.org>
Sun, 24 Aug 2014 10:12:30 +0000 (10:12 +0000)
committerDavid van Moolenbroek <david@minix3.org>
Thu, 18 Sep 2014 12:46:27 +0000 (12:46 +0000)
- fix panic on truncating files with holes;
- remove block-based readahead, to match MFS.

Change-Id: I385552f8019e9c013a6cb937bcc8e4e7181a4a50

20 files changed:
minix/fs/ext2/Makefile
minix/fs/ext2/const.h
minix/fs/ext2/fs.h
minix/fs/ext2/glo.h
minix/fs/ext2/ialloc.c
minix/fs/ext2/inode.c
minix/fs/ext2/link.c
minix/fs/ext2/main.c
minix/fs/ext2/misc.c
minix/fs/ext2/mount.c
minix/fs/ext2/open.c
minix/fs/ext2/path.c
minix/fs/ext2/protect.c
minix/fs/ext2/proto.h
minix/fs/ext2/read.c
minix/fs/ext2/stadir.c
minix/fs/ext2/super.h
minix/fs/ext2/table.c
minix/fs/ext2/time.c
minix/fs/ext2/utility.c

index abbe5b54ec696fd75f853aefaff792e0ba361871..fb09c93fafd65594c6891eba55216b3713545611 100644 (file)
@@ -5,8 +5,8 @@ SRCS=   balloc.c link.c \
        stadir.c table.c time.c utility.c \
        write.c ialloc.c inode.c main.c path.c \
        super.c
-DPADD+=        ${LIBMINIXFS} ${LIBBDEV} ${LIBSYS} 
-LDADD+= -lminixfs -lbdev -lsys 
+DPADD+=        ${LIBMINIXFS} ${LIBFSDRIVER} ${LIBBDEV} ${LIBSYS}
+LDADD+= -lminixfs -lfsdriver -lbdev -lsys
 
 WARNS=3
 
index 17ddd30cbe8f96649a5effdbc5ab654dcbd10ae1..fde065226d7fc4c69816c7153536599bd92056b7 100644 (file)
 #define INODE_HASH_SIZE   ((unsigned long)1<<INODE_HASH_LOG2)
 #define INODE_HASH_MASK   (((unsigned long)1<<INODE_HASH_LOG2)-1)
 
-
-/* The type of sizeof may be (unsigned) long.  Use the following macro for
- * taking the sizes of small objects so that there are no surprises like
- * (small) long constants being passed to routines expecting an int.
- */
-#define usizeof(t) ((unsigned) sizeof(t))
-
 #define SUPER_MAGIC   0xEF53  /* magic number contained in super-block */
 
 #define EXT2_NAME_MAX  255
 /* write_map() args */
 #define WMAP_FREE           (1 << 0)
 
-#define IGN_PERM            0
-#define CHK_PERM            1
-
 #define IN_CLEAN              0    /* inode disk and memory copies identical */
 #define IN_DIRTY              1    /* inode disk and memory copies differ */
 #define ATIME            002    /* set if atime field needs updating */
 #define CTIME            004    /* set if ctime field needs updating */
 #define MTIME            010    /* set if mtime field needs updating */
 
-#define BYTE_SWAP          0    /* tells conv2/conv4 to swap bytes */
-
-#define END_OF_FILE   (-104)    /* eof detected */
-
 #define SUPER_BLOCK_BYTES       (1024)         /* bytes offset */
 
 #define ROOT_INODE      ((ino_t) 2)   /* inode number for root directory */
@@ -60,7 +46,7 @@
 #define START_BLOCK     ((block_t) 2) /* first block of FS (not counting SB) */
 #define BLOCK_ADDRESS_BYTES    4     /* bytes per address */
 
-#define SUPER_SIZE      usizeof (struct super_block) /* sb size in RAM */
+#define SUPER_SIZE      sizeof (struct super_block) /* sb size in RAM */
 #define SUPER_SIZE_D    (1024)  /* max size of superblock stored on disk */
 
 /* Directories related macroses */
@@ -93,8 +79,8 @@
 #define EXT2_TIND_BLOCK         (EXT2_DIND_BLOCK + 1)
 #define EXT2_N_BLOCKS           (EXT2_TIND_BLOCK + 1)
 
-#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk   */
-#define FS_BITCHUNK_BITS        (usizeof(bitchunk_t) * CHAR_BIT)
+#define FS_BITMAP_CHUNKS(b) ((b)/sizeof (bitchunk_t))/* # map chunks/blk   */
+#define FS_BITCHUNK_BITS        (sizeof(bitchunk_t) * CHAR_BIT)
 #define FS_BITS_PER_BLOCK(b)    (FS_BITMAP_CHUNKS(b) * FS_BITCHUNK_BITS)
 
 /* Inodes */
 #define MAX_FAST_SYMLINK_LENGTH \
        ( sizeof(((d_inode *)0)->i_block[0]) * EXT2_N_BLOCKS )
 
-#define NUL(str,l,m) mfs_nul_f(__FILE__,__LINE__,(str), (l), (m))
-
 /* FS states */
 #define EXT2_VALID_FS                   0x0001  /* Cleanly unmounted */
 #define EXT2_ERROR_FS                   0x0002  /* Errors detected */
index 3511d5434815bf1850f05adc05a9b598fffc336e..a305c798a1abde735d1abcd36ad650f472ad8b0b 100644 (file)
@@ -13,7 +13,6 @@
 #include <sys/types.h>
 #include <minix/const.h>
 #include <minix/type.h>
-#include <minix/dmap.h>
 
 #include <lib.h>
 #include <limits.h>
@@ -22,6 +21,8 @@
 #include <minix/syslib.h>
 #include <minix/sysutil.h>
 
+#include <minix/fsdriver.h>
+
 #include "const.h"
 #include "type.h"
 #include "proto.h"
index b805cc00eeffbc50bf4da71685b5581406c340f7..0f11071d7dc054cd2acf09a4bc1ec243c24bb802 100644 (file)
@@ -8,37 +8,13 @@
 #define EXTERN
 #endif
 
-#include <minix/vfsif.h>
-
 /* The following variables are used for returning results to the caller. */
 EXTERN int err_code;        /* temporary storage for error number */
-EXTERN int rdwt_err;        /* status of last disk i/o request */
 
 EXTERN int cch[NR_INODES];
 
-extern char dot1[2];   /* dot1 (&dot1[0]) and dot2 (&dot2[0]) have a special */
-extern char dot2[3];   /* meaning to search_dir: no access permission check. */
-
-extern int(*fs_call_vec[]) (void);
-
-EXTERN message fs_m_in;
-EXTERN message fs_m_out;
-EXTERN vfs_ucred_t credentials;
-
-EXTERN uid_t caller_uid;
-EXTERN gid_t caller_gid;
-
-EXTERN int req_nr;
-
-EXTERN char user_path[PATH_MAX+1];  /* pathname to be processed */
-
 EXTERN dev_t fs_dev;              /* The device that is handled by this FS proc
                                    */
-EXTERN char fs_dev_label[16];    /* Name of the device driver that is handled
-                                  * by this FS proc.
-                                  */
-EXTERN int unmountdone;
-EXTERN int exitsignaled;
 
 /* Little hack for syncing group descriptors. */
 EXTERN int group_descriptors_dirty;
@@ -49,4 +25,6 @@ EXTERN struct opt opt;                /* global options */
  * care about byte swapping, when have BE CPU. */
 EXTERN int le_CPU;     /* little/big endian, if TRUE do not swap bytes */
 
+extern struct fsdriver ext2_table;
+
 #endif /* EXT2_GLO_H */
index 6cb18106da85ad8b09c4a333d54f7a485ed760f9..967a3d2160c6beee18261204487b274417fa51a6 100644 (file)
@@ -29,7 +29,8 @@ static void wipe_inode(struct inode *rip);
 /*===========================================================================*
  *                alloc_inode                                                *
  *===========================================================================*/
-struct inode *alloc_inode(struct inode *parent, mode_t bits)
+struct inode *alloc_inode(struct inode *parent, mode_t bits, uid_t uid,
+       gid_t gid)
 {
 /* Allocate a free inode on parent's dev, and return a pointer to it. */
 
@@ -67,8 +68,8 @@ struct inode *alloc_inode(struct inode *parent, mode_t bits)
        /* An inode slot is available. Put the inode just allocated into it. */
        rip->i_mode = bits;         /* set up RWX bits */
        rip->i_links_count = NO_LINK; /* initial no links */
-       rip->i_uid = caller_uid;    /* file's uid is owner's */
-       rip->i_gid = caller_gid;    /* ditto group id */
+       rip->i_uid = uid;           /* file's uid is owner's */
+       rip->i_gid = gid;           /* ditto group id */
        rip->i_dev = parent->i_dev; /* mark which device it is on */
        rip->i_sp = sp;             /* pointer to super block */
 
index 6396bb00672d61586ea0a550a04beeceea2b2e0f..783ae793cdc2dcf4ace3a206e911b7e7f32b5f1f 100644 (file)
@@ -31,27 +31,21 @@ static void unhash_inode(struct inode *node);
 /*===========================================================================*
  *                fs_putnode                                                 *
  *===========================================================================*/
-int fs_putnode(void)
+int fs_putnode(ino_t ino_nr, unsigned int count)
 {
 /* Find the inode specified by the request message and decrease its counter.*/
 
   struct inode *rip;
-  int count;
 
-  rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_putnode.inode);
+  rip = find_inode(fs_dev, ino_nr);
 
   if (!rip) {
        printf("%s:%d put_inode: inode #%llu dev: %llx not found\n", __FILE__,
-               __LINE__, fs_m_in.m_vfs_fs_putnode.inode, fs_dev);
+               __LINE__, ino_nr, fs_dev);
        panic("fs_putnode failed");
   }
 
-  count = fs_m_in.m_vfs_fs_putnode.count;
-  if (count <= 0) {
-       printf("%s:%d put_inode: bad value for count: %d\n", __FILE__,
-               __LINE__, count);
-       panic("fs_putnode failed");
-  } else if (count > rip->i_count) {
+  if (count > rip->i_count) {
        printf("%s:%d put_inode: count too high: %d > %d\n", __FILE__,
                __LINE__, count, rip->i_count);
        panic("fs_putnode failed");
index c779774dc356b9a50e197a20a3ea19c16ef85553..a2069c73dab9093f63997366e97379cf7e154a0e 100644 (file)
 #define SAME 1000
 
 static int freesp_inode(struct inode *rip, off_t st, off_t end);
-static int remove_dir(struct inode *rldirp, struct inode *rip, char
-       dir_name[NAME_MAX + 1]);
-static int unlink_file(struct inode *dirp, struct inode *rip, char
-       file_name[NAME_MAX + 1]);
+static int remove_dir(struct inode *rldirp, struct inode *rip,
+       const char *dir_name);
+static int unlink_file(struct inode *dirp, struct inode *rip,
+       const char *file_name);
 static off_t nextblock(off_t pos, int blocksize);
 static void zeroblock_half(struct inode *i, off_t p, int l);
 static void zeroblock_range(struct inode *i, off_t p, off_t h);
@@ -31,28 +31,16 @@ static void zeroblock_range(struct inode *i, off_t p, off_t h);
 /*===========================================================================*
  *                             fs_link                                      *
  *===========================================================================*/
-int fs_link()
+int fs_link(ino_t dir_nr, char *name, ino_t ino_nr)
 {
 /* Perform the link(name1, name2) system call. */
 
   struct inode *ip, *rip;
   register int r;
-  char string[NAME_MAX + 1];
   struct inode *new_ip;
-  phys_bytes len;
-
-  /* Copy the link name's last component */
-  len = fs_m_in.m_vfs_fs_link.path_len; /* including trailing '\0' */
-  if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1)
-       return(ENAMETOOLONG);
-
-  r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_link.grant, 0,
-                      (vir_bytes) string, (size_t) len);
-  if (r != OK) return r;
-  NUL(string, len, sizeof(string));
 
   /* Temporarily open the file. */
-  if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_link.inode)) == NULL)
+  if( (rip = get_inode(fs_dev, ino_nr)) == NULL)
          return(EINVAL);
 
   /* Check to see if the file has maximum number of links already. */
@@ -62,9 +50,9 @@ int fs_link()
   if(rip->i_links_count >= LINK_MAX)
          r = EMLINK;
 
-  /* Only super_user may link to directories. */
+  /* Linking to directories is too dangerous to allow. */
   if(r == OK)
-         if( (rip->i_mode & I_TYPE) == I_DIRECTORY && caller_uid != SU_UID)
+         if( (rip->i_mode & I_TYPE) == I_DIRECTORY)
                  r = EPERM;
 
   /* If error with 'name', return the inode. */
@@ -74,7 +62,7 @@ int fs_link()
   }
 
   /* Temporarily open the last dir */
-  if( (ip = get_inode(fs_dev, fs_m_in.m_vfs_fs_link.dir_ino)) == NULL) {
+  if( (ip = get_inode(fs_dev, dir_nr)) == NULL) {
        put_inode(rip);
        return(EINVAL);
   }
@@ -86,7 +74,7 @@ int fs_link()
   }
 
   /* If 'name2' exists in full (even if no space) set 'r' to error. */
-  if ((new_ip = advance(ip, string, IGN_PERM)) == NULL) {
+  if ((new_ip = advance(ip, name)) == NULL) {
        r = err_code;
        if(r == ENOENT)
                r = OK;
@@ -97,8 +85,7 @@ int fs_link()
 
   /* Try to link. */
   if(r == OK)
-         r = search_dir(ip, string, &rip->i_num, ENTER, IGN_PERM,
-                        rip->i_mode & I_TYPE);
+         r = search_dir(ip, name, &rip->i_num, ENTER, rip->i_mode & I_TYPE);
 
   /* If success, register the linking. */
   if(r == OK) {
@@ -117,57 +104,42 @@ int fs_link()
 /*===========================================================================*
  *                             fs_unlink                                    *
  *===========================================================================*/
-int fs_unlink()
+int fs_unlink(ino_t dir_nr, char *name, int call)
 {
 /* Perform the unlink(name) or rmdir(name) system call. The code for these two
- * is almost the same.  They differ only in some condition testing.  Unlink()
- * may be used by the superuser to do dangerous things; rmdir() may not.
+ * is almost the same.  They differ only in some condition testing.
  */
   register struct inode *rip;
   struct inode *rldirp;
   int r;
-  char string[NAME_MAX + 1];
-  phys_bytes len;
-
-  /* Copy the last component */
-  len = fs_m_in.m_vfs_fs_unlink.path_len; /* including trailing '\0' */
-  if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1)
-       return(ENAMETOOLONG);
-
-  r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_unlink.grant,
-                       (vir_bytes) 0, (vir_bytes) string, (size_t) len);
-  if (r != OK) return r;
-  NUL(string, len, sizeof(string));
 
   /* Temporarily open the dir. */
-  if((rldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_unlink.inode)) == NULL)
+  if((rldirp = get_inode(fs_dev, dir_nr)) == NULL)
          return(EINVAL);
 
   /* The last directory exists.  Does the file also exist? */
-  rip = advance(rldirp, string, IGN_PERM);
+  rip = advance(rldirp, name);
   r = err_code;
 
   /* If error, return inode. */
   if(r != OK) {
-       /* Mount point? */
-       if (r == EENTERMOUNT || r == ELEAVEMOUNT) {
-               put_inode(rip);
-               r = EBUSY;
-       }
        put_inode(rldirp);
        return(r);
   }
+  if (rip->i_mountpoint) {
+       put_inode(rip);
+       put_inode(rldirp);
+       return(EBUSY);
+  }
 
   /* Now test if the call is allowed, separately for unlink() and rmdir(). */
-  if(fs_m_in.m_type == REQ_UNLINK) {
-         /* Only the su may unlink directories, but the su can unlink any
-          * dir.*/
+  if (call == FSC_UNLINK) {
          if( (rip->i_mode & I_TYPE) == I_DIRECTORY) r = EPERM;
 
          /* Actually try to unlink the file; fails if parent is mode 0 etc. */
-         if (r == OK) r = unlink_file(rldirp, rip, string);
+         if (r == OK) r = unlink_file(rldirp, rip, name);
   } else {
-         r = remove_dir(rldirp, rip, string); /* call is RMDIR */
+         r = remove_dir(rldirp, rip, name); /* call is RMDIR */
   }
 
   /* If unlink was possible, it has been done, otherwise it has not. */
@@ -180,18 +152,15 @@ int fs_unlink()
 /*===========================================================================*
  *                             fs_rdlink                                     *
  *===========================================================================*/
-int fs_rdlink()
+ssize_t fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes)
 {
   struct buf *bp = NULL;       /* buffer containing link text */
   char* link_text;             /* either bp->b_data or rip->i_block */
   register struct inode *rip;  /* target inode */
   register int r;              /* return value */
-  size_t copylen;
-
-  copylen = min(fs_m_in.m_vfs_fs_rdlink.mem_size, UMAX_FILE_POS);
 
   /* Temporarily open the file. */
-  if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_rdlink.inode)) == NULL)
+  if( (rip = get_inode(fs_dev, ino_nr)) == NULL)
          return(EINVAL);
 
   if (rip->i_size >= MAX_FAST_SYMLINK_LENGTH) {
@@ -208,16 +177,13 @@ int fs_rdlink()
        r = OK;
   }
   if (r == OK) {
-  /* Passed all checks */
-  /* We can safely cast to unsigned, because copylen is guaranteed to be
-     below max file size */
-       copylen = min( copylen, (unsigned) rip->i_size);
-       r = sys_safecopyto(VFS_PROC_NR, fs_m_in.m_vfs_fs_rdlink.grant,
-                          (vir_bytes) 0, (vir_bytes) link_text,
-                          (size_t) copylen);
+       /* Passed all checks */
+       if (bytes > rip->i_size)
+               bytes = rip->i_size;
+       r = fsdriver_copyout(data, 0, link_text, bytes);
        put_block(bp, DIRECTORY_BLOCK);
        if (r == OK)
-               fs_m_out.m_fs_vfs_rdlink.nbytes = copylen;
+               r = bytes;
   }
 
   put_inode(rip);
@@ -231,7 +197,7 @@ int fs_rdlink()
 static int remove_dir(rldirp, rip, dir_name)
 struct inode *rldirp;                  /* parent directory */
 struct inode *rip;                     /* directory to be removed */
-char dir_name[NAME_MAX + 1];   /* name of directory to be removed */
+const char *dir_name;                  /* name of directory to be removed */
 {
   /* A directory file has to be removed. Five conditions have to met:
    *   - The file must be a directory
@@ -243,10 +209,9 @@ char dir_name[NAME_MAX + 1];       /* name of directory to be removed */
   int r;
 
   /* search_dir checks that rip is a directory too. */
-  if ((r = search_dir(rip, "", NULL, IS_EMPTY, IGN_PERM, 0)) != OK)
+  if ((r = search_dir(rip, "", NULL, IS_EMPTY, 0)) != OK)
        return r;
 
-  if (strcmp(dir_name, ".") == 0 || strcmp(dir_name, "..") == 0)return(EINVAL);
   if (rip->i_num == ROOT_INODE) return(EBUSY); /* can't remove 'root' */
 
   /* Actually try to unlink the file; fails if parent is mode 0 etc. */
@@ -255,8 +220,8 @@ char dir_name[NAME_MAX + 1];        /* name of directory to be removed */
   /* Unlink . and .. from the dir. The super user can link and unlink any dir,
    * so don't make too many assumptions about them.
    */
-  (void) unlink_file(rip, NULL, dot1);
-  (void) unlink_file(rip, NULL, dot2);
+  (void) unlink_file(rip, NULL, ".");
+  (void) unlink_file(rip, NULL, "..");
   return(OK);
 }
 
@@ -267,7 +232,7 @@ char dir_name[NAME_MAX + 1];        /* name of directory to be removed */
 static int unlink_file(dirp, rip, file_name)
 struct inode *dirp;            /* parent directory of file */
 struct inode *rip;             /* inode of file, may be NULL too. */
-char file_name[NAME_MAX + 1]; /* name of file to be removed */
+const char *file_name;         /* name of file to be removed */
 {
 /* Unlink 'file_name'; rip must be the inode of 'file_name' or NULL. */
 
@@ -277,14 +242,14 @@ char file_name[NAME_MAX + 1]; /* name of file to be removed */
   /* If rip is not NULL, it is used to get faster access to the inode. */
   if (rip == NULL) {
        /* Search for file in directory and try to get its inode. */
-       err_code = search_dir(dirp, file_name, &numb, LOOK_UP, IGN_PERM, 0);
+       err_code = search_dir(dirp, file_name, &numb, LOOK_UP, 0);
        if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb);
        if (err_code != OK || rip == NULL) return(err_code);
   } else {
        dup_inode(rip);         /* inode will be returned with put_inode */
   }
 
-  r = search_dir(dirp, file_name, NULL, DELETE, IGN_PERM, 0);
+  r = search_dir(dirp, file_name, NULL, DELETE, 0);
 
   if (r == OK) {
        rip->i_links_count--;   /* entry deleted from parent's dir */
@@ -300,7 +265,8 @@ char file_name[NAME_MAX + 1]; /* name of file to be removed */
 /*===========================================================================*
  *                             fs_rename                                    *
  *===========================================================================*/
-int fs_rename()
+int fs_rename(ino_t old_dir_nr, char *old_name, ino_t new_dir_nr,
+       char *new_name)
 {
 /* Perform the rename(name1, name2) system call. */
   struct inode *old_dirp, *old_ip;     /* ptrs to old dir, file inodes */
@@ -309,48 +275,28 @@ int fs_rename()
   int r = OK;                          /* error flag; initially no error */
   int odir, ndir;                      /* TRUE iff {old|new} file is dir */
   int same_pdir = 0;                   /* TRUE iff parent dirs are the same */
-  char old_name[NAME_MAX + 1], new_name[NAME_MAX + 1];
   ino_t numb;
-  phys_bytes len;
-
-  /* Copy the last component of the old name */
-  len = fs_m_in.m_vfs_fs_rename.len_old; /* including trailing '\0' */
-  if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1)
-       return(ENAMETOOLONG);
-
-  r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_rename.grant_old,
-                      (vir_bytes) 0, (vir_bytes) old_name, (size_t) len);
-  if (r != OK) return r;
-  NUL(old_name, len, sizeof(old_name));
-
-  /* Copy the last component of the new name */
-  len = fs_m_in.m_vfs_fs_rename.len_new; /* including trailing '\0' */
-  if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1)
-       return(ENAMETOOLONG);
-
-  r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_rename.grant_new,
-                       (vir_bytes) 0, (vir_bytes) new_name, (size_t) len);
-  if (r != OK) return r;
-  NUL(new_name, len, sizeof(new_name));
 
   /* Get old dir inode */
-  if( (old_dirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_rename.dir_old)) == NULL)
+  if( (old_dirp = get_inode(fs_dev, old_dir_nr)) == NULL)
        return(err_code);
 
-  old_ip = advance(old_dirp, old_name, IGN_PERM);
+  old_ip = advance(old_dirp, old_name);
   r = err_code;
 
-  if (r == EENTERMOUNT || r == ELEAVEMOUNT) {
+  if (old_ip == NULL) {
+       put_inode(old_dirp);
+       return(r);
+  }
+
+  if (old_ip->i_mountpoint) {
        put_inode(old_ip);
-       old_ip = NULL;
-       if (r == EENTERMOUNT) r = EXDEV;        /* should this fail at all? */
-       else if (r == ELEAVEMOUNT) r = EINVAL;  /* rename on dot-dot */
-  } else if (old_ip == NULL) {
-       return(err_code);
+       put_inode(old_dirp);
+       return(EBUSY);
   }
 
   /* Get new dir inode */
-  if ((new_dirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_rename.dir_new)) == NULL){
+  if ((new_dirp = get_inode(fs_dev, new_dir_nr)) == NULL){
        put_inode(old_ip);
        put_inode(old_dirp);
        return(err_code);
@@ -363,11 +309,10 @@ int fs_rename()
        }
   }
 
-  new_ip = advance(new_dirp, new_name, IGN_PERM); /* not required to exist */
+  new_ip = advance(new_dirp, new_name); /* not required to exist */
 
-  /* However, if the check failed because the file does exist, don't continue.
-   * Note that ELEAVEMOUNT is covered by the dot-dot check later. */
-  if(err_code == EENTERMOUNT) {
+  /* If the node does exist, make sure it's not a mountpoint. */
+  if (new_ip != NULL && new_ip->i_mountpoint) {
        put_inode(new_ip);
        new_ip = NULL;
        r = EBUSY;
@@ -391,15 +336,14 @@ int fs_rename()
                                r = EINVAL;
                                break;
                        }
-                       next_new_superdirp = advance(new_superdirp, dot2,
-                                                    IGN_PERM);
+                       next_new_superdirp = advance(new_superdirp, "..");
 
                        put_inode(new_superdirp);
                        if(next_new_superdirp == new_superdirp) {
                                put_inode(new_superdirp);
                                break;
                        }
-                       if(err_code == ELEAVEMOUNT) {
+                       if(next_new_superdirp->i_num == ROOT_INODE) {
                                /* imitate that we are back at the root,
                                 * cross device checked already on VFS */
                                put_inode(next_new_superdirp);
@@ -415,18 +359,8 @@ int fs_rename()
                }
        }
 
-       /* The old or new name must not be . or .. */
-       if(strcmp(old_name, ".") == 0 || strcmp(old_name, "..") == 0 ||
-          strcmp(new_name, ".") == 0 || strcmp(new_name, "..") == 0) {
-               r = EINVAL;
-       }
-       /* Both parent directories must be on the same device.
-       if(old_dirp->i_dev != new_dirp->i_dev) r = EXDEV; */
-
        /* Some tests apply only if the new path exists. */
        if(new_ip == NULL) {
-               /* don't rename a file with a file system mounted on it.
-               if (old_ip->i_dev != old_dirp->i_dev) r = EXDEV;*/
                if(odir && (new_dirp->i_links_count >= SHRT_MAX ||
                            new_dirp->i_links_count >= LINK_MAX) &&
                   !same_pdir && r == OK) {
@@ -474,17 +408,17 @@ int fs_rename()
        numb = old_ip->i_num;           /* inode number of old file */
 
        if(same_pdir) {
-               r = search_dir(old_dirp,old_name, NULL, DELETE,IGN_PERM, 0);
+               r = search_dir(old_dirp,old_name, NULL, DELETE, 0);
                                                /* shouldn't go wrong. */
                if(r == OK)
-                       (void) search_dir(old_dirp, new_name, &numb, ENTER, IGN_PERM,
+                       (void) search_dir(old_dirp, new_name, &numb, ENTER,
                                          old_ip->i_mode & I_TYPE);
        } else {
-               r = search_dir(new_dirp, new_name, &numb, ENTER, IGN_PERM,
+               r = search_dir(new_dirp, new_name, &numb, ENTER,
                                        old_ip->i_mode & I_TYPE);
                if(r == OK) {
                        (void) search_dir(old_dirp, old_name, NULL,
-                                         DELETE, IGN_PERM, 0);
+                                         DELETE, 0);
                }
        }
   }
@@ -494,8 +428,8 @@ int fs_rename()
   if(r == OK && odir && !same_pdir) {
        /* Update the .. entry in the directory (still points to old_dirp).*/
        numb = new_dirp->i_num;
-       (void) unlink_file(old_ip, NULL, dot2);
-       if(search_dir(old_ip, dot2, &numb, ENTER, IGN_PERM, I_DIRECTORY) == OK) {
+       (void) unlink_file(old_ip, NULL, "..");
+       if(search_dir(old_ip, "..", &numb, ENTER, I_DIRECTORY) == OK) {
                /* New link created. */
                new_dirp->i_links_count++;
                new_dirp->i_dirt = IN_DIRTY;
@@ -512,20 +446,16 @@ int fs_rename()
 
 
 /*===========================================================================*
- *                             fs_ftrunc                                    *
+ *                             fs_trunc                                     *
  *===========================================================================*/
-int fs_ftrunc(void)
+int fs_trunc(ino_t ino_nr, off_t start, off_t end)
 {
   struct inode *rip;
-  off_t start, end;
   int r;
 
-  if( (rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_ftrunc.inode)) == NULL)
+  if( (rip = find_inode(fs_dev, ino_nr)) == NULL)
          return(EINVAL);
 
-  start = fs_m_in.m_vfs_fs_ftrunc.trc_start;
-  end = fs_m_in.m_vfs_fs_ftrunc.trc_end;
-
   if (end == 0)
          r = truncate_inode(rip, start);
   else
@@ -716,7 +646,7 @@ off_t len;
 
   if (!len) return; /* no zeroing to be done. */
   if (!(bp = get_block_map(rip, rounddown(pos, rip->i_sp->s_block_size))))
-       panic("zeroblock_range: no block");
+       return; /* skip holes */
   offset = pos % rip->i_sp->s_block_size;
   if (offset + len > rip->i_sp->s_block_size)
        panic("zeroblock_range: len too long: %lld", len);
index 76dc9e08807b70adc6736b50f17a4f6550709f44..86e4360c7604ed8f87863a35c54ccb9be6c0cef1 100644 (file)
@@ -1,20 +1,8 @@
 #include "fs.h"
-#include <assert.h>
-#include <minix/callnr.h>
-#include <signal.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <minix/dmap.h>
-#include <minix/endpoint.h>
-#include <minix/vfsif.h>
-#include <minix/optset.h>
 #include "buf.h"
 #include "inode.h"
-
-/* Declare some local functions. */
-static void get_work(message *m_in);
-static void reply(endpoint_t who, message *m_out);
+#include <string.h>
+#include <minix/optset.h>
 
 /* SEF functions and variables. */
 static void sef_local_startup(void);
@@ -32,7 +20,7 @@ static struct optset optset_table[] = {
   { "reserved",                OPT_BOOL,   &opt.use_reserved_blocks,   TRUE    },
   { "prealloc",                OPT_BOOL,   &opt.use_prealloc,          TRUE    },
   { "noprealloc",      OPT_BOOL,   &opt.use_prealloc,          FALSE   },
-  { NULL,              0,          NULL,                       0                                                               }
+  { NULL,              0,          NULL,                       0       }
 };
 
 /*===========================================================================*
@@ -40,11 +28,7 @@ static struct optset optset_table[] = {
  *===========================================================================*/
 int main(int argc, char *argv[])
 {
-/* This is the main routine of this service. The main loop consists of
- * three major activities: getting new work, processing the work, and
- * sending the reply. The loop never terminates, unless a panic occurs.
- */
-  int error = OK, ind, transid;
+/* This is the main routine of this service. */
   unsigned short test_endian = 1;
 
   /* SEF local startup. */
@@ -56,50 +40,8 @@ int main(int argc, char *argv[])
   /* Server isn't tested on big endian CPU */
   ASSERT(le_CPU == 1);
 
-  while(!unmountdone || !exitsignaled) {
-       endpoint_t src;
-
-       /* Wait for request message. */
-       get_work(&fs_m_in);
-
-       transid = TRNS_GET_ID(fs_m_in.m_type);
-       fs_m_in.m_type = TRNS_DEL_ID(fs_m_in.m_type);
-       if (fs_m_in.m_type == 0) {
-               assert(!IS_VFS_FS_TRANSID(transid));
-               fs_m_in.m_type = transid;       /* Backwards compat. */
-               transid = 0;
-       } else
-               assert(IS_VFS_FS_TRANSID(transid));
-
-       src = fs_m_in.m_source;
-       caller_uid = INVAL_UID; /* To trap errors */
-       caller_gid = INVAL_GID;
-       req_nr = fs_m_in.m_type;
-
-       if (req_nr < FS_BASE) {
-               fs_m_in.m_type += FS_BASE;
-               req_nr = fs_m_in.m_type;
-       }
-       ind = req_nr - FS_BASE;
-
-       if (ind < 0 || ind >= NREQS) {
-               printf("mfs: bad request %d\n", req_nr);
-               printf("ind = %d\n", ind);
-               error = EINVAL;
-       } else {
-               error = (*fs_call_vec[ind])();
-       }
-
-       fs_m_out.m_type = error;
-       if (IS_VFS_FS_TRANSID(transid)) {
-               /* If a transaction ID was set, reset it */
-               fs_m_out.m_type = TRNS_ADD_ID(fs_m_out.m_type, transid);
-       }
-       reply(src, &fs_m_out);
-
-       if (error == OK)
-               read_ahead(); /* do block read ahead */
-  }
+  /* The fsdriver library does the actual work here. */
+  fsdriver_task(&ext2_table);
 
   return 0;
 }
@@ -166,51 +108,7 @@ static void sef_cb_signal_handler(int signo)
   /* Only check for termination signal, ignore anything else. */
   if (signo != SIGTERM) return;
 
-  exitsignaled = 1;
-  (void) fs_sync();
+  fs_sync();
 
-  /* If unmounting has already been performed, exit immediately.
-   * We might not get another message.
-   */
-  if (unmountdone) exit(0);
-}
-
-/*===========================================================================*
- *                             get_work                                     *
- *===========================================================================*/
-static void get_work(m_in)
-message *m_in;                         /* pointer to message */
-{
-  int r, srcok = 0;
-  endpoint_t src;
-
-  do {
-       if ((r = sef_receive(ANY, m_in)) != OK)         /* wait for message */
-               panic("sef_receive failed: %d", r);
-       src = m_in->m_source;
-
-       if(src == VFS_PROC_NR) {
-               if(unmountdone)
-                       printf("ext2: unmounted: unexpected message from FS\n");
-               else
-                       srcok = 1;              /* Normal FS request. */
-
-       } else
-               printf("ext2: unexpected source %d\n", src);
-  } while(!srcok);
-
-   assert((src == VFS_PROC_NR && !unmountdone));
-}
-
-
-/*===========================================================================*
- *                             reply                                        *
- *===========================================================================*/
-static void reply(
-  endpoint_t who,
-  message *m_out                               /* report result */
-)
-{
-  if (OK != ipc_send(who, m_out))    /* send the message */
-       printf("ext2(%d) was unable to send reply\n", sef_self());
+  fsdriver_terminate();
 }
index c3eb6718f6bc2f73b1e2570087493606afb7599d..585db14fa05ae11decc389009b892dae1355f807 100644 (file)
@@ -3,16 +3,14 @@
  */
 
 #include "fs.h"
-#include <assert.h>
-#include <minix/vfsif.h>
-#include <minix/bdev.h>
 #include "inode.h"
 #include "super.h"
+#include <assert.h>
 
 /*===========================================================================*
  *                             fs_sync                                      *
  *===========================================================================*/
-int fs_sync()
+void fs_sync(void)
 {
 /* Perform the sync() system call.  Flush all the tables.
  * The order in which the various tables are flushed is critical.  The
@@ -24,7 +22,7 @@ int fs_sync()
   assert(lmfs_nr_bufs() > 0);
 
   if (superblock->s_rd_only)
-       return(OK); /* nothing to sync */
+       return; /* nothing to sync */
 
   /* Write all the dirty inodes to the disk. */
   for(rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
@@ -36,63 +34,4 @@ int fs_sync()
        superblock->s_wtime = clock_time(NULL);
        write_super(superblock);
   }
-
-  return(OK);          /* sync() can't fail */
-}
-
-
-/*===========================================================================*
- *                             fs_flush                                     *
- *===========================================================================*/
-int fs_flush()
-{
-/* Flush the blocks of a device from the cache after writing any dirty blocks
- * to disk.
- */
-  dev_t dev = fs_m_in.m_vfs_fs_flush.device;
-
-  if(dev == fs_dev) return(EBUSY);
-
-  lmfs_flushall();
-  lmfs_invalidate(dev);
-
-  return(OK);
-}
-
-/*===========================================================================*
- *                             fs_new_driver                                *
- *===========================================================================*/
-int fs_new_driver(void)
-{
-/* Set a new driver endpoint for this device. */
-  dev_t dev;
-  cp_grant_id_t label_gid;
-  size_t label_len;
-  char label[sizeof(fs_dev_label)];
-  int r;
-
-  dev = fs_m_in.m_vfs_fs_new_driver.device;
-  label_gid = fs_m_in.m_vfs_fs_new_driver.grant;
-  label_len = fs_m_in.m_vfs_fs_new_driver.path_len;
-
-  if (label_len > sizeof(label))
-       return(EINVAL);
-
-  r = sys_safecopyfrom(fs_m_in.m_source, label_gid, (vir_bytes) 0,
-       (vir_bytes) label, label_len);
-
-  if (r != OK) {
-       printf("ext2: fs_new_driver safecopyfrom failed (%d)\n", r);
-       return(EINVAL);
-  }
-
-  bdev_driver(dev, label);
-
-  return(OK);
 }
-
-int fs_bpeek(void)      
-{
-       return lmfs_do_bpeek(&fs_m_in);
-}
-
index 24f6a59846a9f4ae95c0bb6f9691a17b1af6dd89..6b9db42076a30aa74ef8aca5a91ab69958413f69 100644 (file)
@@ -3,56 +3,29 @@
  */
 
 #include "fs.h"
-#include <fcntl.h>
-#include <string.h>
-#include <stdlib.h>
-#include <minix/com.h>
-#include <sys/stat.h>
 #include "buf.h"
 #include "inode.h"
 #include "super.h"
+#include <stdlib.h>
 #include <minix/vfsif.h>
 #include <minix/bdev.h>
 
 
 /*===========================================================================*
- *                             fs_readsuper                                 *
+ *                             fs_mount                                     *
  *===========================================================================*/
-int fs_readsuper()
+int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
+       unsigned int *res_flags)
 {
 /* This function reads the superblock of the partition, gets the root inode
- * and sends back the details of them. Note, that the FS process does not
- * know the index of the vmnt object which refers to it, whenever the pathname
- * lookup leaves a partition an ELEAVEMOUNT error is transferred back
- * so that the VFS knows that it has to find the vnode on which this FS
- * process' partition is mounted on.
+ * and sends back the details of them.
  */
   struct inode *root_ip;
-  cp_grant_id_t label_gid;
-  size_t label_len;
-  int r = OK;
-  int readonly, isroot;
+  int r, readonly;
   u32_t mask;
 
-  fs_dev    = fs_m_in.m_vfs_fs_readsuper.device;
-  label_gid = fs_m_in.m_vfs_fs_readsuper.grant;
-  label_len = fs_m_in.m_vfs_fs_readsuper.path_len;
-  readonly  = (fs_m_in.m_vfs_fs_readsuper.flags & REQ_RDONLY) ? 1 : 0;
-  isroot    = (fs_m_in.m_vfs_fs_readsuper.flags & REQ_ISROOT) ? 1 : 0;
-
-  if (label_len > sizeof(fs_dev_label))
-       return(EINVAL);
-
-  r = sys_safecopyfrom(fs_m_in.m_source, label_gid, 0,
-                      (vir_bytes)fs_dev_label, label_len);
-  if (r != OK) {
-       printf("%s:%d fs_readsuper: safecopyfrom failed: %d\n",
-              __FILE__, __LINE__, r);
-       return(EINVAL);
-  }
-
-  /* Map the driver label for this major. */
-  bdev_driver(fs_dev, fs_dev_label);
+  fs_dev = dev;
+  readonly = (flags & REQ_RDONLY) ? 1 : 0;
 
   /* Open the device the file system lives on. */
   if (bdev_open(fs_dev, readonly ? BDEV_R_BIT : (BDEV_R_BIT|BDEV_W_BIT)) !=
@@ -115,7 +88,6 @@ int fs_readsuper()
        return(EINVAL);
   }
 
-
   lmfs_set_blocksize(superblock->s_block_size, major(fs_dev));
 
   /* Get the root inode of the mounted file system. */
@@ -144,7 +116,6 @@ int fs_readsuper()
   }
 
   superblock->s_rd_only = readonly;
-  superblock->s_is_root = isroot;
 
   if (!readonly) {
        superblock->s_state = EXT2_ERROR_FS;
@@ -154,21 +125,23 @@ int fs_readsuper()
   }
 
   /* Root inode properties */
-  fs_m_out.m_fs_vfs_readsuper.inode = root_ip->i_num;
-  fs_m_out.m_fs_vfs_readsuper.mode = root_ip->i_mode;
-  fs_m_out.m_fs_vfs_readsuper.file_size = root_ip->i_size;
-  fs_m_out.m_fs_vfs_readsuper.uid = root_ip->i_uid;
-  fs_m_out.m_fs_vfs_readsuper.gid = root_ip->i_gid;
-  fs_m_out.m_fs_vfs_readsuper.flags = RES_HASPEEK;
+  root_node->fn_ino_nr = root_ip->i_num;
+  root_node->fn_mode = root_ip->i_mode;
+  root_node->fn_size = root_ip->i_size;
+  root_node->fn_uid = root_ip->i_uid;
+  root_node->fn_gid = root_ip->i_gid;
+  root_node->fn_dev = NO_DEV;
+
+  *res_flags = RES_NOFLAGS;
 
   return(r);
 }
 
 
 /*===========================================================================*
- *                             fs_mountpoint                                *
+ *                             fs_mountpt                                   *
  *===========================================================================*/
-int fs_mountpoint()
+int fs_mountpt(ino_t ino_nr)
 {
 /* This function looks up the mount point, it checks the condition whether
  * the partition can be mounted on the inode or not.
@@ -178,10 +151,9 @@ int fs_mountpoint()
   mode_t bits;
 
   /* Temporarily open the file. */
-  if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_mountpoint.inode)) == NULL)
+  if( (rip = get_inode(fs_dev, ino_nr)) == NULL)
          return(EINVAL);
 
-
   if(rip->i_mountpoint) r = EBUSY;
 
   /* It may not be special. */
@@ -199,25 +171,24 @@ int fs_mountpoint()
 /*===========================================================================*
  *                             fs_unmount                                   *
  *===========================================================================*/
-int fs_unmount()
+void fs_unmount(void)
 {
 /* Unmount a file system by device number. */
   int count;
   struct inode *rip, *root_ip;
 
-  if(superblock->s_dev != fs_dev) return(EINVAL);
-
   /* See if the mounted device is busy.  Only 1 inode using it should be
-   * open --the root inode-- and that inode only 1 time. */
+   * open --the root inode-- and that inode only 1 time.  This is an integrity
+   * check only: VFS expects the unmount to succeed either way.
+   */
   count = 0;
   for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
          if (rip->i_count > 0 && rip->i_dev == fs_dev) count += rip->i_count;
+  if (count != 1)
+       printf("ext2: file system has %d in-use inodes!\n", count);
 
-  if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NULL) {
-       printf("ext2: couldn't find root inode. Unmount failed.\n");
+  if ((root_ip = find_inode(fs_dev, ROOT_INODE)) == NULL)
        panic("ext2: couldn't find root inode");
-       return(EINVAL);
-  }
 
   /* Sync fs data before checking count. In some cases VFS can force unmounting
    * and it will damage unsynced FS. We don't sync before checking root_ip since
@@ -226,11 +197,9 @@ int fs_unmount()
    */
   if (!superblock->s_rd_only) {
        /* force any cached blocks out of memory */
-       (void) fs_sync();
+       fs_sync();
   }
 
-  if (count > 1) return(EBUSY);        /* can't umount a busy file system */
-
   put_inode(root_ip);
 
   if (!superblock->s_rd_only) {
@@ -247,7 +216,4 @@ int fs_unmount()
 
   /* Finish off the unmount. */
   superblock->s_dev = NO_DEV;
-  unmountdone = TRUE;
-
-  return(OK);
 }
index c9159345a66d7c04b5e623ed66901632ea8f8015..cb4714b6b1b712714efcaa6f3fae16bd4ebd7616 100644 (file)
@@ -6,51 +6,32 @@
 #include <sys/stat.h>
 #include <string.h>
 #include <assert.h>
-#include <minix/com.h>
 #include "buf.h"
 #include "inode.h"
 #include "super.h"
-#include <minix/vfsif.h>
 
 static struct inode *new_node(struct inode *ldirp, char *string, mode_t
-       bits, block_t z0);
+       bits, uid_t uid, gid_t gid, block_t z0);
 
 
 /*===========================================================================*
  *                             fs_create                                    *
  *===========================================================================*/
-int fs_create()
+int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
+       struct fsdriver_node *node)
 {
-  phys_bytes len;
   int r;
   struct inode *ldirp;
   struct inode *rip;
-  mode_t omode;
-  char lastc[NAME_MAX + 1];
-
-  /* Read request message */
-  omode = fs_m_in.m_vfs_fs_create.mode;
-  caller_uid = fs_m_in.m_vfs_fs_create.uid;
-  caller_gid = fs_m_in.m_vfs_fs_create.gid;
 
   /* Try to make the file. */
 
-  /* Copy the last component (i.e., file name) */
-  len = fs_m_in.m_vfs_fs_create.path_len; /* including trailing '\0' */
-  if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1)
-       return(ENAMETOOLONG);
-
-  err_code = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_create.grant,
-                             (vir_bytes) 0, (vir_bytes) lastc, (size_t) len);
-  if (err_code != OK) return err_code;
-  NUL(lastc, len, sizeof(lastc));
-
   /* Get last directory inode (i.e., directory that will hold the new inode) */
-  if ((ldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_create.inode)) == NULL)
+  if ((ldirp = get_inode(fs_dev, dir_nr)) == NULL)
          return(ENOENT);
 
   /* Create a new inode by calling new_node(). */
-  rip = new_node(ldirp, lastc, omode, NO_BLOCK);
+  rip = new_node(ldirp, name, mode, uid, gid, NO_BLOCK);
   r = err_code;
 
   /* If an error occurred, release inode. */
@@ -61,13 +42,12 @@ int fs_create()
   }
 
   /* Reply message */
-  fs_m_out.m_fs_vfs_create.inode = rip->i_num;
-  fs_m_out.m_fs_vfs_create.mode = rip->i_mode;
-  fs_m_out.m_fs_vfs_create.file_size = rip->i_size;
-
-  /* This values are needed for the execution */
-  fs_m_out.m_fs_vfs_create.uid = rip->i_uid;
-  fs_m_out.m_fs_vfs_create.gid = rip->i_gid;
+  node->fn_ino_nr = rip->i_num;
+  node->fn_mode = rip->i_mode;
+  node->fn_size = rip->i_size;
+  node->fn_uid = rip->i_uid;
+  node->fn_gid = rip->i_gid;
+  node->fn_dev = NO_DEV;
 
   /* Drop parent dir */
   put_inode(ldirp);
@@ -79,32 +59,17 @@ int fs_create()
 /*===========================================================================*
  *                             fs_mknod                                     *
  *===========================================================================*/
-int fs_mknod()
+int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
+       dev_t dev)
 {
   struct inode *ip, *ldirp;
-  char lastc[NAME_MAX + 1];
-  phys_bytes len;
-
-  /* Copy the last component and set up caller's user and group id */
-  len = fs_m_in.m_vfs_fs_mknod.path_len; /* including trailing '\0' */
-  if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1)
-       return(ENAMETOOLONG);
-
-  err_code = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_mknod.grant,
-                             (vir_bytes) 0, (vir_bytes) lastc, (size_t) len);
-  if (err_code != OK) return err_code;
-  NUL(lastc, len, sizeof(lastc));
-
-  caller_uid = fs_m_in.m_vfs_fs_mknod.uid;
-  caller_gid = fs_m_in.m_vfs_fs_mknod.gid;
 
   /* Get last directory inode */
-  if((ldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_mknod.inode)) == NULL)
+  if((ldirp = get_inode(fs_dev, dir_nr)) == NULL)
          return(ENOENT);
 
   /* Try to create the new node */
-  ip = new_node(ldirp, lastc, fs_m_in.m_vfs_fs_mknod.mode,
-               (block_t) fs_m_in.m_vfs_fs_mknod.device);
+  ip = new_node(ldirp, name, mode, uid, gid, (block_t) dev);
 
   put_inode(ip);
   put_inode(ldirp);
@@ -115,33 +80,18 @@ int fs_mknod()
 /*===========================================================================*
  *                             fs_mkdir                                     *
  *===========================================================================*/
-int fs_mkdir()
+int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid)
 {
   int r1, r2;                  /* status codes */
   ino_t dot, dotdot;           /* inode numbers for . and .. */
   struct inode *rip, *ldirp;
-  char lastc[NAME_MAX + 1];         /* last component */
-  phys_bytes len;
-
-  /* Copy the last component and set up caller's user and group id */
-  len = fs_m_in.m_vfs_fs_mkdir.path_len; /* including trailing '\0' */
-  if (len > NAME_MAX + 1 || len > EXT2_NAME_MAX + 1)
-       return(ENAMETOOLONG);
-
-  err_code = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_mkdir.grant,
-                             (vir_bytes) 0, (vir_bytes) lastc, (phys_bytes) len);
-  if(err_code != OK) return(err_code);
-  NUL(lastc, len, sizeof(lastc));
-
-  caller_uid = fs_m_in.m_vfs_fs_mkdir.uid;
-  caller_gid = fs_m_in.m_vfs_fs_mkdir.gid;
 
   /* Get last directory inode */
-  if((ldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_mkdir.inode)) == NULL)
+  if((ldirp = get_inode(fs_dev, dir_nr)) == NULL)
       return(ENOENT);
 
   /* Next make the inode. If that fails, return error code. */
-  rip = new_node(ldirp, lastc, fs_m_in.m_vfs_fs_mkdir.mode, (block_t) 0);
+  rip = new_node(ldirp, name, mode, uid, gid, (block_t) 0);
 
   if(rip == NULL || err_code == EEXIST) {
          put_inode(rip);               /* can't make dir: it already exists */
@@ -154,12 +104,10 @@ int fs_mkdir()
   dot = rip->i_num;            /* inode number of the new dir itself */
 
   /* Now make dir entries for . and .. unless the disk is completely full. */
-  /* Use dot1 and dot2, so the mode of the directory isn't important. */
-  rip->i_mode = fs_m_in.m_vfs_fs_mkdir.mode;   /* set mode */
   /* enter . in the new dir*/
-  r1 = search_dir(rip, dot1, &dot, ENTER, IGN_PERM, I_DIRECTORY);
+  r1 = search_dir(rip, ".", &dot, ENTER, I_DIRECTORY);
   /* enter .. in the new dir */
-  r2 = search_dir(rip, dot2, &dotdot, ENTER, IGN_PERM, I_DIRECTORY);
+  r2 = search_dir(rip, "..", &dotdot, ENTER, I_DIRECTORY);
 
   /* If both . and .. were successfully entered, increment the link counts. */
   if (r1 == OK && r2 == OK) {
@@ -170,11 +118,11 @@ int fs_mkdir()
   } else {
          /* It was not possible to enter . or .. probably disk was full -
           * links counts haven't been touched. */
-         if (search_dir(ldirp, lastc, NULL, DELETE, IGN_PERM, 0) != OK)
+         if (search_dir(ldirp, name, NULL, DELETE, 0) != OK)
                  panic("Dir disappeared: %d ", (int) rip->i_num);
          rip->i_links_count--; /* undo the increment done in new_node() */
   }
-  rip->i_dirt = IN_DIRTY;              /* either way, i_links_count has changed */
+  rip->i_dirt = IN_DIRTY;      /* either way, i_links_count has changed */
 
   put_inode(ldirp);            /* return the inode of the parent dir */
   put_inode(rip);              /* return the inode of the newly made dir */
@@ -185,55 +133,35 @@ int fs_mkdir()
 /*===========================================================================*
  *                             fs_slink                                     *
  *===========================================================================*/
-int fs_slink()
+int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid,
+       struct fsdriver_data *data, size_t bytes)
 {
-  phys_bytes len;
   struct inode *sip;           /* inode containing symbolic link */
   struct inode *ldirp;         /* directory containing link */
   register int r;              /* error code */
-  char string[NAME_MAX];       /* last component of the new dir's path name */
   char* link_target_buf = NULL;       /* either sip->i_block or bp->b_data */
   struct buf *bp = NULL;    /* disk buffer for link */
 
-  caller_uid = fs_m_in.m_vfs_fs_slink.uid;
-  caller_gid = fs_m_in.m_vfs_fs_slink.gid;
-
-  /* Copy the link name's last component */
-  len = fs_m_in.m_vfs_fs_slink.path_len;
-  if (len > NAME_MAX || len > EXT2_NAME_MAX)
-       return(ENAMETOOLONG);
-
-  r = sys_safecopyfrom(VFS_PROC_NR, fs_m_in.m_vfs_fs_slink.grant_path,
-                      (vir_bytes) 0, (vir_bytes) string, (size_t) len);
-  if (r != OK) return(r);
-  NUL(string, len, sizeof(string));
-
   /* Temporarily open the dir. */
-  if( (ldirp = get_inode(fs_dev, fs_m_in.m_vfs_fs_slink.inode)) == NULL)
+  if( (ldirp = get_inode(fs_dev, dir_nr)) == NULL)
          return(EINVAL);
 
   /* Create the inode for the symlink. */
-  sip = new_node(ldirp, string, (I_SYMBOLIC_LINK | RWX_MODES), 0);
+  sip = new_node(ldirp, name, (I_SYMBOLIC_LINK | RWX_MODES), uid, gid, 0);
 
   /* If we can then create fast symlink (store it in inode),
    * Otherwise allocate a disk block for the contents of the symlink and
    * copy contents of symlink (the name pointed to) into first disk block. */
   if( (r = err_code) == OK) {
-       if ( (fs_m_in.m_vfs_fs_slink.mem_size + 1) > sip->i_sp->s_block_size) {
+       if (bytes + 1 > sip->i_sp->s_block_size) {
                r = ENAMETOOLONG;
-       } else if ((fs_m_in.m_vfs_fs_slink.mem_size + 1) <= MAX_FAST_SYMLINK_LENGTH) {
-               r = sys_safecopyfrom(VFS_PROC_NR,
-                                    fs_m_in.m_vfs_fs_slink.grant_target,
-                                    (vir_bytes) 0, (vir_bytes) sip->i_block,
-                                     (vir_bytes) fs_m_in.m_vfs_fs_slink.mem_size);
+       } else if ((bytes + 1) <= MAX_FAST_SYMLINK_LENGTH) {
+               r = fsdriver_copyin(data, 0, (char *) sip->i_block, bytes);
                sip->i_dirt = IN_DIRTY;
                link_target_buf = (char*) sip->i_block;
         } else {
                if ((bp = new_block(sip, (off_t) 0)) != NULL) {
-                       sys_safecopyfrom(VFS_PROC_NR,
-                                        fs_m_in.m_vfs_fs_slink.grant_target,
-                                        (vir_bytes) 0, (vir_bytes) b_data(bp),
-                                        (vir_bytes) fs_m_in.m_vfs_fs_slink.mem_size);
+                       r = fsdriver_copyin(data, 0, b_data(bp), bytes);
                        lmfs_markdirty(bp);
                        link_target_buf = b_data(bp);
                } else {
@@ -242,9 +170,9 @@ int fs_slink()
        }
        if (r == OK) {
                assert(link_target_buf);
-               link_target_buf[fs_m_in.m_vfs_fs_slink.mem_size] = '\0';
+               link_target_buf[bytes] = '\0';
                sip->i_size = (off_t) strlen(link_target_buf);
-               if (sip->i_size != fs_m_in.m_vfs_fs_slink.mem_size) {
+               if (sip->i_size != bytes) {
                          /* This can happen if the user provides a buffer
                           * with a \0 in it. This can cause a lot of trouble
                           * when the symlink is used later. We could just use
@@ -261,7 +189,7 @@ int fs_slink()
 
        if(r != OK) {
                sip->i_links_count = NO_LINK;
-               if (search_dir(ldirp, string, NULL, DELETE, IGN_PERM, 0) != OK)
+               if (search_dir(ldirp, name, NULL, DELETE, 0) != OK)
                        panic("Symbolic link vanished");
        }
   }
@@ -277,7 +205,7 @@ int fs_slink()
  *                             new_node                                     *
  *===========================================================================*/
 static struct inode *new_node(struct inode *ldirp,
-       char *string, mode_t bits, block_t b0)
+       char *string, mode_t bits, uid_t uid, gid_t gid, block_t b0)
 {
 /* 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
@@ -295,20 +223,19 @@ static struct inode *new_node(struct inode *ldirp,
        return(NULL);
   }
 
-  /* Get final component of the path. */
-  rip = advance(ldirp, string, IGN_PERM);
-
   if (S_ISDIR(bits) && (ldirp->i_links_count >= USHRT_MAX ||
                        ldirp->i_links_count >= LINK_MAX)) {
         /* New entry is a directory, alas we can't give it a ".." */
-        put_inode(rip);
         err_code = EMLINK;
         return(NULL);
   }
 
+  /* Get final component of the path. */
+  rip = advance(ldirp, string);
+
   if ( rip == NULL && err_code == ENOENT) {
        /* Last path component does not exist.  Make new directory entry. */
-       if ( (rip = alloc_inode(ldirp, bits)) == NULL) {
+       if ( (rip = alloc_inode(ldirp, bits, uid, gid)) == NULL) {
                /* Can't creat new inode: out of inodes. */
                return(NULL);
        }
@@ -322,7 +249,7 @@ static struct inode *new_node(struct inode *ldirp,
        rw_inode(rip, WRITING);         /* force inode to disk now */
 
        /* New inode acquired.  Try to make directory entry. */
-       if ((r=search_dir(ldirp, string, &rip->i_num, ENTER, IGN_PERM,
+       if ((r=search_dir(ldirp, string, &rip->i_num, ENTER,
                          rip->i_mode & I_TYPE)) != OK) {
                rip->i_links_count--;   /* pity, have to free disk inode */
                rip->i_dirt = IN_DIRTY; /* dirty inodes are written out */
@@ -331,8 +258,6 @@ static struct inode *new_node(struct inode *ldirp,
                return(NULL);
        }
 
-  } else if (err_code == EENTERMOUNT || err_code == ELEAVEMOUNT) {
-       r = EEXIST;
   } else {
        /* Either last component exists, or there is some problem. */
        if (rip != NULL)
@@ -348,17 +273,13 @@ static struct inode *new_node(struct inode *ldirp,
 
 
 /*===========================================================================*
- *                             fs_inhibread                                 *
+ *                             fs_seek                                      *
  *===========================================================================*/
-int fs_inhibread()
+void fs_seek(ino_t ino_nr)
 {
   struct inode *rip;
 
-  if((rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_inhibread.inode)) == NULL)
-         return(EINVAL);
-
   /* inhibit read ahead */
-  rip->i_seek = ISEEK;
-
-  return(OK);
+  if ((rip = find_inode(fs_dev, ino_nr)) != NULL)
+       rip->i_seek = ISEEK;
 }
index 6fdc84bf18a68c67bf310ca17c5772eb64fcd624..cac197b94e6e42682542a1f5d3fb013b9eb0945c 100644 (file)
@@ -1,12 +1,6 @@
 /* This file contains the procedures that look up path names in the directory
  * system and determine the inode number that goes with a given path name.
  *
- *  The entry points into this file are
- *   eat_path:  the 'main' routine of the path-to-inode conversion mechanism
- *   last_dir:  find the final directory on a given path
- *   advance:   parse one component of a path name
- *   search_dir: search a directory for a string and return its inode number
- *
  * Created (MFS based):
  *   February 2010 (Evgeniy Ivanov)
  */
 #include "fs.h"
 #include <assert.h>
 #include <string.h>
-#include <minix/endpoint.h>
-#include <sys/stat.h>
 #include <sys/param.h>
-#include <sys/types.h>
 #include "buf.h"
 #include "inode.h"
 #include "super.h"
-#include <minix/vfsif.h>
-#include <minix/libminixfs.h>
-
-char dot1[2] = ".";    /* used for search_dir to bypass the access */
-char dot2[3] = "..";   /* permissions for . and ..                 */
 
-static char *get_name(char *name, char string[NAME_MAX+1]);
-static int ltraverse(struct inode *rip, char *suffix);
-static int parse_path(ino_t dir_ino, ino_t root_ino, int flags, struct
-       inode **res_inop, size_t *offsetp, int *symlinkp);
 
 /*===========================================================================*
  *                             fs_lookup                                    *
  *===========================================================================*/
-int fs_lookup()
+int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
+       int *is_mountpt)
 {
-  cp_grant_id_t grant;
-  int r, r1, flags, symlinks;
-  unsigned int len;
-  size_t offset = 0, path_size;
-  ino_t dir_ino, root_ino;
-  struct inode *rip;
-
-  grant                = fs_m_in.m_vfs_fs_lookup.grant_path;
-  path_size    = fs_m_in.m_vfs_fs_lookup.path_size;    /* Size of the buffer */
-  len          = fs_m_in.m_vfs_fs_lookup.path_len;     /* including terminating nul */
-  dir_ino      = fs_m_in.m_vfs_fs_lookup.dir_ino;
-  root_ino     = fs_m_in.m_vfs_fs_lookup.root_ino;
-  flags                = fs_m_in.m_vfs_fs_lookup.flags;
-
-  /* Check length. */
-  if(len > sizeof(user_path)) return(E2BIG);   /* too big for buffer */
-  if(len == 0) return(EINVAL);                 /* too small */
-
-  /* Copy the pathname and set up caller's user and group id */
-  r = sys_safecopyfrom(VFS_PROC_NR, grant, /*offset*/ 0,
-            (vir_bytes) user_path, (size_t) len);
-  if(r != OK) return(r);
-
-  /* Verify this is a null-terminated path. */
-  if(user_path[len - 1] != '\0') return(EINVAL);
-
-  memset(&credentials, 0, sizeof(credentials));
-  if(!(flags & PATH_GET_UCRED)) { /* Do we have to copy uid/gid credentials? */
-        caller_uid      = fs_m_in.m_vfs_fs_lookup.uid;
-        caller_gid      = fs_m_in.m_vfs_fs_lookup.gid;
-   } else {
-         if((r=fs_lookup_credentials(&credentials,
-               &caller_uid, &caller_gid, fs_m_in.m_vfs_fs_lookup.grant_ucred,
-               fs_m_in.m_vfs_fs_lookup.ucred_size)) != OK)
-               return r;
-  }
-
-  /* Lookup inode */
-  rip = NULL;
-  r = parse_path(dir_ino, root_ino, flags, &rip, &offset, &symlinks);
-
-  if(symlinks != 0 && (r == ELEAVEMOUNT || r == EENTERMOUNT || r == ESYMLINK)){
-       len = strlen(user_path)+1;
-       if(len > path_size) return(ENAMETOOLONG);
-
-       r1 = sys_safecopyto(VFS_PROC_NR, grant, (vir_bytes) 0,
-                           (vir_bytes) user_path, (size_t) len);
-       if (r1 != OK) return(r1);
-  }
-
-  if(r == ELEAVEMOUNT || r == ESYMLINK) {
-         /* Report offset and the error */
-         fs_m_out.m_fs_vfs_lookup.offset = offset;
-         fs_m_out.m_fs_vfs_lookup.symloop = symlinks;
-
-         return(r);
-  }
-
-  if (r != OK && r != EENTERMOUNT) return(r);
-
-  fs_m_out.m_fs_vfs_lookup.inode               = rip->i_num;
-  fs_m_out.m_fs_vfs_lookup.mode                        = rip->i_mode;
-  fs_m_out.m_fs_vfs_lookup.file_size           = rip->i_size;
-  fs_m_out.m_fs_vfs_lookup.symloop             = symlinks;
-  fs_m_out.m_fs_vfs_lookup.uid                 = rip->i_uid;
-  fs_m_out.m_fs_vfs_lookup.gid                 = rip->i_gid;
-
+  struct inode *dirp, *rip;
+
+  /* Find the starting inode. */
+  if ((dirp = find_inode(fs_dev, dir_nr)) == NULL)
+       return EINVAL;
+
+  /* Look up the directory entry. */
+  if ((rip = advance(dirp, name)) == NULL)
+       return err_code;
+
+  /* On success, leave the resulting inode open and return its details. */
+  node->fn_ino_nr = rip->i_num;
+  node->fn_mode = rip->i_mode;
+  node->fn_size = rip->i_size;
+  node->fn_uid = rip->i_uid;
+  node->fn_gid = rip->i_gid;
   /* This is only valid for block and character specials. But it doesn't
    * cause any harm to always set the device field. */
-  fs_m_out.m_fs_vfs_lookup.device              = (dev_t) rip->i_block[0];
-
-  if(r == EENTERMOUNT) {
-         fs_m_out.m_fs_vfs_lookup.offset       = offset;
-         put_inode(rip); /* Only return a reference to the final object */
-  }
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             parse_path                                   *
- *===========================================================================*/
-static int parse_path(dir_ino, root_ino, flags, res_inop, offsetp, symlinkp)
-ino_t dir_ino;
-ino_t root_ino;
-int flags;
-struct inode **res_inop;
-size_t *offsetp;
-int *symlinkp;
-{
-  /* Parse the path in user_path, starting at dir_ino. If the path is the empty
-   * string, just return dir_ino. It is upto the caller to treat an empty
-   * path in a special way. Otherwise, if the path consists of just one or
-   * more slash ('/') characters, the path is replaced with ".". Otherwise,
-   * just look up the first (or only) component in path after skipping any
-   * leading slashes.
-   */
-  int r, leaving_mount;
-  struct inode *rip, *dir_ip;
-  char *cp, *next_cp; /* component and next component */
-  char component[NAME_MAX+1];
-
-  /* Start parsing path at the first component in user_path */
-  cp = user_path;
-
-  /* No symlinks encountered yet */
-  *symlinkp = 0;
-
-  /* Find starting inode inode according to the request message */
-  if((rip = find_inode(fs_dev, dir_ino)) == NULL)
-       return(ENOENT);
-
-  /* If dir has been removed return ENOENT. */
-  if (rip->i_links_count == NO_LINK) return(ENOENT);
-
-  dup_inode(rip);
-
-  /* If the given start inode is a mountpoint, we must be here because the file
-   * system mounted on top returned an ELEAVEMOUNT error. In this case, we must
-   * only accept ".." as the first path component.
-   */
-  leaving_mount = rip->i_mountpoint; /* True iff rip is a mountpoint */
-
-  /* Scan the path component by component. */
-  while (TRUE) {
-       if(cp[0] == '\0') {
-               /* We're done; either the path was empty or we've parsed all
-                  components of the path */
-
-               *res_inop = rip;
-               *offsetp += cp - user_path;
-
-               /* Return EENTERMOUNT if we are at a mount point */
-               if (rip->i_mountpoint) return(EENTERMOUNT);
-
-               return(OK);
-       }
-
-       while(cp[0] == '/') cp++;
-       next_cp = get_name(cp, component);
-       if (next_cp == NULL) {
-               put_inode(rip);
-               return(err_code);
-       }
-
-       /* Special code for '..'. A process is not allowed to leave a chrooted
-        * environment. A lookup of '..' at the root of a mounted filesystem
-        * has to return ELEAVEMOUNT. In both cases, the caller needs search
-        * permission for the current inode, as it is used as directory.
-        */
-       if(strcmp(component, "..") == 0) {
-               /* 'rip' is now accessed as directory */
-               if ((r = forbidden(rip, X_BIT)) != OK) {
-                       put_inode(rip);
-                       return(r);
-               }
-
-               if (rip->i_num == root_ino) {
-                       cp = next_cp;
-                       continue;       /* Ignore the '..' at a process' root
-                                          and move on to the next component */
-               }
-
-               if (rip->i_num == ROOT_INODE && !rip->i_sp->s_is_root) {
-                       /* Climbing up to parent FS */
-
-                       put_inode(rip);
-                       *offsetp += cp - user_path;
-                       return(ELEAVEMOUNT);
-               }
-       }
-
-       /* Only check for a mount point if we are not coming from one. */
-       if (!leaving_mount && rip->i_mountpoint) {
-               /* Going to enter a child FS */
-
-               *res_inop = rip;
-               *offsetp += cp - user_path;
-               return(EENTERMOUNT);
-       }
-
-       /* There is more path.  Keep parsing.
-        * If we're leaving a mountpoint, skip directory permission checks.
-        */
-       dir_ip = rip;
-       rip = advance(dir_ip, leaving_mount ? dot2 : component, CHK_PERM);
-       if(err_code == ELEAVEMOUNT || err_code == EENTERMOUNT)
-               err_code = OK;
-
-       if (err_code != OK) {
-               put_inode(dir_ip);
-               return(err_code);
-       }
-
-       leaving_mount = 0;
-
-       /* The call to advance() succeeded.  Fetch next component. */
-       if (S_ISLNK(rip->i_mode)) {
-
-               if (next_cp[0] == '\0' && (flags & PATH_RET_SYMLINK)) {
-                       put_inode(dir_ip);
-                       *res_inop = rip;
-                       *offsetp += next_cp - user_path;
-                       return(OK);
-               }
-
-               /* Extract path name from the symlink file */
-               r = ltraverse(rip, next_cp);
-               next_cp = user_path;
-               *offsetp = 0;
-
-               /* Symloop limit reached? */
-               if (++(*symlinkp) > _POSIX_SYMLOOP_MAX)
-                       r = ELOOP;
-
-               if (r != OK) {
-                       put_inode(dir_ip);
-                       put_inode(rip);
-                       return(r);
-               }
-
-               if (next_cp[0] == '/') {
-                        put_inode(dir_ip);
-                        put_inode(rip);
-                        return(ESYMLINK);
-               }
-
-               put_inode(rip);
-               dup_inode(dir_ip);
-               rip = dir_ip;
-       }
-
-       put_inode(dir_ip);
-       cp = next_cp; /* Process subsequent component in next round */
-  }
-
-}
-
-
-/*===========================================================================*
- *                             ltraverse                                    *
- *===========================================================================*/
-static int ltraverse(rip, suffix)
-register struct inode *rip;    /* symbolic link */
-char *suffix;                  /* current remaining path. Has to point in the
-                                * user_path buffer
-                                */
-{
-/* Traverse a symbolic link. Copy the link text from the inode and insert
- * the text into the path. Return error code or report success. Base
- * directory has to be determined according to the first character of the
- * new pathname.
- */
-
-  size_t llen;         /* length of link */
-  size_t slen;         /* length of suffix */
-  struct buf *bp;      /* buffer containing link text */
-  const char *sp;      /* start of link text */
-
-  llen = (size_t) rip->i_size;
-
-  if (llen >= MAX_FAST_SYMLINK_LENGTH) {
-       /* normal symlink */
-       if(!(bp = get_block_map(rip, 0)))
-               return(EIO);
-       sp = b_data(bp);
-  } else {
-       /* fast symlink, stored in inode */
-       sp = (const char*) rip->i_block;
-  }
-
-  slen = strlen(suffix);
-
-  /* The path we're parsing looks like this:
-   * /already/processed/path/<link> or
-   * /already/processed/path/<link>/not/yet/processed/path
-   * After expanding the <link>, the path will look like
-   * <expandedlink> or
-   * <expandedlink>/not/yet/processed
-   * In both cases user_path must have enough room to hold <expandedlink>.
-   * However, in the latter case we have to move /not/yet/processed to the
-   * right place first, before we expand <link>. When strlen(<expandedlink>) is
-   * smaller than strlen(/already/processes/path), we move the suffix to the
-   * left. Is strlen(<expandedlink>) greater then we move it to the right. Else
-   * we do nothing.
-   */
-
-  if (slen > 0) { /* Do we have path after the link? */
-       /* For simplicity we require that suffix starts with a slash */
-       if (suffix[0] != '/') {
-               panic("ltraverse: suffix does not start with a slash");
-       }
+  node->fn_dev = (dev_t) rip->i_block[0];
 
-       /* To be able to expand the <link>, we have to move the 'suffix'
-        * to the right place.
-        */
-       if (slen + llen + 1 > sizeof(user_path))
-               return(ENAMETOOLONG);/* <expandedlink>+suffix+\0 does not fit*/
-       if ((unsigned)(suffix - user_path) != llen) {
-               /* Move suffix left or right if needed */
-               memmove(&user_path[llen], suffix, slen+1);
-       }
-  } else {
-       if (llen + 1 > sizeof(user_path))
-               return(ENAMETOOLONG); /* <expandedlink> + \0 does not fit */
-
-       /* Set terminating nul */
-       user_path[llen]= '\0';
-  }
+  *is_mountpt = rip->i_mountpoint;
 
-  /* Everything is set, now copy the expanded link to user_path */
-  memmove(user_path, sp, llen);
-
-  if (llen >= MAX_FAST_SYMLINK_LENGTH)
-       put_block(bp, DIRECTORY_BLOCK);
-
-  return(OK);
+  return OK;
 }
 
 
 /*===========================================================================*
  *                             advance                                      *
  *===========================================================================*/
-struct inode *advance(dirp, string, chk_perm)
+struct inode *advance(dirp, string)
 struct inode *dirp;            /* inode for directory to be searched */
-char string[NAME_MAX + 1];     /* component name to look for */
-int chk_perm;                  /* check permissions when string is looked up*/
+const char *string;            /* component name to look for */
 {
 /* Given a directory and a component of a path, look up the component in
  * the directory, find the inode, open it, and return a pointer to its inode
@@ -373,136 +60,55 @@ int chk_perm;                     /* check permissions when string is looked up*/
   ino_t numb;
   struct inode *rip;
 
+  assert(dirp != NULL);
+
   /* If 'string' is empty, return an error. */
   if (string[0] == '\0') {
        err_code = ENOENT;
        return(NULL);
   }
 
-  /* Check for NULL. */
-  if (dirp == NULL) return(NULL);
+  /* If dir has been removed return ENOENT. */
+  if (dirp->i_links_count == NO_LINK) {
+       err_code = ENOENT;
+       return(NULL);
+  }
 
   /* If 'string' is not present in the directory, signal error. */
-  if ( (err_code = search_dir(dirp, string, &numb, LOOK_UP,
-                             chk_perm, 0)) != OK) {
+  if ( (err_code = search_dir(dirp, string, &numb, LOOK_UP, 0)) != OK) {
        return(NULL);
   }
 
   /* The component has been found in the directory.  Get inode. */
   if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NULL)  {
+       assert(err_code != OK);
        return(NULL);
   }
 
-  /* The following test is for "mountpoint/.." where mountpoint is a
-   * mountpoint. ".." will refer to the root of the mounted filesystem,
-   * but has to become a reference to the parent of the 'mountpoint'
-   * directory.
-   *
-   * This case is recognized by the looked up name pointing to a
-   * root inode, and the directory in which it is held being a
-   * root inode, _and_ the name[1] being '.'. (This is a test for '..'
-   * and excludes '.'.)
-   */
-  if (rip->i_num == ROOT_INODE) {
-         if (dirp->i_num == ROOT_INODE) {
-                 if (string[1] == '.') {
-                         if (!rip->i_sp->s_is_root) {
-                                 /* Climbing up mountpoint */
-                                 err_code = ELEAVEMOUNT;
-                         }
-                 }
-         }
-  }
-
-  /* See if the inode is mounted on.  If so, switch to root directory of the
-   * mounted file system.  The super_block provides the linkage between the
-   * inode mounted on and the root directory of the mounted file system.
-   */
-  if (rip->i_mountpoint) {
-         /* Mountpoint encountered, report it */
-         err_code = EENTERMOUNT;
-  }
-
   return(rip);
 }
 
 
-/*===========================================================================*
- *                             get_name                                     *
- *===========================================================================*/
-static char *get_name(path_name, string)
-char *path_name;               /* path name to parse */
-char string[NAME_MAX+1];       /* component extracted from 'old_name' */
-{
-/* Given a pointer to a path name in fs space, 'path_name', copy the first
- * component to 'string' (truncated if necessary, always nul terminated).
- * A pointer to the string after the first component of the name as yet
- * unparsed is returned.  Roughly speaking,
- * 'get_name' = 'path_name' - 'string'.
- *
- * This routine follows the standard convention that /usr/ast, /usr//ast,
- * //usr///ast and /usr/ast/ are all equivalent.
- *
- * If len of component is greater, than allowed, then return 0.
- */
-  size_t len;
-  char *cp, *ep;
-
-  cp = path_name;
-
-  /* Skip leading slashes */
-  while (cp[0] == '/') cp++;
-
-  /* Find the end of the first component */
-  ep = cp;
-  while(ep[0] != '\0' && ep[0] != '/')
-       ep++;
-
-  len = (size_t) (ep - cp);
-
-  if (len > NAME_MAX || len > EXT2_NAME_MAX) {
-       err_code = ENAMETOOLONG;
-       return(NULL);
-  }
-
-  /* Special case of the string at cp is empty */
-  if (len == 0)
-       strlcpy(string, ".", NAME_MAX + 1);  /* Return "." */
-  else {
-       memcpy(string, cp, len);
-       string[len]= '\0';
-  }
-
-  return(ep);
-}
-
-
 /*===========================================================================*
  *                             search_dir                                   *
  *===========================================================================*/
-int search_dir(ldir_ptr, string, numb, flag, check_permissions, ftype)
+int search_dir(ldir_ptr, string, numb, flag, ftype)
 register struct inode *ldir_ptr; /* ptr to inode for dir to search */
-const char string[NAME_MAX + 1];        /* component to search for */
+const char *string;             /* component to search for */
 ino_t *numb;                    /* pointer to inode number */
 int flag;                       /* LOOK_UP, ENTER, DELETE or IS_EMPTY */
-int check_permissions;          /* check permissions when flag is !IS_EMPTY */
-int ftype;                      /* used when ENTER and
-                                 * INCOMPAT_FILETYPE */
+int ftype;                      /* used when ENTER and INCOMPAT_FILETYPE */
 {
 /* This function searches the directory whose inode is pointed to by 'ldip':
  * if (flag == ENTER)  enter 'string' in the directory with inode # '*numb';
  * if (flag == DELETE) delete 'string' from the directory;
  * if (flag == LOOK_UP) search for 'string' and return inode # in 'numb';
  * if (flag == IS_EMPTY) return OK if only . and .. in dir else ENOTEMPTY;
- *
- *    if 'string' is dot1 or dot2, no access permissions are checked.
  */
-
   register struct ext2_disk_dir_desc  *dp = NULL;
   register struct ext2_disk_dir_desc  *prev_dp = NULL;
   register struct buf *bp = NULL;
   int i, r, e_hit, t, match;
-  mode_t bits;
   off_t pos;
   unsigned new_slots;
   int extended = 0;
@@ -514,27 +120,15 @@ int ftype;                         /* used when ENTER and
        return(ENOTDIR);
   }
 
-  r = OK;
-
-  if (flag != IS_EMPTY) {
-       bits = (flag == LOOK_UP ? X_BIT : W_BIT | X_BIT);
-
-       if (string == dot1 || string == dot2) {
-               if (flag != LOOK_UP) r = read_only(ldir_ptr);
-                                    /* only a writable device is required. */
-        } else if(check_permissions) {
-               r = forbidden(ldir_ptr, bits); /* check access permissions */
-       }
-  }
-  if (r != OK) return(r);
-
   new_slots = 0;
   e_hit = FALSE;
   match = 0;           /* set when a string match occurs */
   pos = 0;
 
+  if ((string_len = strlen(string)) > EXT2_NAME_MAX)
+       return(ENAMETOOLONG);
+
   if (flag == ENTER) {
-       string_len = strlen(string);
        required_space = MIN_DIR_ENTRY_SIZE + string_len;
        required_space += (required_space & 0x03) == 0 ? 0 :
                             (DIR_ENTRY_ALIGN - (required_space & 0x03) );
index bbd732ef2bccf1df49f5895cedd0fc7b9d132c1b..6aae56dae10333a6aa6ad6a9a7e29cdf232eac23 100644 (file)
@@ -5,34 +5,27 @@
 #include "fs.h"
 #include "inode.h"
 #include "super.h"
-#include <minix/vfsif.h>
-
-static int in_group(gid_t grp);
 
 
 /*===========================================================================*
  *                             fs_chmod                                     *
  *===========================================================================*/
-int fs_chmod()
+int fs_chmod(ino_t ino_nr, mode_t *mode)
 {
 /* Perform the chmod(name, mode) system call. */
-
   register struct inode *rip;
-  mode_t mode;
-
-  mode = fs_m_in.m_vfs_fs_chmod.mode;
 
   /* Temporarily open the file. */
-  if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_chmod.inode)) == NULL)
+  if( (rip = get_inode(fs_dev, ino_nr)) == NULL)
          return(EINVAL);
 
   /* Now make the change. Clear setgid bit if file is not in caller's grp */
-  rip->i_mode = (rip->i_mode & ~ALL_MODES) | (mode & ALL_MODES);
+  rip->i_mode = (rip->i_mode & ~ALL_MODES) | (*mode & ALL_MODES);
   rip->i_update |= CTIME;
   rip->i_dirt = IN_DIRTY;
 
   /* Return full new mode to caller. */
-  fs_m_out.m_fs_vfs_chmod.mode = rip->i_mode;
+  *mode = rip->i_mode;
 
   put_inode(rip);
   return(OK);
@@ -42,117 +35,23 @@ int fs_chmod()
 /*===========================================================================*
  *                             fs_chown                                     *
  *===========================================================================*/
-int fs_chown()
+int fs_chown(ino_t ino_nr, uid_t uid, gid_t gid, mode_t *mode)
 {
   register struct inode *rip;
-  register int r;
 
   /* Temporarily open the file. */
-  if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_chown.inode)) == NULL)
+  if( (rip = get_inode(fs_dev, ino_nr)) == NULL)
          return(EINVAL);
 
-  /* Not permitted to change the owner of a file on a read-only file sys. */
-  r = read_only(rip);
-  if (r == OK) {
-         rip->i_uid = fs_m_in.m_vfs_fs_chown.uid;
-         rip->i_gid = fs_m_in.m_vfs_fs_chown.gid;
-         rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
-         rip->i_update |= CTIME;
-         rip->i_dirt = IN_DIRTY;
-  }
+  rip->i_uid = uid;
+  rip->i_gid = gid;
+  rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
+  rip->i_update |= CTIME;
+  rip->i_dirt = IN_DIRTY;
 
   /* Update caller on current mode, as it may have changed. */
-  fs_m_out.m_fs_vfs_chown.mode = rip->i_mode;
+  *mode = rip->i_mode;
   put_inode(rip);
 
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             forbidden                                    *
- *===========================================================================*/
-int forbidden(struct inode *rip, 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 inode *old_rip = rip;
-  mode_t bits, perm_bits;
-  int r, shift;
-
-  /* Isolate the relevant rwx bits from the mode. */
-  bits = rip->i_mode;
-  if (caller_uid == SU_UID) {
-       /* Grant read and write permission.  Grant search permission for
-        * directories.  Grant execute permission (for non-directories) if
-        * and only if one of the 'X' bits is set.
-        */
-       if ( (bits & I_TYPE) == I_DIRECTORY ||
-            bits & ((X_BIT << 6) | (X_BIT << 3) | X_BIT))
-               perm_bits = R_BIT | W_BIT | X_BIT;
-       else
-               perm_bits = R_BIT | W_BIT;
-  } else {
-       if (caller_uid == rip->i_uid) shift = 6;        /* owner */
-       else if (caller_gid == rip->i_gid) shift = 3;   /* group */
-       else if (in_group(rip->i_gid) == OK) shift = 3; /* other groups */
-       else shift = 0;                                 /* other */
-       perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
-  }
-
-  /* If access desired is not a subset of what is allowed, it is refused. */
-  r = OK;
-  if ((perm_bits | access_desired) != perm_bits) r = EACCES;
-
-  /* Check to see if someone is trying to write on a file system that is
-   * mounted read-only.
-   */
-  if (r == OK) {
-       if (access_desired & W_BIT) {
-               r = read_only(rip);
-       }
-  }
-
-  if (rip != old_rip) put_inode(rip);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             in_group                                     *
- *===========================================================================*/
-static int in_group(gid_t grp)
-{
-  int i;
-
-  if (credentials.vu_ngroups > NGROUPS_MAX)
-       return(EINVAL);
-
-  for (i = 0; i < credentials.vu_ngroups; i++)
-       if (credentials.vu_sgroups[i] == grp)
-               return(OK);
-
-  return(EINVAL);
-}
-
-
-/*===========================================================================*
- *                             read_only                                    *
- *===========================================================================*/
-int read_only(ip)
-struct inode *ip;              /* 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 super_block *sp;
-
-  sp = ip->i_sp;
-  return(sp->s_rd_only ? EROFS : OK);
+  return(OK);
 }
index 868d8a9fe6acd32cd684df595d6943226080ccb4..5f237c64a1b54768492fa33a5f226bae4a66982a 100644 (file)
@@ -12,20 +12,20 @@ struct filp;
 struct inode;
 struct super_block;
 
-
 /* balloc.c */
 void discard_preallocated_blocks(struct inode *rip);
 block_t alloc_block(struct inode *rip, block_t goal);
 void free_block(struct super_block *sp, bit_t bit);
 
 /* ialloc.c */
-struct inode *alloc_inode(struct inode *parent, mode_t bits);
+struct inode *alloc_inode(struct inode *parent, mode_t bits, uid_t uid,
+       gid_t gid);
 void free_inode(struct inode *rip);
 
 /* inode.c */
 void dup_inode(struct inode *ip);
 struct inode *find_inode(dev_t dev, ino_t numb);
-int fs_putnode(void);
+int fs_putnode(ino_t ino_nr, unsigned int count);
 void init_inode_cache(void);
 struct inode *get_inode(dev_t dev, ino_t numb);
 void put_inode(struct inode *rip);
@@ -33,56 +33,56 @@ void update_times(struct inode *rip);
 void rw_inode(struct inode *rip, int rw_flag);
 
 /* link.c */
-int fs_ftrunc(void);
-int fs_link(void);
-int fs_rdlink(void);
-int fs_rename(void);
-int fs_unlink(void);
+int fs_trunc(ino_t ino_nr, off_t start, off_t end);
+int fs_link(ino_t dir_nr, char *name, ino_t ino_nr);
+int fs_rdlink(ino_t ino_nr, struct fsdriver_data *data, size_t bytes);
+int fs_rename(ino_t old_dir_nr, char *old_name, ino_t new_dir_nr,
+       char *new_name);
+int fs_unlink(ino_t dir_nr, char *name, int call);
 int truncate_inode(struct inode *rip, off_t len);
 
 /* misc.c */
-int fs_flush(void);
-int fs_sync(void);
-int fs_new_driver(void);
-int fs_bpeek(void);
+void fs_sync(void);
 
 /* mount.c */
-int fs_mountpoint(void);
-int fs_readsuper(void);
-int fs_unmount(void);
+int fs_mount(dev_t dev, unsigned int flags, struct fsdriver_node *root_node,
+       unsigned int *res_flags);
+void fs_unmount(void);
+int fs_mountpt(ino_t ino_nr);
 
 /* open.c */
-int fs_create(void);
-int fs_inhibread(void);
-int fs_mkdir(void);
-int fs_mknod(void);
-int fs_slink(void);
+int fs_create(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
+       struct fsdriver_node *node);
+int fs_mkdir(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid);
+int fs_mknod(ino_t dir_nr, char *name, mode_t mode, uid_t uid, gid_t gid,
+       dev_t dev);
+int fs_slink(ino_t dir_nr, char *name, uid_t uid, gid_t gid,
+       struct fsdriver_data *data, size_t bytes);
+void fs_seek(ino_t ino_nr);
 
 /* path.c */
-int fs_lookup(void);
-struct inode *advance(struct inode *dirp, char string[NAME_MAX + 1], int
-       chk_perm);
-int search_dir(struct inode *ldir_ptr, const char string [NAME_MAX + 1], ino_t
-       *numb, int flag, int check_permissions, int ftype);
+int fs_lookup(ino_t dir_nr, char *name, struct fsdriver_node *node,
+       int *is_mountpt);
+struct inode *advance(struct inode *dirp, const char *string);
+int search_dir(struct inode *ldir_ptr, const char *string, ino_t *numb,
+       int flag, int ftype);
 
 /* protect.c */
-int fs_chmod(void);
-int fs_chown(void);
-int fs_getdents(void);
-int forbidden(struct inode *rip, mode_t access_desired);
-int read_only(struct inode *ip);
+int fs_chmod(ino_t ino_nr, mode_t *mode);
+int fs_chown(ino_t ino_nr, uid_t uid, gid_t gid, mode_t *mode);
 
 /* read.c */
-int fs_breadwrite(void);
-int fs_readwrite(void);
-void read_ahead(void);
+ssize_t fs_readwrite(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
+       off_t pos, int call);
 block_t rd_indir(struct buf *bp, int index);
 block_t read_map(struct inode *rip, off_t pos, int opportunistic);
 struct buf *get_block_map(register struct inode *rip, u64_t position);
+ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
+       off_t *posp);
 
 /* stadir.c */
-int fs_stat(void);
-int fs_statvfs(void);
+int fs_stat(ino_t ino_nr, struct stat *statbuf);
+int fs_statvfs(struct statvfs *st);
 
 /* super.c */
 unsigned int get_block_size(dev_t dev);
@@ -92,17 +92,11 @@ void write_super(struct super_block *sp);
 struct group_desc* get_group_desc(unsigned int bnum);
 
 /* time.c */
-int fs_utime(void);
+int fs_utime(ino_t ino, struct timespec *atime, struct timespec *mtime);
 
 /* utility.c */
 unsigned conv2(int norm, int w);
 long conv4(int norm, long x);
-void mfs_nul_f(const char *file, int line, const char *str, unsigned int len,
-       unsigned int maxlen);
-int min(unsigned int l, unsigned int r);
-int no_sys(void);
-void sanitycheck(char *file, int line);
-#define SANITYCHECK sanitycheck(__FILE__, __LINE__)
 int ansi_strcmp(register const char* ansi_s, register const char *s2,
        register size_t ansi_s_length);
 bit_t setbit(bitchunk_t *bitmap, bit_t max_bits, unsigned int word);
index 09cb3ee50d1f0b056775bb8681a6eb37b183f64c..544db1ce2488bf94c6112a27e4b3c2b27ab6c3ec 100644 (file)
@@ -6,76 +6,50 @@
 #include <stddef.h>
 #include <string.h>
 #include <stdlib.h>
-#include <minix/com.h>
-#include <minix/u64.h>
 #include "buf.h"
 #include "inode.h"
 #include "super.h"
-#include <minix/vfsif.h>
-#include <minix/minlib.h>
 #include <sys/param.h>
 #include <assert.h>
-#include <sys/param.h>
 
 
 static struct buf *rahead(struct inode *rip, block_t baseblock, u64_t
        position, unsigned bytes_ahead);
 static int rw_chunk(struct inode *rip, u64_t position, unsigned off,
-       size_t chunk, unsigned left, int rw_flag, cp_grant_id_t gid, unsigned
-       buf_off, unsigned int block_size, int *completed);
-
-static off_t rdahedpos;         /* position to read ahead */
-static struct inode *rdahed_inode;      /* pointer to inode to read ahead */
+       size_t chunk, unsigned left, int call, struct fsdriver_data *data,
+       unsigned buf_off, unsigned int block_size, int *completed);
 
 /*===========================================================================*
  *                             fs_readwrite                                 *
  *===========================================================================*/
-int fs_readwrite(void)
+ssize_t fs_readwrite(ino_t ino_nr, struct fsdriver_data *data, size_t nrbytes,
+       off_t position, int call)
 {
-  int r, rw_flag, block_spec;
+  int r;
   int regular;
-  cp_grant_id_t gid;
-  off_t position, f_size, bytes_left;
-  unsigned int off, cum_io, block_size, chunk;
+  off_t f_size, bytes_left;
+  size_t off, cum_io, block_size, chunk;
   mode_t mode_word;
   int completed;
   struct inode *rip;
-  size_t nrbytes;
 
   r = OK;
 
   /* Find the inode referred */
-  if ((rip = find_inode(fs_dev, fs_m_in.m_vfs_fs_readwrite.inode)) == NULL)
+  if ((rip = find_inode(fs_dev, ino_nr)) == NULL)
        return(EINVAL);
 
   mode_word = rip->i_mode & I_TYPE;
-  regular = (mode_word == I_REGULAR || mode_word == I_NAMED_PIPE);
-  block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0);
+  regular = (mode_word == I_REGULAR);
 
   /* Determine blocksize */
-  if (block_spec) {
-       block_size = get_block_size( (dev_t) rip->i_block[0]);
-       f_size = MAX_FILE_POS;
-  } else {
-       block_size = rip->i_sp->s_block_size;
-       f_size = rip->i_size;
-       if (f_size < 0) f_size = MAX_FILE_POS;
-  }
-
-  rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
-  switch(fs_m_in.m_type) {
-       case REQ_READ: rw_flag = READING; break;
-       case REQ_WRITE: rw_flag = WRITING; break;
-       case REQ_PEEK: rw_flag = PEEKING; break;
-       default: panic("odd request");
-  }
-  gid = fs_m_in.m_vfs_fs_readwrite.grant;
-  position = fs_m_in.m_vfs_fs_readwrite.seek_pos;
-  nrbytes = fs_m_in.m_vfs_fs_readwrite.nbytes;
+  block_size = rip->i_sp->s_block_size;
+  f_size = rip->i_size;
+  if (f_size < 0) f_size = MAX_FILE_POS;
 
-  rdwt_err = OK;                /* set to EIO if disk error occurs */
+  lmfs_reset_rdwt_err();
 
-  if (rw_flag == WRITING && !block_spec) {
+  if (call == FSC_WRITE) {
        /* Check in advance to see if file will grow too big. */
        if (position > (off_t) (rip->i_sp->s_max_size - nrbytes))
                return(EFBIG);
@@ -85,9 +59,11 @@ int fs_readwrite(void)
   /* Split the transfer into chunks that don't span two blocks. */
   while (nrbytes != 0) {
        off = (unsigned int) (position % block_size);/* offset in blk*/
-       chunk = MIN(nrbytes, block_size - off);
+       chunk = block_size - off;
+       if (chunk > nrbytes)
+               chunk = nrbytes;
 
-       if (rw_flag == READING) {
+       if (call == FSC_READ) {
                bytes_left = f_size - position;
                if (position >= f_size) break;        /* we are beyond EOF */
                if (chunk > bytes_left) chunk = (int) bytes_left;
@@ -95,10 +71,10 @@ int fs_readwrite(void)
 
        /* Read or write 'chunk' bytes. */
        r = rw_chunk(rip, ((u64_t)((unsigned long)position)), off, chunk,
-                    nrbytes, rw_flag, gid, cum_io, block_size, &completed);
+               nrbytes, call, data, cum_io, block_size, &completed);
 
        if (r != OK) break;   /* EOF reached */
-       if (rdwt_err < 0) break;
+       if (lmfs_rdwt_err() < 0) break;
 
        /* Update counters and pointers. */
        nrbytes -= chunk;     /* bytes yet to be read */
@@ -106,115 +82,42 @@ int fs_readwrite(void)
        position += (off_t) chunk;    /* position within the file */
   }
 
-  fs_m_out.m_fs_vfs_readwrite.seek_pos = position; /* It might change later
-                                                     and the VFS has to know
-                                                     this value */
-
   /* On write, update file size and access time. */
-  if (rw_flag == WRITING) {
+  if (call == FSC_WRITE) {
        if (regular || mode_word == I_DIRECTORY) {
                if (position > f_size) rip->i_size = position;
         }
   }
 
-  /* Check to see if read-ahead is called for, and if so, set it up. */
-  if(rw_flag == READING && rip->i_seek == NO_SEEK &&
-     (unsigned int) position % block_size == 0 &&
-     (regular || mode_word == I_DIRECTORY)) {
-       rdahed_inode = rip;
-       rdahedpos = position;
-  }
-
   rip->i_seek = NO_SEEK;
 
-  if (rdwt_err != OK) r = rdwt_err;     /* check for disk error */
-  if (rdwt_err == END_OF_FILE) r = OK;
+  if (lmfs_rdwt_err() != OK) r = lmfs_rdwt_err(); /* check for disk error */
+  if (lmfs_rdwt_err() == END_OF_FILE) r = OK;
 
-  if (r == OK) {
-       if (rw_flag == READING) rip->i_update |= ATIME;
-       if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
-       rip->i_dirt = IN_DIRTY;          /* inode is thus now dirty */
-  }
+  if (r != OK)
+       return r;
 
-  fs_m_out.m_fs_vfs_readwrite.nbytes = cum_io;
+  if (call == FSC_READ) rip->i_update |= ATIME;
+  if (call == FSC_WRITE) rip->i_update |= CTIME | MTIME;
+  rip->i_dirt = IN_DIRTY;          /* inode is thus now dirty */
 
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             fs_breadwrite                                *
- *===========================================================================*/
-int fs_breadwrite(void)
-{
-  int r, rw_flag, completed;
-  cp_grant_id_t gid;
-  u64_t position;
-  unsigned int off, cum_io, chunk, block_size;
-  size_t nrbytes;
-
-  /* Pseudo inode for rw_chunk */
-  struct inode rip;
-
-  r = OK;
-
-  /* Get the values from the request message */
-  rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
-  gid = fs_m_in.m_vfs_fs_breadwrite.grant;
-  position = fs_m_in.m_vfs_fs_breadwrite.seek_pos;
-  nrbytes = fs_m_in.m_vfs_fs_breadwrite.nbytes;
-
-  block_size = get_block_size(fs_m_in.m_vfs_fs_breadwrite.device);
-
-  rip.i_block[0] = (block_t) fs_m_in.m_vfs_fs_breadwrite.device;
-  rip.i_mode = I_BLOCK_SPECIAL;
-  rip.i_size = 0;
-
-  rdwt_err = OK;                /* set to EIO if disk error occurs */
-
-  cum_io = 0;
-  /* Split the transfer into chunks that don't span two blocks. */
-  while (nrbytes > 0) {
-         off = (unsigned int)(position % block_size);  /* offset in blk*/
-         chunk = min(nrbytes, block_size - off);
-
-         /* Read or write 'chunk' bytes. */
-         r = rw_chunk(&rip, position, off, chunk, nrbytes, rw_flag, gid,
-                      cum_io, block_size, &completed);
-
-         if (r != OK) break;   /* EOF reached */
-         if (rdwt_err < 0) break;
-
-         /* Update counters and pointers. */
-         nrbytes -= chunk;     /* bytes yet to be read */
-         cum_io += chunk;      /* bytes read so far */
-         position += chunk;    /* position within the file */
-  }
-
-  fs_m_out.m_fs_vfs_breadwrite.seek_pos = position;
-
-  if (rdwt_err != OK) r = rdwt_err;     /* check for disk error */
-  if (rdwt_err == END_OF_FILE) r = OK;
-
-  fs_m_out.m_fs_vfs_breadwrite.nbytes = cum_io;
-
-  return(r);
+  return(cum_io);
 }
 
 
 /*===========================================================================*
  *                             rw_chunk                                     *
  *===========================================================================*/
-static int rw_chunk(rip, position, off, chunk, left, rw_flag, gid,
buf_off, block_size, completed)
+static int rw_chunk(rip, position, off, chunk, left, call, data, buf_off,
      block_size, completed)
 register struct inode *rip;     /* pointer to inode for file to be rd/wr */
 u64_t position;                 /* position within file to read or write */
 unsigned off;                   /* off within the current block */
-unsigned int chunk;             /* number of bytes to read or write */
+size_t chunk;                   /* number of bytes to read or write */
 unsigned left;                  /* max number of bytes wanted after position */
-int rw_flag;                    /* READING, WRITING or PEEKING */
-cp_grant_id_t gid;              /* grant */
-unsigned buf_off;               /* offset in grant */
+int call;                       /* FSC_READ, FSC_WRITE, or FSC_PEEK */
+struct fsdriver_data *data;     /* structure for (remote) user buffer */
+unsigned buf_off;               /* offset in user buffer */
 unsigned int block_size;        /* block size of FS operating on */
 int *completed;                 /* number of bytes copied */
 {
@@ -222,43 +125,29 @@ int *completed;                 /* number of bytes copied */
 
   register struct buf *bp = NULL;
   register int r = OK;
-  int n, block_spec;
+  int n;
   block_t b;
   dev_t dev;
   ino_t ino = VMC_NO_INODE;
   u64_t ino_off = rounddown(position, block_size);
 
-  /* rw_flag:
-   *   READING: read from FS, copy to user
-   *   WRITING: copy from user, write to FS
-   *   PEEKING: try to get all the blocks into the cache, no copying
-   */
-
   *completed = 0;
 
-  block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
-
-  if (block_spec) {
-       b = (unsigned long)(position / block_size);
-       dev = (dev_t) rip->i_block[0];
-  } else {
-       if (ex64hi(position) != 0)
-               panic("rw_chunk: position too high");
-       b = read_map(rip, (off_t) ex64lo(position), 0);
-       dev = rip->i_dev;
-       ino = rip->i_num;
-       assert(ino != VMC_NO_INODE);
-  }
+  if (ex64hi(position) != 0)
+       panic("rw_chunk: position too high");
+  b = read_map(rip, (off_t) ex64lo(position), 0);
+  dev = rip->i_dev;
+  ino = rip->i_num;
+  assert(ino != VMC_NO_INODE);
 
-  if (!block_spec && b == NO_BLOCK) {
-       if (rw_flag == READING) {
+  if (b == NO_BLOCK) {
+       if (call == FSC_READ) {
                /* Reading from a nonexistent block.  Must read as all zeros.*/
-               r = sys_safememset(VFS_PROC_NR, gid, (vir_bytes) buf_off,
-                          0, (size_t) chunk);
-               if(r != OK) {
-                       printf("ext2fs: sys_safememset failed\n");
-               }
-               return r;
+               r = fsdriver_zero(data, buf_off, chunk);
+               if(r != OK) {
+                       printf("ext2fs: fsdriver_zero failed\n");
+               }
+               return r;
        } else {
                /* Writing to or peeking a nonexistent block.
                 * Create and enter in inode.
@@ -266,7 +155,7 @@ int *completed;                 /* number of bytes copied */
                if ((bp = new_block(rip, (off_t) ex64lo(position))) == NULL)
                        return(err_code);
         }
-  } else if (rw_flag == READING || rw_flag == PEEKING) {
+  } else if (call != FSC_WRITE) {
        /* Read and read ahead if convenient. */
        bp = rahead(rip, b, position, left);
   } else {
@@ -275,35 +164,28 @@ int *completed;                 /* number of bytes copied */
         * the cache, acquire it, otherwise just acquire a free buffer.
          */
        n = (chunk == block_size ? NO_READ : NORMAL);
-       if (!block_spec && off == 0 && (off_t) ex64lo(position) >= rip->i_size)
+       if (off == 0 && (off_t) ex64lo(position) >= rip->i_size)
                n = NO_READ;
-       if(block_spec) {
-               assert(ino == VMC_NO_INODE);
-               bp = get_block(dev, b, n);
-       } else {
-               assert(ino != VMC_NO_INODE);
-               assert(!(ino_off % block_size));
-               bp = lmfs_get_block_ino(dev, b, n, ino, ino_off);
-       }
+       assert(ino != VMC_NO_INODE);
+       assert(!(ino_off % block_size));
+       bp = lmfs_get_block_ino(dev, b, n, ino, ino_off);
   }
 
   /* In all cases, bp now points to a valid buffer. */
   if (bp == NULL)
        panic("bp not valid in rw_chunk, this can't happen");
 
-  if (rw_flag == WRITING && chunk != block_size && !block_spec &&
+  if (call == FSC_WRITE && chunk != block_size &&
       (off_t) ex64lo(position) >= rip->i_size && off == 0) {
        zero_block(bp);
   }
 
-  if (rw_flag == READING) {
+  if (call == FSC_READ) {
        /* Copy a chunk from the block buffer to user space. */
-       r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) buf_off,
-                          (vir_bytes) (b_data(bp)+off), (size_t) chunk);
-  } else if(rw_flag == WRITING) {
+       r = fsdriver_copyout(data, buf_off, b_data(bp)+off, chunk);
+  } else if (call == FSC_WRITE) {
        /* Copy a chunk from user space to the block buffer. */
-       r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) buf_off,
-                            (vir_bytes) (b_data(bp)+off), (size_t) chunk);
+       r = fsdriver_copyin(data, buf_off, b_data(bp)+off, chunk);
        lmfs_markdirty(bp);
   }
 
@@ -432,32 +314,6 @@ int mindex;                      /* index into *bp */
 }
 
 
-/*===========================================================================*
- *                             read_ahead                                   *
- *===========================================================================*/
-void read_ahead()
-{
-/* Read a block into the cache before it is needed. */
-  unsigned int block_size;
-  register struct inode *rip;
-  struct buf *bp;
-  block_t b;
-
-  if(!rdahed_inode)
-       return;
-
-  rip = rdahed_inode;           /* pointer to inode to read ahead from */
-  block_size = get_block_size(rip->i_dev);
-  rdahed_inode = NULL;     /* turn off read ahead */
-  if ( (b = read_map(rip, rdahedpos, 1)) == NO_BLOCK) return;      /* at EOF */
-
-  assert(rdahedpos >= 0); /* So we can safely cast it to unsigned below */
-
-  bp = rahead(rip, b, ((u64_t)((unsigned long)rdahedpos)), block_size);
-  put_block(bp, PARTIAL_DATA_BLOCK);
-}
-
-
 /*===========================================================================*
  *                             rahead                                       *
  *===========================================================================*/
@@ -477,7 +333,7 @@ unsigned bytes_ahead;           /* bytes beyond position for immediate use */
 /* Minimum number of blocks to prefetch. */
 # define BLOCKS_MINIMUM                (nr_bufs < 50 ? 18 : 32)
   int nr_bufs = lmfs_nr_bufs();
-  int block_spec, read_q_size;
+  int read_q_size;
   unsigned int blocks_ahead, fragment, block_size;
   block_t block, blocks_left;
   off_t ind1_pos;
@@ -503,12 +359,7 @@ unsigned bytes_ahead;           /* bytes beyond position for immediate use */
        readqsize = nr_bufs;
   }
 
-  block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
-  if (block_spec)
-       dev = (dev_t) rip->i_block[0];
-  else
-       dev = rip->i_dev;
-
+  dev = rip->i_dev;
   assert(dev != NO_DEV);
   block_size = get_block_size(dev);
 
@@ -520,12 +371,7 @@ unsigned bytes_ahead;           /* bytes beyond position for immediate use */
   bytes_ahead += fragment;
   blocks_ahead = (bytes_ahead + block_size - 1) / block_size;
 
-  if(block_spec)
-         bp = get_block(dev, block, PREFETCH);
-  else
-         bp = lmfs_get_block_ino(dev, block, PREFETCH, rip->i_num, position);
-
-
+  bp = lmfs_get_block_ino(dev, block, PREFETCH, rip->i_num, position);
   assert(bp != NULL);
   if (lmfs_dev(bp) != NO_DEV) return(bp);
 
@@ -549,20 +395,14 @@ unsigned bytes_ahead;           /* bytes beyond position for immediate use */
    * indirect blocks (but don't call read_map!).
    */
 
-  if (block_spec && rip->i_size == 0) {
-       blocks_left = (block_t) NR_IOREQS;
-  } else {
-       blocks_left = (block_t) (rip->i_size-ex64lo(position)+(block_size-1)) /
+  blocks_left = (block_t) (rip->i_size-ex64lo(position)+(block_size-1)) /
                                                                 block_size;
 
-       /* Go for the first indirect block if we are in its neighborhood. */
-       if (!block_spec) {
-               ind1_pos = (EXT2_NDIR_BLOCKS) * block_size;
-               if ((off_t) ex64lo(position) <= ind1_pos && rip->i_size > ind1_pos) {
-                       blocks_ahead++;
-                       blocks_left++;
-               }
-       }
+  /* Go for the first indirect block if we are in its neighborhood. */
+  ind1_pos = (EXT2_NDIR_BLOCKS) * block_size;
+  if ((off_t) ex64lo(position) <= ind1_pos && rip->i_size > ind1_pos) {
+       blocks_ahead++;
+       blocks_left++;
   }
 
   /* No more than the maximum request. */
@@ -590,9 +430,10 @@ unsigned bytes_ahead;           /* bytes beyond position for immediate use */
        block++;
        position_running += block_size;
 
-       if(!block_spec && 
-         (thisblock = read_map(rip, (off_t) ex64lo(position_running), 1)) != NO_BLOCK) {
-               bp = lmfs_get_block_ino(dev, thisblock, PREFETCH, rip->i_num, position_running);
+       thisblock = read_map(rip, (off_t) ex64lo(position_running), 1);
+       if (thisblock != NO_BLOCK) {
+               bp = lmfs_get_block_ino(dev, thisblock, PREFETCH, rip->i_num,
+                       position_running);
        } else {
                bp = get_block(dev, block, PREFETCH);
        }
@@ -604,41 +445,55 @@ unsigned bytes_ahead;           /* bytes beyond position for immediate use */
   }
   lmfs_rw_scattered(dev, read_q, read_q_size, READING);
 
-  if(block_spec)
-         return get_block(dev, baseblock, NORMAL);
   return(lmfs_get_block_ino(dev, baseblock, NORMAL, rip->i_num, position));
 }
 
 
+/*===========================================================================*
+ *                             get_dtype                                    *
+ *===========================================================================*/
+static unsigned int get_dtype(struct ext2_disk_dir_desc *dp)
+{
+/* Return the type of the file identified by the given directory entry. */
+
+  if (!HAS_INCOMPAT_FEATURE(superblock, INCOMPAT_FILETYPE))
+       return DT_UNKNOWN;
+
+  switch (dp->d_file_type) {
+  case EXT2_FT_REG_FILE:       return DT_REG;
+  case EXT2_FT_DIR:            return DT_DIR;
+  case EXT2_FT_SYMLINK:                return DT_LNK;
+  case EXT2_FT_BLKDEV:         return DT_BLK;
+  case EXT2_FT_CHRDEV:         return DT_CHR;
+  case EXT2_FT_FIFO:           return DT_FIFO;
+  default:                     return DT_UNKNOWN;
+  }
+}
+
 /*===========================================================================*
  *                             fs_getdents                                  *
  *===========================================================================*/
-int fs_getdents(void)
+ssize_t fs_getdents(ino_t ino_nr, struct fsdriver_data *data, size_t bytes,
+       off_t *posp)
 {
 #define GETDENTS_BUFSIZE (sizeof(struct dirent) + EXT2_NAME_MAX + 1)
 #define GETDENTS_ENTRIES       8
   static char getdents_buf[GETDENTS_BUFSIZE * GETDENTS_ENTRIES];
+  struct fsdriver_dentry fsdentry;
   struct inode *rip;
   int r, done;
-  unsigned int block_size, len, reclen;
-  ino_t ino;
-  cp_grant_id_t gid;
-  size_t size, tmpbuf_off, userbuf_off;
+  unsigned int block_size, len;
   off_t pos, off, block_pos, new_pos, ent_pos;
   struct buf *bp;
   struct ext2_disk_dir_desc *d_desc;
-  struct dirent *dep;
-
-  ino = fs_m_in.m_vfs_fs_getdents.inode;
-  gid = fs_m_in.m_vfs_fs_getdents.grant;
-  size = fs_m_in.m_vfs_fs_getdents.mem_size;
-  pos = fs_m_in.m_vfs_fs_getdents.seek_pos;
+  ino_t child_nr;
 
   /* Check whether the position is properly aligned */
+  pos = *posp;
   if ((unsigned int) pos % DIR_ENTRY_ALIGN)
        return(ENOENT);
 
-  if ((rip = get_inode(fs_dev, ino)) == NULL)
+  if ((rip = get_inode(fs_dev, ino_nr)) == NULL)
        return(EINVAL);
 
   block_size = rip->i_sp->s_block_size;
@@ -646,14 +501,15 @@ int fs_getdents(void)
   block_pos = pos - off;
   done = FALSE;       /* Stop processing directory blocks when done is set */
 
-  memset(getdents_buf, '\0', sizeof(getdents_buf));  /* Avoid leaking any data */
-  tmpbuf_off = 0;       /* Offset in getdents_buf */
-  userbuf_off = 0;      /* Offset in the user's buffer */
+  fsdriver_dentry_init(&fsdentry, data, bytes, getdents_buf,
+       sizeof(getdents_buf));
 
   /* The default position for the next request is EOF. If the user's buffer
    * fills up before EOF, new_pos will be modified. */
   new_pos = rip->i_size;
 
+  r = 0;
+
   for (; block_pos < rip->i_size; block_pos += block_size) {
        off_t temp_pos = block_pos;
         /* Since directories don't have holes, 'bp' cannot be NULL. */
@@ -678,30 +534,19 @@ int fs_getdents(void)
                if (d_desc->d_ino == 0)
                        continue; /* Entry is not in use */
 
-#if 0
-               /* read.c:682: error: comparison is always false due to
-                * limited range of data type
-                */
-               if (d_desc->d_name_len > NAME_MAX ||
-                   d_desc->d_name_len > EXT2_NAME_MAX) {
-                       len = min(NAME_MAX, EXT2_NAME_MAX);
-               } else
-#endif
-               {
-                       len = d_desc->d_name_len;
-               }
-
+               len = d_desc->d_name_len;
                assert(len <= NAME_MAX);
                assert(len <= EXT2_NAME_MAX);
 
-               /* Compute record length, incl alignment. */
-                reclen = _DIRENT_RECLEN(dep, len);
-
                /* Need the position of this entry in the directory */
                ent_pos = block_pos + ((char *)d_desc - b_data(bp));
 
-               if (userbuf_off + tmpbuf_off + reclen >= size) {
-                       /* The user has no space for one more record */
+               child_nr = (ino_t) conv4(le_CPU, d_desc->d_ino);
+               r = fsdriver_dentry_add(&fsdentry, child_nr, d_desc->d_name,
+                       len, get_dtype(d_desc));
+
+               /* If the user buffer is full, or an error occurred, stop. */
+               if (r <= 0) {
                        done = TRUE;
 
                        /* Record the position of this entry, it is the
@@ -711,34 +556,6 @@ int fs_getdents(void)
                        new_pos = ent_pos;
                        break;
                }
-
-               if (tmpbuf_off + reclen >= GETDENTS_BUFSIZE*GETDENTS_ENTRIES) {
-                       r = sys_safecopyto(VFS_PROC_NR, gid,
-                                          (vir_bytes) userbuf_off,
-                                          (vir_bytes) getdents_buf,
-                                          (size_t) tmpbuf_off);
-                       if (r != OK) {
-                               put_inode(rip);
-                               return(r);
-                       }
-                       userbuf_off += tmpbuf_off;
-                       tmpbuf_off = 0;
-               }
-
-               dep = (struct dirent *) &getdents_buf[tmpbuf_off];
-               dep->d_fileno = (ino_t) conv4(le_CPU, d_desc->d_ino);
-               dep->d_reclen = (unsigned short) reclen;
-               dep->d_namlen = len;
-               memcpy(dep->d_name, d_desc->d_name, len);
-               dep->d_name[len] = '\0';
-               {
-                       struct inode *entrip;
-                       if(!(entrip = get_inode(fs_dev, dep->d_fileno)))
-                               panic("unexpected get_inode failure");
-                       dep->d_type = fs_mode_to_type(entrip->i_mode);
-                       put_inode(entrip);
-               }
-               tmpbuf_off += reclen;
        }
 
        put_block(bp, DIRECTORY_BLOCK);
@@ -746,25 +563,10 @@ int fs_getdents(void)
                break;
   }
 
-  if (tmpbuf_off != 0) {
-       r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) userbuf_off,
-                          (vir_bytes) getdents_buf, (size_t) tmpbuf_off);
-       if (r != OK) {
-               put_inode(rip);
-               return(r);
-       }
-
-       userbuf_off += tmpbuf_off;
-  }
-
-  if (done && userbuf_off == 0)
-       r = EINVAL;           /* The user's buffer is too small */
-  else {
-       fs_m_out.m_fs_vfs_getdents.nbytes = userbuf_off;
-       fs_m_out.m_fs_vfs_getdents.seek_pos = new_pos;
+  if (r >= 0 && (r = fsdriver_dentry_finish(&fsdentry)) >= 0) {
+       *posp = new_pos;
        rip->i_update |= ATIME;
        rip->i_dirt = IN_DIRTY;
-       r = OK;
   }
 
   put_inode(rip);               /* release the inode */
index df491a573f305c400db49cf6bd3ddf578995511c..720b7389e7aa3be55c8b07e10e3b3dbbe4689e43 100644 (file)
@@ -8,23 +8,19 @@
 #include <sys/statvfs.h>
 #include "inode.h"
 #include "super.h"
-#include <minix/vfsif.h>
 
 
 /*===========================================================================*
- *                             stat_inode                                   *
+ *                             fs_stat                                      *
  *===========================================================================*/
-static int stat_inode(
-  register struct inode *rip,  /* pointer to inode to stat */
-  endpoint_t who_e,            /* Caller endpoint */
-  cp_grant_id_t gid            /* grant for the stat buf */
-)
+int fs_stat(ino_t ino_nr, struct stat *statbuf)
 {
-/* Common code for stat and fstat system calls. */
-
-  struct stat statbuf;
+  struct inode *rip;
   mode_t mo;
-  int r, s;
+  int s;
+
+  if ((rip = get_inode(fs_dev, ino_nr)) == NULL)
+       return(EINVAL);
 
   /* Update the atime, ctime, and mtime fields in the inode, if need be. */
   if (rip->i_update) update_times(rip);
@@ -35,81 +31,52 @@ static int stat_inode(
   /* true iff special */
   s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);
 
-  memset(&statbuf, 0, sizeof(struct stat));
-
-  statbuf.st_dev = rip->i_dev;
-  statbuf.st_ino = rip->i_num;
-  statbuf.st_mode = rip->i_mode;
-  statbuf.st_nlink = rip->i_links_count;
-  statbuf.st_uid = rip->i_uid;
-  statbuf.st_gid = rip->i_gid;
-  statbuf.st_rdev = (s ? (dev_t)rip->i_block[0] : NO_DEV);
-  statbuf.st_size = rip->i_size;
-  statbuf.st_atime = rip->i_atime;
-  statbuf.st_mtime = rip->i_mtime;
-  statbuf.st_ctime = rip->i_ctime;
-  statbuf.st_blksize = rip->i_sp->s_block_size;
-  statbuf.st_blocks = rip->i_blocks;
-
-  /* Copy the struct to user space. */
-  r = sys_safecopyto(who_e, gid, (vir_bytes) 0, (vir_bytes) &statbuf,
-                    (size_t) sizeof(statbuf));
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             fs_stat                                      *
- *===========================================================================*/
-int fs_stat()
-{
-  register int r;              /* return value */
-  register struct inode *rip;  /* target inode */
-
-  if ((rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_stat.inode)) == NULL)
-       return(EINVAL);
+  statbuf->st_dev = rip->i_dev;
+  statbuf->st_ino = rip->i_num;
+  statbuf->st_mode = rip->i_mode;
+  statbuf->st_nlink = rip->i_links_count;
+  statbuf->st_uid = rip->i_uid;
+  statbuf->st_gid = rip->i_gid;
+  statbuf->st_rdev = (s ? (dev_t)rip->i_block[0] : NO_DEV);
+  statbuf->st_size = rip->i_size;
+  statbuf->st_atime = rip->i_atime;
+  statbuf->st_mtime = rip->i_mtime;
+  statbuf->st_ctime = rip->i_ctime;
+  statbuf->st_blksize = rip->i_sp->s_block_size;
+  statbuf->st_blocks = rip->i_blocks;
 
-  r = stat_inode(rip, fs_m_in.m_source, fs_m_in.m_vfs_fs_stat.grant);
   put_inode(rip);              /* release the inode */
-  return(r);
+
+  return(OK);
 }
 
 /*===========================================================================*
  *                             fs_statvfs                                    *
  *===========================================================================*/
-int fs_statvfs()
+int fs_statvfs(struct statvfs *st)
 {
-  struct statvfs st;
   struct super_block *sp;
-  int r;
-
-  memset(&st, 0, sizeof(st));
 
   sp = get_super(fs_dev);
 
-  st.f_flag = ST_NOTRUNC;
-  st.f_bsize =  sp->s_block_size;
-  st.f_frsize = sp->s_block_size;
-  st.f_iosize = sp->s_block_size;
-  st.f_blocks = sp->s_blocks_count;
-  st.f_bfree = sp->s_free_blocks_count;
-  st.f_bavail = sp->s_free_blocks_count - sp->s_r_blocks_count;
-  st.f_files = sp->s_inodes_count;
-  st.f_ffree = sp->s_free_inodes_count;
-  st.f_favail = sp->s_free_inodes_count;
-  st.f_namemax = NAME_MAX;
-
-  /* Copy the struct to user space. */
-  r = sys_safecopyto(fs_m_in.m_source, fs_m_in.m_vfs_fs_statvfs.grant, 0,
-                       (vir_bytes) &st, (phys_bytes) sizeof(st));
-
-  return(r);
+  st->f_flag = ST_NOTRUNC;
+  st->f_bsize =  sp->s_block_size;
+  st->f_frsize = sp->s_block_size;
+  st->f_iosize = sp->s_block_size;
+  st->f_blocks = sp->s_blocks_count;
+  st->f_bfree = sp->s_free_blocks_count;
+  st->f_bavail = sp->s_free_blocks_count - sp->s_r_blocks_count;
+  st->f_files = sp->s_inodes_count;
+  st->f_ffree = sp->s_free_inodes_count;
+  st->f_favail = sp->s_free_inodes_count;
+  st->f_namemax = EXT2_NAME_MAX;
+
+  return(OK);
 }
 
 /*===========================================================================*
  *                              blockstats                                   *
 *===========================================================================*/
+ *===========================================================================*/
 void fs_blockstats(u64_t *blocks, u64_t *free, u64_t *used)
 {
         struct super_block *sp = get_super(fs_dev);
index 09192a4e072f174e6e95784da153ced74350cd03..998f6b4e5dd2c8c25f71c18604312abbb0318efb 100644 (file)
@@ -100,7 +100,6 @@ EXTERN struct super_block {
     int     s_rd_only;          /* set to 1 if file sys mounted read only */
     block_t s_bsearch; /* all data blocks  below this block are in use*/
     int     s_igsearch; /* all groups below this one have no free inodes */
-    char    s_is_root;
     u32_t   s_dirs_counter;
 
 } *superblock, *ondisk_superblock;
index 7f35284276a8ba6b28b45178d2a7c64ea5790752..684d89c1329e869e424c3224a1cf2bdfaf6bae26 100644 (file)
@@ -1,4 +1,4 @@
-/* This file contains the table used to map system call numbers onto the
+/* This file contains the table used to map file system calls onto the
  * routines that perform them.
  *
  * Created (MFS based):
 #include "buf.h"
 #include "super.h"
 
-int (*fs_call_vec[])(void) = {
-    no_sys,             /* 0   not used */
-    no_sys,             /* 1   */       /* Was: fs_getnode */
-    fs_putnode,         /* 2   */
-    fs_slink,           /* 3   */
-    fs_ftrunc,          /* 4   */
-    fs_chown,           /* 5   */
-    fs_chmod,           /* 6   */
-    fs_inhibread,       /* 7   */
-    fs_stat,            /* 8   */
-    fs_utime,           /* 9   */
-    fs_statvfs,                /* 10  */
-    fs_breadwrite,      /* 11  */
-    fs_breadwrite,      /* 12  */
-    fs_unlink,          /* 13  */
-    fs_unlink,          /* 14  */
-    fs_unmount,         /* 15  */
-    fs_sync,            /* 16  */
-    fs_new_driver,      /* 17  */
-    fs_flush,           /* 18  */
-    fs_readwrite,       /* 19  */
-    fs_readwrite,       /* 20  */
-    fs_mknod,           /* 21  */
-    fs_mkdir,           /* 22  */
-    fs_create,          /* 23  */
-    fs_link,            /* 24  */
-    fs_rename,          /* 25  */
-    fs_lookup,          /* 26  */
-    fs_mountpoint,      /* 27  */
-    fs_readsuper,       /* 28  */
-    no_sys,            /* 29  */       /* Was: fs_newnode */
-    fs_rdlink,          /* 30  */
-    fs_getdents,        /* 31  */
-    fs_readwrite,       /* 32  */
-    fs_bpeek,           /* 33  */
+struct fsdriver ext2_table = {
+       .fdr_mount      = fs_mount,
+       .fdr_unmount    = fs_unmount,
+       .fdr_lookup     = fs_lookup,
+       .fdr_putnode    = fs_putnode,
+       .fdr_read       = fs_readwrite,
+       .fdr_write      = fs_readwrite,
+       .fdr_peek       = fs_readwrite,
+       .fdr_getdents   = fs_getdents,
+       .fdr_trunc      = fs_trunc,
+       .fdr_seek       = fs_seek,
+       .fdr_create     = fs_create,
+       .fdr_mkdir      = fs_mkdir,
+       .fdr_mknod      = fs_mknod,
+       .fdr_link       = fs_link,
+       .fdr_unlink     = fs_unlink,
+       .fdr_rmdir      = fs_unlink,
+       .fdr_rename     = fs_rename,
+       .fdr_slink      = fs_slink,
+       .fdr_rdlink     = fs_rdlink,
+       .fdr_stat       = fs_stat,
+       .fdr_chown      = fs_chown,
+       .fdr_chmod      = fs_chmod,
+       .fdr_utime      = fs_utime,
+       .fdr_mountpt    = fs_mountpt,
+       .fdr_statvfs    = fs_statvfs,
+       .fdr_sync       = fs_sync,
+       .fdr_driver     = lmfs_driver,
+       .fdr_bread      = lmfs_bio,
+       .fdr_bwrite     = lmfs_bio,
+       .fdr_bpeek      = lmfs_bio,
+       .fdr_bflush     = lmfs_bflush
 };
index 647bedfb02461ced628448670c611d1d9a500672..fa98f8e9af688f3ff550922f803fa3702dc6c988 100644 (file)
@@ -3,75 +3,50 @@
  */
 
 #include "fs.h"
-#include <minix/callnr.h>
-#include <minix/com.h>
 #include "inode.h"
+#include <sys/time.h>
 #include <sys/stat.h>
-#include <minix/vfsif.h>
 
 
 /*===========================================================================*
  *                             fs_utime                                     *
  *===========================================================================*/
-int fs_utime()
+int fs_utime(ino_t ino_nr, struct timespec *atime, struct timespec *mtime)
 {
   register struct inode *rip;
-  register int r;
 
   /* Temporarily open the file. */
-  if( (rip = get_inode(fs_dev, fs_m_in.m_vfs_fs_utime.inode)) == NULL)
+  if( (rip = get_inode(fs_dev, ino_nr)) == NULL)
         return(EINVAL);
 
-  /*
-   * Only the owner of a file or the super_user can change the timestamps.
-   * Here we assume VFS did that check before.
-   */
-
-  r = OK;
-  if(read_only(rip) != OK) r = EROFS;  /* not even su can touch if R/O */
-  if(r == OK) {
-       rip->i_update = CTIME;  /* discard any stale ATIME and MTIME flags */
-       switch(fs_m_in.m_vfs_fs_utime.acnsec) {
-       case UTIME_NOW:
-               rip->i_update |= ATIME;
-               break;
-       case UTIME_OMIT: /* do not touch */
-               break;
-       default:
-               /*
-                * cases fs_m_in.m_vfs_fs_utime.acnsec < 0 || fs_m_in.m_vfs_fs_utime.acnsec >= 1E9
-                * are caught by VFS to cooperate with old instances of EXT2
-                */
-               rip->i_atime = fs_m_in.m_vfs_fs_utime.actime;
-               /*
-                * Ext2FS does not support better than second resolution,
-                * so we discard ACNSEC to round down
-                */
-               break;
-       }
-
-       switch(fs_m_in.m_vfs_fs_utime.modnsec) {
-       case UTIME_NOW:
-               rip->i_update |= MTIME;
-               break;
-       case UTIME_OMIT: /* do not touch */
-               break;
-       default:
-               /*
-                * cases fs_m_in.m_vfs_fs_utime.modnsec < 0 || fs_m_in.m_vfs_fs_utime.modnsec >= 1E9
-                * are caught by VFS to cooperate with old instances of EXT2
-                */
-               rip->i_mtime = fs_m_in.m_vfs_fs_utime.modtime;
-               /*
-                * Ext2FS does not support better than second resolution,
-                * so we discard MODNSEC to round down
-                */
-               break;
-       }
+  rip->i_update = CTIME;       /* discard any stale ATIME and MTIME flags */
+
+  switch (atime->tv_nsec) {
+  case UTIME_NOW:
+       rip->i_update |= ATIME;
+       break;
+  case UTIME_OMIT: /* do not touch */
+       break;
+  default:
+       /* Ext2FS does not support subsecond resolution, so we round down. */
+       rip->i_atime = atime->tv_sec;
+       break;
+  }
 
-       rip->i_dirt = IN_DIRTY;
+  switch (mtime->tv_nsec) {
+  case UTIME_NOW:
+       rip->i_update |= MTIME;
+       break;
+  case UTIME_OMIT: /* do not touch */
+       break;
+  default:
+       /* Ext2FS does not support subsecond resolution, so we round down. */
+       rip->i_mtime = mtime->tv_sec;
+       break;
   }
 
+  rip->i_dirt = IN_DIRTY;
+
   put_inode(rip);
-  return(r);
+  return(OK);
 }
index db1ba15807530ca18da0e739bfcdb58a73a21b71..f2c37e72ce17051cea048e255930054fd61c91c4 100644 (file)
@@ -8,17 +8,6 @@
 #include "super.h"
 
 
-/*===========================================================================*
- *                             no_sys                                       *
- *===========================================================================*/
-int no_sys()
-{
-/* Somebody has used an illegal system call number */
-  printf("no_sys: invalid call %d\n", req_nr);
-  return(EINVAL);
-}
-
-
 /*===========================================================================*
  *                             conv2                                        *
  *===========================================================================*/
@@ -51,33 +40,6 @@ long x;                              /* 32-bit long to be byte swapped */
 }
 
 
-/*===========================================================================*
- *                             mfs_min                                      *
- *===========================================================================*/
-int min(unsigned int l, unsigned int r)
-{
-  if(r >= l) return(l);
-
-  return(r);
-}
-
-
-/*===========================================================================*
- *                             mfs_nul                                      *
- *===========================================================================*/
-void mfs_nul_f(const char *file, int line, const char *str, unsigned int len,
-                     unsigned int maxlen)
-{
-  if(len < maxlen && str[len-1] != '\0') {
-       printf("ext2 %s:%d string (length %d, maxlen %d) not null-terminated\n",
-               file, line, len, maxlen);
-  }
-}
-
-#define MYASSERT(c) if(!(c)) { printf("ext2:%s:%d: sanity check: %s failed\n", \
-  file, line, #c); panic("sanity check " #c " failed: %d", __LINE__); }
-
-
 /*===========================================================================*
  *                             ansi_strcmp                                  *
  *===========================================================================*/