]> Zhao Yanbai Git Server - minix.git/commitdiff
Merge of VFS by Balasz Gerofi with Minix trunk.
authorBen Gras <ben@minix3.org>
Wed, 25 Oct 2006 13:40:36 +0000 (13:40 +0000)
committerBen Gras <ben@minix3.org>
Wed, 25 Oct 2006 13:40:36 +0000 (13:40 +0000)
116 files changed:
commands/bzip2-1.0.3/Makefile
commands/de/de.c
commands/de/de_diskio.c
commands/de/de_recover.c
commands/de/de_stdin.c
commands/de/de_stdout.c
commands/ps/Makefile
commands/ps/ps.c
commands/scripts/packman.sh
commands/simple/Makefile
commands/simple/badblocks.c
commands/simple/cdprobe.c
commands/simple/df.c
commands/simple/fsck.c
commands/simple/fsck1.c
commands/simple/mkfs.c
commands/simple/mkswap.c
commands/simple/mount.c
commands/simple/readfs.c
drivers/at_wini/at_wini.c
drivers/memory/ramdisk/Makefile
drivers/memory/ramdisk/proto
drivers/memory/ramdisk/proto.sh
include/minix/com.h
include/minix/ipc.h
include/minix/vfsif.h [new file with mode: 0644]
kernel/table.c
lib/ansi/system.c
lib/other/fslib.c
lib/other/fsversion.c
lib/posix/_mount.c
servers/Makefile
servers/fs/cache2.c [deleted file]
servers/fs/mount.c [deleted file]
servers/fs/open.c [deleted file]
servers/fs/stadir.c [deleted file]
servers/is/dmp_fs.c
servers/mfs/Makefile [new file with mode: 0644]
servers/mfs/buf.h [moved from servers/fs/buf.h with 100% similarity]
servers/mfs/cache.c [moved from servers/fs/cache.c with 84% similarity]
servers/mfs/const.h [new file with mode: 0644]
servers/mfs/device.c [new file with mode: 0644]
servers/mfs/drivers.h [new file with mode: 0644]
servers/mfs/file.h [moved from servers/fs/file.h with 100% similarity]
servers/mfs/fproc.h [moved from servers/fs/fproc.h with 100% similarity]
servers/mfs/fs.h [moved from servers/fs/fs.h with 100% similarity]
servers/mfs/glo.h [new file with mode: 0644]
servers/mfs/inc.h [new file with mode: 0644]
servers/mfs/inode.c [moved from servers/fs/inode.c with 69% similarity]
servers/mfs/inode.h [new file with mode: 0644]
servers/mfs/link.c [moved from servers/fs/link.c with 74% similarity]
servers/mfs/lock.h [moved from servers/fs/lock.h with 100% similarity]
servers/mfs/main.c [new file with mode: 0644]
servers/mfs/misc.c [new file with mode: 0644]
servers/mfs/mount.c [new file with mode: 0644]
servers/mfs/open.c [new file with mode: 0644]
servers/mfs/param.h [moved from servers/fs/param.h with 100% similarity]
servers/mfs/path.c [moved from servers/fs/path.c with 63% similarity]
servers/mfs/pipe.c [new file with mode: 0644]
servers/mfs/protect.c [moved from servers/fs/protect.c with 53% similarity]
servers/mfs/proto.h [moved from servers/fs/proto.h with 63% similarity]
servers/mfs/queue.h [new file with mode: 0644]
servers/mfs/read.c [moved from servers/fs/read.c with 68% similarity]
servers/mfs/select.h [moved from servers/fs/select.h with 100% similarity]
servers/mfs/stadir.c [new file with mode: 0644]
servers/mfs/super.c [moved from servers/fs/super.c with 94% similarity]
servers/mfs/super.h [new file with mode: 0644]
servers/mfs/table.c [new file with mode: 0644]
servers/mfs/time.c [new file with mode: 0644]
servers/mfs/type.h [moved from servers/fs/type.h with 100% similarity]
servers/mfs/utility.c [new file with mode: 0644]
servers/mfs/write.c [moved from servers/fs/write.c with 96% similarity]
servers/rs/main.c
servers/rs/manager.c
servers/vfs/Makefile [moved from servers/fs/Makefile with 76% similarity]
servers/vfs/buf.h [new file with mode: 0644]
servers/vfs/const.h [moved from servers/fs/const.h with 97% similarity]
servers/vfs/device.c [moved from servers/fs/device.c with 82% similarity]
servers/vfs/dmap.c [moved from servers/fs/dmap.c with 100% similarity]
servers/vfs/exec.c [moved from servers/fs/exec.c with 58% similarity]
servers/vfs/file.h [new file with mode: 0644]
servers/vfs/filedes.c [moved from servers/fs/filedes.c with 88% similarity]
servers/vfs/fproc.h [new file with mode: 0644]
servers/vfs/fs.h [new file with mode: 0644]
servers/vfs/glo.h [moved from servers/fs/glo.h with 75% similarity]
servers/vfs/inode.h [moved from servers/fs/inode.h with 100% similarity]
servers/vfs/link.c [new file with mode: 0644]
servers/vfs/lock.c [moved from servers/fs/lock.c with 95% similarity]
servers/vfs/lock.h [new file with mode: 0644]
servers/vfs/main.c [moved from servers/fs/main.c with 73% similarity]
servers/vfs/misc.c [moved from servers/fs/misc.c with 64% similarity]
servers/vfs/mount.c [new file with mode: 0644]
servers/vfs/open.c [new file with mode: 0644]
servers/vfs/param.h [new file with mode: 0644]
servers/vfs/path.c [new file with mode: 0644]
servers/vfs/pipe.c [moved from servers/fs/pipe.c with 82% similarity]
servers/vfs/protect.c [new file with mode: 0644]
servers/vfs/proto.h [new file with mode: 0644]
servers/vfs/read.c [new file with mode: 0644]
servers/vfs/request.c [new file with mode: 0644]
servers/vfs/request.h [new file with mode: 0644]
servers/vfs/select.c [moved from servers/fs/select.c with 92% similarity]
servers/vfs/select.h [new file with mode: 0644]
servers/vfs/stadir.c [new file with mode: 0644]
servers/vfs/super.h [moved from servers/fs/super.h with 100% similarity]
servers/vfs/table.c [moved from servers/fs/table.c with 96% similarity]
servers/vfs/time.c [moved from servers/fs/time.c with 52% similarity]
servers/vfs/timers.c [moved from servers/fs/timers.c with 100% similarity]
servers/vfs/type.h [new file with mode: 0644]
servers/vfs/utility.c [moved from servers/fs/utility.c with 66% similarity]
servers/vfs/vmnt.c [new file with mode: 0644]
servers/vfs/vmnt.h [new file with mode: 0644]
servers/vfs/vnode.c [new file with mode: 0644]
servers/vfs/vnode.h [new file with mode: 0644]
servers/vfs/write.c [new file with mode: 0644]
tools/Makefile

index a9790f29366b438aaeb0b90492353c01e087496b..54a54ef9a72eb4fbd0dcdf72a293392cd116115b 100644 (file)
@@ -12,7 +12,7 @@ BIGFILES=#-D_FILE_OFFSET_BITS=64
 CFLAGS=-Wall -Winline -O -g $(BIGFILES) -Dlstat=stat -D_POSIX_SOURCE=1
 
 # Where you want it installed when you do 'make install'
-PREFIX=/usr/local
+PREFIX=/usr
 PREFIX_BIN=$(PREFIX)/bin
 PREFIX_LIB=$(PREFIX)/lib
 PREFIX_MAN=$(PREFIX)/man
index f5b5a1ecfe2d4f54a1a4a9dd4c8ca9d156300d80..a8d93e379a370a60c65b006c9774a7220a89a1d8 100755 (executable)
@@ -27,9 +27,9 @@
 
 #include <minix/const.h>
 #include <minix/type.h>
-#include "../../servers/fs/const.h"
-#include "../../servers/fs/type.h"
-#include "../../servers/fs/inode.h"
+#include "../../servers/mfs/const.h"
+#include "../../servers/mfs/type.h"
+#include "../../servers/mfs/inode.h"
 
 #include "de.h"
 
index e4162782d91ce58dad94b1d702ad50aa6553dcd5..e14383bd9378a646e09995b86cb19944c4634851 100755 (executable)
 
 #include <minix/const.h>
 #include <minix/type.h>
-#include "../../servers/fs/const.h"
-#include "../../servers/fs/type.h"
-#include "../../servers/fs/super.h"
-#include "../../servers/fs/inode.h"
+#include "../../servers/mfs/const.h"
+#include "../../servers/mfs/type.h"
+#include "../../servers/mfs/super.h"
+#include "../../servers/mfs/inode.h"
 #include <minix/fslib.h>
 
 #include "de.h"
index add90cfc8d6da05109c16b5b9b5d77fcb1e7bc70..a26b4cc88cd6c3c18a5c92585f5de8b10ba9e9d8 100755 (executable)
@@ -23,9 +23,9 @@
 
 #include <minix/const.h>
 #include <minix/type.h>
-#include "../../servers/fs/const.h"
-#include "../../servers/fs/type.h"
-#include "../../servers/fs/inode.h"
+#include "../../servers/mfs/const.h"
+#include "../../servers/mfs/type.h"
+#include "../../servers/mfs/inode.h"
 #include <minix/fslib.h>
 
 #include "de.h"
index 2bd2531eb81a2e382d99a627ddf9460ac01f9ff2..5f440d8d6edf315f921476aee50f7514bf80ed01 100755 (executable)
@@ -17,8 +17,8 @@
 
 #include <minix/config.h>
 #include <minix/const.h>
-#include "../../servers/fs/const.h"
-#include "../../servers/fs/inode.h"
+#include "../../servers/mfs/const.h"
+#include "../../servers/mfs/inode.h"
 
 #include "de.h"
 
index c95a1c2bc8d87ad0ae06cf0e51a4fc03f2e8b1fe..e3f86fd04250009874c77c0b743b98d461649d83 100755 (executable)
@@ -25,9 +25,9 @@
 
 #include <minix/const.h>
 #include <minix/type.h>
-#include "../../servers/fs/const.h"
-#include "../../servers/fs/type.h"
-#include "../../servers/fs/inode.h"
+#include "../../servers/mfs/const.h"
+#include "../../servers/mfs/type.h"
+#include "../../servers/mfs/inode.h"
 #include <minix/fslib.h>
 
 #include "de.h"
index a20f0b025cdecca2dce20f17540cf1d22f147fcf..77b29ce75d5a61097c54219c16f5dc8c72c61acc 100644 (file)
@@ -11,7 +11,7 @@ all: ps
 ps:    ps.c /usr/include/minix/config.h /usr/include/minix/const.h \
                ../../kernel/const.h ../../kernel/type.h \
                ../../kernel/proc.h ../../servers/pm/mproc.h \
-               ../../servers/fs/fproc.h ../../servers/fs/const.h
+               ../../servers/vfs/fproc.h ../../servers/mfs/const.h
        $(CC) -i $(CFLAGS) -o $@ ps.c
        install -S 32kw $@
 install:       /usr/bin/ps
index 11641025ff288aac19d9ee342646c9ea3f599d05..ce73d79d87ddeccea5ec0b80bb98c50bc50ebf9f 100644 (file)
@@ -81,8 +81,8 @@
 #include "../../kernel/proc.h"
 
 #include "../../servers/pm/mproc.h"
-#include "../../servers/fs/fproc.h"
-#include "../../servers/fs/const.h"
+#include "../../servers/vfs/fproc.h"
+#include "../../servers/mfs/const.h"
 
 
 /*----- ps's local stuff below this line ------*/
index 8254552eae837436d5406881ad68bf73213eff9c..d97eab591674a7cfb6f2b5dd45fbb7c1a3a97510 100644 (file)
@@ -13,6 +13,7 @@ TMPDIR=/usr/tmp/packages
 mkdir -p $TMPDIR
 URL1=http://www.minix3.org/packages/$PACKDIR
 SRCURL1=http://www.minix3.org/software
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
 
 # can we execute bunzip2?
 if bunzip2 --help 2>&1 | grep usage >/dev/null
index 3b53b37f3f855db2baf545469aaec0872c4a09ed..a3a25a32c487df238102ece2617d013a6c9d0fd9 100755 (executable)
@@ -355,7 +355,7 @@ dhrystone:  dhrystone.c
 
 diff:  diff.c
        $(CCLD) -o $@ $?
-       @install -S 40kw $@
+       @install -S 512kw $@
 
 dirname:       dirname.c
        $(CCLD) -o $@ $?
index f1cc4c4f7c1f3fd5b2fa4717a00882982a54ccd0..36682c3779ccefb4f87685edcad40ff0446e3563 100755 (executable)
 #include <dirent.h>
 #include <stdlib.h>
 
-#include "../../servers/fs/const.h"    /* must be included before stdio.h */
+#include "../../servers/mfs/const.h"   /* must be included before stdio.h */
 #undef printf                  /* so its define of printf can be undone */
-#include "../../servers/fs/type.h"
+#include "../../servers/mfs/type.h"
 
 #include <string.h>
 #include <stdio.h>
 
 #define EXTERN extern
-#include "../../servers/fs/super.h"
+#include "../../servers/mfs/super.h"
 
 _PROTOTYPE(int main, (int argc, char **argv));
 _PROTOTYPE(void rw_super, (int flag));
index 26e3f22e4b8f8f11fe93da64265548258d6d8601..3512dcc68f7cf7dac23822334651077dd24e2723 100644 (file)
@@ -22,7 +22,7 @@
 #include <string.h>
 #include <unistd.h>
 
-#include "../../servers/fs/const.h"
+#include "../../servers/vfs/const.h"
 
 char pvd[CD_SECTOR];
 
index f1d69e0318d4594eb6195c6726deb8f85b61e382..ec921936f2b4bb37142fa22f8b04ac63233eb5db 100755 (executable)
@@ -30,9 +30,9 @@
 #include <minix/config.h>
 #include <minix/const.h>
 #include <minix/type.h>
-#include <servers/fs/const.h>
-#include <servers/fs/type.h>
-#include <servers/fs/super.h>
+#include <servers/mfs/const.h>
+#include <servers/mfs/type.h>
+#include <servers/mfs/super.h>
 #undef printf
 
 #if !__minix_vmd
index f7e9a1c599ca64ce9b5028fa143c621476f685bc..c23bbc21e8813ea308b5eb5bd02e1d9c237ed271 100755 (executable)
@@ -47,9 +47,9 @@
 #include <minix/config.h>
 #include <minix/const.h>
 #include <minix/type.h>
-#include "../../servers/fs/const.h"
-#include "../../servers/fs/inode.h"
-#include "../../servers/fs/type.h"
+#include "../../servers/mfs/const.h"
+#include "../../servers/mfs/inode.h"
+#include "../../servers/mfs/type.h"
 #include <minix/fslib.h>
 #include <stdio.h>
 #include <sys/stat.h>
@@ -87,7 +87,7 @@ unsigned int fs_version = 2, block_size = 0;
 #define ZONE_CT        360     /* default zones  (when making file system) */
 #define INODE_CT        95     /* default inodes (when making file system) */
 
-#include "../../servers/fs/super.h"
+#include "../../servers/mfs/super.h"
 static struct super_block sb;
 
 #define STICKY_BIT     01000   /* not defined anywhere else */
index 92dd6a13ef9f5fc9f7633fcf6155f12ed55da169..b36dbb8c5bf3d655487beb90cd70806c5bdaf070 100755 (executable)
@@ -49,9 +49,9 @@
 #include <minix/config.h>
 #include <minix/const.h>
 #include <minix/type.h>
-#include "../../servers/fs/const.h"
-#include "../../servers/fs/inode.h"
-#include "../../servers/fs/type.h"
+#include "../../servers/mfs/const.h"
+#include "../../servers/mfs/inode.h"
+#include "../../servers/mfs/type.h"
 #include <minix/fslib.h>
 #include <stdio.h>
 #include <dirent.h>
@@ -71,7 +71,7 @@
 #define ZONE_CT        360     /* default zones  (when making file system) */
 #define INODE_CT        95     /* default inodes (when making file system) */
 
-#include "../../servers/fs/super.h"
+#include "../../servers/mfs/super.h"
 struct super_block sb;
 
 #define STICKY_BIT     01000   /* not defined anywhere else */
index 3f0d4d30713507df26e55bc584bae333af45e5fd..de78824890e5d033a8bbe2920dd980a7bb7286da 100755 (executable)
@@ -23,7 +23,7 @@
 #include <minix/const.h>
 #include <minix/type.h>
 #include <minix/minlib.h>
-#include "../../servers/fs/const.h"
+#include "../../servers/mfs/const.h"
 #if (MACHINE == IBM_PC)
 #include <minix/partition.h>
 #include <minix/u64.h>
@@ -35,8 +35,8 @@
 
 #undef EXTERN
 #define EXTERN                 /* get rid of EXTERN by making it null */
-#include "../../servers/fs/type.h"
-#include "../../servers/fs/super.h"
+#include "../../servers/mfs/type.h"
+#include "../../servers/mfs/super.h"
 #include <minix/fslib.h>
 
 #ifndef max
index 5211661f32c62311456afec698ce5af1b9ad1d85..aaf66e579ffacb15cf04a4dad62ba64df33d053d 100755 (executable)
@@ -19,9 +19,9 @@
 #include <minix/u64.h>
 #include <minix/partition.h>
 #include <minix/swap.h>
-#include <servers/fs/const.h>
-#include <servers/fs/type.h>
-#include <servers/fs/super.h>
+#include <servers/mfs/const.h>
+#include <servers/mfs/type.h>
+#include <servers/mfs/super.h>
 
 static void usage(void)
 {
index cc7119854a49fe3ce289f6279aef5ae2b6050e91..603fcedd106148db92daf311abac35163ecf5d26 100755 (executable)
@@ -14,7 +14,7 @@
 #include <minix/swap.h>
 #include <sys/svrctl.h>
 #include <stdio.h>
-#include "../../servers/fs/const.h"
+#include "../../servers/vfs/const.h"
 
 _PROTOTYPE(int main, (int argc, char **argv));
 _PROTOTYPE(void list, (void));
index 0d2667a4639dac33259cbb3ca50b96265dac4842..77f4d8cd7052b28adfcaae86550647c4a1263d64 100755 (executable)
 #include <minix/config.h>
 #include <minix/const.h>
 #include <minix/type.h>
-#include "../../servers/fs/const.h"
-#include "../../servers/fs/type.h"
-#include "../../servers/fs/buf.h"
-#include "../../servers/fs/super.h"
+#include "../../servers/mfs/const.h"
+#include "../../servers/mfs/type.h"
+#include "../../servers/mfs/buf.h"
+#include "../../servers/mfs/super.h"
 
 #undef printf                  /* Definition used only in the kernel */
 #include <stdio.h>
index 8e79483bd95210f3f6e0cc16a849d396dfea6b19..846580207df066240cb78269763d70f459ed5353 100644 (file)
@@ -1923,7 +1923,7 @@ PRIVATE void w_intr_wait()
        /* Wait for an interrupt that sets w_status to "not busy". */
        while (w_wn->w_status & (STATUS_ADMBSY|STATUS_BSY)) {
                int rr;
-               if((rr=receive(ANY, &m)) != OK) { /* expect HARD_INT message */
+               if((rr=receive(HARDWARE, &m)) != OK) { /* expect HARD_INT message */
                        printf("w_intr_wait: receive from ANY failed (%d)\n",
                                r);
                        continue;       /* try again */
index a45db86b16d2131af82e9fd896cc753359a45c70..dce479feaee7f1141b4a782ad41846d0341551dc 100644 (file)
@@ -1,7 +1,7 @@
 # Makefile for ramdisk image
 
 PROGRAMS=at_wini bios_wini cdprobe dev2name floppy loadramdisk newroot \
-       pci sh service sysenv
+       pci sh service sysenv mfs
 
 MAKEDEV=/usr/bin/MAKEDEV
 
@@ -90,6 +90,12 @@ service: ../../../servers/rs/service
 ../../../servers/rs/service: 
        cd ../../../servers/rs && make service
 
+mfs: ../../../servers/mfs/mfs
+       install -s ../../../servers/mfs/$@ $@
+
+../../../servers/mfs/mfs: 
+       cd ../../../servers/mfs && make
+
 depend: 
        /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
 
index 38b861269ebeb84991a9e84489b07fb39c6e17a1..38987d9bb105e95049338520cb78144cecc291b5 100644 (file)
@@ -1,5 +1,5 @@
 boot 
-200 250
+210 250
 d--755 0 0
        bin d--755 0 0
                at_wini ---755 0 0 at_wini
@@ -13,6 +13,7 @@ d--755 0 0
                sh ---755 0 0 sh
                service ---755 0 0 service
                sysenv ---755 0 0 sysenv
+               mfs ---755 0 0 mfs
        $
        dev d--755 0 0
 @DEV@
index 00d593902843324ccd73d34fabadb1a041a5b4b6..cab7fc8417d18202dbae32693cbb9bef64d2eb3c 100644 (file)
@@ -1,4 +1,5 @@
 #!/bin/sh
+PATH=/bin:/sbin:/usr/bin:/usr/sbin
 sed -n '1,/@DEV/p' <proto  | grep -v @DEV@
 (
 cd /dev
index b143cf1d0bdbb708edcd7fa26c0f8e1e3d730636..32f4305c500cb74158aeb1ad8b96391a01932827 100755 (executable)
@@ -41,7 +41,8 @@
 #define LOG_PROC_NR      4     /* log device driver */
 #define TTY_PROC_NR      5     /* terminal (TTY) driver */
 #define DS_PROC_NR       6     /* data store server */
-#define INIT_PROC_NR     7     /* init -- goes multiuser */
+#define MFS_PROC_NR       7     /* minix root filesystem */
+#define INIT_PROC_NR     8     /* init -- goes multiuser */
 
 /* Number of processes contained in the system image. */
 #define NR_BOOT_PROCS  (NR_TASKS + INIT_PROC_NR + 1)
 #  define RS_PERIOD            m1_i2           /* heartbeat period */
 #  define RS_DEV_MAJOR          m1_i3           /* major device number */
 
+#  define RS_ENDPOINT          m1_i1           /* endpoint number in reply */
+
 /*===========================================================================*
  *                Messages for the Data Store Server                        *
  *===========================================================================*/
index 4d7c0a5682cc3599d7b9fbea17484cf195a850bc..1cf3a6751ba0b60d32fd5ea0fcd8fc1bb79f012e 100644 (file)
 #define M3_STRING         14
 
 typedef struct {int m1i1, m1i2, m1i3; char *m1p1, *m1p2, *m1p3;} mess_1;
-typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1;} mess_2;
+typedef struct {int m2i1, m2i2, m2i3; long m2l1, m2l2; char *m2p1; 
+        short m2s1;} mess_2;
 typedef struct {int m3i1, m3i2; char *m3p1; char m3ca1[M3_STRING];} mess_3;
 typedef struct {long m4l1, m4l2, m4l3, m4l4, m4l5;} mess_4;
 typedef struct {short m5c1, m5c2; int m5i1, m5i2; long m5l1, m5l2, m5l3;}mess_5;
+typedef struct {long m6l1, m6l2, m6l3; short m6s1, m6s2, m6s3; char m6c1, m6c2;
+        char *m6p1, *m6p2;} mess_6;
 typedef struct {int m7i1, m7i2, m7i3, m7i4; char *m7p1, *m7p2;} mess_7;
 typedef struct {int m8i1, m8i2; char *m8p1, *m8p2, *m8p3, *m8p4;} mess_8;
 
@@ -29,6 +32,7 @@ typedef struct {
        mess_5 m_m5;
        mess_7 m_m7;
        mess_8 m_m8;
+       mess_6 m_m6;
   } m_u;
 } message;
 
@@ -47,6 +51,8 @@ typedef struct {
 #define m2_l2  m_u.m_m2.m2l2
 #define m2_p1  m_u.m_m2.m2p1
 
+#define m2_s1  m_u.m_m2.m2s1
+
 #define m3_i1  m_u.m_m3.m3i1
 #define m3_i2  m_u.m_m3.m3i2
 #define m3_p1  m_u.m_m3.m3p1
@@ -66,6 +72,17 @@ typedef struct {
 #define m5_l2  m_u.m_m5.m5l2
 #define m5_l3  m_u.m_m5.m5l3
 
+#define m6_l1  m_u.m_m6.m6l1
+#define m6_l2  m_u.m_m6.m6l2
+#define m6_l3  m_u.m_m6.m6l3
+#define m6_s1  m_u.m_m6.m6s1
+#define m6_s2  m_u.m_m6.m6s2
+#define m6_s3  m_u.m_m6.m6s3
+#define m6_c1  m_u.m_m6.m6c1
+#define m6_c2  m_u.m_m6.m6c2
+#define m6_p1  m_u.m_m6.m6p1
+#define m6_p2  m_u.m_m6.m6p2
+
 #define m7_i1  m_u.m_m7.m7i1
 #define m7_i2  m_u.m_m7.m7i2
 #define m7_i3  m_u.m_m7.m7i3
@@ -94,7 +111,7 @@ typedef struct {
 _PROTOTYPE( int echo, (message *m_ptr)                                 );
 _PROTOTYPE( int notify, (endpoint_t dest)                              );
 _PROTOTYPE( int sendrec, (endpoint_t src_dest, message *m_ptr)         );
-_PROTOTYPE( int receive, (endpoint_t src, message *m_ptr)              );
+_PROTOTYPE( int receive, (endpoint_t src, message *m_ptr)              );
 _PROTOTYPE( int send, (endpoint_t dest, message *m_ptr)                        );
 
 #define ipc_request    _ipc_request
diff --git a/include/minix/vfsif.h b/include/minix/vfsif.h
new file mode 100644 (file)
index 0000000..c20e206
--- /dev/null
@@ -0,0 +1,146 @@
+
+/* Fields of VFS/FS request messages */
+#define REQ_INODE_NR             m6_l1
+#define REQ_CHROOT_NR            m6_l2
+#define REQ_UID                  m6_s1
+#define REQ_GID                  m6_c1
+#define REQ_MODE                 m6_s3
+#define REQ_PATH                 m6_p1
+#define REQ_PATH_LEN             m6_s2
+#define REQ_FLAGS                m6_l3
+#define REQ_DEV                  m6_l3
+#define REQ_WHO_E                m6_l3
+#define REQ_USER_ADDR            m6_p2
+#define REQ_LENGTH               m6_l3
+#define REQ_SYMLOOP              m6_c2
+
+#define REQ_NEW_UID              m6_s3
+#define REQ_NEW_GID              m6_c2
+
+#define REQ_INODE_INDEX          m6_l3
+
+#define REQ_ACTIME               m6_l2
+#define REQ_MODTIME              m6_l3
+
+#define REQ_VMNT_IND             m6_c2
+#define REQ_SLINK_STORAGE        m6_p1
+#define REQ_BOOTTIME             m6_l1
+#define REQ_DRIVER_E             m6_l2
+#define REQ_READONLY             m6_c1
+#define REQ_ISROOT              m6_c2
+
+#define REQ_REMOUNT              m6_c2
+
+#define REQ_LINKED_FILE          m6_l1
+#define REQ_LINK_PARENT          m6_l2
+
+#define REQ_OLD_DIR              m6_l2
+#define REQ_NEW_DIR              m6_l3
+#define REQ_SLENGTH              m6_s3
+
+#define REQ_PIPE_POS             m6_l1
+
+#define REQ_FD_INODE_NR          m2_i1
+#define REQ_FD_WHO_E             m2_i2
+#define REQ_FD_POS               m2_i3
+#define REQ_FD_NBYTES            m2_l1
+#define REQ_FD_SEG               m2_l2
+#define REQ_FD_INODE_INDEX       m2_s1
+
+#define REQ_FD_USER_ADDR         m2_p1
+#define REQ_FD_LENGTH            m2_i2
+#define REQ_FD_START             m2_i2
+#define REQ_FD_END               m2_i3
+
+#define REQ_FD_BLOCK_SIZE        m2_s1
+#define REQ_FD_BDRIVER_E         m2_i1
+#define REQ_FD_BDEV              m2_l2
+
+/* Fields of VFS/FS respons messages */
+#define RES_MOUNTED              m6_s1
+#define RES_OFFSET               m6_s2
+#define RES_INODE_NR             m6_l1
+#define RES_MODE                 m6_s1
+#define RES_FILE_SIZE            m6_l2
+#define RES_DEV                  m6_l3
+#define RES_POS                  m6_l3
+#define RES_INODE_INDEX          m6_s2
+#define RES_NLINKS               m6_s3
+#define RES_SYMLOOP              m6_c1
+
+#define RES_UID                  m6_s3
+#define RES_GID                  m6_c1
+#define RES_CTIME                m6_l3
+
+#define RES_FD_POS               m2_i1
+#define RES_FD_CUM_IO            m2_i2
+#define RES_FD_SIZE              m2_i3
+
+#define RES_DIR                  m6_l1
+#define RES_FILE                 m6_l2
+
+#define RES_MAXSIZE              m6_l3
+#define RES_BLOCKSIZE            m6_s2
+
+
+/* Request numbers (offset in the fs callvector) */
+#define REQ_GETNODE              1
+#define REQ_PUTNODE              2
+#define REQ_OPEN                 3
+#define REQ_PIPE                 4
+#define REQ_READ                 5
+#define REQ_WRITE                6
+#define REQ_CLONE_OPCL           7
+#define REQ_FTRUNC               8
+
+#define REQ_CHOWN                9
+#define REQ_CHMOD                10
+#define REQ_ACCESS               11
+#define REQ_MKNOD                12
+#define REQ_MKDIR                13
+#define REQ_INHIBREAD            14
+#define REQ_STAT                 15
+#define REQ_FSTAT                16
+#define REQ_UNLINK               17
+#define REQ_RMDIR                18
+#define REQ_UTIME                19
+#define REQ_FSTATFS              20
+#define REQ_LSTAT                21      /* NO POINT !!! */
+#define REQ_GETDIR               22
+
+#define REQ_LINK                 25
+
+#define REQ_SLINK                26
+#define REQ_RDLINK               27
+
+#define REQ_RENAME               28
+
+#define REQ_MOUNTPOINT           30
+#define REQ_READSUPER            31
+#define REQ_UNMOUNT              32
+#define REQ_TRUNC                33
+#define REQ_SYNC                 34
+
+#define REQ_LOOKUP               35
+#define REQ_STIME               36
+#define REQ_NEW_DRIVER           37
+
+#define REQ_BREAD                38
+#define REQ_BWRITE               39
+
+#define NREQS                    40
+
+#define FS_READY                 57
+
+#define EENTERMOUNT              301 
+#define ELEAVEMOUNT              302
+#define ESYMLINK                 303
+
+
+
+
+
+
+
+
+
index 1ed9dfcae130179e797d7a61f6839e8ce5f02cb1..3af05c4e18a0329402517152f1b7bc4512dd2a74 100755 (executable)
@@ -115,12 +115,13 @@ PUBLIC struct boot_image image[] = {
 {SYSTEM, sys_task,TSK_F,  8, TASK_Q, TSK_S, TSK_T,     0, no_c,"system"},
 {HARDWARE,      0,TSK_F,  8, TASK_Q, HRD_S,     0,     0, no_c,"kernel"},
 {PM_PROC_NR,    0,SRV_F, 32,      3, 0,     SRV_T, SRV_M, c(pm_c),"pm"    },
-{FS_PROC_NR,    0,SRV_F, 32,      4, 0,     SRV_T, SRV_M, c(fs_c),"fs"    },
+{FS_PROC_NR,    0,SRV_F, 32,      4, 0,     SRV_T, SRV_M, c(fs_c),"vfs"   },
 {RS_PROC_NR,    0,SRV_F,  4,      3, 0,     SRV_T, SYS_M, c(rs_c),"rs"    },
 {DS_PROC_NR,    0,SRV_F,  4,      3, 0,     SRV_T, SYS_M, c(ds_c),"ds"    },
 {TTY_PROC_NR,   0,SRV_F,  4,      1, 0,     SRV_T, SYS_M,c(tty_c),"tty"   },
 {MEM_PROC_NR,   0,SRV_F,  4,      2, 0,     SRV_T, SYS_M,c(mem_c),"memory"},
 {LOG_PROC_NR,   0,SRV_F,  4,      2, 0,     SRV_T, SYS_M,c(drv_c),"log"   },
+{MFS_PROC_NR,   0,SRV_F, 32,      4, 0,     SRV_T, SRV_M, c(fs_c),"mfs"   },
 {INIT_PROC_NR,  0,USR_F,  8, USER_Q, 0,     USR_T, USR_M, no_c,"init"  },
 };
 
index 8c9bd52849b4de6e3c614211bbb1bb5d907dc5b0..100e0cde4d3f1942d0d6d26009d7e0c3cb1fff27 100755 (executable)
@@ -9,6 +9,7 @@
 #endif
 #include       <stdlib.h>
 #include       <signal.h>
+#include       <limits.h>
 
 extern pid_t _fork(void);
 extern pid_t _wait(int *);
@@ -35,7 +36,7 @@ system(const char *str)
        if ((pid = _fork()) < 0) return str ? -1 : 0;
 
        if (pid == 0) {
-               for (i = 3; i <= 20; i++)
+               for (i = 3; i <= OPEN_MAX; i++)
                        _close(i);
                if (!str) str = "cd .";         /* just testing for a shell */
                exec_tab[2] = str;              /* fill in command */
index 2b11a55b01f910dbf6c0eec84ce93ba446ca6c9c..a24c886ce8c50ef9db7f8ae1eccbfcea1cbacd73 100755 (executable)
@@ -7,10 +7,10 @@
 #include <sys/types.h>
 #include <minix/const.h>
 #include <minix/type.h>                /* for unshort :-( */
-#include "fs/const.h"          /* depends of -I flag in Makefile */
-#include "fs/type.h"           /* ditto */
-#include "fs/inode.h"          /* ditto */
-#include "fs/super.h"
+#include "mfs/const.h"         /* depends of -I flag in Makefile */
+#include "mfs/type.h"          /* ditto */
+#include "mfs/inode.h"         /* ditto */
+#include "mfs/super.h"
 #include <minix/fslib.h>
 
 /* The next routine is copied from fsck.c and mkfs.c...  (Re)define some
index 6e74d0d4e09e0fa4c6f99888fa331ef72991e7be..3a0faa59f447611d3308e992e352d015f213d5e9 100755 (executable)
@@ -17,9 +17,9 @@
 #include <unistd.h>
 #include <stdio.h>
 
-#include "fs/const.h"
-#include "fs/type.h"
-#include "fs/super.h"
+#include "mfs/const.h"
+#include "mfs/type.h"
+#include "mfs/super.h"
 
 static struct super_block super, *sp;
 
index c32542ae9179eb90ac78eee5919df44c8e3a1f81..7130d450de47177c296d40585852ec03c924377b 100755 (executable)
@@ -1,14 +1,51 @@
+
 #include <lib.h>
 #define mount  _mount
 #include <string.h>
 #include <unistd.h>
+#include <stdio.h>
+#include <sys/stat.h>
+#include <minix/syslib.h>
+
+#define OK     0
 
 PUBLIC int mount(special, name, rwflag)
 char *name, *special;
 int rwflag;
 {
+  struct stat stat_buf;
   message m;
-
+  
+  m.RS_CMD_ADDR = "/sbin/mfs";
+  if (stat(m.RS_CMD_ADDR, &stat_buf) == -1) {
+         printf("MOUNT: /sbin/mfs doesn't exist\n");
+         m.RS_CMD_ADDR = 0;
+  }
+  
+  if (!m.RS_CMD_ADDR) {
+         m.RS_CMD_ADDR = "/bin/mfs";
+         if (stat(m.RS_CMD_ADDR, &stat_buf) == -1) {
+                 printf("MOUNT: /bin/mfs doesn't exist\n");
+                 m.RS_CMD_ADDR = 0;
+         }
+  } 
+  
+  if (m.RS_CMD_ADDR) { 
+         if (!(stat_buf.st_mode & S_IFREG)) {
+                 printf("MOUNT: FS binary is not a regular file\n");
+         }
+         m.RS_CMD_LEN = strlen(m.RS_CMD_ADDR);
+         m.RS_DEV_MAJOR = 0;
+         m.RS_PERIOD = 0;
+         if (OK != _taskcall(RS_PROC_NR, RS_UP, &m)) {
+                 printf("MOUNT: error sending request to RS\n");
+         } 
+         else {
+                 /* copy endpointnumber */
+                 m.m1_p3 = (char*)(unsigned long)m.RS_ENDPOINT;   
+         }
+  }
+  
   m.m1_i1 = strlen(special) + 1;
   m.m1_i2 = strlen(name) + 1;
   m.m1_i3 = rwflag;
index 938e7585449c38a5c10da76a630d843864651ea7..a534e56868292391243047e8d33f09fa7dbc1d1e 100644 (file)
@@ -16,7 +16,8 @@ usage:
 build: all
 all install depend clean:
        cd ./pm && $(MAKE) $@
-       cd ./fs && $(MAKE) $@
+       cd ./vfs && $(MAKE) $@
+       cd ./mfs && $(MAKE) $@
        cd ./rs && $(MAKE) $@
        cd ./ds && $(MAKE) $@
        cd ./is && $(MAKE) $@
@@ -25,7 +26,8 @@ all install depend clean:
 
 image:
        cd ./pm && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
-       cd ./fs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
+       cd ./vfs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
+       cd ./mfs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
        cd ./rs && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
        cd ./ds && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
        cd ./init && $(MAKE) EXTRA_OPTS=$(EXTRA_OPTS) build
diff --git a/servers/fs/cache2.c b/servers/fs/cache2.c
deleted file mode 100644 (file)
index 6ef2e31..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-/* Second level block cache to supplement the file system cache.  The block
- * cache of a 16-bit Minix system is very small, too small to prevent trashing.
- * A generic 32-bit system also doesn't have a very large cache to allow it
- * to run on systems with little memory.  On a system with lots of memory one
- * can use the RAM disk as a read-only second level cache.  Any blocks pushed
- * out of the primary cache are cached on the RAM disk.  This code manages the
- * second level cache.  The cache is a simple FIFO where old blocks are put
- * into and drop out at the other end.  Must be searched backwards.
- *
- * The entry points into this file are:
- *   init_cache2: initialize the second level cache
- *   get_block2:  get a block from the 2nd level cache
- *   put_block2:  store a block in the 2nd level cache
- *   invalidate2: remove all the cache blocks on some device
- */
-
-#include "fs.h"
-#include <minix/com.h>
-#include "buf.h"
-
-#if ENABLE_CACHE2
-
-#define MAX_BUF2       (256 * sizeof(char *))
-
-PRIVATE struct buf2 {  /* 2nd level cache per block administration */
-  block_t b2_blocknr;          /* block number */
-  dev_t b2_dev;                        /* device number */
-  u16_t b2_count;              /* count of in-cache block groups */
-} buf2[MAX_BUF2];
-
-PRIVATE unsigned nr_buf2;              /* actual cache size */
-PRIVATE unsigned buf2_idx;             /* round-robin reuse index */
-
-#define hash2(block)   ((unsigned) ((block) & (MAX_BUF2 - 1)))
-
-/*===========================================================================*
- *                             init_cache2                                  *
- *===========================================================================*/
-PUBLIC void init_cache2(size)
-unsigned long size;
-{
-/* Initialize the second level disk buffer cache of 'size' blocks. */
-
-  nr_buf2 = size > MAX_BUF2 ? MAX_BUF2 : (unsigned) size;
-}
-
-/*===========================================================================*
- *                             get_block2                                   *
- *===========================================================================*/
-PUBLIC int get_block2(bp, only_search)
-struct buf *bp;                        /* buffer to get from the 2nd level cache */
-int only_search;               /* if NO_READ, do nothing, else act normal */
-{
-/* Fill a buffer from the 2nd level cache.  Return true iff block acquired. */
-  unsigned b;
-  struct buf2 *bp2;
-
-  /* If the block wanted is in the RAM disk then our game is over. */
-  if (bp->b_dev == DEV_RAM) nr_buf2 = 0;
-
-  /* Cache enabled?  NO_READ?  Any blocks with the same hash key? */
-  if (nr_buf2 == 0 || only_search == NO_READ
-                       || buf2[hash2(bp->b_blocknr)].b2_count == 0) return(0);
-
-  /* Search backwards (there may be older versions). */
-  b = buf2_idx;
-  for (;;) {
-       if (b == 0) b = nr_buf2;
-       bp2 = &buf2[--b];
-       if (bp2->b2_blocknr == bp->b_blocknr && bp2->b2_dev == bp->b_dev) break;
-       if (b == buf2_idx) return(0);
-  }
-
-  /* Block is in the cache, get it. */
-  if (dev_io(DEV_READ, DEV_RAM, FS_PROC_NR, bp->b_data,
-                       (off_t) b * BLOCK_SIZE, BLOCK_SIZE, 0) == BLOCK_SIZE) {
-       return(1);
-  }
-  return(0);
-}
-
-/*===========================================================================*
- *                             put_block2                                   *
- *===========================================================================*/
-PUBLIC void put_block2(bp)
-struct buf *bp;                        /* buffer to store in the 2nd level cache */
-{
-/* Store a buffer into the 2nd level cache. */
-  unsigned b;
-  struct buf2 *bp2;
-
-  if (nr_buf2 == 0) return;    /* no 2nd level cache */
-
-  b = buf2_idx++;
-  if (buf2_idx == nr_buf2) buf2_idx = 0;
-
-  bp2 = &buf2[b];
-
-  if (dev_io(DEV_WRITE, DEV_RAM, FS_PROC_NR, bp->b_data,
-                       (off_t) b * BLOCK_SIZE, BLOCK_SIZE, 0) == BLOCK_SIZE) {
-       if (bp2->b2_dev != NO_DEV) buf2[hash2(bp2->b2_blocknr)].b2_count--;
-       bp2->b2_dev = bp->b_dev;
-       bp2->b2_blocknr = bp->b_blocknr;
-       buf2[hash2(bp2->b2_blocknr)].b2_count++;
-  }
-}
-
-/*===========================================================================*
- *                             invalidate2                                  *
- *===========================================================================*/
-PUBLIC void invalidate2(device)
-dev_t device;
-{
-/* Invalidate all blocks from a given device in the 2nd level cache. */
-  unsigned b;
-  struct buf2 *bp2;
-
-  for (b = 0; b < nr_buf2; b++) {
-       bp2 = &buf2[b];
-       if (bp2->b2_dev == device) {
-               bp2->b2_dev = NO_DEV;
-               buf2[hash2(bp2->b2_blocknr)].b2_count--;
-       }
-  }
-}
-#endif /* ENABLE_CACHE2 */
diff --git a/servers/fs/mount.c b/servers/fs/mount.c
deleted file mode 100644 (file)
index d6a8d71..0000000
+++ /dev/null
@@ -1,353 +0,0 @@
-/* This file performs the MOUNT and UMOUNT system calls.
- *
- * The entry points into this file are
- *   do_mount: perform the MOUNT system call
- *   do_umount:        perform the UMOUNT system call
- */
-
-#include "fs.h"
-#include <fcntl.h>
-#include <string.h>
-#include <minix/com.h>
-#include <sys/stat.h>
-#include "buf.h"
-#include "file.h"
-#include "fproc.h"
-#include "inode.h"
-#include "param.h"
-#include "super.h"
-
-/* Allow the root to be replaced before the first 'real' mount. */
-PRIVATE int allow_newroot= 1;
-
-FORWARD _PROTOTYPE( dev_t name_to_dev, (char *path)                    );
-
-/*===========================================================================*
- *                             do_mount                                     *
- *===========================================================================*/
-PUBLIC int do_mount()
-{
-/* Perform the mount(name, mfile, rd_only) system call. */
-
-  register struct inode *rip, *root_ip;
-  struct super_block *xp, *sp;
-  dev_t dev;
-  mode_t bits;
-  int rdir, mdir;              /* TRUE iff {root|mount} file is dir */
-  int i, r, found;
-  struct fproc *tfp;
-
-  /* Only the super-user may do MOUNT. */
-  if (!super_user) return(EPERM);
-
-  /* If 'name' is not for a block special file, return error. */
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
-
-  /* Scan super block table to see if dev already mounted & find a free slot.*/
-  sp = NIL_SUPER;
-  found = FALSE;
-  for (xp = &super_block[0]; xp < &super_block[NR_SUPERS]; xp++) {
-       if (xp->s_dev == dev)
-       {
-               /* is it mounted already? */
-               found = TRUE;
-               sp= xp;
-               break;
-       }
-       if (xp->s_dev == NO_DEV) sp = xp;       /* record free slot */
-  }
-  if (found)
-  {
-       printf(
-"do_mount: s_imount = 0x%x (%x, %d), s_isup = 0x%x (%x, %d), fp_rootdir = 0x%x\n",
-               xp->s_imount, xp->s_imount->i_dev, xp->s_imount->i_num,
-               xp->s_isup, xp->s_isup->i_dev, xp->s_isup->i_num,
-               fproc[FS_PROC_NR].fp_rootdir);
-       /* It is possible that we have an old root lying around that 
-        * needs to be remounted.
-        */
-       if (xp->s_imount != xp->s_isup ||
-               xp->s_isup == fproc[FS_PROC_NR].fp_rootdir)
-       {
-               /* Normally, s_imount refers to the mount point. For a root
-                * filesystem, s_imount is equal to the root inode. We assume
-                * that the root of FS is always the real root. If the two
-                * inodes are different or if the root of FS is equal two the
-                * root of the filesystem we found, we found a filesystem that
-                * is in use.
-                */
-               return(EBUSY);  /* already mounted */
-       }
-
-       if (root_dev == xp->s_dev)
-       {
-               panic("fs", "inconsistency remounting old root",
-                       NO_NUM);
-       }
-
-       /* Now get the inode of the file to be mounted on. */
-       if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
-               return(err_code);
-       }
-
-       if ( (rip = eat_path(user_path)) == NIL_INODE) {
-               return(err_code);
-       }
-
-       r = OK;
-
-       /* It may not be special. */
-       bits = rip->i_mode & I_TYPE;
-       if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL)
-               r = ENOTDIR;
-
-       /* Get the root inode of the mounted file system. */
-       root_ip= sp->s_isup;
-
-       /* File types of 'rip' and 'root_ip' may not conflict. */
-       if (r == OK) {
-               mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY); 
-                                               /* TRUE iff dir */
-               rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
-               if (!mdir && rdir) r = EISDIR;
-       }
-
-       /* If error, return the mount point. */
-       if (r != OK) {
-               put_inode(rip);
-               return(r);
-       }
-
-       /* Nothing else can go wrong.  Perform the mount. */
-       rip->i_mount = I_MOUNT; /* this bit says the inode is
-                                * mounted on
-                                */
-       put_inode(sp->s_imount);
-       sp->s_imount = rip;
-       sp->s_rd_only = m_in.rd_only;
-       allow_newroot= 0;               /* The root is now fixed */
-       return(OK);
-  }
-  if (sp == NIL_SUPER) return(ENFILE); /* no super block available */
-
-  /* Open the device the file system lives on. */
-  if (dev_open(dev, who_e, m_in.rd_only ? R_BIT : (R_BIT|W_BIT)) != OK) 
-       return(EINVAL);
-
-  /* Make the cache forget about blocks it has open on the filesystem */
-  (void) do_sync();
-  invalidate(dev);
-
-  /* Fill in the super block. */
-  sp->s_dev = dev;             /* read_super() needs to know which dev */
-  r = read_super(sp);
-
-  /* Is it recognized as a Minix filesystem? */
-  if (r != OK) {
-       dev_close(dev);
-       sp->s_dev = NO_DEV;
-       return(r);
-  }
-
-  /* Now get the inode of the file to be mounted on. */
-  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
-       dev_close(dev);
-       sp->s_dev = NO_DEV;
-       return(err_code);
-  }
-
-  if (strcmp(user_path, "/") == 0 && allow_newroot)
-  {
-       printf("Replacing root\n");
-
-       /* Get the root inode of the mounted file system. */
-       if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
-       if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
-               r = EINVAL;
-       }
-
-       /* If error, return the super block and both inodes; release the
-        * maps.
-        */
-       if (r != OK) {
-               put_inode(root_ip);
-               (void) do_sync();
-               invalidate(dev);
-               dev_close(dev);
-               sp->s_dev = NO_DEV;
-               return(r);
-       }
-
-       /* Nothing else can go wrong.  Perform the mount. */
-       sp->s_imount = root_ip;
-       dup_inode(root_ip);
-       sp->s_isup = root_ip;
-       sp->s_rd_only = m_in.rd_only;
-       root_dev= dev;
-
-       /* Replace all root and working directories */
-       for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++)
-       {
-               if (tfp->fp_pid == PID_FREE)
-                       continue;
-               if (tfp->fp_rootdir == NULL)
-                       panic("fs", "do_mount: null rootdir", i);
-               put_inode(tfp->fp_rootdir);
-               dup_inode(root_ip);
-               tfp->fp_rootdir= root_ip;
-
-               if (tfp->fp_workdir == NULL)
-                       panic("fs", "do_mount: null workdir", i);
-               put_inode(tfp->fp_workdir);
-               dup_inode(root_ip);
-               tfp->fp_workdir= root_ip;
-       }
-
-       /* Leave the old filesystem lying around. */
-       return(OK);
-  }
-
-  if ( (rip = eat_path(user_path)) == NIL_INODE) {
-       dev_close(dev);
-       sp->s_dev = NO_DEV;
-       return(err_code);
-  }
-
-  /* It may not be busy. */
-  r = OK;
-  if (rip->i_count > 1) r = EBUSY;
-
-  /* It may not be special. */
-  bits = rip->i_mode & I_TYPE;
-  if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
-
-  /* Get the root inode of the mounted file system. */
-  root_ip = NIL_INODE;         /* if 'r' not OK, make sure this is defined */
-  if (r == OK) {
-       if ( (root_ip = get_inode(dev, ROOT_INODE)) == NIL_INODE) r = err_code;
-  }
-  if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
-       r = EINVAL;
-  }
-
-  /* File types of 'rip' and 'root_ip' may not conflict. */
-  if (r == OK) {
-       mdir = ((rip->i_mode & I_TYPE) == I_DIRECTORY);  /* TRUE iff dir */
-       rdir = ((root_ip->i_mode & I_TYPE) == I_DIRECTORY);
-       if (!mdir && rdir) r = EISDIR;
-  }
-
-  /* If error, return the super block and both inodes; release the maps. */
-  if (r != OK) {
-       put_inode(rip);
-       put_inode(root_ip);
-       (void) do_sync();
-       invalidate(dev);
-       dev_close(dev);
-       sp->s_dev = NO_DEV;
-       return(r);
-  }
-
-  /* Nothing else can go wrong.  Perform the mount. */
-  rip->i_mount = I_MOUNT;      /* this bit says the inode is mounted on */
-  sp->s_imount = rip;
-  sp->s_isup = root_ip;
-  sp->s_rd_only = m_in.rd_only;
-  allow_newroot= 0;            /* The root is now fixed */
-  return(OK);
-}
-
-/*===========================================================================*
- *                             do_umount                                    *
- *===========================================================================*/
-PUBLIC int do_umount()
-{
-/* Perform the umount(name) system call. */
-  dev_t dev;
-
-  /* Only the super-user may do UMOUNT. */
-  if (!super_user) return(EPERM);
-
-  /* If 'name' is not for a block special file, return error. */
-  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  if ( (dev = name_to_dev(user_path)) == NO_DEV) return(err_code);
-
-  return(unmount(dev));
-}
-
-/*===========================================================================*
- *                             unmount                                      *
- *===========================================================================*/
-PUBLIC int unmount(dev)
-Dev_t dev;
-{
-/* Unmount a file system by device number. */
-  register struct inode *rip;
-  struct super_block *sp, *sp1;
-  int count;
-
-  /* See if the mounted device is busy.  Only 1 inode using it should be
-   * open -- the root inode -- and that inode only 1 time.
-   */
-  count = 0;
-  for (rip = &inode[0]; rip< &inode[NR_INODES]; rip++)
-       if (rip->i_count > 0 && rip->i_dev == dev) count += rip->i_count;
-  if (count > 1) return(EBUSY);        /* can't umount a busy file system */
-
-  /* Find the super block. */
-  sp = NIL_SUPER;
-  for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
-       if (sp1->s_dev == dev) {
-               sp = sp1;
-               break;
-       }
-  }
-
-  /* Sync the disk, and invalidate cache. */
-  (void) do_sync();            /* force any cached blocks out of memory */
-  invalidate(dev);             /* invalidate cache entries for this dev */
-  if (sp == NIL_SUPER) {
-       return(EINVAL);
-  }
-
-  /* Close the device the file system lives on. */
-  dev_close(dev);
-
-  /* Finish off the unmount. */
-  sp->s_imount->i_mount = NO_MOUNT;    /* inode returns to normal */
-  put_inode(sp->s_imount);     /* release the inode mounted on */
-  put_inode(sp->s_isup);       /* release the root inode of the mounted fs */
-  sp->s_imount = NIL_INODE;
-  sp->s_dev = NO_DEV;
-  return(OK);
-}
-
-/*===========================================================================*
- *                             name_to_dev                                  *
- *===========================================================================*/
-PRIVATE dev_t name_to_dev(path)
-char *path;                    /* pointer to path name */
-{
-/* Convert the block special file 'path' to a device number.  If 'path'
- * is not a block special file, return error code in 'err_code'.
- */
-
-  register struct inode *rip;
-  register dev_t dev;
-
-  /* If 'path' can't be opened, give up immediately. */
-  if ( (rip = eat_path(path)) == NIL_INODE) return(NO_DEV);
-
-  /* If 'path' is not a block special file, return error. */
-  if ( (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) {
-       err_code = ENOTBLK;
-       put_inode(rip);
-       return(NO_DEV);
-  }
-
-  /* Extract the device number. */
-  dev = (dev_t) rip->i_zone[0];
-  put_inode(rip);
-  return(dev);
-}
diff --git a/servers/fs/open.c b/servers/fs/open.c
deleted file mode 100644 (file)
index 6657fd4..0000000
+++ /dev/null
@@ -1,573 +0,0 @@
-/* This file contains the procedures for creating, opening, closing, and
- * seeking on files.
- *
- * The entry points into this file are
- *   do_creat: perform the CREAT system call
- *   do_open:  perform the OPEN system call
- *   do_mknod: perform the MKNOD system call
- *   do_mkdir: perform the MKDIR system call
- *   do_close: perform the CLOSE system call
- *   do_lseek:  perform the LSEEK system call
- *   new_node:  create a new file, directory, etc.
- */
-
-#include "fs.h"
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <string.h>
-#include <unistd.h>
-#include <minix/callnr.h>
-#include <minix/com.h>
-#include "buf.h"
-#include "file.h"
-#include "fproc.h"
-#include "inode.h"
-#include "lock.h"
-#include "param.h"
-#include "super.h"
-
-#define offset m2_l1
-
-PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
-
-FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode)                );
-FORWARD _PROTOTYPE( int pipe_open, (struct inode *rip,mode_t bits,int oflags));
-
-/*===========================================================================*
- *                             do_creat                                     *
- *===========================================================================*/
-PUBLIC int do_creat()
-{
-/* Perform the creat(name, mode) system call. */
-  int r;
-
-  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_open                                      *
- *===========================================================================*/
-PUBLIC int do_open()
-{
-/* Perform the open(name, flags,...) system call. */
-
-  int create_mode = 0;         /* is really mode_t but this gives problems */
-  int r;
-
-  /* If O_CREAT is set, open has three parameters, otherwise two. */
-  if (m_in.mode & O_CREAT) {
-       create_mode = m_in.c_mode;      
-       r = fetch_name(m_in.c_name, m_in.name1_length, M1);
-  } else {
-       r = fetch_name(m_in.name, m_in.name_length, M3);
-  }
-
-  if (r != OK) return(err_code); /* name was bad */
-  r = common_open(m_in.mode, create_mode);
-  return(r);
-}
-
-/*===========================================================================*
- *                             common_open                                  *
- *===========================================================================*/
-PRIVATE int common_open(register int oflags, mode_t omode)
-{
-/* Common code from do_creat and do_open. */
-
-  struct inode *rip, *ldirp;
-  int r, b, exist = TRUE;
-  dev_t dev;
-  mode_t bits;
-  off_t pos;
-  struct filp *fil_ptr, *filp2;
-
-  /* Remap the bottom two bits of oflags. */
-  bits = (mode_t) mode_map[oflags & O_ACCMODE];
-
-  /* See if file descriptor and filp slots are available. */
-  if ( (r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);
-
-  /* If O_CREATE is set, try to make the file. */ 
-  if (oflags & O_CREAT) {
-       /* Create a new inode by calling new_node(). */
-        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
-       rip = new_node(&ldirp, user_path, omode, NO_ZONE, oflags&O_EXCL, NULL);
-       r = err_code;
-        put_inode(ldirp);
-       if (r == OK) exist = FALSE;      /* we just created the file */
-       else if (r != EEXIST) return(r); /* other error */
-       else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
-                                           flag is set this is an error */
-  } else {
-        /* Scan path name. */
-       if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
-  }
-
-  /* Claim the file descriptor and filp slot and fill them in. */
-  fp->fp_filp[m_in.fd] = fil_ptr;
-  FD_SET(m_in.fd, &fp->fp_filp_inuse);
-  fil_ptr->filp_count = 1;
-  fil_ptr->filp_ino = rip;
-  fil_ptr->filp_flags = oflags;
-
-  /* Only do the normal open code if we didn't just create the file. */
-  if (exist) {
-       /* Check protections. */
-       if ((r = forbidden(rip, bits)) == OK) {
-               /* Opening reg. files directories and special files differ. */
-               switch (rip->i_mode & I_TYPE) {
-                  case I_REGULAR: 
-                       /* Truncate regular file if O_TRUNC. */
-                       if (oflags & O_TRUNC) {
-                               if ((r = forbidden(rip, W_BIT)) !=OK) break;
-                               truncate_inode(rip, 0);
-                               wipe_inode(rip);
-                               /* Send the inode from the inode cache to the
-                                * block cache, so it gets written on the next
-                                * cache flush.
-                                */
-                               rw_inode(rip, WRITING);
-                       }
-                       break;
-                  case I_DIRECTORY: 
-                       /* Directories may be read but not written. */
-                       r = (bits & W_BIT ? EISDIR : OK);
-                       break;
-
-                  case I_CHAR_SPECIAL:
-                  case I_BLOCK_SPECIAL:
-                       /* Invoke the driver for special processing. */
-                       dev = (dev_t) rip->i_zone[0];
-                       r = dev_open(dev, who_e, bits | (oflags & ~O_ACCMODE));
-                       break;
-
-                  case I_NAMED_PIPE:
-                       oflags |= O_APPEND;     /* force append mode */
-                       fil_ptr->filp_flags = oflags;
-                       r = pipe_open(rip, bits, oflags);
-                       if (r != ENXIO) {
-                               /* See if someone else is doing a rd or wt on
-                                * the FIFO.  If so, use its filp entry so the
-                                * file position will be automatically shared.
-                                */
-                               b = (bits & R_BIT ? R_BIT : W_BIT);
-                               fil_ptr->filp_count = 0; /* don't find self */
-                               if ((filp2 = find_filp(rip, b)) != NIL_FILP) {
-                                       /* Co-reader or writer found. Use it.*/
-                                       fp->fp_filp[m_in.fd] = filp2;
-                                       filp2->filp_count++;
-                                       filp2->filp_ino = rip;
-                                       filp2->filp_flags = oflags;
-
-                                       /* i_count was incremented incorrectly
-                                        * by eatpath above, not knowing that
-                                        * we were going to use an existing
-                                        * filp entry.  Correct this error.
-                                        */
-                                       rip->i_count--;
-                               } else {
-                                       /* Nobody else found.  Restore filp. */
-                                       fil_ptr->filp_count = 1;
-                                       if (b == R_BIT)
-                                            pos = rip->i_zone[V2_NR_DZONES+0];
-                                       else
-                                            pos = rip->i_zone[V2_NR_DZONES+1];
-                                       fil_ptr->filp_pos = pos;
-                               }
-                       }
-                       break;
-               }
-       }
-  }
-
-  /* If error, release inode. */
-  if (r != OK) {
-       if (r == SUSPEND) return(r);            /* Oops, just suspended */
-       fp->fp_filp[m_in.fd] = NIL_FILP;
-       FD_CLR(m_in.fd, &fp->fp_filp_inuse);
-       fil_ptr->filp_count= 0;
-       put_inode(rip);
-       return(r);
-  }
-  
-  return(m_in.fd);
-}
-
-/*===========================================================================*
- *                             new_node                                     *
- *===========================================================================*/
-PUBLIC struct inode *new_node(struct inode **ldirp,
-       char *path, mode_t bits, zone_t z0, int opaque, char *parsed)
-{
-/* New_node() is called by common_open(), do_mknod(), and do_mkdir().  
- * In all cases it allocates a new inode, makes a directory entry for it on 
- * the path 'path', and initializes it.  It returns a pointer to the inode if 
- * it can do this; otherwise it returns NIL_INODE.  It always sets 'err_code'
- * to an appropriate value (OK or an error code).
- * 
- * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
- * has to hold at least NAME_MAX bytes.
- */
-
-  register struct inode *rip;
-  register int r;
-  char string[NAME_MAX];
-
-  *ldirp = parse_path(path, string, opaque ? LAST_DIR : LAST_DIR_EATSYM);       
-  if (*ldirp == NIL_INODE) return(NIL_INODE);
-
-  /* The final directory is accessible. Get final component of the path. */
-  rip = advance(ldirp, string);
-
-  if (S_ISDIR(bits) && 
-      (*ldirp)->i_nlinks >= ((*ldirp)->i_sp->s_version == V1 ?
-      CHAR_MAX : SHRT_MAX)) {
-        /* New entry is a directory, alas we can't give it a ".." */
-        put_inode(rip);
-        err_code = EMLINK;
-        return(NIL_INODE);
-  }
-
-  if ( rip == NIL_INODE && err_code == ENOENT) {
-       /* Last path component does not exist.  Make new directory entry. */
-       if ( (rip = alloc_inode((*ldirp)->i_dev, bits)) == NIL_INODE) {
-               /* Can't creat new inode: out of inodes. */
-               return(NIL_INODE);
-       }
-
-       /* Force inode to the disk before making directory entry to make
-        * the system more robust in the face of a crash: an inode with
-        * no directory entry is much better than the opposite.
-        */
-       rip->i_nlinks++;
-       rip->i_zone[0] = z0;            /* major/minor device numbers */
-       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)) != OK) {
-               rip->i_nlinks--;        /* pity, have to free disk inode */
-               rip->i_dirt = DIRTY;    /* dirty inodes are written out */
-               put_inode(rip); /* this call frees the inode */
-               err_code = r;
-               return(NIL_INODE);
-       }
-
-  } else {
-       /* Either last component exists, or there is some problem. */
-       if (rip != NIL_INODE)
-               r = EEXIST;
-       else
-               r = err_code;
-  }
-
-  if(parsed) { /* Give the caller the parsed string if requested. */
-       strncpy(parsed, string, NAME_MAX-1);
-       parsed[NAME_MAX-1] = '\0';
-  }
-
-  /* The caller has to return the directory inode (*ldirp).  */
-  err_code = r;
-  return(rip);
-}
-
-/*===========================================================================*
- *                             pipe_open                                    *
- *===========================================================================*/
-PRIVATE int pipe_open(register struct inode *rip, register mode_t bits,
-       register int oflags)
-{
-/*  This function is called from common_open. It checks if
- *  there is at least one reader/writer pair for the pipe, if not
- *  it suspends the caller, otherwise it revives all other blocked
- *  processes hanging on the pipe.
- */
-
-  rip->i_pipe = I_PIPE; 
-
-  if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) {
-       printf("pipe opened RW.\n");
-       return ENXIO;
-  }
-
-  if (find_filp(rip, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { 
-       if (oflags & O_NONBLOCK) {
-               if (bits & W_BIT) return(ENXIO);
-       } else {
-               suspend(XPOPEN);        /* suspend caller */
-               return(SUSPEND);
-       }
-  } else if (susp_count > 0) {/* revive blocked processes */
-       release(rip, OPEN, susp_count);
-       release(rip, CREAT, susp_count);
-  }
-  return(OK);
-}
-
-/*===========================================================================*
- *                             do_mknod                                     *
- *===========================================================================*/
-PUBLIC int do_mknod()
-{
-/* Perform the mknod(name, mode, addr) system call. */
-
-  register mode_t bits, mode_bits;
-  struct inode *ip, *ldirp;
-
-  /* Only the super_user may make nodes other than fifos. */
-  mode_bits = (mode_t) m_in.mk_mode;           /* mode of the inode */
-  if (!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM);
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
-  ip = new_node(&ldirp, user_path, bits, (zone_t) m_in.mk_z0, TRUE, NULL);
-  put_inode(ip);
-  put_inode(ldirp);
-  return(err_code);
-}
-
-/*===========================================================================*
- *                             do_mkdir                                     *
- *===========================================================================*/
-PUBLIC int do_mkdir()
-{
-/* Perform the mkdir(name, mode) system call. */
-
-  int r1, r2;                  /* status codes */
-  ino_t dot, dotdot;           /* inode numbers for . and .. */
-  mode_t bits;                 /* mode bits for the new inode */
-  char string[NAME_MAX];       /* last component of the new dir's path name */
-  struct inode *rip, *ldirp;
-
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-
-  /* Next make the inode. If that fails, return error code. */
-  bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
-  rip = new_node(&ldirp, user_path, bits, (zone_t) 0, TRUE, string);
-  if (rip == NIL_INODE || err_code == EEXIST) {
-       put_inode(rip);         /* can't make dir: it already exists */
-       put_inode(ldirp);
-       return(err_code);
-  }
-
-  /* Get the inode numbers for . and .. to enter in the directory. */
-  dotdot = ldirp->i_num;       /* parent's inode number */
-  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 = bits;  /* set mode */
-  r1 = search_dir(rip, dot1, &dot, ENTER);     /* enter . in the new dir */
-  r2 = search_dir(rip, dot2, &dotdot, ENTER);  /* enter .. in the new dir */
-
-  /* If both . and .. were successfully entered, increment the link counts. */
-  if (r1 == OK && r2 == OK) {
-       /* Normal case.  It was possible to enter . and .. in the new dir. */
-       rip->i_nlinks++;        /* this accounts for . */
-       ldirp->i_nlinks++;      /* this accounts for .. */
-       ldirp->i_dirt = DIRTY;  /* mark parent's inode as dirty */
-  } else {
-       /* It was not possible to enter . or .. probably disk was full -
-        * links counts haven't been touched.
-        */
-       if(search_dir(ldirp, string, (ino_t *) 0, DELETE) != OK)
-               panic(__FILE__, "Dir disappeared ", rip->i_num);
-       rip->i_nlinks--;        /* undo the increment done in new_node() */
-  }
-  rip->i_dirt = DIRTY;         /* either way, i_nlinks has changed */
-
-  put_inode(ldirp);            /* return the inode of the parent dir */
-  put_inode(rip);              /* return the inode of the newly made dir */
-  return(err_code);            /* new_node() always sets 'err_code' */
-}
-
-/*===========================================================================*
- *                             do_close                                     *
- *===========================================================================*/
-PUBLIC int do_close()
-{
-/* Perform the close(fd) system call. */
-  return close_fd(fp, m_in.fd);
-}
-
-/*===========================================================================*
- *                             close_fd                                     *
- *===========================================================================*/
-PUBLIC int close_fd(rfp, fd_nr)
-struct fproc *rfp;
-int fd_nr;
-{
-/* Close a filedescriptor for a process. */
-
-  register struct filp *rfilp;
-  register struct inode *rip;
-  struct file_lock *flp;
-  int rw, mode_word, lock_count;
-  dev_t dev;
-
-  /* First locate the inode that belongs to the file descriptor. */
-  if ( (rfilp = get_filp2(rfp, fd_nr)) == NIL_FILP) return(err_code);
-  rip = rfilp->filp_ino;       /* 'rip' points to the inode */
-
-  if (rfilp->filp_count - 1 == 0 && rfilp->filp_mode != FILP_CLOSED) {
-       /* Check to see if the file is special. */
-       mode_word = rip->i_mode & I_TYPE;
-       if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
-               dev = (dev_t) rip->i_zone[0];
-               if (mode_word == I_BLOCK_SPECIAL)  {
-                       /* Invalidate cache entries unless special is mounted
-                        * or ROOT
-                        */
-                       if (!mounted(rip)) {
-                               (void) do_sync();       /* purge cache */
-                               invalidate(dev);
-                       }    
-               }
-               /* Do any special processing on device close. */
-               dev_close(dev);
-       }
-  }
-
-  /* If the inode being closed is a pipe, release everyone hanging on it. */
-  if (rip->i_pipe == I_PIPE) {
-       rw = (rfilp->filp_mode & R_BIT ? WRITE : READ);
-       release(rip, rw, NR_PROCS);
-  }
-
-  /* If a write has been done, the inode is already marked as DIRTY. */
-  if (--rfilp->filp_count == 0) {
-       if (rip->i_pipe == I_PIPE && rip->i_count > 1) {
-               /* Save the file position in the i-node in case needed later.
-                * The read and write positions are saved separately.  The
-                * last 3 zones in the i-node are not used for (named) pipes.
-                */
-               if (rfilp->filp_mode == R_BIT)
-                       rip->i_zone[V2_NR_DZONES+0] = (zone_t) rfilp->filp_pos;
-               else
-                       rip->i_zone[V2_NR_DZONES+1] = (zone_t) rfilp->filp_pos;
-       }
-       put_inode(rip);
-  }
-
-  FD_CLR(fd_nr, &rfp->fp_cloexec_set);
-  rfp->fp_filp[fd_nr] = NIL_FILP;
-  FD_CLR(fd_nr, &rfp->fp_filp_inuse);
-
-  /* Check to see if the file is locked.  If so, release all locks. */
-  if (nr_locks == 0) return(OK);
-  lock_count = nr_locks;       /* save count of locks */
-  for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
-       if (flp->lock_type == 0) continue;      /* slot not in use */
-       if (flp->lock_inode == rip && flp->lock_pid == rfp->fp_pid) {
-               flp->lock_type = 0;
-               nr_locks--;
-       }
-  }
-  if (nr_locks < lock_count) lock_revive();    /* lock released */
-  return(OK);
-}
-
-/*===========================================================================*
- *                             do_lseek                                     *
- *===========================================================================*/
-PUBLIC int do_lseek()
-{
-/* Perform the lseek(ls_fd, offset, whence) system call. */
-
-  register struct filp *rfilp;
-  register off_t pos;
-
-  /* Check to see if the file descriptor is valid. */
-  if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
-
-  /* No lseek on pipes. */
-  if (rfilp->filp_ino->i_pipe == I_PIPE) return(ESPIPE);
-
-  /* The value of 'whence' determines the start position to use. */
-  switch(m_in.whence) {
-       case SEEK_SET: pos = 0; break;
-       case SEEK_CUR: pos = rfilp->filp_pos;   break;
-       case SEEK_END: pos = rfilp->filp_ino->i_size;   break;
-       default: return(EINVAL);
-  }
-
-  /* Check for overflow. */
-  if (((long)m_in.offset > 0) && ((long)(pos + m_in.offset) < (long)pos)) 
-       return(EINVAL);
-  if (((long)m_in.offset < 0) && ((long)(pos + m_in.offset) > (long)pos)) 
-       return(EINVAL);
-  pos = pos + m_in.offset;
-
-  if (pos != rfilp->filp_pos)
-       rfilp->filp_ino->i_seek = ISEEK;        /* inhibit read ahead */
-  rfilp->filp_pos = pos;
-  m_out.reply_l1 = pos;                /* insert the long into the output message */
-  return(OK);
-}
-
-/*===========================================================================*
- *                             do_slink                                             *
- *===========================================================================*/
-PUBLIC int do_slink()
-{
-/* Perform the symlink(name1, name2) system call. */
-
-  register int r;              /* error code */
-  char string[NAME_MAX];       /* last component of the new dir's path name */
-  struct inode *sip;           /* inode containing symbolic link */
-  struct buf *bp;              /* disk buffer for link */
-  struct inode *ldirp;         /* directory containing link */
-
-  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
-       return(err_code);
-
-  if (m_in.name1_length <= 1 || m_in.name1_length >= _MIN_BLOCK_SIZE)
-       return(ENAMETOOLONG);
-
-  /* Create the inode for the symlink. */
-  sip = new_node(&ldirp, user_path, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
-                 (zone_t) 0, TRUE, string);
-
-  /* Allocate a disk block for the contents of the symlink.
-   * Copy contents of symlink (the name pointed to) into first disk block.
-   */
-  if ((r = err_code) == OK) {
-       r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF
-           ? err_code
-           : sys_vircopy(who_e, D, (vir_bytes) m_in.name1,
-                       SELF, D, (vir_bytes) bp->b_data,
-                      (vir_bytes) m_in.name1_length-1);
-
-       if(r == OK) {
-               bp->b_data[_MIN_BLOCK_SIZE-1] = '\0';
-               sip->i_size = strlen(bp->b_data);
-               if(sip->i_size != m_in.name1_length-1) {
-                       /* 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
-                        * the strlen() value, but we want to let the user
-                        * know he did something wrong. ENAMETOOLONG doesn't
-                        * exactly describe the error, but there is no
-                        * ENAMETOOWRONG.
-                        */
-                       r = ENAMETOOLONG;
-               }
-       }
-  
-       put_block(bp, DIRECTORY_BLOCK);         /* put_block() accepts NIL_BUF. */
-  
-       if (r != OK) {
-               sip->i_nlinks = 0;
-               if (search_dir(ldirp, string, (ino_t *) 0, DELETE) != OK)
-                       panic(__FILE__, "Symbolic link vanished", NO_NUM);
-       } 
-  }
-
-  /* put_inode() accepts NIL_INODE as a noop, so the below are safe. */
-  put_inode(sip);
-  put_inode(ldirp);
-
-  return(r);
-}
-
diff --git a/servers/fs/stadir.c b/servers/fs/stadir.c
deleted file mode 100644 (file)
index c84b5ec..0000000
+++ /dev/null
@@ -1,303 +0,0 @@
-/* This file contains the code for performing four system calls relating to
- * status and directories.
- *
- * The entry points into this file are
- *   do_chdir: perform the CHDIR system call
- *   do_chroot:        perform the CHROOT system call
- *   do_stat:  perform the STAT system call
- *   do_fstat: perform the FSTAT system call
- *   do_fstatfs: perform the FSTATFS system call
- *   do_lstat:  perform the LSTAT system call
- *   do_rdlink: perform the RDLNK system call
- */
-
-#include "fs.h"
-#include <sys/stat.h>
-#include <sys/statfs.h>
-#include <minix/com.h>
-#include <string.h>
-#include "buf.h"
-#include "file.h"
-#include "fproc.h"
-#include "inode.h"
-#include "param.h"
-#include "super.h"
-
-FORWARD _PROTOTYPE( int change, (struct inode **iip, char *name_ptr, int len));
-FORWARD _PROTOTYPE( int change_into, (struct inode **iip, struct inode *ip));
-FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, struct filp *fil_ptr,
-                       char *user_addr)                                );
-
-/*===========================================================================*
- *                             do_fchdir                                    *
- *===========================================================================*/
-PUBLIC int do_fchdir()
-{
-       /* Change directory on already-opened fd. */
-       struct filp *rfilp;
-
-       /* Is the file descriptor valid? */
-       if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
-       dup_inode(rfilp->filp_ino);
-       return change_into(&fp->fp_workdir, rfilp->filp_ino);
-}
-
-/*===========================================================================*
- *                             do_chdir                                     *
- *===========================================================================*/
-PUBLIC int do_chdir()
-{
-/* Change directory.  This function is  also called by MM to simulate a chdir
- * in order to do EXEC, etc.  It also changes the root directory, the uids and
- * gids, and the umask. 
- */
-
-  int r;
-  register struct fproc *rfp;
-
-  if (who_e == PM_PROC_NR) {
-       int slot;
-       if(isokendpt(m_in.endpt1, &slot) != OK)
-               return EINVAL;
-       rfp = &fproc[slot];
-       put_inode(fp->fp_rootdir);
-       dup_inode(fp->fp_rootdir = rfp->fp_rootdir);
-       put_inode(fp->fp_workdir);
-       dup_inode(fp->fp_workdir = rfp->fp_workdir);
-
-       /* MM uses access() to check permissions.  To make this work, pretend
-        * that the user's real ids are the same as the user's effective ids.
-        * FS calls other than access() do not use the real ids, so are not
-        * affected.
-        */
-       fp->fp_realuid =
-       fp->fp_effuid = rfp->fp_effuid;
-       fp->fp_realgid =
-       fp->fp_effgid = rfp->fp_effgid;
-       fp->fp_umask = rfp->fp_umask;
-       return(OK);
-  }
-
-  /* Perform the chdir(name) system call. */
-  r = change(&fp->fp_workdir, m_in.name, m_in.name_length);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_chroot                                    *
- *===========================================================================*/
-PUBLIC int do_chroot()
-{
-/* Perform the chroot(name) system call. */
-
-  register int r;
-
-  if (!super_user) return(EPERM);      /* only su may chroot() */
-  r = change(&fp->fp_rootdir, m_in.name, m_in.name_length);
-  return(r);
-}
-
-/*===========================================================================*
- *                             change                                       *
- *===========================================================================*/
-PRIVATE int change(iip, name_ptr, len)
-struct inode **iip;            /* pointer to the inode pointer for the dir */
-char *name_ptr;                        /* pointer to the directory name to change to */
-int len;                       /* length of the directory name string */
-{
-/* Do the actual work for chdir() and chroot(). */
-  struct inode *rip;
-
-  /* Try to open the new directory. */
-  if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
-  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
-  return change_into(iip, rip);
-}
-
-/*===========================================================================*
- *                             change_into                                  *
- *===========================================================================*/
-PRIVATE int change_into(iip, rip)
-struct inode **iip;            /* pointer to the inode pointer for the dir */
-struct inode *rip;             /* this is what the inode has to become */
-{
-  register int r;
-
-  /* It must be a directory and also be searchable. */
-  if ( (rip->i_mode & I_TYPE) != I_DIRECTORY)
-       r = ENOTDIR;
-  else
-       r = forbidden(rip, X_BIT);      /* check if dir is searchable */
-
-  /* If error, return inode. */
-  if (r != OK) {
-       put_inode(rip);
-       return(r);
-  }
-
-  /* Everything is OK.  Make the change. */
-  put_inode(*iip);             /* release the old directory */
-  *iip = rip;                  /* acquire the new one */
-  return(OK);
-}
-
-/*===========================================================================*
- *                             do_stat                                      *
- *===========================================================================*/
-PUBLIC int do_stat()
-{
-/* Perform the stat(name, buf) system call. */
-
-  register struct inode *rip;
-  register int r;
-
-  /* Both stat() and fstat() use the same routine to do the real work.  That
-   * routine expects an inode, so acquire it temporarily.
-   */
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
-  r = stat_inode(rip, NIL_FILP, m_in.name2);   /* actually do the work.*/
-  put_inode(rip);              /* release the inode */
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_fstat                                     *
- *===========================================================================*/
-PUBLIC int do_fstat()
-{
-/* Perform the fstat(fd, buf) system call. */
-
-  register struct filp *rfilp;
-
-  /* Is the file descriptor valid? */
-  if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
-
-  return(stat_inode(rfilp->filp_ino, rfilp, m_in.buffer));
-}
-
-/*===========================================================================*
- *                             stat_inode                                   *
- *===========================================================================*/
-PRIVATE int stat_inode(rip, fil_ptr, user_addr)
-register struct inode *rip;    /* pointer to inode to stat */
-struct filp *fil_ptr;          /* filp pointer, supplied by 'fstat' */
-char *user_addr;               /* user space address where stat buf goes */
-{
-/* Common code for stat and fstat system calls. */
-
-  struct stat statbuf;
-  mode_t mo;
-  int r, s;
-
-  /* Update the atime, ctime, and mtime fields in the inode, if need be. */
-  if (rip->i_update) update_times(rip);
-
-  /* Fill in the statbuf struct. */
-  mo = rip->i_mode & I_TYPE;
-
-  /* true iff special */
-  s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);
-
-  statbuf.st_dev = rip->i_dev;
-  statbuf.st_ino = rip->i_num;
-  statbuf.st_mode = rip->i_mode;
-  statbuf.st_nlink = rip->i_nlinks;
-  statbuf.st_uid = rip->i_uid;
-  statbuf.st_gid = rip->i_gid;
-  statbuf.st_rdev = (dev_t) (s ? rip->i_zone[0] : NO_DEV);
-  statbuf.st_size = rip->i_size;
-
-  if (rip->i_pipe == I_PIPE) {
-       statbuf.st_mode &= ~I_REGULAR;  /* wipe out I_REGULAR bit for pipes */
-       if (fil_ptr != NIL_FILP && fil_ptr->filp_mode & R_BIT) 
-               statbuf.st_size -= fil_ptr->filp_pos;
-  }
-
-  statbuf.st_atime = rip->i_atime;
-  statbuf.st_mtime = rip->i_mtime;
-  statbuf.st_ctime = rip->i_ctime;
-
-  /* Copy the struct to user space. */
-  r = sys_datacopy(FS_PROC_NR, (vir_bytes) &statbuf,
-               who_e, (vir_bytes) user_addr, (phys_bytes) sizeof(statbuf));
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_fstatfs                                   *
- *===========================================================================*/
-PUBLIC int do_fstatfs()
-{
-  /* Perform the fstatfs(fd, buf) system call. */
-  struct statfs st;
-  register struct filp *rfilp;
-  int r;
-
-  /* Is the file descriptor valid? */
-  if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
-
-  st.f_bsize = rfilp->filp_ino->i_sp->s_block_size;
-
-  r = sys_datacopy(FS_PROC_NR, (vir_bytes) &st,
-               who_e, (vir_bytes) m_in.buffer, (phys_bytes) sizeof(st));
-
-   return(r);
-}
-
-/*===========================================================================*
- *                             do_lstat                                     *
- *===========================================================================*/
-PUBLIC int do_lstat()
-{
-/* Perform the lstat(name, buf) system call. */
-
-  register int r;              /* return value */
-  register struct inode *rip;  /* target inode */
-
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((rip = parse_path(user_path, (char *) 0, EAT_PATH_OPAQUE)) == NIL_INODE)
-       return(err_code);
-  r = stat_inode(rip, NIL_FILP, m_in.name2);
-  put_inode(rip);
-  return(r);
-}
-
-/*===========================================================================*
- *                             do_rdlink                                    *
- *===========================================================================*/
-PUBLIC int do_rdlink()
-{
-/* Perform the readlink(name, buf) system call. */
-
-  register int r;              /* return value */
-  block_t b;                   /* block containing link text */
-  struct buf *bp;              /* buffer containing link text */
-  register struct inode *rip;  /* target inode */
-  int copylen;
-  copylen = m_in.m1_i2;
-  if(copylen < 0) return EINVAL;
-
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ((rip = parse_path(user_path, (char *) 0, EAT_PATH_OPAQUE)) == NIL_INODE)
-       return(err_code);
-
-  r = EACCES;
-  if (S_ISLNK(rip->i_mode) && (b = read_map(rip, (off_t) 0)) != NO_BLOCK) {
-       if (m_in.name2_length <= 0) r = EINVAL;
-       else if (m_in.name2_length < rip->i_size) r = ERANGE;
-       else {
-              if(rip->i_size < copylen) copylen = rip->i_size;
-               bp = get_block(rip->i_dev, b, NORMAL);
-               r = sys_vircopy(SELF, D, (vir_bytes) bp->b_data,
-               who_e, D, (vir_bytes) m_in.name2, (vir_bytes) copylen);
-
-               if (r == OK) r = copylen;
-               put_block(bp, DIRECTORY_BLOCK);
-       }
-  }
-
-  put_inode(rip);
-  return(r);
-}
-
index d67fc67cb008f20fb6192147a3207386790303eb..0eeea95890887f1969cc30f735d35b5c60ce7680 100644 (file)
@@ -9,8 +9,8 @@
  */
 
 #include "inc.h"
-#include "../fs/const.h"
-#include "../fs/fproc.h"
+#include "../mfs/const.h"
+#include "../vfs/fproc.h"
 #include <minix/dmap.h>
 
 PUBLIC struct fproc fproc[NR_PROCS];
diff --git a/servers/mfs/Makefile b/servers/mfs/Makefile
new file mode 100644 (file)
index 0000000..8ed054e
--- /dev/null
@@ -0,0 +1,37 @@
+# Makefile for File System (FS)
+SERVER = mfs
+
+# directories
+u = /usr
+i = $u/include
+s = $i/sys
+h = $i/minix
+
+# programs, flags, etc.
+CC =   exec cc
+CFLAGS = -I$i $(EXTRA_OPTS)
+LDFLAGS = -i
+LIBS = -lsys -lsysutil -ltimers
+
+OBJ =  cache.o device.o link.o \
+       mount.o misc.o open.o pipe.o protect.o read.o \
+       stadir.o table.o time.o utility.o \
+       write.o inode.o main.o path.o super.o
+
+# build local binary 
+install all build:     $(SERVER)
+$(SERVER):     $(OBJ)
+       $(CC) -o $@ $(LDFLAGS) $(OBJ) $(LIBS)
+       install -S 16k $@ /sbin
+
+# clean up local files
+clean:
+       rm -f $(SERVER) *.o *.bak 
+
+depend: 
+       /usr/bin/mkdep "$(CC) -E $(CPPFLAGS)" *.c > .depend
+
+# Include generated dependencies.
+include .depend
+
+
similarity index 100%
rename from servers/fs/buf.h
rename to servers/mfs/buf.h
similarity index 84%
rename from servers/fs/cache.c
rename to servers/mfs/cache.c
index f5e7100b4d4ad6571154e7de7ced097afc5b3f0d..02e2a8c2cb3d0080790db5bc61dd7128b95ec1e4 100644 (file)
 #include "fs.h"
 #include <minix/com.h>
 #include "buf.h"
-#include "file.h"
-#include "fproc.h"
 #include "super.h"
 
 FORWARD _PROTOTYPE( void rm_lru, (struct buf *bp) );
 FORWARD _PROTOTYPE( int rw_block, (struct buf *, int) );
 
+#define ENABLE_CACHE2 0
+
 /*===========================================================================*
  *                             get_block                                    *
  *===========================================================================*/
@@ -58,7 +58,6 @@ int only_search;              /* if NO_READ, don't read, else act normal */
   if (dev != NO_DEV) {
        b = (int) block & HASH_MASK;
        bp = buf_hash[b];
-
        while (bp != NIL_BUF) {
                if (bp->b_blocknr == block && bp->b_dev == dev) {
                        /* Block needed has been found. */
@@ -70,7 +69,6 @@ int only_search;              /* if NO_READ, don't read, else act normal */
                        /* This block is not the one sought. */
                        bp = bp->b_hash; /* move to next block on hash chain */
                }
-
        }
   }
 
@@ -86,14 +84,12 @@ int only_search;            /* if NO_READ, don't read, else act normal */
   } else {
        /* The block just taken is not on the front of its hash chain. */
        while (prev_ptr->b_hash != NIL_BUF)
-       {
                if (prev_ptr->b_hash == bp) {
                        prev_ptr->b_hash = bp->b_hash;  /* found it */
                        break;
                } else {
                        prev_ptr = prev_ptr->b_hash;    /* keep looking */
                }
-       }
   }
 
   /* If the block taken is dirty, make it clean by writing it to the disk.
@@ -167,7 +163,8 @@ int block_type;                     /* INODE_BLOCK, DIRECTORY_BLOCK, or whatever */
        else
                front->b_prev = bp;
        front = bp;
-  } else {
+  } 
+  else {
        /* Block probably will be needed quickly.  Put it on rear of chain.
         * It will not be evicted from the cache for a long time.
         */
@@ -222,8 +219,7 @@ zone_t z;                   /* try to allocate new zone near this one */
        err_code = ENOSPC;
        major = (int) (sp->s_dev >> MAJOR) & BYTE;
        minor = (int) (sp->s_dev >> MINOR) & BYTE;
-       printf("No space on %sdevice %d/%d\n",
-               sp->s_dev == root_dev ? "root " : "", major, minor);
+       printf("No space on device %d/%d\n", major, minor);
        return(NO_ZONE);
   }
   if (z == sp->s_firstdatazone) sp->s_zsearch = b;     /* for next time */
@@ -262,7 +258,6 @@ int rw_flag;                        /* READING or WRITING */
  * is not reported to the caller.  If the error occurred while purging a block
  * from the cache, it is not clear what the caller could do about it anyway.
  */
-
   int r, op;
   off_t pos;
   dev_t dev;
@@ -271,19 +266,21 @@ int rw_flag;                      /* READING or WRITING */
   block_size = get_block_size(bp->b_dev);
 
   if ( (dev = bp->b_dev) != NO_DEV) {
-       pos = (off_t) bp->b_blocknr * block_size;
-       op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
-       r = dev_bio(op, dev, FS_PROC_NR, bp->b_data, pos, block_size);
-       if (r != block_size) {
-           if (r >= 0) r = END_OF_FILE;
-           if (r != END_OF_FILE)
-             printf("Unrecoverable disk error on device %d/%d, block %ld\n",
-                       (dev>>MAJOR)&BYTE, (dev>>MINOR)&BYTE, bp->b_blocknr);
-               bp->b_dev = NO_DEV;     /* invalidate block */
-
-               /* Report read errors to interested parties. */
-               if (rw_flag == READING) rdwt_err = r;
-       }
+         pos = (off_t) bp->b_blocknr * block_size;
+         op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
+         r = block_dev_io(op, dev, SELF_E, bp->b_data, pos, block_size, 0);
+         if (r != block_size) {
+                 if (r >= 0) r = END_OF_FILE;
+                 if (r != END_OF_FILE)
+                       printf("MFS(%d) I/O error on device %d/%d, block %ld\n",
+                       SELF_E, (dev>>MAJOR)&BYTE, (dev>>MINOR)&BYTE, 
+                       bp->b_blocknr);
+                 
+                 bp->b_dev = NO_DEV;   /* invalidate block */
+
+                 /* Report read errors to interested parties. */
+                 if (rw_flag == READING) rdwt_err = r;
+         }
   }
 
   bp->b_dirt = CLEAN;
@@ -375,9 +372,9 @@ int rw_flag;                        /* READING or WRITING */
                iop->iov_addr = (vir_bytes) bp->b_data;
                iop->iov_size = block_size;
        }
-       r = dev_bio(rw_flag == WRITING ? DEV_SCATTER : DEV_GATHER,
-               dev, FS_PROC_NR, iovec,
-               (off_t) bufq[0]->b_blocknr * block_size, j);
+       r = block_dev_io(rw_flag == WRITING ? DEV_SCATTER : DEV_GATHER,
+               dev, SELF_E, iovec,
+               (off_t) bufq[0]->b_blocknr * block_size, j, 0);
 
        /* Harvest the results.  Dev_io reports the first error it may have
         * encountered, but we only care if it's the first block that failed.
@@ -437,123 +434,12 @@ struct buf *bp;
   next_ptr = bp->b_next;       /* successor on LRU chain */
   prev_ptr = bp->b_prev;       /* predecessor on LRU chain */
   if (prev_ptr != NIL_BUF)
-  {
        prev_ptr->b_next = next_ptr;
-  }
   else
        front = next_ptr;       /* this block was at front of chain */
 
   if (next_ptr != NIL_BUF)
-  {
        next_ptr->b_prev = prev_ptr;
-  }
   else
        rear = prev_ptr;        /* this block was at rear of chain */
 }
-
-#if 0
-PRIVATE void check_lru()
-{
-       int i;
-       struct buf *bp, *nbp;
-
-       for (i= 0; i<NR_BUFS; i++)
-       {
-               bp= &buf[i];
-               nbp= bp->b_next;
-               if (nbp != NULL && (nbp < buf || nbp >= &buf[NR_BUFS]))
-               {
-                       stacktrace();
-                       panic(__FILE__, "check_lru: bad next", nbp);
-               }
-               nbp= bp->b_prev;
-               if (nbp != NULL && (nbp < buf || nbp >= &buf[NR_BUFS]))
-               {
-                       stacktrace();
-                       panic(__FILE__, "check_lru: bad next", nbp);
-               }
-       }
-}
-
-PRIVATE void check_buf(bp)
-struct buf *bp;
-{
-       struct buf *nbp;
-
-       if (bp < buf || bp >= &buf[NR_BUFS])
-       {
-               stacktrace();
-               panic(__FILE__, "check_buf: bad buf", bp);
-       }
-       nbp= bp->b_next;
-       if (nbp != NULL && (nbp < buf || nbp >= &buf[NR_BUFS]))
-       {
-               stacktrace();
-               panic(__FILE__, "check_buf: bad next", nbp);
-       }
-       nbp= bp->b_prev;
-       if (nbp != NULL && (nbp < buf || nbp >= &buf[NR_BUFS]))
-       {
-               stacktrace();
-               panic(__FILE__, "check_buf: bad next", nbp);
-       }
-}
-
-PRIVATE void check_hash_chains()
-{
-       int i;
-       struct buf *bp;
-
-       for (i= 0; i<NR_BUFS; i++)
-       {
-               bp= &buf[i];
-               while (bp)
-               {
-                       if (bp < buf || bp >= &buf[NR_BUFS])
-                       {
-                               panic(__FILE__, "check_hash_chains: bad buf",
-                                       bp);
-                       }
-                       bp= bp->b_hash;
-               }
-       }
-}
-
-PUBLIC void check_hash_chainsX(file, line)
-char *file;
-int line;
-{
-       int i;
-       struct buf *bp;
-
-       for (i= 0; i<NR_BUF_HASH; i++)
-       {
-               bp= buf_hash[i];
-               while (bp)
-               {
-                       if (bp < buf || bp >= &buf[NR_BUFS])
-                       {
-                               printf(
-                               "check_hash_chainsX: called from %s, %d\n",
-                                       file, line);
-                               panic(__FILE__, "check_hash_chainsX: bad buf",
-                                       bp);
-                       }
-                       bp= bp->b_hash;
-               }
-       }
-}
-
-PRIVATE void check_hash_chain(bp)
-struct buf *bp;
-{
-       while (bp)
-       {
-               if (bp < buf || bp >= &buf[NR_BUFS])
-               {
-                       panic(__FILE__, "check_hash_chain: bad buf", bp);
-               }
-               bp= bp->b_hash;
-       }
-}
-#endif
diff --git a/servers/mfs/const.h b/servers/mfs/const.h
new file mode 100644 (file)
index 0000000..e6b77e5
--- /dev/null
@@ -0,0 +1,108 @@
+/* Tables sizes */
+#define V1_NR_DZONES       7   /* # direct zone numbers in a V1 inode */
+#define V1_NR_TZONES       9   /* total # zone numbers in a V1 inode */
+#define V2_NR_DZONES       7   /* # direct zone numbers in a V2 inode */
+#define V2_NR_TZONES      10   /* total # zone numbers in a V2 inode */
+
+#define NR_INODES        256   /* # slots in "in core" inode table */
+#define NR_SUPERS          1   /* # slots in super block table */
+
+#define INODE_HASH_LOG2   7     /* 2 based logarithm of the inode hash size */
+#define INODE_HASH_SIZE   ((unsigned long)1<<INODE_HASH_LOG2)
+#define INODE_HASH_MASK   (((unsigned long)1<<INODE_HASH_LOG2)-1)
+
+
+/* The type of sizeof may be (unsigned) long.  Use the following macro for
+ * taking the sizes of small objects so that there are no surprises like
+ * (small) long constants being passed to routines expecting an int.
+ */
+#define usizeof(t) ((unsigned) sizeof(t))
+
+/* File system types. */
+#define SUPER_MAGIC   0x137F   /* magic number contained in super-block */
+#define SUPER_REV     0x7F13   /* magic # when 68000 disk read on PC or vv */
+#define SUPER_V2      0x2468   /* magic # for V2 file systems */
+#define SUPER_V2_REV  0x6824   /* V2 magic written on PC, read on 68K or vv */
+#define SUPER_V3      0x4d5a   /* magic # for V3 file systems */
+
+#define V1                1    /* version number of V1 file systems */ 
+#define V2                2    /* version number of V2 file systems */ 
+#define V3                3    /* version number of V3 file systems */ 
+
+/* Miscellaneous constants */
+#define SU_UID          ((uid_t) 0)    /* super_user's uid_t */
+#define SERVERS_UID ((uid_t) 11) /* who may do FSSIGNON */
+#define SYS_UID  ((uid_t) 0)   /* uid_t for processes MM and INIT */
+#define SYS_GID  ((gid_t) 0)   /* gid_t for processes MM and INIT */
+#define NORMAL            0    /* forces get_block to do disk read */
+#define NO_READ            1   /* prevents get_block from doing disk read */
+#define PREFETCH           2   /* tells get_block not to read or mark dev */
+
+#define XPIPE   (-NR_TASKS-1)  /* used in fp_task when susp'd on pipe */
+#define XLOCK   (-NR_TASKS-2)  /* used in fp_task when susp'd on lock */
+#define XPOPEN  (-NR_TASKS-3)  /* used in fp_task when susp'd on pipe open */
+#define XSELECT (-NR_TASKS-4)  /* used in fp_task when susp'd on select */
+
+#define NO_BIT   ((bit_t) 0)   /* returned by alloc_bit() to signal failure */
+
+#define DUP_MASK        0100   /* mask to distinguish dup2 from dup */
+
+#define LOOK_UP            0 /* tells search_dir to lookup string */
+#define ENTER              1 /* tells search_dir to make dir entry */
+#define DELETE             2 /* tells search_dir to delete entry */
+#define IS_EMPTY           3 /* tells search_dir to ret. OK or ENOTEMPTY */  
+
+/* write_map() args */
+#define WMAP_FREE      (1 << 0)
+
+#define PATH_TRANSPARENT 000   /* parse_path stops at final object */
+#define PATH_PENULTIMATE 001   /* parse_path stops at last but one name */
+#define PATH_OPAQUE      002   /* parse_path stops at final name */
+#define PATH_NONSYMBOLIC 004   /* parse_path scans final name if symbolic */
+#define PATH_STRIPDOT    010   /* parse_path strips /. from path */
+#define EAT_PATH         PATH_TRANSPARENT
+#define EAT_PATH_OPAQUE  PATH_OPAQUE 
+#define LAST_DIR         PATH_PENULTIMATE
+#define LAST_DIR_NOTDOT  PATH_PENULTIMATE | PATH_STRIPDOT
+#define LAST_DIR_EATSYM  PATH_NONSYMBOLIC
+#define SYMLOOP                16
+
+#define CLEAN              0   /* disk and memory copies identical */
+#define DIRTY              1   /* disk and memory copies differ */
+#define ATIME            002   /* set if atime field needs updating */
+#define CTIME            004   /* set if ctime field needs updating */
+#define MTIME            010   /* set if mtime field needs updating */
+
+#define BYTE_SWAP          0   /* tells conv2/conv4 to swap bytes */
+
+#define END_OF_FILE   (-104)   /* eof detected */
+
+#define ROOT_INODE         1           /* inode number for root directory */
+#define BOOT_BLOCK  ((block_t) 0)      /* block number of boot block */
+#define SUPER_BLOCK_BYTES (1024)       /* bytes offset */
+#define START_BLOCK    2               /* first block of FS (not counting SB) */
+
+#define DIR_ENTRY_SIZE       usizeof (struct direct)  /* # bytes/dir entry   */
+#define NR_DIR_ENTRIES(b)   ((b)/DIR_ENTRY_SIZE)  /* # dir entries/blk   */
+#define SUPER_SIZE      usizeof (struct super_block)  /* super_block size    */
+#define PIPE_SIZE(b)          (V1_NR_DZONES*(b))  /* pipe size in bytes  */
+
+#define FS_BITMAP_CHUNKS(b) ((b)/usizeof (bitchunk_t))/* # map chunks/blk   */
+#define FS_BITCHUNK_BITS               (usizeof(bitchunk_t) * CHAR_BIT)
+#define FS_BITS_PER_BLOCK(b)   (FS_BITMAP_CHUNKS(b) * FS_BITCHUNK_BITS)
+
+/* Derived sizes pertaining to the V1 file system. */
+#define V1_ZONE_NUM_SIZE           usizeof (zone1_t)  /* # bytes in V1 zone  */
+#define V1_INODE_SIZE             usizeof (d1_inode)  /* bytes in V1 dsk ino */
+
+/* # zones/indir block */
+#define V1_INDIRECTS (_STATIC_BLOCK_SIZE/V1_ZONE_NUM_SIZE)  
+
+/* # V1 dsk inodes/blk */
+#define V1_INODES_PER_BLOCK (_STATIC_BLOCK_SIZE/V1_INODE_SIZE)
+
+/* Derived sizes pertaining to the V2 file system. */
+#define V2_ZONE_NUM_SIZE            usizeof (zone_t)  /* # bytes in V2 zone  */
+#define V2_INODE_SIZE             usizeof (d2_inode)  /* bytes in V2 dsk ino */
+#define V2_INDIRECTS(b)   ((b)/V2_ZONE_NUM_SIZE)  /* # zones/indir block */
+#define V2_INODES_PER_BLOCK(b) ((b)/V2_INODE_SIZE)/* # V2 dsk inodes/blk */
diff --git a/servers/mfs/device.c b/servers/mfs/device.c
new file mode 100644 (file)
index 0000000..7940dde
--- /dev/null
@@ -0,0 +1,299 @@
+
+#include "fs.h"
+#include <fcntl.h>
+#include <assert.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/endpoint.h>
+#include <minix/ioctl.h>
+#include <minix/safecopies.h>
+#include <string.h>
+#include "inode.h"
+#include "super.h"
+#include "const.h"
+#include "drivers.h"
+
+#include <minix/vfsif.h>
+
+PRIVATE int dummyproc;
+
+FORWARD _PROTOTYPE( int safe_io_conversion, (endpoint_t,
+  cp_grant_id_t *, int *, cp_grant_id_t *, int, endpoint_t *,
+  void **, int *, vir_bytes, off_t *));
+FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *,
+       int));
+
+/*===========================================================================*
+ *                             fs_clone_opcl                                *
+ *===========================================================================*/
+PUBLIC int fs_clone_opcl(void)
+{
+ /* A new minor device number has been returned.
+  * Create a temporary device file to hold it. 
+  */
+  struct inode *ip;
+  dev_t dev; 
+
+  dev = fs_m_in.REQ_DEV;   /* Device number */
+
+  ip = alloc_inode(fs_dev, ALL_MODES | I_CHAR_SPECIAL);
+
+  if (ip == NIL_INODE) return err_code;
+
+  ip->i_zone[0] = dev;
+
+  fs_m_out.m_source = ip->i_dev;
+  fs_m_out.RES_INODE_NR = ip->i_num;
+  fs_m_out.RES_MODE = ip->i_mode;
+  return OK;
+}
+
+
+/*===========================================================================*
+ *                             fs_new_driver                                *
+ *===========================================================================*/
+PUBLIC int fs_new_driver(void)
+{
+ /* New driver endpoint for this device */
+  driver_endpoints[(fs_m_in.REQ_DEV >> MAJOR) & BYTE].driver_e =
+      fs_m_in.REQ_DRIVER_E;
+  return OK;
+}
+
+
+/*===========================================================================*
+ *                             safe_io_conversion                           *
+ *===========================================================================*/
+PRIVATE int safe_io_conversion(driver, gid, op, gids, gids_size,
+       io_ept, buf, vec_grants, bytes, pos)
+endpoint_t driver;
+cp_grant_id_t *gid;
+int *op;
+cp_grant_id_t *gids;
+int gids_size;
+endpoint_t *io_ept;
+void **buf;
+int *vec_grants;
+vir_bytes bytes;
+off_t *pos;
+{
+       int access = 0, size;
+       int j;
+       iovec_t *v;
+       static iovec_t new_iovec[NR_IOREQS];
+
+       /* Number of grants allocated in vector I/O. */
+       *vec_grants = 0;
+
+       /* Driver can handle it - change request to a safe one. */
+
+       *gid = GRANT_INVALID;
+
+       switch(*op) {
+               case DEV_READ:
+               case DEV_WRITE:
+                       /* Change to safe op. */
+                       *op = *op == DEV_READ ? DEV_READ_S : DEV_WRITE_S;
+
+                       if((*gid=cpf_grant_direct(driver, (vir_bytes) *buf, 
+                               bytes, *op == DEV_READ_S ? CPF_WRITE : 
+                               CPF_READ)) < 0) {
+                               panic(__FILE__,
+                                "cpf_grant_magic of buffer failed\n", NO_NUM);
+                       }
+
+                       break;
+               case DEV_GATHER:
+               case DEV_SCATTER:
+                       /* Change to safe op. */
+                       *op = *op == DEV_GATHER ? DEV_GATHER_S : DEV_SCATTER_S;
+
+                       /* Grant access to my new i/o vector. */
+                       if((*gid = cpf_grant_direct(driver,
+                         (vir_bytes) new_iovec, bytes * sizeof(iovec_t),
+                         CPF_READ | CPF_WRITE)) < 0) {
+                               panic(__FILE__,
+                               "cpf_grant_direct of vector failed", NO_NUM);
+                       }
+                       v = (iovec_t *) *buf;
+                       /* Grant access to i/o buffers. */
+                       for(j = 0; j < bytes; j++) {
+                          if(j >= NR_IOREQS) 
+                               panic(__FILE__, "vec too big", bytes);
+                          new_iovec[j].iov_addr = gids[j] =
+                            cpf_grant_direct(driver, (vir_bytes)
+                            v[j].iov_addr, v[j].iov_size,
+                            *op == DEV_GATHER_S ? CPF_WRITE : CPF_READ);
+                          if(!GRANT_VALID(gids[j])) {
+                               panic(__FILE__, "grant to iovec buf failed",
+                                NO_NUM);
+                          }
+                          new_iovec[j].iov_size = v[j].iov_size;
+                          (*vec_grants)++;
+                       }
+
+                       /* Set user's vector to the new one. */
+                       *buf = new_iovec;
+                       break;
+               /*      
+               case DEV_IOCTL:
+                       *pos = *io_ept; 
+                       *op = DEV_IOCTL_S;
+                       if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE;
+                       if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ;
+                       size = _MINIX_IOCTL_SIZE(m_in.REQUEST);
+
+                       if((*gid=cpf_grant_magic(driver, *io_ept,
+                               (vir_bytes) *buf, size, access)) < 0) {
+                               panic(__FILE__,
+                               "cpf_grant_magic failed (ioctl)\n",
+                               NO_NUM);
+                       }
+               */
+       }
+
+       /* If we have converted to a safe operation, I/O
+        * endpoint becomes FS if it wasn't already.
+        */
+       if(GRANT_VALID(*gid)) {
+               *io_ept = SELF_E;
+               return 1;
+       }
+
+       /* Not converted to a safe operation (because there is no
+        * copying involved in this operation).
+        */
+       return 0;
+}
+
+/*===========================================================================*
+ *                     safe_io_cleanup                                      *
+ *===========================================================================*/
+PRIVATE void safe_io_cleanup(gid, gids, gids_size)
+cp_grant_id_t gid;
+cp_grant_id_t *gids;
+int gids_size;
+{
+/* Free resources (specifically, grants) allocated by safe_io_conversion(). */
+       int j;
+
+       cpf_revoke(gid);
+
+       for(j = 0; j < gids_size; j++)
+               cpf_revoke(gids[j]);
+
+       return;
+}
+
+/*===========================================================================*
+ *                     block_dev_io                                         *
+ *===========================================================================*/
+PUBLIC int block_dev_io(op, dev, proc_e, buf, pos, bytes, flags)
+int op;                                /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */
+dev_t dev;                     /* major-minor device number */
+int proc_e;                    /* in whose address space is buf? */
+void *buf;                     /* virtual address of the buffer */
+off_t pos;                     /* byte position */
+int bytes;                     /* how many bytes to transfer */
+int flags;                     /* special flags, like O_NONBLOCK */
+{
+/* Read or write from a device.  The parameter 'dev' tells which one. */
+  struct dmap *dp;
+  int r, safe;
+  message m;
+  iovec_t *v;
+  cp_grant_id_t gid = GRANT_INVALID;
+  int vec_grants;
+  int op_used;
+  void *buf_used;
+  static cp_grant_id_t gids[NR_IOREQS];
+  endpoint_t driver_e;
+  /* Determine driver endpoint for this device */
+  driver_e = driver_endpoints[(dev >> MAJOR) & BYTE].driver_e;
+  
+  /* See if driver is roughly valid. */
+  if (driver_e == NONE) {
+      printf("MFS(%d) block_dev_io: no driver for dev %x\n", SELF_E, dev);
+      return EDSTDIED;
+  }
+  
+  /* The io vector copying relies on this I/O being for FS itself. */
+  if(proc_e != SELF_E) {
+      printf("MFS(%d) doing block_dev_io for non-self %d\n", SELF_E, proc_e);
+      panic(__FILE__, "doing block_dev_io for non-self", proc_e);
+  }
+  
+  /* By default, these are right. */
+  m.IO_ENDPT = proc_e;
+  m.ADDRESS  = buf;
+  buf_used = buf;
+
+  /* Convert parameters to 'safe mode'. */
+  op_used = op;
+  safe = safe_io_conversion(driver_e, &gid,
+          &op_used, gids, NR_IOREQS, &m.IO_ENDPT, &buf_used,
+          &vec_grants, bytes, &pos);
+
+  /* Set up rest of the message. */
+  if (safe) m.IO_GRANT = (char *) gid;
+
+  m.m_type   = op_used;
+  m.DEVICE   = (dev >> MINOR) & BYTE;
+  m.POSITION = pos;
+  m.COUNT    = bytes;
+  m.HIGHPOS  = 0;
+
+  /* Call the task. */
+  r = sendrec(driver_e, &m);
+
+  /* As block I/O never SUSPENDs, safe cleanup must be done whether
+   * the I/O succeeded or not. */
+  if (safe) safe_io_cleanup(gid, gids, vec_grants);
+  
+  /* RECOVERY:
+   * - send back dead driver number
+   * - VFS unmaps it, waits for new driver
+   * - VFS sends the new dirver endp for the FS proc and the request again 
+   */
+  if (r != OK) {
+      if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) {
+          printf("MFS(%d) dead driver %d\n", SELF_E, driver_e);
+          driver_endpoints[(dev >> MAJOR) & BYTE].driver_e = NONE;
+          return r;
+          /*dmap_unmap_by_endpt(task_nr);    <- in the VFS proc...  */
+      }
+      else if (r == ELOCKED) {
+          printf("MFS(%d) ELOCKED talking to %d\n", SELF_E, driver_e);
+          return r;
+      }
+      else 
+          panic(__FILE__,"call_task: can't send/receive", r);
+  } 
+  else {
+      /* Did the process we did the sendrec() for get a result? */
+      if (m.REP_ENDPT != proc_e) {
+          printf("MFS(%d) strange device reply from %d, type = %d, proc = %d (not %d) (2) ignored\n", SELF_E, m.m_source, m.m_type, proc_e, m.REP_ENDPT);
+          r = EIO;
+      }
+  }
+
+  /* Task has completed.  See if call completed. */
+  if (m.REP_STATUS == SUSPEND) {
+      panic(__FILE__, "MFS block_dev_io: driver returned SUSPEND", NO_NUM);
+  }
+
+  if(buf != buf_used && r == OK) {
+      memcpy(buf, buf_used, bytes * sizeof(iovec_t));
+  }
+
+  return(m.REP_STATUS);
+}
+
+
+
+
+
+
+
+
diff --git a/servers/mfs/drivers.h b/servers/mfs/drivers.h
new file mode 100644 (file)
index 0000000..2f41fdd
--- /dev/null
@@ -0,0 +1,9 @@
+
+/* Driver endpoints for major devices. Only the block devices
+ * are mapped here, it's a subset of the mapping in the VFS */
+
+EXTERN struct driver_endpoints {
+    endpoint_t driver_e;
+} driver_endpoints[NR_DEVICES];
+
+
similarity index 100%
rename from servers/fs/file.h
rename to servers/mfs/file.h
similarity index 100%
rename from servers/fs/fproc.h
rename to servers/mfs/fproc.h
similarity index 100%
rename from servers/fs/fs.h
rename to servers/mfs/fs.h
diff --git a/servers/mfs/glo.h b/servers/mfs/glo.h
new file mode 100644 (file)
index 0000000..36cd883
--- /dev/null
@@ -0,0 +1,43 @@
+/* EXTERN should be extern except for the table file */
+#ifdef _TABLE
+#undef EXTERN
+#define EXTERN
+#endif
+
+EXTERN off_t rdahedpos;                /* position to read ahead */
+EXTERN struct inode *rdahed_inode;     /* pointer to inode to read ahead */
+
+/* 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 _PROTOTYPE (int (*fs_call_vec[]), (void) ); /* fs call table */
+
+EXTERN message fs_m_in;
+EXTERN message fs_m_out;
+EXTERN int FS_STATE;
+
+EXTERN uid_t caller_uid;
+EXTERN gid_t caller_gid;
+
+EXTERN time_t boottime;                /* time in seconds at system boot */
+EXTERN int req_nr;
+
+EXTERN int SELF_E;
+
+EXTERN struct inode *chroot_dir;
+
+EXTERN short path_processed;      /* number of characters processed */
+EXTERN char user_path[PATH_MAX];  /* pathname to be processed */
+EXTERN char *vfs_slink_storage;
+EXTERN int symloop;
+
+EXTERN dev_t fs_dev;    /* the device that is handled by this FS proc */
+
+
+
diff --git a/servers/mfs/inc.h b/servers/mfs/inc.h
new file mode 100644 (file)
index 0000000..9f22b60
--- /dev/null
@@ -0,0 +1,31 @@
+
+#define _SYSTEM            1    /* get OK and negative error codes */
+#define _MINIX             1   /* tell headers to include MINIX stuff */
+
+#define VERBOSE                   0    /* display diagnostics */
+
+#include <ansi.h>
+#include <sys/types.h>
+#include <limits.h>
+#include <errno.h>
+#include <signal.h>
+#include <unistd.h>
+
+#include <minix/callnr.h>
+#include <minix/config.h>
+#include <minix/type.h>
+#include <minix/const.h>
+#include <minix/com.h>
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+#include <minix/keymap.h>
+#include <minix/bitmap.h>
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include "proto.h"
+
similarity index 69%
rename from servers/fs/inode.c
rename to servers/mfs/inode.c
index 519c8244b20e4785b8a48b56c69bdae0122e6462..a98fc9671d8be976c5ebe536525e453b3e465232 100644 (file)
 
 #include "fs.h"
 #include "buf.h"
-#include "file.h"
-#include "fproc.h"
 #include "inode.h"
 #include "super.h"
 
+#include <minix/vfsif.h>
+
 FORWARD _PROTOTYPE( void old_icopy, (struct inode *rip, d1_inode *dip,
                                                int direction, int norm));
 FORWARD _PROTOTYPE( void new_icopy, (struct inode *rip, d2_inode *dip,
                                                int direction, int norm));
 
+
+/*===========================================================================*
+ *                             fs_putnode                                   *
+ *===========================================================================*/
+PUBLIC int fs_putnode()
+{
+/* Find the inode specified by the request message and decrease its counter.
+ */
+  struct inode *rip;
+  
+  /* Sanity check for the direct index */
+  if (fs_m_in.REQ_INODE_INDEX >= 0 && 
+          fs_m_in.REQ_INODE_INDEX < NR_INODES &&
+          inode[fs_m_in.REQ_INODE_INDEX].i_num == fs_m_in.REQ_INODE_NR) {
+      rip = &inode[fs_m_in.REQ_INODE_INDEX];
+  }
+  /* Otherwise find it */
+  else { 
+      rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR);
+  }
+
+  if (!rip)
+      printf("FSput_inode: inode #%d dev: %d couldn't be put, req_nr: %d\n", 
+            fs_m_in.REQ_INODE_NR, fs_dev, req_nr);
+
+  put_inode(rip);
+  return OK;
+}
+
+
+/*===========================================================================*
+ *                             fs_getnode                                   *
+ *===========================================================================*/
+PUBLIC int fs_getnode()
+{
+/* Increase the inode's counter specified in the request message
+ */
+  struct inode *rip;
+  /* Get the inode */
+  rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR);
+
+  if (!rip) {
+      printf("FS: inode #%d couldn't be found\n", fs_m_in.REQ_INODE_NR);
+      return EINVAL;
+  }
+
+  /* Transfer back the inode's details */
+  fs_m_out.m_source = rip->i_dev;
+  fs_m_out.RES_INODE_NR = rip->i_num;
+  fs_m_out.RES_MODE = rip->i_mode;
+  fs_m_out.RES_FILE_SIZE = rip->i_size;
+  fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0];
+
+  return OK;
+}
+
+
+/*===========================================================================*
+ *                             init_inode_cache                             *
+ *===========================================================================*/
+PUBLIC void init_inode_cache()
+{
+  struct inode *rip;
+  struct inodelist *rlp;
+
+  inode_cache_hit = 0;
+  inode_cache_miss = 0;
+
+  /* init free/unused list */
+  TAILQ_INIT(&unused_inodes);
+  
+  /* init hash lists */
+  for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp) 
+      LIST_INIT(rlp);
+
+  /* add free inodes to unused/free list */
+  for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) {
+      rip->i_num = 0;
+      TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
+  }
+}
+
+
+/*===========================================================================*
+ *                             addhash_inode                                *
+ *===========================================================================*/
+PRIVATE int addhash_inode(struct inode *node) 
+{
+  int hashi = node->i_num & INODE_HASH_MASK;
+  
+  /* insert into hash table */
+  LIST_INSERT_HEAD(&hash_inodes[hashi], node, i_hash);
+  return OK;
+}
+
+/*===========================================================================*
+ *                             unhash_inode                                 *
+ *===========================================================================*/
+PRIVATE int unhash_inode(struct inode *node) 
+{
+  /* remove from hash table */
+  LIST_REMOVE(node, i_hash);
+  return OK;
+}
+
 /*===========================================================================*
  *                             get_inode                                    *
  *===========================================================================*/
@@ -35,42 +140,81 @@ PUBLIC struct inode *get_inode(dev, numb)
 dev_t dev;                     /* device on which inode resides */
 int numb;                      /* inode number (ANSI: may not be unshort) */
 {
-/* Find a slot in the inode table, load the specified inode into it, and
- * return a pointer to the slot.  If 'dev' == NO_DEV, just return a free slot.
+/* Find the inode in the hash table. If it is not there, get a free inode
+ * load it from the disk if it's necessary and put on the hash list 
  */
-
   register struct inode *rip, *xp;
-
-  /* Search the inode table both for (dev, numb) and a free slot. */
-  xp = NIL_INODE;
-  for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
-       if (rip->i_count > 0) { /* only check used slots for (dev, numb) */
-               if (rip->i_dev == dev && rip->i_num == numb) {
-                       /* This is the inode that we are looking for. */
-                       rip->i_count++;
-                       return(rip);    /* (dev, numb) found */
-               }
-       } else {
-               xp = rip;       /* remember this free slot for later */
-       }
+  int hashi;
+
+  hashi = numb & INODE_HASH_MASK;
+
+  /* Search inode in the hash table */
+  LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
+      if (rip->i_num == numb && rip->i_dev == dev) {
+          /* If unused, remove it from the unused/free list */
+          if (rip->i_count == 0) {
+             inode_cache_hit++;
+              TAILQ_REMOVE(&unused_inodes, rip, i_unused);
+         }
+          ++rip->i_count;
+          return rip;
+      }
   }
 
-  /* Inode we want is not currently in use.  Did we find a free slot? */
-  if (xp == NIL_INODE) {       /* inode table completely full */
-       err_code = ENFILE;
-       return(NIL_INODE);
+  inode_cache_miss++;
+
+  /* Inode is not on the hash, get a free one */
+  if (TAILQ_EMPTY(&unused_inodes)) {
+      err_code = ENFILE;
+      return NIL_INODE;
   }
+  rip = TAILQ_FIRST(&unused_inodes);
+
+  /* If not free unhash it */
+  if (rip->i_num != 0)
+      unhash_inode(rip);
+  
+  /* Inode is not unused any more */
+  TAILQ_REMOVE(&unused_inodes, rip, i_unused);
+
+  /* Load the inode. */
+  rip->i_dev = dev;
+  rip->i_num = numb;
+  rip->i_count = 1;
+  if (dev != NO_DEV) rw_inode(rip, READING);   /* get inode from disk */
+  rip->i_update = 0;           /* all the times are initially up-to-date */
+
+  /* Add to hash */
+  addhash_inode(rip);
+  
+  return(rip);
+}
+
+/*===========================================================================*
+ *                             find_inode                                   *
+ *===========================================================================*/
+PUBLIC struct inode *find_inode(dev, numb)
+dev_t dev;                     /* device on which inode resides */
+int numb;                      /* inode number (ANSI: may not be unshort) */
+{
+/* Find the inode specified by the inode and device number.
+ */
+  struct inode *rip;
+  int hashi;
 
-  /* A free inode slot has been located.  Load the inode into it. */
-  xp->i_dev = dev;
-  xp->i_num = numb;
-  xp->i_count = 1;
-  if (dev != NO_DEV) rw_inode(xp, READING);    /* get inode from disk */
-  xp->i_update = 0;            /* all the times are initially up-to-date */
+  hashi = numb & INODE_HASH_MASK;
 
-  return(xp);
+  /* Search inode in the hash table */
+  LIST_FOREACH(rip, &hash_inodes[hashi], i_hash) {
+      if (rip->i_count > 0 && rip->i_num == numb && rip->i_dev == dev) {
+          return rip;
+      }
+  }
+  
+  return NIL_INODE;
 }
 
+
 /*===========================================================================*
  *                             put_inode                                    *
  *===========================================================================*/
@@ -83,6 +227,7 @@ register struct inode *rip;  /* pointer to inode to be released */
  */
 
   if (rip == NIL_INODE) return;        /* checking here is easier than in caller */
+
   if (--rip->i_count == 0) {   /* i_count == 0 means no one is using it now */
        if (rip->i_nlinks == 0) {
                /* i_nlinks == 0 means free the inode. */
@@ -90,14 +235,28 @@ register struct inode *rip;        /* pointer to inode to be released */
                rip->i_mode = I_NOT_ALLOC;      /* clear I_TYPE field */
                rip->i_dirt = DIRTY;
                free_inode(rip->i_dev, rip->i_num);
-       } else {
+       } 
+        else {
                if (rip->i_pipe == I_PIPE) truncate_inode(rip, 0);
        }
+        rip->i_mount = NO_MOUNT;
        rip->i_pipe = NO_PIPE;  /* should always be cleared */
        if (rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
+
+       if (rip->i_nlinks == 0) {
+               /* free, put at the front of the LRU list */
+               unhash_inode(rip);
+               rip->i_num = 0;
+               TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
+       }
+       else {
+               /* unused, put at the back of the LRU (cache it) */
+               TAILQ_INSERT_TAIL(&unused_inodes, rip, i_unused);
+       }
   }
 }
 
+
 /*===========================================================================*
  *                             alloc_inode                                  *
  *===========================================================================*/
@@ -122,8 +281,7 @@ PUBLIC struct inode *alloc_inode(dev_t dev, mode_t bits)
        err_code = ENFILE;
        major = (int) (sp->s_dev >> MAJOR) & BYTE;
        minor = (int) (sp->s_dev >> MINOR) & BYTE;
-       printf("Out of i-nodes on %sdevice %d/%d\n",
-               sp->s_dev == root_dev ? "root " : "", major, minor);
+       printf("Out of i-nodes on device %d/%d\n", major, minor);
        return(NIL_INODE);
   }
   sp->s_isearch = b;           /* next time start here */
@@ -137,8 +295,8 @@ PUBLIC struct inode *alloc_inode(dev_t dev, 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_nlinks = 0;              /* initial no links */
-       rip->i_uid = fp->fp_effuid;     /* file's uid is owner's */
-       rip->i_gid = fp->fp_effgid;     /* ditto group id */
+       rip->i_uid = caller_uid;        /* file's uid is owner's */
+       rip->i_gid = caller_gid;        /* ditto group id */
        rip->i_dev = dev;               /* mark which device it is on */
        rip->i_ndzones = sp->s_ndzones; /* number of direct zones */
        rip->i_nindirs = sp->s_nindirs; /* number of indirect zones per blk*/
diff --git a/servers/mfs/inode.h b/servers/mfs/inode.h
new file mode 100644 (file)
index 0000000..77effb0
--- /dev/null
@@ -0,0 +1,62 @@
+/* Inode table.  This table holds inodes that are currently in use.  In some
+ * cases they have been opened by an open() or creat() system call, in other
+ * cases the file system itself needs the inode for one reason or another,
+ * such as to search a directory for a path name.
+ * The first part of the struct holds fields that are present on the
+ * disk; the second part holds fields not present on the disk.
+ * The disk inode part is also declared in "type.h" as 'd1_inode' for V1
+ * file systems and 'd2_inode' for V2 file systems.
+ */
+
+#include "queue.h"
+
+EXTERN struct inode {
+  mode_t i_mode;               /* file type, protection, etc. */
+  nlink_t i_nlinks;            /* how many links to this file */
+  uid_t i_uid;                 /* user id of the file's owner */
+  gid_t i_gid;                 /* group number */
+  off_t i_size;                        /* current file size in bytes */
+  time_t i_atime;              /* time of last access (V2 only) */
+  time_t i_mtime;              /* when was file data last changed */
+  time_t i_ctime;              /* when was inode itself changed (V2 only)*/
+  zone_t i_zone[V2_NR_TZONES]; /* zone numbers for direct, ind, and dbl ind */
+  
+  /* The following items are not present on the disk. */
+  dev_t i_dev;                 /* which device is the inode on */
+  ino_t i_num;                 /* inode number on its (minor) device */
+  int i_count;                 /* # times inode used; 0 means slot is free */
+  int i_ndzones;               /* # direct zones (Vx_NR_DZONES) */
+  int i_nindirs;               /* # indirect zones per indirect block */
+  struct super_block *i_sp;    /* pointer to super block for inode's device */
+  char i_dirt;                 /* CLEAN or DIRTY */
+  char i_pipe;                 /* set to I_PIPE if pipe */
+  
+  char i_mount;                        /* this bit is set if file mounted on */
+  short i_vmnt_ind;             /* index of the vmnt mounted on */
+
+  char i_seek;                 /* set on LSEEK, cleared on READ/WRITE */
+  char i_update;               /* the ATIME, CTIME, and MTIME bits are here */
+
+  LIST_ENTRY(inode) i_hash;     /* hash list */
+  TAILQ_ENTRY(inode) i_unused;  /* free and unused list */
+  
+} inode[NR_INODES];
+
+/* list of unused/free inodes */ 
+EXTERN TAILQ_HEAD(unused_inodes_t, inode)  unused_inodes;
+
+/* inode hashtable */
+EXTERN LIST_HEAD(inodelist, inode)         hash_inodes[INODE_HASH_SIZE];
+
+EXTERN unsigned int inode_cache_hit;
+EXTERN unsigned int inode_cache_miss;
+
+#define NIL_INODE (struct inode *) 0   /* indicates absence of inode slot */
+
+/* Field values.  Note that CLEAN and DIRTY are defined in "const.h" */
+#define NO_PIPE            0   /* i_pipe is NO_PIPE if inode is not a pipe */
+#define I_PIPE             1   /* i_pipe is I_PIPE if inode is a pipe */
+#define NO_MOUNT           0   /* i_mount is NO_MOUNT if file not mounted on*/
+#define I_MOUNT            1   /* i_mount is I_MOUNT if file mounted on */
+#define NO_SEEK            0   /* i_seek = NO_SEEK if last op was not SEEK */
+#define ISEEK              1   /* i_seek = ISEEK if last op was SEEK */
similarity index 74%
rename from servers/fs/link.c
rename to servers/mfs/link.c
index 8fef8f8e275c88b5167d88c7e76ae8e4de0f7b5b..155421ee7954077e9aadea7ff5a1a4d46d6236ed 100644 (file)
@@ -1,29 +1,17 @@
-/* This file handles the LINK and UNLINK system calls.  It also deals with
- * deallocating the storage used by a file when the last UNLINK is done to a
- * file and the blocks must be returned to the free block pool.
- *
- * The entry points into this file are
- *   do_link:         perform the LINK system call
- *   do_unlink:              perform the UNLINK and RMDIR system calls
- *   do_rename:              perform the RENAME system call
- *   do_truncate:     perform the TRUNCATE system call
- *   do_ftruncate:    perform the FTRUNCATE system call
- *   truncate_inode:  release the blocks associated with an inode up to a size
- *   freesp_inode:    release a range of blocks without setting the size
- */
+
 
 #include "fs.h"
 #include <sys/stat.h>
 #include <string.h>
 #include <minix/com.h>
 #include <minix/callnr.h>
+
 #include "buf.h"
-#include "file.h"
-#include "fproc.h"
 #include "inode.h"
-#include "param.h"
 #include "super.h"
 
+#include <minix/vfsif.h>
+
 #define SAME 1000
 
 FORWARD _PROTOTYPE( int remove_dir, (struct inode *rldirp, struct inode *rip,
@@ -38,10 +26,11 @@ FORWARD _PROTOTYPE( void zeroblock_range, (struct inode *i, off_t p, off_t h));
 #define FIRST_HALF     0
 #define LAST_HALF      1
 
+
 /*===========================================================================*
- *                             do_link                                      *
+ *                             fs_link                                      *
  *===========================================================================*/
-PUBLIC int do_link()
+PUBLIC int fs_link()
 {
 /* Perform the link(name1, name2) system call. */
 
@@ -50,10 +39,20 @@ PUBLIC int do_link()
   char string[NAME_MAX];
   struct inode *new_ip;
 
-  /* See if 'name' (file to be linked) exists. */
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
-
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Copy the link name's last component */
+  r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH,
+          SELF, (vir_bytes) string, 
+          (phys_bytes) fs_m_in.REQ_PATH_LEN);
+  
+  /* Temporarily open the file. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_LINKED_FILE)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_link() failed\n", SELF_E);
+        return(EINVAL);
+  }
+  
   /* Check to see if the file has maximum number of links already. */
   r = OK;
   if (rip->i_nlinks >= (rip->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX))
@@ -61,7 +60,8 @@ PUBLIC int do_link()
 
   /* Only super_user may link to directories. */
   if (r == OK)
-       if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;
+       if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && caller_uid != SU_UID) 
+               r = EPERM;
 
   /* If error with 'name', return the inode. */
   if (r != OK) {
@@ -69,12 +69,11 @@ PUBLIC int do_link()
        return(r);
   }
 
-  /* Does the final directory of 'name2' exist? */
-  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
-       put_inode(rip);
-       return(err_code);
+  /* Temporarily open the last dir */
+  if ( (ip = get_inode(fs_dev, fs_m_in.REQ_LINK_PARENT)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_link() failed\n", SELF_E);
+        return(EINVAL);
   }
-  if ( (ip = last_dir(user_path, string)) == NIL_INODE) r = err_code;
 
   /* If 'name2' exists in full (even if no space) set 'r' to error. */
   if (r == OK) {
@@ -87,10 +86,6 @@ PUBLIC int do_link()
        }
   }
 
-  /* Check for links across devices. */
-  if (r == OK)
-       if (rip->i_dev != ip->i_dev) r = EXDEV;
-
   /* Try to link. */
   if (r == OK)
        r = search_dir(ip, string, &rip->i_num, ENTER);
@@ -108,47 +103,54 @@ PUBLIC int do_link()
   return(r);
 }
 
+
 /*===========================================================================*
- *                             do_unlink                                    *
+ *                             fs_unlink                                    *
  *===========================================================================*/
-PUBLIC int do_unlink()
+PUBLIC int fs_unlink()
 {
 /* Perform the unlink(name) or rmdir(name) system call. The code for these two
  * is almost the same.  They differ only in some condition testing.  Unlink()
  * may be used by the superuser to do dangerous things; rmdir() may not.
  */
-
   register struct inode *rip;
   struct inode *rldirp;
   int r;
   char string[NAME_MAX];
+  
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Copy the last component */
+  r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH,
+          SELF, (vir_bytes) string, 
+          (phys_bytes) fs_m_in.REQ_PATH_LEN);
 
-  /* Get the last directory in the path. */
-  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  if ( (rldirp = last_dir(user_path, string)) == NIL_INODE)
-       return(err_code);
-
+  if (r != OK) return r;
+  
+  /* Temporarily open the dir. */
+  if ( (rldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+        return(EINVAL);
+  }
+  
   /* The last directory exists.  Does the file also exist? */
   r = OK;
   if ( (rip = advance(&rldirp, string)) == NIL_INODE) r = err_code;
 
   /* If error, return inode. */
   if (r != OK) {
+        /* Mount point? */
+        if (r == EENTERMOUNT || r == ELEAVEMOUNT)
+            r = EBUSY;
        put_inode(rldirp);
        return(r);
   }
 
-  /* Do not remove a mount point. */
-  if (rip->i_num == ROOT_INODE) {
-       put_inode(rldirp);
-       put_inode(rip);
-       return(EBUSY);
-  }
-
   /* Now test if the call is allowed, separately for unlink() and rmdir(). */
-  if (call_nr == UNLINK) {
+  if (fs_m_in.m_type == REQ_UNLINK) {
        /* Only the su may unlink directories, but the su can unlink any dir.*/
-       if ( (rip->i_mode & I_TYPE) == I_DIRECTORY && !super_user) r = EPERM;
+       if ( (rip->i_mode & I_TYPE) == I_DIRECTORY 
+                && caller_uid != SU_UID) r = EPERM;
 
        /* Don't unlink a file if it is the root of a mounted file system. */
        if (rip->i_num == ROOT_INODE) r = EBUSY;
@@ -156,7 +158,8 @@ PUBLIC int do_unlink()
        /* Actually try to unlink the file; fails if parent is mode 0 etc. */
        if (r == OK) r = unlink_file(rldirp, rip, string);
 
-  } else {
+  } 
+  else {
        r = remove_dir(rldirp, rip, string); /* call is RMDIR */
   }
 
@@ -166,13 +169,126 @@ PUBLIC int do_unlink()
   return(r);
 }
 
+
+
 /*===========================================================================*
- *                             do_rename                                    *
+ *                             fs_rdlink                                     *
  *===========================================================================*/
-PUBLIC int do_rename()
+PUBLIC int fs_rdlink()
 {
-/* Perform the rename(name1, name2) system call. */
+  block_t b;                   /* block containing link text */
+  struct buf *bp;              /* buffer containing link text */
+  register struct inode *rip;  /* target inode */
+  register int r;              /* return value */
+  int copylen;
+  
+  copylen = fs_m_in.REQ_SLENGTH;
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+
+  /* Temporarily open the file. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+        return(EINVAL);
+  }
+
+  r = EACCES;
+  if (S_ISLNK(rip->i_mode) && (b = read_map(rip, (off_t) 0)) != NO_BLOCK) {
+       if (copylen <= 0) r = EINVAL;
+       else if (copylen < rip->i_size) r = ERANGE;
+       else {
+              if(rip->i_size < copylen) copylen = rip->i_size;
+               bp = get_block(rip->i_dev, b, NORMAL);
+               r = sys_vircopy(SELF, D, (vir_bytes) bp->b_data,
+               fs_m_in.REQ_WHO_E, D, (vir_bytes) fs_m_in.REQ_USER_ADDR, 
+                (vir_bytes) copylen);
+
+               if (r == OK) r = copylen;
+               put_block(bp, DIRECTORY_BLOCK);
+       }
+  }
+
+  put_inode(rip);
+  return(r);
+}
+
+
+/*===========================================================================*
+ *                             remove_dir                                   *
+ *===========================================================================*/
+PRIVATE int remove_dir(rldirp, rip, dir_name)
+struct inode *rldirp;                  /* parent directory */
+struct inode *rip;                     /* directory to be removed */
+char dir_name[NAME_MAX];               /* name of directory to be removed */
+{
+  /* A directory file has to be removed. Five conditions have to met:
+   *   - The file must be a directory
+   *   - The directory must be empty (except for . and ..)
+   *   - The final component of the path must not be . or ..
+   *   - The directory must not be the root of a mounted file system (VFS)
+   *   - The directory must not be anybody's root/working directory (VFS)
+   */
+  int r;
+
+  /* search_dir checks that rip is a directory too. */
+  if ((r = search_dir(rip, "", (ino_t *) 0, IS_EMPTY)) != 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. */
+  if ((r = unlink_file(rldirp, rip, dir_name)) != OK) return r;
 
+  /* 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, NIL_INODE, dot1);
+  (void) unlink_file(rip, NIL_INODE, dot2);
+  return(OK);
+}
+
+
+/*===========================================================================*
+ *                             unlink_file                                  *
+ *===========================================================================*/
+PRIVATE int unlink_file(dirp, rip, file_name)
+struct inode *dirp;            /* parent directory of file */
+struct inode *rip;             /* inode of file, may be NIL_INODE too. */
+char file_name[NAME_MAX];      /* name of file to be removed */
+{
+/* Unlink 'file_name'; rip must be the inode of 'file_name' or NIL_INODE. */
+
+  ino_t numb;                  /* inode number */
+  int  r;
+
+  /* If rip is not NIL_INODE, it is used to get faster access to the inode. */
+  if (rip == NIL_INODE) {
+       /* Search for file in directory and try to get its inode. */
+       err_code = search_dir(dirp, file_name, &numb, LOOK_UP);
+       if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb);
+       if (err_code != OK || rip == NIL_INODE) return(err_code);
+  } else {
+       dup_inode(rip);         /* inode will be returned with put_inode */
+  }
+
+  r = search_dir(dirp, file_name, (ino_t *) 0, DELETE);
+
+  if (r == OK) {
+       rip->i_nlinks--;        /* entry deleted from parent's dir */
+       rip->i_update |= CTIME;
+       rip->i_dirt = DIRTY;
+  }
+
+  put_inode(rip);
+  return(r);
+}
+
+
+/*===========================================================================*
+ *                             fs_rename                                    *
+ *===========================================================================*/
+PUBLIC int fs_rename()
+{
+/* Perform the rename(name1, name2) system call. */
   struct inode *old_dirp, *old_ip;     /* ptrs to old dir, file inodes */
   struct inode *new_dirp, *new_ip;     /* ptrs to new dir, file inodes */
   struct inode *new_superdirp, *next_new_superdirp;
@@ -183,15 +299,30 @@ PUBLIC int do_rename()
   ino_t numb;
   int r1;
   
-  /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
-  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-  if ( (old_dirp = last_dir(user_path, old_name))==NIL_INODE) return(err_code);
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Copy the last component of the old name */
+  r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH,
+          SELF, (vir_bytes) old_name, 
+          (phys_bytes) fs_m_in.REQ_PATH_LEN);
+  if (r != OK) return r;
+  
+  /* Copy the last component of the new name */
+  r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_USER_ADDR,
+          SELF, (vir_bytes) new_name, 
+          (phys_bytes) fs_m_in.REQ_SLENGTH);
+  if (r != OK) return r;
+
+  /* Get old dir inode */ 
+  if ( (old_dirp = get_inode(fs_dev, fs_m_in.REQ_OLD_DIR)) == NIL_INODE) 
+        return(err_code);
 
   if ( (old_ip = advance(&old_dirp, old_name)) == NIL_INODE) r = err_code;
 
-  /* See if 'name2' (new name) exists.  Get dir and file inodes. */
-  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) r = err_code;
-  if ( (new_dirp = last_dir(user_path, new_name)) == NIL_INODE) r = err_code;
+  /* Get new dir inode */ 
+  if ( (new_dirp = get_inode(fs_dev, fs_m_in.REQ_NEW_DIR)) == NIL_INODE) 
+      r = err_code;
   new_ip = advance(&new_dirp, new_name);       /* not required to exist */
 
   if (old_ip != NIL_INODE)
@@ -206,13 +337,25 @@ PUBLIC int do_rename()
                dup_inode(new_superdirp = new_dirp);
                while (TRUE) {          /* may hang in a file system loop */
                        if (new_superdirp == old_ip) {
+                               put_inode(new_superdirp);
                                r = EINVAL;
                                break;
                        }
                        next_new_superdirp = advance(&new_superdirp, dot2);
                        put_inode(new_superdirp);
-                       if (next_new_superdirp == new_superdirp)
-                               break;  /* back at system root directory */
+                       /*
+                       if (next_new_superdirp == new_superdirp) {
+                               put_inode(new_superdirp);
+                               break;  
+                       }
+                       */
+                       if (err_code == ELEAVEMOUNT) {
+                               /* imitate that we are back at the root,
+                                * cross device checked already on VFS */
+                               /*next_new_superdirp = new_superdirp;*/
+                               err_code = OK;
+                               break;
+                       }
                        new_superdirp = next_new_superdirp;
                        if (new_superdirp == NIL_INODE) {
                                /* Missing ".." entry.  Assume the worst. */
@@ -220,36 +363,49 @@ PUBLIC int do_rename()
                                break;
                        }
                }       
-               put_inode(new_superdirp);
+               /*put_inode(new_superdirp);*/
        }       
 
        /* 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;
+           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; */
 
        /* Parent dirs must be writable, searchable and on a writable device */
        if ((r1 = forbidden(old_dirp, W_BIT | X_BIT)) != OK ||
-           (r1 = forbidden(new_dirp, W_BIT | X_BIT)) != OK) r = r1;
+           (r1 = forbidden(new_dirp, W_BIT | X_BIT)) != OK) {
+               r = r1;
+       }
 
        /* Some tests apply only if the new path exists. */
        if (new_ip == NIL_INODE) {
-               /* don't rename a file with a file system mounted on it. */
-               if (old_ip->i_dev != old_dirp->i_dev) r = EXDEV;
+               /* 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_nlinks >=
                    (new_dirp->i_sp->s_version == V1 ? CHAR_MAX : SHRT_MAX) &&
-                   !same_pdir && r == OK) r = EMLINK;
-       } else {
-               if (old_ip == new_ip) r = SAME; /* old=new */
-
-               /* has the old file or new file a file system mounted on it? */
+                   !same_pdir && r == OK) { 
+                       r = EMLINK;
+               }
+       } 
+       else {
+               if (old_ip == new_ip) {
+                       r = SAME; /* old=new */
+               }
+               
+               /* has the old file or new file a file system mounted on it? 
                if (old_ip->i_dev != new_ip->i_dev) r = EXDEV;
+               */
 
                ndir = ((new_ip->i_mode & I_TYPE) == I_DIRECTORY); /* dir ? */
-               if (odir == TRUE && ndir == FALSE) r = ENOTDIR;
-               if (odir == FALSE && ndir == TRUE) r = EISDIR;
+               if (odir == TRUE && ndir == FALSE) {
+                       r = ENOTDIR;
+               }
+               if (odir == FALSE && ndir == TRUE) {
+                       r = EISDIR;
+               }
        }
   }
 
@@ -320,46 +476,65 @@ PUBLIC int do_rename()
   return(r == SAME ? OK : r);
 }
 
+
 /*===========================================================================*
- *                             do_truncate                                  *
+ *                             fs_trunc                                     *
  *===========================================================================*/
-PUBLIC int do_truncate()
+PUBLIC int fs_trunc()
 {
-/* truncate_inode() does the actual work of do_truncate() and do_ftruncate().
- * do_truncate() and do_ftruncate() have to get hold of the inode, either
- * by name or fd, do checks on it, and call truncate_inode() to do the
- * work.
- */
-       int r;
-       struct inode *rip;      /* pointer to inode to be truncated */
-
-       if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK)
-               return err_code;
-       if( (rip = eat_path(user_path)) == NIL_INODE)
-               return err_code;
-       if ( (rip->i_mode & I_TYPE) != I_REGULAR)
-               r = EINVAL;
-       else
-               r = truncate_inode(rip, m_in.m2_l1); 
-       put_inode(rip);
+  struct inode *rip;
+  int r = OK;
+  
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Temporarily open the file. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_chmod() failed\n", SELF_E);
+        return(EINVAL);
+  }
+  
+  if ( (rip->i_mode & I_TYPE) != I_REGULAR)
+        r = EINVAL;
+  else
+        r = truncate_inode(rip, fs_m_in.REQ_LENGTH); 
+  
+  put_inode(rip);
 
-       return r;
+  return r;
 }
 
 /*===========================================================================*
- *                             do_ftruncate                                 *
+ *                             fs_ftrunc                                    *
  *===========================================================================*/
-PUBLIC int do_ftruncate()
+PUBLIC int fs_ftrunc(void)
 {
-/* As with do_truncate(), truncate_inode() does the actual work. */
-       struct filp *rfilp;
-       if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP)
-               return err_code;
-       if ( (rfilp->filp_ino->i_mode & I_TYPE) != I_REGULAR)
-               return EINVAL;
-       return truncate_inode(rfilp->filp_ino, m_in.m2_l1);
+  struct inode *rip;
+  off_t start, end;
+  int r;
+  
+  if ( (rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR)) 
+                 == NIL_INODE) {
+          printf("FSfreesp: couldn't find inode %d\n", 
+                         fs_m_in.REQ_FD_INODE_NR); 
+          return EINVAL;
+  }
+
+  start = fs_m_in.REQ_FD_START;
+  end = fs_m_in.REQ_FD_END;
+
+  if (end == 0) {
+      r = truncate_inode(rip, start);
+  }
+  else {
+      r = freesp_inode(rip, start, end);
+  }
+  
+  return r;
 }
 
+    
+
 /*===========================================================================*
  *                             truncate_inode                               *
  *===========================================================================*/
@@ -539,78 +714,4 @@ off_t len;
        put_block(bp, FULL_DATA_BLOCK);
 }
 
-/*===========================================================================*
- *                             remove_dir                                   *
- *===========================================================================*/
-PRIVATE int remove_dir(rldirp, rip, dir_name)
-struct inode *rldirp;                  /* parent directory */
-struct inode *rip;                     /* directory to be removed */
-char dir_name[NAME_MAX];               /* name of directory to be removed */
-{
-  /* A directory file has to be removed. Five conditions have to met:
-   *   - The file must be a directory
-   *   - The directory must be empty (except for . and ..)
-   *   - The final component of the path must not be . or ..
-   *   - The directory must not be the root of a mounted file system
-   *   - The directory must not be anybody's root/working directory
-   */
-
-  int r;
-  register struct fproc *rfp;
 
-  /* search_dir checks that rip is a directory too. */
-  if ((r = search_dir(rip, "", (ino_t *) 0, IS_EMPTY)) != 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' */
-  
-  for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS]; rfp++)
-       if (rfp->fp_pid != PID_FREE &&
-            (rfp->fp_workdir == rip || rfp->fp_rootdir == rip))
-               return(EBUSY); /* can't remove anybody's working dir */
-
-  /* Actually try to unlink the file; fails if parent is mode 0 etc. */
-  if ((r = unlink_file(rldirp, rip, dir_name)) != OK) return r;
-
-  /* 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, NIL_INODE, dot1);
-  (void) unlink_file(rip, NIL_INODE, dot2);
-  return(OK);
-}
-
-/*===========================================================================*
- *                             unlink_file                                  *
- *===========================================================================*/
-PRIVATE int unlink_file(dirp, rip, file_name)
-struct inode *dirp;            /* parent directory of file */
-struct inode *rip;             /* inode of file, may be NIL_INODE too. */
-char file_name[NAME_MAX];      /* name of file to be removed */
-{
-/* Unlink 'file_name'; rip must be the inode of 'file_name' or NIL_INODE. */
-
-  ino_t numb;                  /* inode number */
-  int  r;
-
-  /* If rip is not NIL_INODE, it is used to get faster access to the inode. */
-  if (rip == NIL_INODE) {
-       /* Search for file in directory and try to get its inode. */
-       err_code = search_dir(dirp, file_name, &numb, LOOK_UP);
-       if (err_code == OK) rip = get_inode(dirp->i_dev, (int) numb);
-       if (err_code != OK || rip == NIL_INODE) return(err_code);
-  } else {
-       dup_inode(rip);         /* inode will be returned with put_inode */
-  }
-
-  r = search_dir(dirp, file_name, (ino_t *) 0, DELETE);
-
-  if (r == OK) {
-       rip->i_nlinks--;        /* entry deleted from parent's dir */
-       rip->i_update |= CTIME;
-       rip->i_dirt = DIRTY;
-  }
-
-  put_inode(rip);
-  return(r);
-}
similarity index 100%
rename from servers/fs/lock.h
rename to servers/mfs/lock.h
diff --git a/servers/mfs/main.c b/servers/mfs/main.c
new file mode 100644 (file)
index 0000000..5da82d7
--- /dev/null
@@ -0,0 +1,198 @@
+
+#include "inc.h"
+#include <minix/dmap.h>
+#include <minix/endpoint.h>
+
+#include <minix/vfsif.h>
+#include "fs.h"
+#include "buf.h"
+#include "inode.h"
+#include "drivers.h"
+
+
+/* Declare some local functions. */
+FORWARD _PROTOTYPE(void init_server, (void)                            );
+FORWARD _PROTOTYPE(void get_work, (message *m_in)                      );
+
+FORWARD _PROTOTYPE(void cch_check, (void)                              );
+
+
+/*===========================================================================*
+ *                             main                                         *
+ *===========================================================================*/
+PUBLIC int main(void)
+{
+/* 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 who_e;                                   /* caller */
+  int error;
+  message m;
+
+  /* Initialize the server, then go to work. */
+  init_server();       
+
+  printf("\nMFS(%d): STARTED: Logging in to VFS\n", SELF_E);
+  fs_m_in.m_type = FS_READY;
+
+  if (sendrec(FS_PROC_NR, &fs_m_in) != OK) {
+      printf("MFS(%d): Error sending login to VFS\n", SELF_E);
+      return -1;
+  }
+
+  if (fs_m_in.m_type != REQ_READSUPER) {
+      printf("MFS(%d): Invalid login reply\n", SELF_E);
+      return -1;
+  }
+  else {
+      fs_m_out.m_type = fs_readsuper();
+      reply(FS_PROC_NR, &fs_m_out);
+      if (fs_m_out.m_type != OK) return -1;
+  }
+  printf("MFS(%d): Login + Readsuper OK\n", SELF_E);
+
+
+  for (;;) {
+      /* Wait for request message. */
+      get_work(&fs_m_in);
+      error = OK;
+
+      who_e = fs_m_in.m_source;
+      if (who_e != FS_PROC_NR) {
+          if (who_e == 0) {
+            /*
+               printf("MFS(%d): MSG from PM\n", SELF_E); 
+              error = 1;
+              fs_m_out.m_type = error; 
+              reply(who_e, &fs_m_out);
+            */
+          }
+          continue;
+      }
+
+      req_nr = fs_m_in.m_type;
+
+      if (req_nr < 0 || req_nr >= NREQS) {
+          error = EINVAL; 
+      }
+      else {
+          error = (*fs_call_vec[req_nr])();
+         /*cch_check();*/
+      }
+
+      fs_m_out.m_type = error; 
+      reply(who_e, &fs_m_out);
+      
+               
+      if (error == OK && rdahed_inode != NIL_INODE) {
+          read_ahead(); /* do block read ahead */
+      }
+
+      /*
+       * VFS asks RS to bring down the FS... */
+      /*
+      if (req_nr == REQ_UNMOUNT || 
+              (req_nr == REQ_READSUPER && error != OK)) {
+          printf("MFS(%d) exit() cachehit: %d cachemiss: %d\n", SELF_E,
+                         inode_cache_hit, inode_cache_miss);
+          return 0;
+      }
+      */
+  }
+}
+
+/*===========================================================================*
+ *                             buf_pool                                     *
+ *===========================================================================*/
+PRIVATE void buf_pool(void)
+{
+/* Initialize the buffer pool. */
+  register struct buf *bp;
+
+  bufs_in_use = 0;
+  front = &buf[0];
+  rear = &buf[NR_BUFS - 1];
+
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
+       bp->b_blocknr = NO_BLOCK;
+       bp->b_dev = NO_DEV;
+       bp->b_next = bp + 1;
+       bp->b_prev = bp - 1;
+  }
+  buf[0].b_prev = NIL_BUF;
+  buf[NR_BUFS - 1].b_next = NIL_BUF;
+
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
+  buf_hash[0] = front;
+
+}
+
+
+/*===========================================================================*
+ *                             init_server                                  *
+ *===========================================================================*/
+PRIVATE void init_server(void)
+{
+   int i;
+
+   /* Init inode table */
+   for (i = 0; i < NR_INODES; ++i) {
+          inode[i].i_count = 0;
+          cch[i] = 0;
+   }
+       
+   init_inode_cache();
+
+   /* Init driver mapping */
+   for (i = 0; i < NR_DEVICES; ++i) 
+       driver_endpoints[i].driver_e = NONE;
+       
+   SELF_E = getprocnr();
+   buf_pool();
+}
+
+/*===========================================================================*
+ *                             get_work                                     *
+ *===========================================================================*/
+PRIVATE void get_work(m_in)
+message *m_in;                         /* pointer to message */
+{
+    int s;                             /* receive status */
+    if (OK != (s = receive(ANY, m_in)))        /* wait for message */
+        panic("MFS","receive failed", s);
+}
+
+
+/*===========================================================================*
+ *                             reply                                        *
+ *===========================================================================*/
+PUBLIC void reply(who, m_out)
+int who;       
+message *m_out;                        /* report result */
+{
+    if (OK != send(who, m_out))    /* send the message */
+        printf("MFS(%d) was unable to send reply\n", SELF_E);
+}
+
+PRIVATE void cch_check(void) 
+{
+  int i;
+
+  for (i = 0; i < NR_INODES; ++i) {
+         if (inode[i].i_count != cch[i] &&
+               req_nr != REQ_OPEN && req_nr != REQ_GETNODE &&
+               req_nr != REQ_PUTNODE && req_nr != REQ_GETDIR &&
+               req_nr != REQ_CLONE_OPCL && req_nr != REQ_READSUPER &&
+               req_nr != REQ_MOUNTPOINT && req_nr != REQ_UNMOUNT &&
+               req_nr != REQ_PIPE && req_nr != REQ_SYNC && 
+               req_nr != REQ_LOOKUP)
+printf("MFS(%d) inode(%d) cc: %d req_nr: %d\n",
+       SELF_E, inode[i].i_num, inode[i].i_count - cch[i], req_nr);
+         
+         cch[i] = inode[i].i_count;
+  }
+}
+
+
+
diff --git a/servers/mfs/misc.c b/servers/mfs/misc.c
new file mode 100644 (file)
index 0000000..3613fc7
--- /dev/null
@@ -0,0 +1,34 @@
+
+#include "fs.h"
+#include <fcntl.h>
+
+#include "buf.h"
+#include "inode.h"
+
+
+/*===========================================================================*
+ *                             fs_sync                                      *
+ *===========================================================================*/
+PUBLIC int fs_sync()
+{
+/* Perform the sync() system call.  Flush all the tables. 
+ * The order in which the various tables are flushed is critical.  The
+ * blocks must be flushed last, since rw_inode() leaves its results in
+ * the block cache.
+ */
+  register struct inode *rip;
+  register struct buf *bp;
+
+  /* Write all the dirty inodes to the disk. */
+  for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
+       if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
+
+  /* Write all the dirty blocks to the disk, one drive at a time. */
+  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
+       if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) 
+            flushall(bp->b_dev);
+
+  return(OK);          /* sync() can't fail */
+}
+
+
diff --git a/servers/mfs/mount.c b/servers/mfs/mount.c
new file mode 100644 (file)
index 0000000..ae19bf4
--- /dev/null
@@ -0,0 +1,196 @@
+
+
+#include "fs.h"
+#include <fcntl.h>
+#include <string.h>
+#include <minix/com.h>
+#include <sys/stat.h>
+#include "buf.h"
+#include "inode.h"
+#include "super.h"
+#include "drivers.h"
+#include <minix/vfsif.h>
+
+
+
+
+
+/*===========================================================================*
+ *                             fs_readsuper                                 *
+ *===========================================================================*/
+PUBLIC int fs_readsuper()
+{
+/* 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.
+ */
+  struct super_block *xp, *sp;
+  struct inode *root_ip;
+  int r = OK;
+
+  fs_dev = fs_m_in.REQ_DEV;
+
+  /* Map the driver endpoint for this major */
+  driver_endpoints[(fs_dev >> MAJOR) & BYTE].driver_e =  fs_m_in.REQ_DRIVER_E;
+  boottime = fs_m_in.REQ_BOOTTIME;
+  vfs_slink_storage = fs_m_in.REQ_SLINK_STORAGE;
+
+  sp = &super_block[0];
+  
+  /* Fill in the super block. */
+  sp->s_dev = fs_dev;          /* read_super() needs to know which dev */
+  r = read_super(sp);
+
+  /* Is it recognized as a Minix filesystem? */
+  if (r != OK) {
+printf("MFS(%d)readsuper read_super() ERROR\n", SELF_E);
+       sp->s_dev = NO_DEV;
+       return(r);
+  }
+  
+  /* Get the root inode of the mounted file system. */
+  root_ip = NIL_INODE;         /* if 'r' not OK, make sure this is defined */
+  if (r == OK) {
+       if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NIL_INODE) 
+               r = err_code;
+  }
+  
+  if (root_ip != NIL_INODE && root_ip->i_mode == 0) {
+        put_inode(root_ip);
+       r = EINVAL;
+  }
+
+  if (r != OK) return r;
+  sp->s_rd_only = fs_m_in.REQ_READONLY;
+  sp->s_is_root = fs_m_in.REQ_ISROOT;
+  
+  /* Root inode properties */
+  fs_m_out.RES_INODE_NR = root_ip->i_num;
+  fs_m_out.RES_MODE = root_ip->i_mode;
+  fs_m_out.RES_FILE_SIZE = root_ip->i_size;
+
+  /* Partition properties */
+  fs_m_out.RES_MAXSIZE = sp->s_max_size;
+  fs_m_out.RES_BLOCKSIZE = sp->s_block_size;
+  
+if (r == OK) 
+       printf("MFS(%d)readsuper DEV: %d driver_e: %d BOOTT: %d\n", 
+               SELF_E, fs_dev, fs_m_in.REQ_DRIVER_E, boottime);  
+  return r;
+}
+
+
+/*===========================================================================*
+ *                             fs_mountpoint                                *
+ *===========================================================================*/
+PUBLIC int fs_mountpoint()
+{
+/* This function looks up the mount point, it checks the condition whether
+ * the partition can be mounted on the inode or not. If ok, it gets the
+ * mountpoint inode's details and stores the mounted vmnt's index (in the
+ * vmnt table) so that it can be transferred back when the pathname lookup
+ * encounters a mountpoint.
+ */
+  register struct inode *rip;
+  int r = OK;
+  mode_t bits;
+  
+  /* Get inode */
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Temporarily open the file. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_mountpoint() failed\n", SELF_E);
+        return(EINVAL);
+  }
+
+  /* It may not be busy. */
+  if (rip->i_count > 1) r = EBUSY;
+
+  /* It may not be special. */
+  bits = rip->i_mode & I_TYPE;
+  if (bits == I_BLOCK_SPECIAL || bits == I_CHAR_SPECIAL) r = ENOTDIR;
+       
+  if ((rip->i_mode & I_TYPE) != I_DIRECTORY) r = ENOTDIR;
+      
+  if (r != OK) {
+      put_inode(rip);
+      return r;
+  }
+  
+  rip->i_mount = I_MOUNT;
+  rip->i_vmnt_ind = fs_m_in.REQ_VMNT_IND;
+
+  fs_m_out.m_source = rip->i_dev;/* Filled with the FS endp by the system */
+  fs_m_out.RES_INODE_NR = rip->i_num;
+  fs_m_out.RES_FILE_SIZE = rip->i_size;
+  fs_m_out.RES_MODE = rip->i_mode;
+
+  return r;
+}
+
+
+/*===========================================================================*
+ *                             fs_unmount                                   *
+ *===========================================================================*/
+PUBLIC int fs_unmount()
+{
+/* Unmount a file system by device number. */
+  struct super_block *sp, *sp1;
+  int count;
+  register struct inode *rip;
+
+  /* !!!!!!!!!!!!! REMOVE THIS LATER !!!!!!!!!!!!!!!!!!!!!!! */
+  /* Find the super block. */
+  sp = NIL_SUPER;
+  for (sp1 = &super_block[0]; sp1 < &super_block[NR_SUPERS]; sp1++) {
+       if (sp1->s_dev == fs_dev) {
+               sp = sp1;
+               break;
+       }
+  }
+  if (sp == NIL_SUPER) {
+       return(EINVAL);
+  }
+  /* !!!!!!!!!!!!! REMOVE THIS LATER !!!!!!!!!!!!!!!!!!!!!!! */
+  
+  /* See if the mounted device is busy.  Only 1 inode using it should be
+   * open -- the root inode -- and that inode only 1 time.
+   */
+  count = 0;
+  for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++) {
+       if (rip->i_count > 0 && rip->i_dev == fs_dev) {
+/*printf("FSunmount DEV: %d inode: %d count: %d iaddr: %d\n", 
+               rip->i_dev, rip->i_num, rip->i_count, rip);*/   
+               count += rip->i_count;
+       }
+  }
+  
+  if (count > 1) {
+      printf("MFS(%d) unmount: filesystem is busy %d\n", SELF_E, count);
+      return(EBUSY);   /* can't umount a busy file system */
+  }
+
+  /* Put the root inode */
+  rip = get_inode(fs_dev, ROOT_INODE);
+  put_inode(rip);
+  put_inode(rip);
+
+  /* Sync the disk, and invalidate cache. */
+  (void) fs_sync();            /* force any cached blocks out of memory */
+  /*invalidate(fs_dev);*/      /* invalidate cache entries for this dev */
+
+  /* Finish off the unmount. */
+  sp->s_dev = NO_DEV;
+  
+
+printf("MFS(%d) DEV %d unmounted\n", SELF_E, fs_dev);  
+  return OK;
+}
+
+
+
diff --git a/servers/mfs/open.c b/servers/mfs/open.c
new file mode 100644 (file)
index 0000000..9e040c1
--- /dev/null
@@ -0,0 +1,426 @@
+
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "buf.h"
+#include "inode.h"
+#include "super.h"
+
+#include <minix/vfsif.h>
+
+PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
+FORWARD _PROTOTYPE( struct inode *new_node, (struct inode *ldirp, 
+       char *string, mode_t bits, zone_t z0, int opaque, char *parsed));
+
+
+/*===========================================================================*
+ *                             fs_open                                      *
+ *===========================================================================*/
+PUBLIC int fs_open()
+{
+  int r, b, exist = TRUE;
+  struct inode *ldirp;
+  struct inode *rip;
+  int oflags;
+  mode_t omode;
+  mode_t bits;
+  char lastc[NAME_MAX];
+  
+  /* Read request message */
+  oflags = fs_m_in.REQ_FLAGS;
+  omode = fs_m_in.REQ_MODE;
+  
+  
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Device number only for device special files */
+  fs_m_out.RES_DEV = NO_DEV;
+  
+  /* Remap the bottom two bits of oflags. */
+  bits = (mode_t) mode_map[oflags & O_ACCMODE];
+  
+
+  /* If O_CREATE is set, try to make the file. */ 
+  if (oflags & O_CREAT) {
+         /* Copy the last component */
+         err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, 
+                 SELF, (vir_bytes) lastc, (phys_bytes) fs_m_in.REQ_PATH_LEN);
+
+         if (err_code != OK) return err_code;
+
+         /* Get last directory inode */
+         if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode for parent dir by creat() failed\n", SELF_E);
+                 return ENOENT;
+         }
+
+         /* Create a new inode by calling new_node(). */
+         rip = new_node(ldirp, lastc, omode, NO_ZONE, oflags&O_EXCL, NULL);
+         r = err_code;
+         if (r == OK) exist = FALSE;      /* we just created the file */
+         else if (r != EEXIST) {
+                 put_inode(ldirp);
+                 return(r); /* other error */
+         }
+         else exist = !(oflags & O_EXCL); /* file exists, if the O_EXCL 
+                                             flag is set this is an error */
+  } 
+  else {
+         /* Get file inode. */
+         if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by open() failed\n", SELF_E);
+                 return ENOENT;
+         }
+         ldirp = NIL_INODE;
+  }
+
+  /* Only do the normal open code if we didn't just create the file. */
+  if (exist) {
+       /* Check protections. */
+       if ((r = forbidden(rip, bits)) == OK) {
+               /* Opening reg. files directories and special files differ. */
+               switch (rip->i_mode & I_TYPE) {
+                  case I_REGULAR: 
+                       /* Truncate regular file if O_TRUNC. */
+                       if (oflags & O_TRUNC) {
+                               if ((r = forbidden(rip, W_BIT)) !=OK) break;
+                               truncate_inode(rip, 0);
+                               wipe_inode(rip);
+                               /* Send the inode from the inode cache to the
+                                * block cache, so it gets written on the next
+                                * cache flush.
+                                */
+                               rw_inode(rip, WRITING);
+                       }
+                       break;
+                  case I_DIRECTORY: 
+                       /* Directories may be read but not written. */
+                       r = (bits & W_BIT ? EISDIR : OK);
+                       break;
+
+                  case I_CHAR_SPECIAL:
+                  case I_BLOCK_SPECIAL:
+                        /* Send back the device number */
+                       fs_m_out.RES_DEV = (Dev_t) rip->i_zone[0];
+                       break;
+                        
+                   case I_NAMED_PIPE:
+                       rip->i_pipe = I_PIPE;
+                        b = (bits & R_BIT ? R_BIT : W_BIT);
+                        if (b == R_BIT)
+                            fs_m_out.RES_POS = rip->i_zone[V2_NR_DZONES+0];
+                        else
+                            fs_m_out.RES_POS = rip->i_zone[V2_NR_DZONES+1];
+                        break;
+               }
+       }
+  }
+
+  /* If error, release inode. */
+  if (r != OK) {
+        put_inode(ldirp);
+       put_inode(rip);
+       return(r);
+  }
+
+  /* Reply message */
+  fs_m_out.m_source = rip->i_dev;  /* filled with FS endpoint by the system */
+  fs_m_out.RES_INODE_NR = rip->i_num;
+  fs_m_out.RES_MODE = rip->i_mode;
+  fs_m_out.RES_FILE_SIZE = rip->i_size;
+  fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode);
+
+  /* This values are needed for the execution */
+  fs_m_out.RES_UID = rip->i_uid;
+  fs_m_out.RES_GID = rip->i_gid;
+  if ((rip->i_mode & I_TYPE) == I_REGULAR) fs_m_out.RES_CTIME = rip->i_ctime;
+
+  /* Drop parent dir */
+  put_inode(ldirp);
+  
+  return OK;
+}
+
+/*===========================================================================*
+ *                             fs_mknod                                     *
+ *===========================================================================*/
+PUBLIC int fs_mknod()
+{
+  struct inode *ip, *ldirp;
+  char lastc[NAME_MAX];
+
+  /* Copy the last component and set up caller's user and group id */
+  err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF, 
+            (vir_bytes) lastc, (phys_bytes) fs_m_in.REQ_PATH_LEN);
+
+  if (err_code != OK) return err_code;
+  
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Get last directory inode */
+  if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode for parent dir by mknod() failed\n", SELF_E);
+      return ENOENT;
+  }
+  
+  /* Try to create the new node */
+  ip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) fs_m_in.REQ_DEV, 
+          TRUE, NULL);
+
+  put_inode(ip);
+  put_inode(ldirp);
+  return(err_code);
+}
+
+
+/*===========================================================================*
+ *                             fs_mkdir                                     *
+ *===========================================================================*/
+PUBLIC int fs_mkdir()
+{
+  int r1, r2;                  /* status codes */
+  ino_t dot, dotdot;           /* inode numbers for . and .. */
+  struct inode *rip, *ldirp;
+  char lastc[NAME_MAX];         /* last component */
+
+  /* Copy the last component and set up caller's user and group id */
+  err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF, 
+            (vir_bytes) lastc, (phys_bytes) 
+           MIN(fs_m_in.REQ_PATH_LEN, NAME_MAX));
+
+  if (err_code != OK) return err_code;
+  
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Get last directory inode */
+  if ((ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode for parent dir by mkdir() failed\n", SELF_E);
+      return ENOENT;
+  }
+  
+  /* Next make the inode. If that fails, return error code. */
+  rip = new_node(ldirp, lastc, fs_m_in.REQ_MODE, (zone_t) 0, TRUE, NULL);
+
+  if (rip == NIL_INODE || err_code == EEXIST) {
+       put_inode(rip);         /* can't make dir: it already exists */
+       put_inode(ldirp);
+       return(err_code);
+  }
+
+  /* Get the inode numbers for . and .. to enter in the directory. */
+  dotdot = ldirp->i_num;       /* parent's inode number */
+  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.REQ_MODE;      /* set mode */
+  r1 = search_dir(rip, dot1, &dot, ENTER);     /* enter . in the new dir */
+  r2 = search_dir(rip, dot2, &dotdot, ENTER);  /* enter .. in the new dir */
+
+  /* If both . and .. were successfully entered, increment the link counts. */
+  if (r1 == OK && r2 == OK) {
+       /* Normal case.  It was possible to enter . and .. in the new dir. */
+       rip->i_nlinks++;        /* this accounts for . */
+       ldirp->i_nlinks++;      /* this accounts for .. */
+       ldirp->i_dirt = DIRTY;  /* mark parent's inode as dirty */
+  } else {
+       /* It was not possible to enter . or .. probably disk was full -
+        * links counts haven't been touched.
+        */
+       if(search_dir(ldirp, lastc, (ino_t *) 0, DELETE) != OK)
+               panic(__FILE__, "Dir disappeared ", rip->i_num);
+       rip->i_nlinks--;        /* undo the increment done in new_node() */
+  }
+  rip->i_dirt = DIRTY;         /* either way, i_nlinks has changed */
+
+  put_inode(ldirp);            /* return the inode of the parent dir */
+  put_inode(rip);              /* return the inode of the newly made dir */
+  return(err_code);            /* new_node() always sets 'err_code' */
+}
+
+/*===========================================================================*
+ *                             fs_slink                                             *
+ *===========================================================================*/
+PUBLIC int fs_slink()
+{
+  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 */
+  struct buf *bp;              /* disk buffer for link */
+    
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Temporarily open the dir. */
+  if ( (ldirp = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+        return(EINVAL);
+  }
+  
+  /* Copy the link name's last component */
+  r = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH,
+          SELF, (vir_bytes) string, 
+          (phys_bytes) fs_m_in.REQ_PATH_LEN);
+  
+  if (r != OK) return r;
+  
+  /* Create the inode for the symlink. */
+  sip = new_node(ldirp, string, (mode_t) (I_SYMBOLIC_LINK | RWX_MODES),
+                 (zone_t) 0, TRUE, NULL);
+
+  /* Allocate a disk block for the contents of the symlink.
+   * Copy contents of symlink (the name pointed to) into first disk block.
+   */
+  if ((r = err_code) == OK) {
+       r = (bp = new_block(sip, (off_t) 0)) == NIL_BUF ? err_code : 
+           sys_vircopy(fs_m_in.REQ_WHO_E, D, (vir_bytes) fs_m_in.REQ_USER_ADDR,
+                   SELF, D, (vir_bytes) bp->b_data, 
+                   (vir_bytes) fs_m_in.REQ_SLENGTH);
+
+       if(r == OK) {
+               bp->b_data[_MIN_BLOCK_SIZE-1] = '\0';
+               sip->i_size = strlen(bp->b_data);
+               /*if(sip->i_size != m_in.name1_length-1) {*/
+               if(sip->i_size != fs_m_in.REQ_SLENGTH) {
+                       /* 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
+                        * the strlen() value, but we want to let the user
+                        * know he did something wrong. ENAMETOOLONG doesn't
+                        * exactly describe the error, but there is no
+                        * ENAMETOOWRONG.
+                        */
+                       r = ENAMETOOLONG;
+               }
+       }
+  
+       put_block(bp, DIRECTORY_BLOCK);         /* put_block() accepts NIL_BUF. */
+  
+       if (r != OK) {
+               sip->i_nlinks = 0;
+               if (search_dir(ldirp, string, (ino_t *) 0, DELETE) != OK)
+                       panic(__FILE__, "Symbolic link vanished", NO_NUM);
+       } 
+  }
+
+  /* put_inode() accepts NIL_INODE as a noop, so the below are safe. */
+  put_inode(sip);
+  put_inode(ldirp);
+
+  return(r);
+}
+
+
+
+/*===========================================================================*
+ *                             new_node                                     *
+ *===========================================================================*/
+PRIVATE struct inode *new_node(struct inode *ldirp,
+       char *string, mode_t bits, zone_t z0, int opaque, char *parsed)
+{
+/* 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
+ * the ldirp directory with string name, and initializes it.  
+ * It returns a pointer to the inode if it can do this; 
+ * otherwise it returns NIL_INODE.  It always sets 'err_code'
+ * to an appropriate value (OK or an error code).
+ * 
+ * The parsed path rest is returned in 'parsed' if parsed is nonzero. It
+ * has to hold at least NAME_MAX bytes.
+ */
+
+  register struct inode *rip;
+  register int r;
+
+  /*
+  *ldirp = parse_path(path, string, opaque ? LAST_DIR : LAST_DIR_EATSYM);       
+  if (*ldirp == NIL_INODE) return(NIL_INODE);
+  */
+  
+  /* Get final component of the path. */
+  rip = advance(&ldirp, string);
+
+  if (S_ISDIR(bits) && 
+      (ldirp)->i_nlinks >= ((ldirp)->i_sp->s_version == V1 ?
+      CHAR_MAX : SHRT_MAX)) {
+        /* New entry is a directory, alas we can't give it a ".." */
+        put_inode(rip);
+        err_code = EMLINK;
+        return(NIL_INODE);
+  }
+
+  if ( rip == NIL_INODE && err_code == ENOENT) {
+       /* Last path component does not exist.  Make new directory entry. */
+       if ( (rip = alloc_inode((ldirp)->i_dev, bits)) == NIL_INODE) {
+               /* Can't creat new inode: out of inodes. */
+               return(NIL_INODE);
+       }
+
+       /* Force inode to the disk before making directory entry to make
+        * the system more robust in the face of a crash: an inode with
+        * no directory entry is much better than the opposite.
+        */
+       rip->i_nlinks++;
+       rip->i_zone[0] = z0;            /* major/minor device numbers */
+       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)) != OK) {
+               rip->i_nlinks--;        /* pity, have to free disk inode */
+               rip->i_dirt = DIRTY;    /* dirty inodes are written out */
+               put_inode(rip); /* this call frees the inode */
+               err_code = r;
+               return(NIL_INODE);
+       }
+
+  } else {
+       /* Either last component exists, or there is some problem. */
+       if (rip != NIL_INODE || err_code == EENTERMOUNT || 
+                       err_code == ELEAVEMOUNT)
+               r = EEXIST;
+       else
+               r = err_code;
+  }
+
+  if(parsed) { /* Give the caller the parsed string if requested. */
+       strncpy(parsed, string, NAME_MAX-1);
+       parsed[NAME_MAX-1] = '\0';
+  }
+
+  /* The caller has to return the directory inode (*ldirp).  */
+  err_code = r;
+  return(rip);
+}
+
+
+
+
+
+
+/*===========================================================================*
+ *                             fs_inhibread                                 *
+ *===========================================================================*/
+PUBLIC int fs_inhibread()
+{
+  struct inode *rip;
+  
+  if ((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR))== NIL_INODE){
+      printf("FSinhibread: couldn't find inode %d\n", fs_m_in.REQ_INODE_NR);
+      return EINVAL;
+  }
+
+  /* inhibit read ahead */
+  rip->i_seek = ISEEK; 
+  
+  return OK;
+}
+
similarity index 100%
rename from servers/fs/param.h
rename to servers/mfs/param.h
similarity index 63%
rename from servers/fs/path.c
rename to servers/mfs/path.c
index 18b1f9b21e763a3fd7049552b6e2205e0d019872..ab0b80cefb180a228f175ce07d6fb63ab968d4fe 100644 (file)
 #include "fs.h"
 #include <string.h>
 #include <minix/callnr.h>
+#include <minix/endpoint.h>
 #include <sys/stat.h>
 #include "buf.h"
-#include "file.h"
-#include "fproc.h"
 #include "inode.h"
 #include "super.h"
 
+#include <minix/vfsif.h>
+
+
 PUBLIC char dot1[2] = ".";     /* used for search_dir to bypass the access */
 PUBLIC char dot2[3] = "..";    /* permissions for . and ..                 */
 
 FORWARD _PROTOTYPE( char *get_name, (char *old_name, char string [NAME_MAX]) );
+FORWARD _PROTOTYPE( int ltraverse, (struct inode *rip, char *path, 
+                    char *suffix)                                           );
+
+
+/*===========================================================================*
+ *                             lookup                                       *
+ *===========================================================================*/
+PUBLIC int lookup()
+{
+  char string[NAME_MAX];
+  struct inode *rip;
+  int s_error;
+
+  string[0] = '\0';
+  
+  /* Copy the pathname and set up caller's user and group id */
+  err_code = sys_datacopy(FS_PROC_NR, (vir_bytes) fs_m_in.REQ_PATH, SELF, 
+            (vir_bytes) user_path, (phys_bytes) fs_m_in.REQ_PATH_LEN);
+
+  if (err_code != OK) return err_code;
+
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+
+  /* Lookup inode */
+  rip = parse_path(user_path, string, fs_m_in.REQ_FLAGS);
+  
+  /* Copy back the last name if it is required */
+  if ((fs_m_in.REQ_FLAGS & LAST_DIR || fs_m_in.REQ_FLAGS & LAST_DIR_EATSYM)
+                 && err_code != ENAMETOOLONG) {
+       s_error = sys_datacopy(SELF_E, (vir_bytes) string, FS_PROC_NR, 
+              (vir_bytes) fs_m_in.REQ_USER_ADDR, (phys_bytes) 
+              MIN(strlen(string)+1, NAME_MAX));
+      if (s_error != OK) return s_error;
+  }
+
+  /* Error or mount point encountered */
+  if (rip == NIL_INODE)
+      return err_code;
+
+  fs_m_out.RES_INODE_NR = rip->i_num;
+  fs_m_out.RES_MODE = rip->i_mode;
+  fs_m_out.RES_FILE_SIZE = rip->i_size;
+  
+  /* If 'path' is a block special file, return dev number. */
+  if ( (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL) {
+        fs_m_out.RES_DEV = (dev_t) rip->i_zone[0];
+  }
+
+  /* Drop inode (path parse increased the counter) */
+  put_inode(rip);
+
+  return OK;
+}
 
-FORWARD _PROTOTYPE( struct inode *ltraverse, (struct inode *rip,
-                       char *path, char *suffix, struct inode *ldip)   );
 
 /*===========================================================================*
  *                             parse_path                                   *
@@ -44,22 +98,69 @@ int action;                    /* action on last part of path */
  */
 
   struct inode *rip, *dir_ip;
+  struct inode *ver_rip;
   char *new_name;
-  int symloop;
   char lstring[NAME_MAX];
+  
+  /* Find starting inode inode according to the request message */
+  if ((rip = find_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+        printf("FS: couldn't find starting inode req_nr: %d %s\n", req_nr,
+                       user_path);
+        err_code = ENOENT;
+        return NIL_INODE;
+  }
 
-  /* Is the path absolute or relative?  Initialize 'rip' accordingly. */
-  rip = (*path == '/' ? fp->fp_rootdir : fp->fp_workdir);
+  /* Find chroot inode according to the request message */
+  if (fs_m_in.REQ_CHROOT_NR != 0) {
+         if ((chroot_dir = find_inode(fs_dev, fs_m_in.REQ_CHROOT_NR)) 
+                         == NIL_INODE) {
+                 printf("FS: couldn't find chroot inode\n");
+                 err_code = ENOENT;
+                 return NIL_INODE;
+         }
+  }
+  else chroot_dir = NIL_INODE;
 
-  /* If dir has been removed or path is empty, return ENOENT. */
-  if (rip->i_nlinks == 0 || *path == '\0') {
+  /* Set user and group ID */
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+      
+  /* No characters were processed yet */
+  path_processed = 0;  
+
+  /* Current number of symlinks encountered */
+  symloop = fs_m_in.REQ_SYMLOOP;
+
+  /* If dir has been removed return ENOENT. */
+  /* Note: empty (start) path is checked in the VFS process */
+  if (rip->i_nlinks == 0/* || *path == '\0'*/) {
        err_code = ENOENT;
        return(NIL_INODE);
   }
 
+  /* There is only one way how the starting directory of the lookup
+   * can be a mount point which is not a root directory, 
+   * namely: climbing up on a mount (ELEAVEMOUNT).
+   * In this case the lookup is intrested in the parent dir of the mount
+   * point, but the last ".." component was processed in the 'previous'
+   * FS process. Let's do that first.
+   */
+  if (rip->i_mount == I_MOUNT && rip->i_num != ROOT_INODE) {
+       dir_ip = rip;
+       rip = advance(&dir_ip, "..");
+       if (rip == NIL_INODE) return rip;
+       put_inode(rip);         /* advance() increased the counter */
+  }
+
   dup_inode(rip);              /* inode will be returned with put_inode */
+  
+  /* Looking for the starting directory? 
+   * Note: this happens after EENTERMOUNT or ELEAVEMOUNT 
+   * without more path component */
+  if (*path == '\0') {
+         return rip;
+  }
 
-  symloop = 0;                 /* symbolic link traversal count */
   if (string == (char *) 0) string = lstring;
 
   /* Scan the path component by component. */
@@ -83,31 +184,64 @@ int action;                    /* action on last part of path */
        /* There is more path.  Keep parsing. */
        dir_ip = rip;
        rip = advance(&dir_ip, string);
+       
+       /* Mount point encountered? */
+       if (rip == NIL_INODE && (err_code == EENTERMOUNT || 
+                               err_code == ELEAVEMOUNT)) {
+               put_inode(dir_ip);
+               return NIL_INODE;
+       }
 
-       if (rip == NIL_INODE) {
-               if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0)
-                       return(dir_ip);
-               else {
-                       put_inode(dir_ip);
-                       return(NIL_INODE);
-               }
-       }
+       if (rip == NIL_INODE) {
+               if (*new_name == '\0' && (action & PATH_NONSYMBOLIC) != 0)
+                       return(dir_ip);
+               else {
+                       put_inode(dir_ip);
+                       return(NIL_INODE);
+               }
+       }
 
        /* The call to advance() succeeded.  Fetch next component. */
        if (S_ISLNK(rip->i_mode)) {
-               if (*new_name != '\0' || (action & PATH_OPAQUE) == 0) {
+                if (*new_name != '\0' || (action & PATH_OPAQUE) == 0) {
+                    
                        if (*new_name != '\0') new_name--;
-                       rip = ltraverse(rip, path, new_name, dir_ip);
-                       put_inode(dir_ip);
+
+                       /* Extract path name from the symlink file */
+                       if (ltraverse(rip, user_path, new_name) != OK) {
+                           put_inode(dir_ip);
+                           err_code = ENOENT;
+                           return NIL_INODE;
+                       }
+
+                       /* Symloop limit reached? */
                        if (++symloop > SYMLOOP) {
-                               err_code = ELOOP;
-                               put_inode(rip);
-                               rip = NIL_INODE;
+                           put_inode(dir_ip);
+                           err_code = ELOOP;
+                           return NIL_INODE;
+                       }
+
+                       /* Start over counting */
+                       path_processed = 0;
+                       
+                       /* Check whether new path is relative or absolute */
+                       if (user_path[0] == '/') {
+                           /* Go back to VFS */
+                           put_inode(dir_ip);
+                           err_code = ESYMLINK;
+                           fs_m_out.RES_OFFSET = path_processed;
+                           fs_m_out.RES_SYMLOOP = symloop;
+                           return NIL_INODE;
+                       }
+                       /* Path is relative */
+                       else {
+                           rip = dir_ip;
+                           path = user_path;
+                           continue;
                        }
-                       if (rip == NIL_INODE) return(NIL_INODE);
-                       continue;
                }
-       } else if (*new_name != '\0') {
+       } 
+       else if (*new_name != '\0') {
                put_inode(dir_ip);
                path = new_name;
                continue;
@@ -124,60 +258,27 @@ int action;                    /* action on last part of path */
   }
 }
 
-/*===========================================================================*
- *                             eat_path                                             *
- *===========================================================================*/
-PUBLIC struct inode *eat_path(path)
-char *path;                    /* the path name to be parsed */
-{
- /* Parse the path 'path' and put its inode in the inode table. If not possible,
-  * return NIL_INODE as function value and an error code in 'err_code'.
-  */
-  
-  return parse_path(path, (char *) 0, EAT_PATH);
-}
-
-/*===========================================================================*
- *                             last_dir                                             *
- *===========================================================================*/
-PUBLIC struct inode *last_dir(path, string)
-char *path;                    /* the path name to be parsed */
-char string[NAME_MAX];         /* the final component is returned here */
-{
-/* Given a path, 'path', located in the fs address space, parse it as
- * far as the last directory, fetch the inode for the last directory into
- * the inode table, and return a pointer to the inode.  In
- * addition, return the final component of the path in 'string'.
- * If the last directory can't be opened, return NIL_INODE and
- * the reason for failure in 'err_code'.
- */
-  
-  return parse_path(path, string, LAST_DIR);
-}
-
 /*===========================================================================*
  *                             ltraverse                                    *
  *===========================================================================*/
-PRIVATE struct inode *ltraverse(rip, path, suffix, ldip)
+PRIVATE int ltraverse(rip, path, suffix)
 register struct inode *rip;    /* symbolic link */
 char *path;                    /* path containing link */
 char *suffix;                  /* suffix following link within path */
-register struct inode *ldip;   /* directory containing link */
 {
 /* Traverse a symbolic link. Copy the link text from the inode and insert
- * the text into the path. Return the inode of base directory and the
- * ammended path. The symbolic link inode is always freed. The inode
- * returned is already duplicated. NIL_INODE is returned on error.
+ * 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.
  */
   
   block_t b;                   /* block containing link text */
-  struct inode *bip;           /* inode of base directory */
   struct buf *bp;              /* buffer containing link text */
   size_t sl;                   /* length of link */
   size_t tl;                   /* length of suffix */
   char *sp;                    /* start of link text */
+  int r = OK;
 
-  bip = NIL_INODE;
   bp  = NIL_BUF;
 
   if ((b = read_map(rip, (off_t) 0)) != NO_BLOCK) {
@@ -188,62 +289,30 @@ register struct inode *ldip;   /* directory containing link */
        /* Insert symbolic text into path name. */
        tl = strlen(suffix);
        if (sl > 0 && sl + tl <= PATH_MAX-1) {
-               memmove(path+sl, suffix, tl);
-               memmove(path, sp, sl);
-               path[sl+tl] = 0;
-               dup_inode(bip = path[0] == '/' ? fp->fp_rootdir : ldip);
+           memmove(path+sl, suffix, tl);
+           memmove(path, sp, sl);
+           path[sl+tl] = 0;
+           
+           /* Copy back to VFS layer   THIS SHOULD BE IN parse_path */
+           r = sys_datacopy(SELF_E, (vir_bytes) path, FS_PROC_NR, 
+                   (vir_bytes) vfs_slink_storage, (phys_bytes) sl+tl+1);
+           
+           /*
+           dup_inode(bip = path[0] == '/' ? chroot_dir : ldip);
+           */
        }
   }
+  else {
+       r = ENOENT;
+  }
   
   put_block(bp, DIRECTORY_BLOCK);
   put_inode(rip);
-  if (bip == NIL_INODE)
-  {
-       err_code = ENOENT;
-  }
-  return (bip);
+  return r;
 }
 
-/*===========================================================================*
- *                             get_name                                     *
- *===========================================================================*/
-PRIVATE char *get_name(old_name, string)
-char *old_name;                        /* path name to parse */
-char string[NAME_MAX];         /* component extracted from 'old_name' */
-{
-/* Given a pointer to a path name in fs space, 'old_name', copy the next
- * component to 'string' and pad with zeros.  A pointer to that part of
- * the name as yet unparsed is returned.  Roughly speaking,
- * 'get_name' = 'old_name' - 'string'.
- *
- * This routine follows the standard convention that /usr/ast, /usr//ast,
- * //usr///ast and /usr/ast/ are all equivalent.
- */
-
-  register int c;
-  register char *np, *rnp;
-
-  np = string;                 /* 'np' points to current position */
-  rnp = old_name;              /* 'rnp' points to unparsed string */
-  while ( (c = *rnp) == '/') rnp++;    /* skip leading slashes */
 
-  /* Copy the unparsed path, 'old_name', to the array, 'string'. */
-  while ( rnp < &old_name[PATH_MAX]  &&  c != '/'   &&  c != '\0') {
-       if (np < &string[NAME_MAX]) *np++ = c;
-       c = *++rnp;             /* advance to next character */
-  }
 
-  /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */
-  while (c == '/' && rnp < &old_name[PATH_MAX]) c = *++rnp;
-
-  if (np < &string[NAME_MAX]) *np = '\0';      /* Terminate string */
-
-  if (rnp >= &old_name[PATH_MAX]) {
-       err_code = ENAMETOOLONG;
-       return((char *) 0);
-  }
-  return(rnp);
-}
 
 /*===========================================================================*
  *                             advance                                      *
@@ -277,14 +346,18 @@ char string[NAME_MAX];            /* component name to look for */
        return(NIL_INODE);
   }
 
-  /* Don't go beyond the current root directory, unless the string is dot2. */
-  if (dirp == fp->fp_rootdir && strcmp(string, "..") == 0 && string != dot2)
-               return(get_inode(dirp->i_dev, (int) dirp->i_num));
+  /* Don't go beyond the current root directory, unless the string is dot2. 
+   * Note: it has to be checked only if this FS process owns the chroot
+   * directory of the process */
+  if (chroot_dir != NIL_INODE) {
+         if (dirp == chroot_dir && strcmp(string, "..") == 0 && string != dot2)
+                 return(get_inode(dirp->i_dev, (int) dirp->i_num));
+  }
 
   /* The component has been found in the directory.  Get inode. */
   if ( (rip = get_inode(dirp->i_dev, (int) numb)) == NIL_INODE)  {
        return(NIL_INODE);
-       }
+  }
 
   /* The following test is for "mountpoint/.." where mountpoint is a
    * mountpoint. ".." will refer to the root of the mounted filesystem,
@@ -296,46 +369,97 @@ char string[NAME_MAX];            /* component name to look for */
    * 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] == '.') {
-               sp= rip->i_sp;
-               if (sp->s_imount != sp->s_isup)
-               {
-                       /* Release the root inode.  Replace by the
-                        * inode mounted on. Update parent.
-                        */
-                       put_inode(rip);
-                       put_inode(dirp);
-                       mnt_dev = sp->s_imount->i_dev;
-                       inumb = (int) sp->s_imount->i_num;
-                       dirp = *pdirp = get_inode(mnt_dev, inumb);
-                       rip = advance(pdirp, string);
-               }
-           }
-       }
+  if (rip->i_num == ROOT_INODE) {
+         if (dirp->i_num == ROOT_INODE) {
+                 if (string[1] == '.') {
+                         sp = rip->i_sp;
+                         if (!sp->s_is_root) {
+/*printf("FSadvance: ELEAVEMOUNT callnr: %d, cp: %d, restp: %s\n", 
+       call_nr, path_processed, user_path + path_processed);*/
+
+                                 /* Climbing up mountpoint */
+                                 err_code = ELEAVEMOUNT;
+                                 /* This will be the FS process endoint */
+                                 fs_m_out.m_source = rip->i_dev;
+                                 fs_m_out.RES_OFFSET = path_processed;
+                                  fs_m_out.RES_SYMLOOP = symloop;
+                                 put_inode(rip);
+                                 /*put_inode(dirp);*/
+                                 rip = NIL_INODE;
+                         }
+                 }
+         }
+  }
   if (rip == NIL_INODE) return(NIL_INODE);
 
   /* 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.
    */
-  while (rip != NIL_INODE && rip->i_mount == I_MOUNT) {
-       /* The inode is indeed mounted on. */
-       for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
-               if (sp->s_imount == rip) {
-                       /* Release the inode mounted on.  Replace by the
-                        * inode of the root inode of the mounted device.
-                        */
-                       put_inode(rip);
-                       rip = get_inode(sp->s_dev, ROOT_INODE);
-                       break;
-               }
-       }
+  if (rip != NIL_INODE && rip->i_mount == I_MOUNT) {
+/*printf("FSadvance: EENTERMOUNT callnr: %d, cp: %d, vmnti: %d, restp: %s\n", 
+       call_nr, path_processed, rip->i_vmnt_ind, user_path + path_processed);*/
+
+         /* Mountpoint encountered, report it */
+         err_code = EENTERMOUNT;
+         fs_m_out.RES_INODE_NR = rip->i_num;
+         fs_m_out.RES_OFFSET = path_processed;
+          fs_m_out.RES_SYMLOOP = symloop;
+         put_inode(rip);
+         rip = NIL_INODE;
   }
   return(rip);         /* return pointer to inode's component */
 }
 
+
+/*===========================================================================*
+ *                             get_name                                     *
+ *===========================================================================*/
+PRIVATE char *get_name(old_name, string)
+char *old_name;                        /* path name to parse */
+char string[NAME_MAX];         /* component extracted from 'old_name' */
+{
+/* Given a pointer to a path name in fs space, 'old_name', copy the next
+ * component to 'string' and pad with zeros.  A pointer to that part of
+ * the name as yet unparsed is returned.  Roughly speaking,
+ * 'get_name' = 'old_name' - 'string'.
+ *
+ * This routine follows the standard convention that /usr/ast, /usr//ast,
+ * //usr///ast and /usr/ast/ are all equivalent.
+ */
+
+  register int c;
+  register char *np, *rnp;
+
+  np = string;                 /* 'np' points to current position */
+  rnp = old_name;              /* 'rnp' points to unparsed string */
+  while ( (c = *rnp) == '/') {
+         rnp++;        /* skip leading slashes */
+         path_processed++; /* count characters */
+  }
+
+  /* Copy the unparsed path, 'old_name', to the array, 'string'. */
+  while ( rnp < &old_name[PATH_MAX]  &&  c != '/'   &&  c != '\0') {
+         if (np < &string[NAME_MAX]) *np++ = c;
+         c = *++rnp;           /* advance to next character */
+         path_processed++;     /* count characters */
+  }
+
+  /* To make /usr/ast/ equivalent to /usr/ast, skip trailing slashes. */
+  while (c == '/' && rnp < &old_name[PATH_MAX]) {
+         c = *++rnp;
+         path_processed++;     /* count characters */
+  }
+
+  if (np < &string[NAME_MAX]) *np = '\0';      /* Terminate string */
+
+  if (rnp >= &old_name[PATH_MAX]) {
+         err_code = ENAMETOOLONG;
+         return((char *) 0);
+  }
+  return(rnp);
+}
+
 /*===========================================================================*
  *                             search_dir                                   *
  *===========================================================================*/
@@ -368,7 +492,7 @@ int flag;                    /* LOOK_UP, ENTER, DELETE or IS_EMPTY */
   if ( (ldir_ptr->i_mode & I_TYPE) != I_DIRECTORY)  {
        return(ENOTDIR);
    }
-
+  
   r = OK;
 
   if (flag != IS_EMPTY) {
@@ -413,7 +537,7 @@ int flag;                    /* LOOK_UP, ENTER, DELETE or IS_EMPTY */
                                if (strcmp(dp->d_name, "." ) != 0 &&
                                    strcmp(dp->d_name, "..") != 0) match = 1;
                        } else {
-                               if (strncmp(dp->d_name, string, NAME_MAX) == 0) {
+                               if (strncmp(dp->d_name, string, NAME_MAX) == 0){
                                        match = 1;
                                }
                        }
@@ -484,3 +608,35 @@ int flag;                   /* LOOK_UP, ENTER, DELETE or IS_EMPTY */
   }
   return(OK);
 }
+
+
+/*===========================================================================*
+ *                             eat_path                                             *
+ *===========================================================================*/
+PUBLIC struct inode *eat_path(path)
+char *path;                    /* the path name to be parsed */
+{
+ /* Parse the path 'path' and put its inode in the inode table. If not possible,
+  * return NIL_INODE as function value and an error code in 'err_code'.
+  */
+  
+  return parse_path(path, (char *) 0, EAT_PATH);
+}
+
+/*===========================================================================*
+ *                             last_dir                                             *
+ *===========================================================================*/
+PUBLIC struct inode *last_dir(path, string)
+char *path;                    /* the path name to be parsed */
+char string[NAME_MAX];         /* the final component is returned here */
+{
+/* Given a path, 'path', located in the fs address space, parse it as
+ * far as the last directory, fetch the inode for the last directory into
+ * the inode table, and return a pointer to the inode.  In
+ * addition, return the final component of the path in 'string'.
+ * If the last directory can't be opened, return NIL_INODE and
+ * the reason for failure in 'err_code'.
+ */
+  
+  return parse_path(path, string, LAST_DIR);
+}
diff --git a/servers/mfs/pipe.c b/servers/mfs/pipe.c
new file mode 100644 (file)
index 0000000..188cf27
--- /dev/null
@@ -0,0 +1,57 @@
+
+#include "fs.h"
+#include <fcntl.h>
+#include <signal.h>
+#include <minix/callnr.h>
+#include <minix/endpoint.h>
+#include <minix/com.h>
+#include <sys/select.h>
+#include <sys/time.h>
+#include "inode.h"
+#include "super.h"
+
+#include <minix/vfsif.h>
+
+
+
+/*===========================================================================*
+ *                             fs_pipe                                      *
+ *===========================================================================*/
+PUBLIC int fs_pipe(void)
+{
+  struct inode *rip;
+  
+  /* Get caller's user and group id from the request */
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Try to allocate the inode */
+  if ( (rip = alloc_inode(fs_dev, I_REGULAR) ) == NIL_INODE) {
+        return err_code;
+  }
+
+  /* !!! already checked in alloc_inode 
+  if (read_only(rip) != OK) 
+       panic(__FILE__,"pipe device is read only", NO_NUM); 
+  */
+  
+  /* Fill in the fields of the inode */
+  rip->i_pipe = I_PIPE;
+  rip->i_mode &= ~I_REGULAR;
+  rip->i_mode |= I_NAMED_PIPE; /* pipes and FIFOs have this bit set */
+  
+  /* We'll need it twice, nothing can go wrong here */
+  dup_inode(rip);
+  rw_inode(rip, WRITING);      /* mark inode as allocated */
+  rip->i_update = ATIME | CTIME | MTIME;
+  
+  /* Fill in the fields of the response message */
+  fs_m_out.m_source = fs_dev;  /* filled with FS endpoint by the system */
+  fs_m_out.RES_INODE_NR = rip->i_num;
+  fs_m_out.RES_MODE = rip->i_mode;
+  fs_m_out.RES_INODE_INDEX = (rip - &inode[0]) / sizeof(struct inode);
+
+  return OK;
+}
+
+
similarity index 53%
rename from servers/fs/protect.c
rename to servers/mfs/protect.c
index 295b2dfb2a30e4cd0a058220d988b3e7918404ad..a2d1d609bc857dc6af6df4e210087cd4453dff74 100644 (file)
-/* This file deals with protection in the file system.  It contains the code
- * for four system calls that relate to protection.
- *
- * The entry points into this file are
- *   do_chmod: perform the CHMOD and FCHMOD system calls
- *   do_chown: perform the CHOWN and FCHOWN system calls
- *   do_umask: perform the UMASK system call
- *   do_access:        perform the ACCESS system call
- *   forbidden:        check to see if a given access is allowed on a given inode
- */
+
 
 #include "fs.h"
 #include <unistd.h>
 #include <minix/callnr.h>
 #include "buf.h"
-#include "file.h"
-#include "fproc.h"
 #include "inode.h"
-#include "param.h"
 #include "super.h"
 
+#include <minix/vfsif.h>
+
+
 /*===========================================================================*
- *                             do_chmod                                     *
+ *                             fs_chmod                                     *
  *===========================================================================*/
-PUBLIC int do_chmod()
+PUBLIC int fs_chmod()
 {
 /* Perform the chmod(name, mode) system call. */
 
-  register struct inode *rip = NULL;
+  register struct inode *rip;
   register int r;
-
-  if(call_nr == CHMOD) {
-    /* Temporarily open the file. */
-    if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-    if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
-  } else if(call_nr == FCHMOD) {
-    struct filp *filp;
-    if(!(filp = get_filp(m_in.m3_i1))) return(err_code);
-    rip = filp->filp_ino;
-  } else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
+  
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Temporarily open the file. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_chmod() failed\n", SELF_E);
+        return(EINVAL);
+  }
 
   /* Only the owner or the super_user may change the mode of a file.
    * No one may change the mode of a file on a read-only file system.
    */
-  if (rip->i_uid != fp->fp_effuid && !super_user)
+  if (rip->i_uid != caller_uid && caller_uid != SU_UID)
        r = EPERM;
   else
        r = read_only(rip);
 
   /* If error, return inode. */
   if (r != OK) {
-       if(call_nr == CHMOD) put_inode(rip);
+       put_inode(rip);
        return(r);
   }
 
   /* Now make the change. Clear setgid bit if file is not in caller's grp */
-  rip->i_mode = (rip->i_mode & ~ALL_MODES) | (m_in.mode & ALL_MODES);
-  if (!super_user && rip->i_gid != fp->fp_effgid)rip->i_mode &= ~I_SET_GID_BIT;
+  rip->i_mode = (rip->i_mode & ~ALL_MODES) | (fs_m_in.REQ_MODE & ALL_MODES);
+  if (caller_uid != SU_UID && rip->i_gid != caller_gid) 
+         rip->i_mode &= ~I_SET_GID_BIT;
   rip->i_update |= CTIME;
   rip->i_dirt = DIRTY;
 
-  if(call_nr == CHMOD) put_inode(rip);
+  put_inode(rip);
   return(OK);
 }
 
+
 /*===========================================================================*
- *                             do_chown                                     *
+ *                             fs_chown                                     *
  *===========================================================================*/
-PUBLIC int do_chown()
+PUBLIC int fs_chown()
 {
-/* Perform the chown(name, owner, group) system call. */
-
-  register struct inode *rip = NULL;
+  register struct inode *rip;
   register int r;
-
-  if(call_nr == CHOWN) {
-    /* Temporarily open the file. */
-    if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
-    if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
-  } else if(call_nr == FCHOWN) {
-    struct filp *filp;
-    if(!(filp = get_filp(m_in.m1_i1))) return(err_code);
-    rip = filp->filp_ino;
-  } else panic(__FILE__, "do_chown called with strange call_nr", call_nr);
+  /* Temporarily open the file. */
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Temporarily open the file. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_chown() failed\n", SELF_E);
+        return(EINVAL);
+  }
 
   /* Not permitted to change the owner of a file on a read-only file sys. */
   r = read_only(rip);
   if (r == OK) {
        /* FS is R/W.  Whether call is allowed depends on ownership, etc. */
-       if (super_user) {
+       if (caller_uid == SU_UID) {
                /* The super user can do anything. */
-               rip->i_uid = m_in.owner;        /* others later */
+               rip->i_uid = fs_m_in.REQ_NEW_UID;       /* others later */
        } else {
                /* Regular users can only change groups of their own files. */
-               if (rip->i_uid != fp->fp_effuid) r = EPERM;
-               if (rip->i_uid != m_in.owner) r = EPERM;  /* no giving away */
-               if (fp->fp_effgid != m_in.group) r = EPERM;
+               if (rip->i_uid != caller_uid) r = EPERM;
+               if (rip->i_uid != fs_m_in.REQ_NEW_UID) 
+                    r = EPERM;  /* no giving away */
+               if (caller_gid != fs_m_in.REQ_NEW_GID) r = EPERM;
        }
   }
   if (r == OK) {
-       rip->i_gid = m_in.group;
+       rip->i_gid = fs_m_in.REQ_NEW_GID;
        rip->i_mode &= ~(I_SET_UID_BIT | I_SET_GID_BIT);
        rip->i_update |= CTIME;
        rip->i_dirt = DIRTY;
   }
 
-  if(call_nr == CHOWN) put_inode(rip);
+  put_inode(rip);
   return(r);
 }
 
 /*===========================================================================*
- *                             do_umask                                     *
+ *                             fs_access                                    *
  *===========================================================================*/
-PUBLIC int do_umask()
+PUBLIC int fs_access()
 {
-/* Perform the umask(co_mode) system call. */
-  register mode_t r;
-
-  r = ~fp->fp_umask;           /* set 'r' to complement of old mask */
-  fp->fp_umask = ~(m_in.co_mode & RWX_MODES);
-  return(r);                   /* return complement of old mask */
-}
-
-/*===========================================================================*
- *                             do_access                                    *
- *===========================================================================*/
-PUBLIC int do_access()
-{
-/* Perform the access(name, mode) system call. */
-
   struct inode *rip;
   register int r;
-
-  /* First check to see if the mode is correct. */
-  if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
-       return(EINVAL);
-
+  
   /* Temporarily open the file whose access is to be checked. */
-  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
-  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Temporarily open the file. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_access() failed\n", SELF_E);
+        return(EINVAL);
+  }
 
   /* Now check the permissions. */
-  r = forbidden(rip, (mode_t) m_in.mode);
+  r = forbidden(rip, (mode_t) fs_m_in.REQ_MODE);
   put_inode(rip);
   return(r);
 }
@@ -159,20 +136,20 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
   register struct inode *old_rip = rip;
   register struct super_block *sp;
   register mode_t bits, perm_bits;
-  int r, shift, test_uid, test_gid, type;
+  int r, shift, type;
 
-  if (rip->i_mount == I_MOUNT) /* The inode is mounted on. */
+  /*
+  if (rip->i_mount == I_MOUNT) 
        for (sp = &super_block[1]; sp < &super_block[NR_SUPERS]; sp++)
                if (sp->s_imount == rip) {
                        rip = get_inode(sp->s_dev, ROOT_INODE);
                        break;
-               } /* if */
+               } 
+  */
 
   /* Isolate the relevant rwx bits from the mode. */
   bits = rip->i_mode;
-  test_uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid);
-  test_gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid);
-  if (test_uid == SU_UID) {
+  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.
@@ -183,8 +160,8 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
        else
                perm_bits = R_BIT | W_BIT;
   } else {
-       if (test_uid == rip->i_uid) shift = 6;          /* owner */
-       else if (test_gid == rip->i_gid ) shift = 3;    /* group */
+       if (caller_uid == rip->i_uid) shift = 6;        /* owner */
+       else if (caller_gid == rip->i_gid ) shift = 3;  /* group */
        else shift = 0;                                 /* other */
        perm_bits = (bits >> shift) & (R_BIT | W_BIT | X_BIT);
   }
@@ -203,6 +180,7 @@ PUBLIC int forbidden(register struct inode *rip, mode_t access_desired)
 
   if (rip != old_rip) put_inode(rip);
 
+/*printf("FSforbidden: %s %s\n", user_path, (r == OK ? "OK" : "notOK")); */
   return(r);
 }
 
@@ -221,3 +199,6 @@ struct inode *ip;           /* ptr to inode whose file sys is to be cked */
   sp = ip->i_sp;
   return(sp->s_rd_only ? EROFS : OK);
 }
+
+
+
similarity index 63%
rename from servers/fs/proto.h
rename to servers/mfs/proto.h
index c37d668433619ebe3de4717de48a803f05cb2e85..2ed4d75b951009973d2badf0cffa2152821c08cb 100644 (file)
@@ -2,15 +2,53 @@
 
 #include "timers.h"
 
-#include <minix/safecopies.h>
-
 /* Structs used in prototypes must be declared as such first. */
 struct buf;
 struct filp;           
-struct fproc;
 struct inode;
 struct super_block;
 
+
+int fs_open(void);
+int fs_putnode(void);
+int fs_getnode(void);
+int fs_pipe(void);
+int fs_readwrite(void);
+int fs_clone_opcl(void);
+int fs_new_driver(void);
+int fs_ftrunc(void);
+int fs_chown(void);
+int fs_chmod(void);
+int fs_access(void);
+int fs_mknod(void);
+int fs_mkdir(void);
+int fs_inhibread(void);
+int fs_stat(void);
+int fs_fstat(void);
+int fs_unlink(void);
+int fs_utime(void);
+int fs_fstatfs(void);
+int fs_lstat(void);
+int fs_getdir(void);
+int fs_link(void);
+int fs_lookup_rn_old(void);
+int fs_lookup_rn_new(void);
+int fs_rename(void);
+
+int fs_mountpoint(void);
+int fs_readsuper(void);
+int fs_unmount(void);
+int fs_trunc(void);
+int fs_sync(void);
+int fs_stime(void);
+int lookup(void);
+
+int fs_slink(void);
+int fs_rdlink(void);
+int fs_breadwrite(void);
+
+void init_inode_cache(void);
+
 /* cache.c */
 _PROTOTYPE( zone_t alloc_zone, (Dev_t dev, zone_t z)                   );
 _PROTOTYPE( void flushall, (Dev_t dev)                                 );
@@ -30,51 +68,13 @@ _PROTOTYPE( void invalidate2, (Dev_t device)                                );
 #endif
 
 /* device.c */
-_PROTOTYPE( int dev_open, (Dev_t dev, int proc, int flags)             );
-_PROTOTYPE( void dev_close, (Dev_t dev)                                        );
-_PROTOTYPE( int dev_bio, (int op, Dev_t dev, int proc, void *buf,
-                       off_t pos, int bytes)                           );
-_PROTOTYPE( int dev_io, (int op, Dev_t dev, int proc, void *buf,
+_PROTOTYPE( int block_dev_io, (int op, Dev_t dev, int proc, void *buf,
                        off_t pos, int bytes, int flags)                );
-_PROTOTYPE( int gen_opcl, (int op, Dev_t dev, int proc, int flags)     );
-_PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr)               );
-_PROTOTYPE( int no_dev, (int op, Dev_t dev, int proc, int flags)       );
-_PROTOTYPE( int no_dev_io, (int, message *)                            );
-_PROTOTYPE( int tty_opcl, (int op, Dev_t dev, int proc, int flags)     );
-_PROTOTYPE( int ctty_opcl, (int op, Dev_t dev, int proc, int flags)    );
-_PROTOTYPE( int clone_opcl, (int op, Dev_t dev, int proc, int flags)   );
-_PROTOTYPE( int ctty_io, (int task_nr, message *mess_ptr)              );
-_PROTOTYPE( int do_ioctl, (void)                                       );
-_PROTOTYPE( void pm_setsid, (int proc_e)                               );
-_PROTOTYPE( void dev_status, (message *)                               );
-_PROTOTYPE( void dev_up, (int major)                                   );
-
-/* dmp.c */
-_PROTOTYPE( int do_fkey_pressed, (void)                                        );
-
-/* dmap.c */
-_PROTOTYPE( int do_devctl, (void)                                      );
-_PROTOTYPE( int fs_devctl, (int req, int dev, int proc_nr_e, int style,
-       int force)                                                      );
-_PROTOTYPE( void build_dmap, (void)                                    );
-_PROTOTYPE( int map_driver, (int major, int proc_nr, int dev_style,
-       int force)                                                      );
-_PROTOTYPE( int dmap_driver_match, (int proc, int major)               );
-_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr)                    );
-_PROTOTYPE( void dmap_endpt_up, (int proc_nr)                          );
-
-/* exec.c */
-_PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
-                               char *frame, vir_bytes frame_len)       );
-
-/* filedes.c */
-_PROTOTYPE( struct filp *find_filp, (struct inode *rip, mode_t bits)   );
-_PROTOTYPE( int get_fd, (int start, mode_t bits, int *k, struct filp **fpt) );
-_PROTOTYPE( struct filp *get_filp, (int fild)                          );
-_PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild)      );
-_PROTOTYPE( int inval_filp, (struct filp *)                            );
+
 
 /* inode.c */
+_PROTOTYPE( struct inode *find_inode, (Dev_t dev, int numb)            );
+
 _PROTOTYPE( struct inode *alloc_inode, (dev_t dev, mode_t bits)                );
 _PROTOTYPE( void dup_inode, (struct inode *ip)                         );
 _PROTOTYPE( void free_inode, (Dev_t dev, Ino_t numb)                   );
@@ -85,11 +85,6 @@ _PROTOTYPE( void rw_inode, (struct inode *rip, int rw_flag)          );
 _PROTOTYPE( void wipe_inode, (struct inode *rip)                       );
 
 /* link.c */
-_PROTOTYPE( int do_link, (void)                                                );
-_PROTOTYPE( int do_unlink, (void)                                      );
-_PROTOTYPE( int do_rename, (void)                                      );
-_PROTOTYPE( int do_truncate, (void)                                    );
-_PROTOTYPE( int do_ftruncate, (void)                                   );
 _PROTOTYPE( int truncate_inode, (struct inode *rip, off_t len)         );
 _PROTOTYPE( int freesp_inode, (struct inode *rip, off_t st, off_t end) );
 
@@ -99,21 +94,21 @@ _PROTOTYPE( void lock_revive, (void)                                        );
 
 /* main.c */
 _PROTOTYPE( int main, (void)                                           );
-_PROTOTYPE( void reply, (int whom, int result)                         );
+_PROTOTYPE( void reply, (int who, message *m_out)                      );
 
 /* misc.c */
 _PROTOTYPE( int do_dup, (void)                                         );
-_PROTOTYPE( void pm_exit, (int proc)                                   );
+_PROTOTYPE( int do_exit, (void)                                                );
 _PROTOTYPE( int do_fcntl, (void)                                       );
-_PROTOTYPE( void pm_fork, (int pproc, int cproc, int cpid)             );
-_PROTOTYPE( void pm_setgid, (int proc_e, int egid, int rgid)           );
-_PROTOTYPE( void pm_setuid, (int proc_e, int euid, int ruid)           );
+_PROTOTYPE( int do_fork, (void)                                                );
+_PROTOTYPE( int do_exec, (void)                                                );
+_PROTOTYPE( int do_revive, (void)                                      );
+_PROTOTYPE( int do_set, (void)                                         );
 _PROTOTYPE( int do_sync, (void)                                                );
 _PROTOTYPE( int do_fsync, (void)                                       );
-_PROTOTYPE( void pm_reboot, (void)                                     );
+_PROTOTYPE( int do_reboot, (void)                                      );
 _PROTOTYPE( int do_svrctl, (void)                                      );
 _PROTOTYPE( int do_getsysinfo, (void)                                  );
-_PROTOTYPE( int pm_dumpcore, (int proc_e, struct mem_map *seg_ptr)     );
 
 /* mount.c */
 _PROTOTYPE( int do_mount, (void)                                       );
@@ -122,15 +117,12 @@ _PROTOTYPE( int unmount, (Dev_t dev)                                      );
 
 /* open.c */
 _PROTOTYPE( int do_close, (void)                                       );
-_PROTOTYPE( int close_fd, (struct fproc *rfp, int fd_nr)               );
 _PROTOTYPE( int do_creat, (void)                                       );
 _PROTOTYPE( int do_lseek, (void)                                       );
 _PROTOTYPE( int do_mknod, (void)                                       );
 _PROTOTYPE( int do_mkdir, (void)                                       );
 _PROTOTYPE( int do_open, (void)                                                );
-_PROTOTYPE( int do_slink, (void)                                       );
-_PROTOTYPE( struct inode *new_node, (struct inode **ldirp, 
-       char *path, mode_t bits, zone_t z0, int opaque, char *string)   );
+_PROTOTYPE( int do_slink, (void)                                       );
 
 /* path.c */
 _PROTOTYPE( struct inode *advance,(struct inode **dirp, char string[NAME_MAX]));
@@ -141,19 +133,6 @@ _PROTOTYPE( struct inode *last_dir, (char *path, char string [NAME_MAX]));
 _PROTOTYPE( struct inode *parse_path, (char *path, char string[NAME_MAX], 
                                                        int action)     );
 
-/* pipe.c */
-_PROTOTYPE( int do_pipe, (void)                                                );
-_PROTOTYPE( int do_unpause, (void)                                     );
-_PROTOTYPE( int unpause, (int proc_nr_e)                               );
-_PROTOTYPE( int pipe_check, (struct inode *rip, int rw_flag,
-       int oflags, int bytes, off_t position, int *canwrite, int notouch));
-_PROTOTYPE( void release, (struct inode *ip, int call_nr, int count)   );
-_PROTOTYPE( void revive, (int proc_nr, int bytes)                      );
-_PROTOTYPE( void suspend, (int task)                                   );
-_PROTOTYPE( int select_request_pipe, (struct filp *f, int *ops, int bl)        );
-_PROTOTYPE( int select_cancel_pipe, (struct filp *f)                   );
-_PROTOTYPE( int select_match_pipe, (struct filp *f)                    );
-_PROTOTYPE( void unsuspend_by_endpt, (int)                             );
 
 /* protect.c */
 _PROTOTYPE( int do_access, (void)                                      );
@@ -228,3 +207,6 @@ _PROTOTYPE( void fs_set_timer, (timer_t *tp, int delta, tmr_func_t watchdog, int
 _PROTOTYPE( void fs_expire_timers, (clock_t now)                       );
 _PROTOTYPE( void fs_cancel_timer, (timer_t *tp)                                );
 _PROTOTYPE( void fs_init_timer, (timer_t *tp)                          );
+
+/* cdprobe.c */
+_PROTOTYPE( int cdprobe, (void)                                                );
diff --git a/servers/mfs/queue.h b/servers/mfs/queue.h
new file mode 100644 (file)
index 0000000..b5aef4e
--- /dev/null
@@ -0,0 +1,215 @@
+
+#ifndef _SYS_QUEUE_H_
+#define        _SYS_QUEUE_H_
+
+#define        __offsetof(type, field) ((size_t)(&((type *)0)->field))
+#define        __rangeof(type, start, end) \
+       (__offsetof(type, end) - __offsetof(type, start))
+
+#define        QMD_TRACE_ELEM(elem)
+#define        QMD_TRACE_HEAD(head)
+#define        TRACEBUF
+#define        TRASHIT(x)
+
+/*
+ * List declarations.
+ */
+#define        LIST_HEAD(name, type)                                           \
+struct name {                                                          \
+       struct type *lh_first;  /* first element */                     \
+}
+
+#define        LIST_HEAD_INITIALIZER(head)                                     \
+       { NULL }
+
+#define        LIST_ENTRY(type)                                                \
+struct {                                                               \
+       struct type *le_next;   /* next element */                      \
+       struct type **le_prev;  /* address of previous next element */  \
+}
+
+/*
+ * List functions.
+ */
+
+#define        LIST_EMPTY(head)        ((head)->lh_first == NULL)
+
+#define        LIST_FIRST(head)        ((head)->lh_first)
+
+#define        LIST_FOREACH(var, head, field)                                  \
+       for ((var) = LIST_FIRST((head));                                \
+           (var);                                                      \
+           (var) = LIST_NEXT((var), field))
+
+#define        LIST_FOREACH_SAFE(var, head, field, tvar)                       \
+       for ((var) = LIST_FIRST((head));                                \
+           (var) && ((tvar) = LIST_NEXT((var), field), 1);             \
+           (var) = (tvar))
+
+#define        LIST_INIT(head) do {                                            \
+       LIST_FIRST((head)) = NULL;                                      \
+} while (0)
+
+#define        LIST_INSERT_AFTER(listelm, elm, field) do {                     \
+       if ((LIST_NEXT((elm), field) = LIST_NEXT((listelm), field)) != NULL)\
+               LIST_NEXT((listelm), field)->field.le_prev =            \
+                   &LIST_NEXT((elm), field);                           \
+       LIST_NEXT((listelm), field) = (elm);                            \
+       (elm)->field.le_prev = &LIST_NEXT((listelm), field);            \
+} while (0)
+
+#define        LIST_INSERT_BEFORE(listelm, elm, field) do {                    \
+       (elm)->field.le_prev = (listelm)->field.le_prev;                \
+       LIST_NEXT((elm), field) = (listelm);                            \
+       *(listelm)->field.le_prev = (elm);                              \
+       (listelm)->field.le_prev = &LIST_NEXT((elm), field);            \
+} while (0)
+
+#define        LIST_INSERT_HEAD(head, elm, field) do {                         \
+       if ((LIST_NEXT((elm), field) = LIST_FIRST((head))) != NULL)     \
+               LIST_FIRST((head))->field.le_prev = &LIST_NEXT((elm), field);\
+       LIST_FIRST((head)) = (elm);                                     \
+       (elm)->field.le_prev = &LIST_FIRST((head));                     \
+} while (0)
+
+#define        LIST_NEXT(elm, field)   ((elm)->field.le_next)
+
+#define        LIST_REMOVE(elm, field) do {                                    \
+       if (LIST_NEXT((elm), field) != NULL)                            \
+               LIST_NEXT((elm), field)->field.le_prev =                \
+                   (elm)->field.le_prev;                               \
+       *(elm)->field.le_prev = LIST_NEXT((elm), field);                \
+} while (0)
+
+/*
+ * Tail queue declarations.
+ */
+#define        TAILQ_HEAD(name, type)                                          \
+struct name {                                                          \
+       struct type *tqh_first; /* first element */                     \
+       struct type **tqh_last; /* addr of last next element */         \
+       TRACEBUF                                                        \
+}
+
+#define        TAILQ_HEAD_INITIALIZER(head)                                    \
+       { NULL, &(head).tqh_first }
+
+#define        TAILQ_ENTRY(type)                                               \
+struct {                                                               \
+       struct type *tqe_next;  /* next element */                      \
+       struct type **tqe_prev; /* address of previous next element */  \
+       TRACEBUF                                                        \
+}
+
+/*
+ * Tail queue functions.
+ */
+#define        TAILQ_CONCAT(head1, head2, field) do {                          \
+       if (!TAILQ_EMPTY(head2)) {                                      \
+               *(head1)->tqh_last = (head2)->tqh_first;                \
+               (head2)->tqh_first->field.tqe_prev = (head1)->tqh_last; \
+               (head1)->tqh_last = (head2)->tqh_last;                  \
+               TAILQ_INIT((head2));                                    \
+               QMD_TRACE_HEAD(head);                                   \
+               QMD_TRACE_HEAD(head2);                                  \
+       }                                                               \
+} while (0)
+
+#define        TAILQ_EMPTY(head)       ((head)->tqh_first == NULL)
+
+#define        TAILQ_FIRST(head)       ((head)->tqh_first)
+
+#define        TAILQ_FOREACH(var, head, field)                                 \
+       for ((var) = TAILQ_FIRST((head));                               \
+           (var);                                                      \
+           (var) = TAILQ_NEXT((var), field))
+
+#define        TAILQ_FOREACH_SAFE(var, head, field, tvar)                      \
+       for ((var) = TAILQ_FIRST((head));                               \
+           (var) && ((tvar) = TAILQ_NEXT((var), field), 1);            \
+           (var) = (tvar))
+
+#define        TAILQ_FOREACH_REVERSE(var, head, headname, field)               \
+       for ((var) = TAILQ_LAST((head), headname);                      \
+           (var);                                                      \
+           (var) = TAILQ_PREV((var), headname, field))
+
+#define        TAILQ_FOREACH_REVERSE_SAFE(var, head, headname, field, tvar)    \
+       for ((var) = TAILQ_LAST((head), headname);                      \
+           (var) && ((tvar) = TAILQ_PREV((var), headname, field), 1);  \
+           (var) = (tvar))
+
+#define        TAILQ_INIT(head) do {                                           \
+       TAILQ_FIRST((head)) = NULL;                                     \
+       (head)->tqh_last = &TAILQ_FIRST((head));                        \
+       QMD_TRACE_HEAD(head);                                           \
+} while (0)
+
+#define        TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              \
+       if ((TAILQ_NEXT((elm), field) = TAILQ_NEXT((listelm), field)) != NULL)\
+               TAILQ_NEXT((elm), field)->field.tqe_prev =              \
+                   &TAILQ_NEXT((elm), field);                          \
+       else {                                                          \
+               (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
+               QMD_TRACE_HEAD(head);                                   \
+       }                                                               \
+       TAILQ_NEXT((listelm), field) = (elm);                           \
+       (elm)->field.tqe_prev = &TAILQ_NEXT((listelm), field);          \
+       QMD_TRACE_ELEM(&(elm)->field);                                  \
+       QMD_TRACE_ELEM(&listelm->field);                                \
+} while (0)
+
+#define        TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   \
+       (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              \
+       TAILQ_NEXT((elm), field) = (listelm);                           \
+       *(listelm)->field.tqe_prev = (elm);                             \
+       (listelm)->field.tqe_prev = &TAILQ_NEXT((elm), field);          \
+       QMD_TRACE_ELEM(&(elm)->field);                                  \
+       QMD_TRACE_ELEM(&listelm->field);                                \
+} while (0)
+
+#define        TAILQ_INSERT_HEAD(head, elm, field) do {                        \
+       if ((TAILQ_NEXT((elm), field) = TAILQ_FIRST((head))) != NULL)   \
+               TAILQ_FIRST((head))->field.tqe_prev =                   \
+                   &TAILQ_NEXT((elm), field);                          \
+       else                                                            \
+               (head)->tqh_last = &TAILQ_NEXT((elm), field);           \
+       TAILQ_FIRST((head)) = (elm);                                    \
+       (elm)->field.tqe_prev = &TAILQ_FIRST((head));                   \
+       QMD_TRACE_HEAD(head);                                           \
+       QMD_TRACE_ELEM(&(elm)->field);                                  \
+} while (0)
+
+#define        TAILQ_INSERT_TAIL(head, elm, field) do {                        \
+       TAILQ_NEXT((elm), field) = NULL;                                \
+       (elm)->field.tqe_prev = (head)->tqh_last;                       \
+       *(head)->tqh_last = (elm);                                      \
+       (head)->tqh_last = &TAILQ_NEXT((elm), field);                   \
+       QMD_TRACE_HEAD(head);                                           \
+       QMD_TRACE_ELEM(&(elm)->field);                                  \
+} while (0)
+
+#define        TAILQ_LAST(head, headname)                                      \
+       (*(((struct headname *)((head)->tqh_last))->tqh_last))
+
+#define        TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+
+#define        TAILQ_PREV(elm, headname, field)                                \
+       (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+
+#define        TAILQ_REMOVE(head, elm, field) do {                             \
+       if ((TAILQ_NEXT((elm), field)) != NULL)                         \
+               TAILQ_NEXT((elm), field)->field.tqe_prev =              \
+                   (elm)->field.tqe_prev;                              \
+       else {                                                          \
+               (head)->tqh_last = (elm)->field.tqe_prev;               \
+               QMD_TRACE_HEAD(head);                                   \
+       }                                                               \
+       *(elm)->field.tqe_prev = TAILQ_NEXT((elm), field);              \
+       TRASHIT((elm)->field.tqe_next);                                 \
+       TRASHIT((elm)->field.tqe_prev);                                 \
+       QMD_TRACE_ELEM(&(elm)->field);                                  \
+} while (0)
+
+
+#endif /* _SYS_QUEUE_H */
similarity index 68%
rename from servers/fs/read.c
rename to servers/mfs/read.c
index b049aef898c612f83517b20ec4e8a6682b7e87cb..44b1724ec83a4d8a944c4df4ca0467b598547499 100644 (file)
-/* This file contains the heart of the mechanism used to read (and write)
- * files.  Read and write requests are split up into chunks that do not cross
- * block boundaries.  Each chunk is then processed in turn.  Reads on special
- * files are also detected and handled.
- *
- * The entry points into this file are
- *   do_read:   perform the READ system call by calling read_write
- *   read_write: actually do the work of READ and WRITE
- *   read_map:  given an inode and file position, look up its zone number
- *   rd_indir:  read an entry in an indirect block 
- *   read_ahead: manage the block read ahead business
- */
+
 
 #include "fs.h"
 #include <fcntl.h>
 #include <unistd.h>
 #include <minix/com.h>
 #include "buf.h"
-#include "file.h"
-#include "fproc.h"
 #include "inode.h"
-#include "param.h"
 #include "super.h"
 
+#include <minix/vfsif.h>
+
+
+
 FORWARD _PROTOTYPE( int rw_chunk, (struct inode *rip, off_t position,
        unsigned off, int chunk, unsigned left, int rw_flag,
        char *buff, int seg, int usr, int block_size, int *completed));
 
-/*===========================================================================*
- *                             do_read                                      *
- *===========================================================================*/
-PUBLIC int do_read()
-{
-  return(read_write(READING));
-}
 
 /*===========================================================================*
- *                             read_write                                   *
+ *                             fs_readwrite                                 *
  *===========================================================================*/
-PUBLIC int read_write(rw_flag)
-int rw_flag;                   /* READING or WRITING */
+PUBLIC int fs_readwrite(void)
 {
-/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
-
-  register struct inode *rip;
-  register struct filp *f;
-  off_t bytes_left, f_size, position;
+  int r, usr, seg, rw_flag, chunk, block_size, block_spec;
+  int partial_cnt, regular, partial_pipe, nrbytes;
+  off_t position, f_size, bytes_left;
   unsigned int off, cum_io;
-  int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
-  int regular, partial_pipe = 0, partial_cnt = 0;
   mode_t mode_word;
-  struct filp *wf;
-  int block_size = 0;
   int completed, r2 = OK;
-  phys_bytes p;
-
-  /* PM loads segments by putting funny things in other bits of the
-   * message, indicated by a high bit in fd.
-   */
-  if (who_e == PM_PROC_NR && (m_in.fd & _PM_SEG_FLAG)) {
-       seg = (int) m_in.m1_p2;
-       usr = (int) m_in.m1_p3;
-       m_in.fd &= ~(_PM_SEG_FLAG);     /* get rid of flag bit */
-  } else {
-       usr = who_e;            /* normal case */
-       seg = D;
-  }
-
-  /* If the file descriptor is valid, get the inode, size and mode. */
-  if (m_in.nbytes < 0) return(EINVAL);
-  if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
-  if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
-       return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
-  }
-  if (m_in.nbytes == 0)
-        return(0);     /* so char special files need not check for 0*/
-
-  /* check if user process has the memory it needs.
-   * if not, copying will fail later.
-   * do this after 0-check above because umap doesn't want to map 0 bytes.
-   */
-  if ((r = sys_umap(usr, seg, (vir_bytes) m_in.buffer, m_in.nbytes, &p)) != OK) {
-       printf("FS: read_write: umap failed for process %d\n", usr);
-       return r;
-  }
-  position = f->filp_pos;
-  oflags = f->filp_flags;
-  rip = f->filp_ino;
-  f_size = rip->i_size;
+  char *user_addr;
+  struct inode *rip;
+  
+  partial_pipe = 0;
   r = OK;
-  if (rip->i_pipe == I_PIPE) {
-       /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
-       cum_io = fp->fp_cum_io_partial; 
-  } else {
-       cum_io = 0;
-  }
-  op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
-  mode_word = rip->i_mode & I_TYPE;
-  regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
-
-  if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
-       if (rip->i_zone[0] == NO_DEV)
-               panic(__FILE__,"read_write tries to read from "
-                       "character device NO_DEV", NO_NUM);
-       block_size = get_block_size(rip->i_zone[0]);
+  
+  /* Try to get inode according to its index */
+  if (fs_m_in.REQ_FD_INODE_INDEX >= 0 && 
+          fs_m_in.REQ_FD_INODE_INDEX < NR_INODES &&
+          inode[fs_m_in.REQ_FD_INODE_INDEX].i_num == fs_m_in.REQ_FD_INODE_NR) {
+      rip = &inode[fs_m_in.REQ_FD_INODE_INDEX];
   }
-  if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) {
-       f_size = ULONG_MAX;
-       if (rip->i_zone[0] == NO_DEV)
-               panic(__FILE__,"read_write tries to read from "
-               " block device NO_DEV", NO_NUM);
-       block_size = get_block_size(rip->i_zone[0]);
+  else { 
+      /* Find the inode referred */
+      rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR);
+      if (!rip) {
+          printf("FS: unavaliable inode by fs_readwrite(), nr: %d\n", 
+                  fs_m_in.REQ_FD_INODE_NR);
+          return EINVAL; 
+      }
   }
 
-  if (!char_spec && !block_spec)
-       block_size = rip->i_sp->s_block_size;
+  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);
+  
+  /* Determine blocksize */
+  block_size = (block_spec ? get_block_size(rip->i_zone[0]) 
+      : rip->i_sp->s_block_size);
 
+  f_size = (block_spec ? ULONG_MAX : rip->i_size);
+  
+  /* Get the values from the request message */ 
+  rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
+  usr = fs_m_in.REQ_FD_WHO_E;
+  seg = fs_m_in.REQ_FD_SEG;
+  position = fs_m_in.REQ_FD_POS;
+  nrbytes = (unsigned) fs_m_in.REQ_FD_NBYTES;
+  /*partial_cnt = fs_m_in.REQ_FD_PARTIAL;*/
+  user_addr = fs_m_in.REQ_FD_USER_ADDR;
+
+  /*if (partial_cnt > 0) partial_pipe = 1;*/
+  
   rdwt_err = OK;               /* set to EIO if disk error occurs */
-
-  /* Check for character special files. */
-  if (char_spec) {
-       dev_t dev;
-       dev = (dev_t) rip->i_zone[0];
-       r = dev_io(op, dev, usr, m_in.buffer, position, m_in.nbytes, oflags);
-       if (r >= 0) {
-               cum_io = r;
-               position += r;
-               r = OK;
-       }
-  } else {
-       if (rw_flag == WRITING && block_spec == 0) {
-               /* Check in advance to see if file will grow too big. */
-               if (position > rip->i_sp->s_max_size - m_in.nbytes) 
-                       return(EFBIG);
-
-               /* Check for O_APPEND flag. */
-               if (oflags & O_APPEND) position = f_size;
-
-               /* Clear the zone containing present EOF if hole about
-                * to be created.  This is necessary because all unwritten
-                * blocks prior to the EOF must read as zeros.
-                */
-               if (position > f_size) clear_zone(rip, f_size, 0);
-       }
-
-       /* Pipes are a little different.  Check. */
-       if (rip->i_pipe == I_PIPE) {
-              r = pipe_check(rip, rw_flag, oflags,
-                       m_in.nbytes, position, &partial_cnt, 0);
-              if (r <= 0) return(r);
-       }
-
-       if (partial_cnt > 0) partial_pipe = 1;
-
-       /* Split the transfer into chunks that don't span two blocks. */
-       while (m_in.nbytes != 0) {
-
-               off = (unsigned int) (position % block_size);/* offset in blk*/
-               if (partial_pipe) {  /* pipes only */
-                       chunk = MIN(partial_cnt, block_size - off);
-               } else
-                       chunk = MIN(m_in.nbytes, block_size - off);
-               if (chunk < 0) chunk = block_size - off;
-
-               if (rw_flag == READING) {
-                       bytes_left = f_size - position;
-                       if (position >= f_size) break;  /* we are beyond EOF */
-                       if (chunk > bytes_left) chunk = (int) bytes_left;
-               }
-
-               /* Read or write 'chunk' bytes. */
-               r = rw_chunk(rip, position, off, chunk, (unsigned) m_in.nbytes,
-                            rw_flag, m_in.buffer, seg, usr, block_size, &completed);
-
-               if (r != OK) break;     /* EOF reached */
-               if (rdwt_err < 0) break;
-
-               /* Update counters and pointers. */
-               m_in.buffer += chunk;   /* user buffer address */
-               m_in.nbytes -= chunk;   /* bytes yet to be read */
-               cum_io += chunk;        /* bytes read so far */
-               position += chunk;      /* position within the file */
-
-               if (partial_pipe) {
-                       partial_cnt -= chunk;
-                       if (partial_cnt <= 0)  break;
-               }
-       }
+  
+  if (rw_flag == WRITING && block_spec == 0) {
+      /* Clear the zone containing present EOF if hole about
+       * to be created.  This is necessary because all unwritten
+       * blocks prior to the EOF must read as zeros.
+       */
+      if (position > f_size) clear_zone(rip, f_size, 0);
+  }
+             
+  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);
+      if (chunk < 0) chunk = block_size - off;
+
+      if (rw_flag == READING) {
+          bytes_left = f_size - position;
+          if (position >= f_size) break;       /* we are beyond EOF */
+          if (chunk > bytes_left) chunk = (int) bytes_left;
+      }
+
+      /* Read or write 'chunk' bytes. */
+      r = rw_chunk(rip, position, off, chunk, (unsigned) nrbytes,
+              rw_flag, user_addr, seg, usr, block_size, &completed);
+
+      if (r != OK) break;      /* EOF reached */
+      if (rdwt_err < 0) break;
+
+      /* Update counters and pointers. */
+      user_addr += chunk;      /* user buffer address */
+      nrbytes -= chunk;        /* bytes yet to be read */
+      cum_io += chunk; /* bytes read so far */
+      position += chunk;       /* position within the file */
   }
 
+  fs_m_out.RES_FD_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 (regular || mode_word == I_DIRECTORY) {
                if (position > f_size) rip->i_size = position;
        }
-  } else {
+  } 
+  else {
        if (rip->i_pipe == I_PIPE) {
                if ( position >= rip->i_size) {
                        /* Reset pipe pointers. */
                        rip->i_size = 0;        /* no data left */
                        position = 0;           /* reset reader(s) */
-                       wf = find_filp(rip, W_BIT);
-                       if (wf != NIL_FILP) wf->filp_pos = 0;
                }
        }
   }
-  f->filp_pos = 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 && position % block_size== 0
+  if (rw_flag == READING && rip->i_seek == NO_SEEK && position % block_size == 0
                && (regular || mode_word == I_DIRECTORY)) {
        rdahed_inode = rip;
        rdahedpos = position;
@@ -221,26 +143,94 @@ int rw_flag;                      /* READING or WRITING */
   if (r == OK && r2 != OK) {
        r = r2;
   }
+  
   if (r == OK) {
        if (rw_flag == READING) rip->i_update |= ATIME;
        if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
        rip->i_dirt = DIRTY;            /* inode is thus now dirty */
-       if (partial_pipe) {
-               partial_pipe = 0;
-                       /* partial write on pipe with */
-               /* O_NONBLOCK, return write count */
-               if (!(oflags & O_NONBLOCK)) {
-                       fp->fp_cum_io_partial = cum_io;
-                       suspend(XPIPE);   /* partial write on pipe with */
-                       return(SUSPEND);  /* nbyte > PIPE_SIZE - non-atomic */
-               }
-       }
-       fp->fp_cum_io_partial = 0;
-       return(cum_io);
   }
+  
+  fs_m_out.RES_FD_CUM_IO = cum_io;
+  fs_m_out.RES_FD_SIZE = rip->i_size;
+  
+  return(r);
+}
+
+
+/*===========================================================================*
+ *                             fs_breadwrite                                *
+ *===========================================================================*/
+PUBLIC int fs_breadwrite(void)
+{
+  int r, usr, rw_flag, chunk, block_size;
+  int nrbytes;
+  off_t position, f_size, bytes_left;
+  unsigned int off, cum_io;
+  mode_t mode_word;
+  int completed, r2 = OK;
+  char *user_addr;
+
+  /* Pseudo inode for rw_chunk */
+  struct inode rip;
+  
+  r = OK;
+  f_size = ULONG_MAX;
+  
+  /* Get the values from the request message */ 
+  rw_flag = (fs_m_in.m_type == REQ_BREAD ? READING : WRITING);
+  usr = fs_m_in.REQ_FD_WHO_E;
+  position = fs_m_in.REQ_FD_POS;
+  nrbytes = (unsigned) fs_m_in.REQ_FD_NBYTES;
+  user_addr = fs_m_in.REQ_FD_USER_ADDR;
+  
+  block_size = get_block_size(fs_m_in.REQ_FD_BDEV);
+
+  rip.i_zone[0] = fs_m_in.REQ_FD_BDEV;
+  rip.i_mode = I_BLOCK_SPECIAL;
+  rip.i_size = f_size;
+
+  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);
+      if (chunk < 0) chunk = block_size - off;
+
+      if (rw_flag == READING) {
+          bytes_left = f_size - position;
+          if (position >= f_size) break;       /* we are beyond EOF */
+          if (chunk > bytes_left) chunk = (int) bytes_left;
+      }
+
+      /* Read or write 'chunk' bytes. */
+      r = rw_chunk(&rip, position, off, chunk, (unsigned) nrbytes,
+              rw_flag, user_addr, D, usr, block_size, &completed);
+
+      if (r != OK) break;      /* EOF reached */
+      if (rdwt_err < 0) break;
+
+      /* Update counters and pointers. */
+      user_addr += chunk;      /* user buffer address */
+      nrbytes -= chunk;                /* bytes yet to be read */
+      cum_io += chunk;         /* bytes read so far */
+      position += chunk;       /* position within the file */
+  }
+  
+  fs_m_out.RES_FD_POS = position; 
+  
+  if (rdwt_err != OK) r = rdwt_err;    /* check for disk error */
+  if (rdwt_err == END_OF_FILE) r = OK;
+
+  fs_m_out.RES_FD_CUM_IO = cum_io;
+  fs_m_out.RES_FD_SIZE = rip.i_size;
+  
   return(r);
 }
 
+
 /*===========================================================================*
  *                             rw_chunk                                     *
  *===========================================================================*/
@@ -269,10 +259,12 @@ int *completed;                   /* number of bytes copied */
   *completed = 0;
 
   block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
+
   if (block_spec) {
        b = position/block_size;
        dev = (dev_t) rip->i_zone[0];
-  } else {
+  } 
+  else {
        b = read_map(rip, position);
        dev = rip->i_dev;
   }
@@ -282,14 +274,17 @@ int *completed;                   /* number of bytes copied */
                /* Reading from a nonexistent block.  Must read as all zeros.*/
                bp = get_block(NO_DEV, NO_BLOCK, NORMAL);    /* get a buffer */
                zero_block(bp);
-       } else {
+       } 
+        else {
                /* Writing to a nonexistent block. Create and enter in inode.*/
                if ((bp= new_block(rip, position)) == NIL_BUF)return(err_code);
        }
-  } else if (rw_flag == READING) {
+  } 
+  else if (rw_flag == READING) {
        /* Read and read ahead if convenient. */
        bp = rahead(rip, b, position, left);
-  } else {
+  } 
+  else {
        /* Normally an existing block to be partially overwritten is first read
         * in.  However, a full block need not be read in.  If it is already in
         * the cache, acquire it, otherwise just acquire a free buffer.
@@ -303,6 +298,7 @@ int *completed;                     /* number of bytes copied */
   if (bp == NIL_BUF) {
        panic(__FILE__,"bp not valid in rw_chunk, this can't happen", NO_NUM);
   }
+  
   if (rw_flag == WRITING && chunk != block_size && !block_spec &&
                                        position >= rip->i_size && off == 0) {
        zero_block(bp);
@@ -310,13 +306,14 @@ int *completed;                   /* number of bytes copied */
 
   if (rw_flag == READING) {
        /* Copy a chunk from the block buffer to user space. */
-       r = sys_vircopy(FS_PROC_NR, D, (phys_bytes) (bp->b_data+off),
+       r = sys_vircopy(SELF_E, D, (phys_bytes) (bp->b_data+off),
                        usr, seg, (phys_bytes) buff,
                        (phys_bytes) chunk);
-  } else {
+  } 
+  else {
        /* Copy a chunk from user space to the block buffer. */
        r = sys_vircopy(usr, seg, (phys_bytes) buff,
-                       FS_PROC_NR, D, (phys_bytes) (bp->b_data+off),
+                       SELF_E, D, (phys_bytes) (bp->b_data+off),
                        (phys_bytes) chunk);
        bp->b_dirt = DIRTY;
   }
@@ -558,3 +555,4 @@ unsigned bytes_ahead;               /* bytes beyond position for immediate use */
   rw_scattered(dev, read_q, read_q_size, READING);
   return(get_block(dev, baseblock, NORMAL));
 }
+
similarity index 100%
rename from servers/fs/select.h
rename to servers/mfs/select.h
diff --git a/servers/mfs/stadir.c b/servers/mfs/stadir.c
new file mode 100644 (file)
index 0000000..6b7d7cb
--- /dev/null
@@ -0,0 +1,209 @@
+
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <minix/com.h>
+#include <string.h>
+#include "buf.h"
+#include "inode.h"
+#include "super.h"
+
+#include <minix/vfsif.h>
+
+
+FORWARD _PROTOTYPE( int stat_inode, (struct inode *rip, int pipe_pos,
+                       char *user_addr, int who_e)                     );
+
+
+/*===========================================================================*
+ *                             fs_getdir                                    *
+ *===========================================================================*/
+PUBLIC int fs_getdir()
+{
+  register int r;
+  register struct inode *rip;
+
+  struct inodelist *rlp;
+
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Try to open the new directory. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_getdir() failed\n", SELF_E);
+        return(EINVAL);
+  }
+  
+  r = forbidden(rip, X_BIT);   /* check if dir is searchable */
+
+  /* If error, return inode. */
+  if (r != OK) {
+       put_inode(rip);
+       return(r);
+  }
+  
+  /* If OK send back inode details */
+  fs_m_out.m_source = rip->i_dev; /* filled with FS endpoint by the system */
+  fs_m_out.RES_INODE_NR = rip->i_num;
+  fs_m_out.RES_MODE = rip->i_mode;
+  fs_m_out.RES_FILE_SIZE = rip->i_size;
+
+/*
+printf("MFS(%d): ", SELF_E);
+for (rlp = &hash_inodes[0]; rlp < &hash_inodes[INODE_HASH_SIZE]; ++rlp) {
+       int elements = 0;
+       LIST_FOREACH(rip, rlp, i_hash) elements++;
+       printf("%d ", elements);
+}
+printf("\n");
+*/
+       
+  return OK;  
+}
+
+/*===========================================================================*
+ *                             fs_stat                                      *
+ *===========================================================================*/
+PUBLIC int fs_stat()
+{
+  register struct inode *rip;
+  register int r;
+  
+  /* Both stat() and fstat() use the same routine to do the real work.  That
+   * routine expects an inode, so acquire it temporarily.
+   */
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_stat() failed\n", SELF_E);
+        return(EINVAL);
+  }
+  
+  r = stat_inode(rip, 0, fs_m_in.REQ_USER_ADDR, fs_m_in.REQ_WHO_E);
+  put_inode(rip);              /* release the inode */
+  return(r);
+}
+
+
+/*===========================================================================*
+ *                             fs_fstat                                     *
+ *===========================================================================*/
+PUBLIC int fs_fstat()
+{
+  int r;   
+  struct inode *rip;
+
+  /* Both stat() and fstat() use the same routine to do the real work.  That
+   * routine expects an inode, so acquire it temporarily.
+   */
+  if ((rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR))
+          == NIL_INODE) {
+      printf("FSfstat: couldn't find inode %d\n", fs_m_in.REQ_FD_INODE_NR);
+      return EINVAL;
+  }
+  
+  r = stat_inode(rip, fs_m_in.REQ_FD_POS, fs_m_in.REQ_FD_USER_ADDR, 
+          fs_m_in.REQ_FD_WHO_E);
+
+  return r;
+}
+
+/*===========================================================================*
+ *                             stat_inode                                   *
+ *===========================================================================*/
+PRIVATE int stat_inode(rip, pipe_pos, user_addr, who_e)
+register struct inode *rip;    /* pointer to inode to stat */
+int pipe_pos;                  /* position in a pipe, supplied by fstat() */
+char *user_addr;               /* user space address where stat buf goes */
+int who_e;                      /* kernel endpoint of the caller */
+{
+/* Common code for stat and fstat system calls. */
+
+  struct stat statbuf;
+  mode_t mo;
+  int r, s;
+
+  /* Update the atime, ctime, and mtime fields in the inode, if need be. */
+  if (rip->i_update) update_times(rip);
+
+  /* Fill in the statbuf struct. */
+  mo = rip->i_mode & I_TYPE;
+
+  /* true iff special */
+  s = (mo == I_CHAR_SPECIAL || mo == I_BLOCK_SPECIAL);
+
+  statbuf.st_dev = rip->i_dev;
+  statbuf.st_ino = rip->i_num;
+  statbuf.st_mode = rip->i_mode;
+  statbuf.st_nlink = rip->i_nlinks;
+  statbuf.st_uid = rip->i_uid;
+  statbuf.st_gid = rip->i_gid;
+  statbuf.st_rdev = (dev_t) (s ? rip->i_zone[0] : NO_DEV);
+  statbuf.st_size = rip->i_size;
+
+  if (rip->i_pipe == I_PIPE) {
+       statbuf.st_mode &= ~I_REGULAR;  /* wipe out I_REGULAR bit for pipes */
+       statbuf.st_size -= pipe_pos;
+  }
+
+  statbuf.st_atime = rip->i_atime;
+  statbuf.st_mtime = rip->i_mtime;
+  statbuf.st_ctime = rip->i_ctime;
+
+  /* Copy the struct to user space. */
+  r = sys_datacopy(SELF, (vir_bytes) &statbuf,
+               who_e, (vir_bytes) user_addr, (phys_bytes) sizeof(statbuf));
+  
+  return(r);
+}
+
+
+
+/*===========================================================================*
+ *                             fs_fstatfs                                   *
+ *===========================================================================*/
+PUBLIC int fs_fstatfs()
+{
+  struct statfs st;
+  struct inode *rip;
+  int r;
+  
+  if ((rip = find_inode(fs_dev, fs_m_in.REQ_FD_INODE_NR))
+          == NIL_INODE) {
+      printf("FSfstatfs: couldn't find inode %d\n", fs_m_in.REQ_FD_INODE_NR);
+      return EINVAL;
+  }
+  
+  st.f_bsize = rip->i_sp->s_block_size;
+  
+  /* Copy the struct to user space. */
+  r = sys_datacopy(SELF, (vir_bytes) &st, fs_m_in.REQ_FD_WHO_E, 
+          (vir_bytes) fs_m_in.REQ_FD_USER_ADDR, (phys_bytes) sizeof(st));
+  
+  return(r);
+}
+
+/*===========================================================================*
+ *                             fs_lstat                                     *
+ *===========================================================================*/
+PUBLIC int fs_lstat()
+{
+  register int r;              /* return value */
+  register struct inode *rip;  /* target inode */
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_lstat() failed\n", SELF_E);
+        return(EINVAL);
+  }
+  
+  r = stat_inode(rip, 0, fs_m_in.REQ_USER_ADDR, fs_m_in.REQ_WHO_E);
+  put_inode(rip);              /* release the inode */
+  return(r);
+}
+
+
+
similarity index 94%
rename from servers/fs/super.c
rename to servers/mfs/super.c
index 4f1279fc2b4bcceaefb1acdb83f8e8dd88025ff5..bc94da198ed598f4da03d32f8655e8b08957a1be 100644 (file)
@@ -19,6 +19,7 @@
 #include "super.h"
 #include "const.h"
 
+
 /*===========================================================================*
  *                             alloc_bit                                    *
  *===========================================================================*/
@@ -155,6 +156,7 @@ dev_t dev;                  /* device number whose super_block is sought */
 
   for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
        if (sp->s_dev == dev) return(sp);
+printf("MFS(%d)get_super: sp->s_dev: %d, dev: %d\n", SELF_E, sp->s_dev, dev);  
 
   /* Search failed.  Something wrong. */
   panic(__FILE__,"can't find superblock for device (in decimal)", (int) dev);
@@ -187,23 +189,24 @@ PUBLIC int get_block_size(dev_t dev)
 /*===========================================================================*
  *                             mounted                                      *
  *===========================================================================*/
+/* Report on whether the given inode is on a mounted (or ROOT) file system. */
+/*
 PUBLIC int mounted(rip)
-register struct inode *rip;    /* pointer to inode */
+register struct inode *rip;
 {
-/* Report on whether the given inode is on a mounted (or ROOT) file system. */
 
   register struct super_block *sp;
   register dev_t dev;
 
   dev = (dev_t) rip->i_zone[0];
-  if (dev == root_dev) return(TRUE);   /* inode is on root file system */
+  if (dev == root_dev) return(TRUE);
 
   for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
        if (sp->s_dev == dev) return(TRUE);
 
   return(FALSE);
 }
-
+*/
 /*===========================================================================*
  *                             read_super                                   *
  *===========================================================================*/
@@ -219,9 +222,11 @@ register struct super_block *sp; /* pointer to a superblock */
   dev = sp->s_dev;             /* save device (will be overwritten by copy) */
   if (dev == NO_DEV)
        panic(__FILE__,"request for super_block of NO_DEV", NO_NUM);
-  r = dev_io(DEV_READ, dev, FS_PROC_NR,
+  
+  r = block_dev_io(DEV_READ, dev, SELF_E,
        sbbuf, SUPER_BLOCK_BYTES, _MIN_BLOCK_SIZE, 0);
   if (r != _MIN_BLOCK_SIZE) {
+printf("MFSread_super r != _MIN_BLOCK_SIZE\n");
        return EINVAL;
   }
   memcpy(sp, sbbuf, sizeof(*sp));
@@ -239,6 +244,7 @@ register struct super_block *sp; /* pointer to a superblock */
        version = V3;
        native = 1;
   } else {
+printf("MFSread_super invalid version\n");
        return(EINVAL);
   }
 
@@ -273,14 +279,17 @@ register struct super_block *sp; /* pointer to a superblock */
   } else {
        if (version == V2)
                sp->s_block_size = _STATIC_BLOCK_SIZE;
-       if (sp->s_block_size < _MIN_BLOCK_SIZE)
+       if (sp->s_block_size < _MIN_BLOCK_SIZE) {
+printf("MFSread_super block size ERROR1\n");
                return EINVAL;
+       }
        sp->s_inodes_per_block = V2_INODES_PER_BLOCK(sp->s_block_size);
        sp->s_ndzones = V2_NR_DZONES;
        sp->s_nindirs = V2_INDIRECTS(sp->s_block_size);
   }
 
   if (sp->s_block_size < _MIN_BLOCK_SIZE) {
+printf("MFSread_super block size ERROR2\n");
        return EINVAL;
   }
   if (sp->s_block_size > _MAX_BLOCK_SIZE) {
@@ -290,13 +299,16 @@ register struct super_block *sp; /* pointer to a superblock */
        return EINVAL;
   }
   if ((sp->s_block_size % 512) != 0) {
+printf("MFSread_super block_size !% 512 \n");
        return EINVAL;
   }
   if (SUPER_SIZE > sp->s_block_size) {
+printf("MFSread_super block_size < SUPER_SIZE \n");
        return EINVAL;
   }
   if ((sp->s_block_size % V2_INODE_SIZE) != 0 ||
      (sp->s_block_size % V1_INODE_SIZE) != 0) {
+printf("MFSread_super block_sizr % INODE_SIZE notOK \n");
        return EINVAL;
   }
 
diff --git a/servers/mfs/super.h b/servers/mfs/super.h
new file mode 100644 (file)
index 0000000..c9e4761
--- /dev/null
@@ -0,0 +1,61 @@
+/* Super block table.  The root file system and every mounted file system
+ * has an entry here.  The entry holds information about the sizes of the bit
+ * maps and inodes.  The s_ninodes field gives the number of inodes available
+ * for files and directories, including the root directory.  Inode 0 is 
+ * on the disk, but not used.  Thus s_ninodes = 4 means that 5 bits will be
+ * used in the bit map, bit 0, which is always 1 and not used, and bits 1-4
+ * for files and directories.  The disk layout is:
+ *
+ *    Item        # blocks
+ *    boot block      1
+ *    super block     1    (offset 1kB)
+ *    inode map     s_imap_blocks
+ *    zone map      s_zmap_blocks
+ *    inodes        (s_ninodes + 'inodes per block' - 1)/'inodes per block'
+ *    unused        whatever is needed to fill out the current zone
+ *    data zones    (s_zones - s_firstdatazone) << s_log_zone_size
+ *
+ * A super_block slot is free if s_dev == NO_DEV. 
+ */
+
+EXTERN struct super_block {
+  ino_t s_ninodes;             /* # usable inodes on the minor device */
+  zone1_t  s_nzones;           /* total device size, including bit maps etc */
+  short s_imap_blocks;         /* # of blocks used by inode bit map */
+  short s_zmap_blocks;         /* # of blocks used by zone bit map */
+  zone1_t s_firstdatazone;     /* number of first data zone */
+  short s_log_zone_size;       /* log2 of blocks/zone */
+  short s_pad;                 /* try to avoid compiler-dependent padding */
+  off_t s_max_size;            /* maximum file size on this device */
+  zone_t s_zones;              /* number of zones (replaces s_nzones in V2) */
+  short s_magic;               /* magic number to recognize super-blocks */
+
+  /* The following items are valid on disk only for V3 and above */
+
+  /* The block size in bytes. Minimum MIN_BLOCK SIZE. SECTOR_SIZE
+   * multiple. If V1 or V2 filesystem, this should be
+   * initialised to STATIC_BLOCK_SIZE. Maximum MAX_BLOCK_SIZE.
+   */
+  short s_pad2;                        /* try to avoid compiler-dependent padding */
+  unsigned short s_block_size; /* block size in bytes. */
+  char s_disk_version;         /* filesystem format sub-version */
+
+  /* The following items are only used when the super_block is in memory. */
+  
+  /*struct inode *s_isup;*/    /* inode for root dir of mounted file sys */
+  /*struct inode *s_imount;*/   /* inode mounted on */
+  unsigned s_inodes_per_block; /* precalculated from magic number */
+  dev_t s_dev;                 /* whose super block is this? */
+  int s_rd_only;               /* set to 1 iff file sys mounted read only */
+  int s_native;                        /* set to 1 iff not byte swapped file system */
+  int s_version;               /* file system version, zero means bad magic */
+  int s_ndzones;               /* # direct zones in an inode */
+  int s_nindirs;               /* # indirect zones per indirect block */
+  bit_t s_isearch;             /* inodes below this bit number are in use */
+  bit_t s_zsearch;             /* all zones below this bit number are in use*/
+  char s_is_root;
+} super_block[NR_SUPERS];
+
+#define NIL_SUPER (struct super_block *) 0
+#define IMAP           0       /* operating on the inode bit map */
+#define ZMAP           1       /* operating on the zone bit map */
diff --git a/servers/mfs/table.c b/servers/mfs/table.c
new file mode 100644 (file)
index 0000000..cc7fae3
--- /dev/null
@@ -0,0 +1,62 @@
+
+/* This file contains the table used to map system call numbers onto the
+ * routines that perform them.
+ */
+
+#define _TABLE
+
+#include "fs.h"
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "inode.h"
+#include "buf.h"
+#include "super.h"
+#include "drivers.h"
+
+PUBLIC _PROTOTYPE (int (*fs_call_vec[]), (void) ) = {
+        no_sys,             /* 0   not used */
+        fs_getnode,         /* 1   */
+        fs_putnode,         /* 2   */
+        fs_open,            /* 3   */
+       fs_pipe,            /* 4   */
+       fs_readwrite,       /* 5   */       /* read() */
+       fs_readwrite,       /* 6   */       /* write() */
+        fs_clone_opcl,      /* 7   */
+        fs_ftrunc,          /* 8   */
+
+        fs_chown,           /* 9   */
+       fs_chmod,           /* 10  */
+        fs_access,          /* 11  */
+        fs_mknod,           /* 12  */
+        fs_mkdir,           /* 13  */
+        fs_inhibread,       /* 14  */       /* for lseek() */
+        fs_stat,            /* 15  */
+        fs_fstat,           /* 16  */
+        fs_unlink,          /* 17  */       /* unlink() */
+        fs_unlink,          /* 18  */       /* rmdir() */
+        fs_utime,           /* 19  */
+        fs_fstatfs,         /* 20  */
+        fs_lstat,           /* 21  */
+        fs_getdir,          /* 22  */       /* chdir(), chroot() */
+
+        no_sys,             /* 23  */
+        no_sys,             /* 24  */    
+        fs_link,            /* 25  */
+        
+        fs_slink,           /* 26  */
+        fs_rdlink,          /* 27  */
+
+        fs_rename,          /* 28  */
+        no_sys,             /* 29  */
+        fs_mountpoint,      /* 30  */
+        fs_readsuper,       /* 31  */
+        fs_unmount,         /* 32  */
+        fs_trunc,           /* 33  */
+       fs_sync,            /* 34  */
+        lookup,             /* 35  */
+       fs_stime,           /* 36  */
+        fs_new_driver,      /* 37  */
+        fs_breadwrite,       /* 38  */
+        fs_breadwrite,       /* 39  */
+};
+
diff --git a/servers/mfs/time.c b/servers/mfs/time.c
new file mode 100644 (file)
index 0000000..32785d2
--- /dev/null
@@ -0,0 +1,56 @@
+
+
+
+#include "fs.h"
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "inode.h"
+
+#include <minix/vfsif.h>
+
+
+/*===========================================================================*
+ *                             fs_utime                                     *
+ *===========================================================================*/
+PUBLIC int fs_utime()
+{
+  register struct inode *rip;
+  register int r;
+  
+  caller_uid = fs_m_in.REQ_UID;
+  caller_gid = fs_m_in.REQ_GID;
+  
+  /* Temporarily open the file. */
+  if ( (rip = get_inode(fs_dev, fs_m_in.REQ_INODE_NR)) == NIL_INODE) {
+printf("MFS(%d) get_inode by fs_utime() failed\n", SELF_E);
+        return(EINVAL);
+  }
+
+  /* Only the owner of a file or the super_user can change its time. */
+  r = OK;
+  if (rip->i_uid != caller_uid && caller_uid != SU_UID) r = EPERM;
+  if (fs_m_in.REQ_ACTIME == 0 && r != OK) r = forbidden(rip, W_BIT);
+  if (read_only(rip) != OK) r = EROFS; /* not even su can touch if R/O */
+  if (r == OK) {
+       if (fs_m_in.REQ_ACTIME == 0) {
+                rip->i_atime = fs_m_in.REQ_MODTIME;
+               rip->i_mtime = rip->i_atime;
+       } else {
+               rip->i_atime = fs_m_in.REQ_ACTIME;
+               rip->i_mtime = fs_m_in.REQ_MODTIME;
+       }
+       rip->i_update = CTIME;  /* discard any stale ATIME and MTIME flags */
+       rip->i_dirt = DIRTY;
+  }
+
+  put_inode(rip);
+  return(r);
+}
+
+PUBLIC int fs_stime()
+{
+  boottime = fs_m_in.REQ_BOOTTIME;
+printf("MFS(%d) boottime: %d\n", SELF_E, boottime);    
+  return OK;
+}
+
similarity index 100%
rename from servers/fs/type.h
rename to servers/mfs/type.h
diff --git a/servers/mfs/utility.c b/servers/mfs/utility.c
new file mode 100644 (file)
index 0000000..b9995dc
--- /dev/null
@@ -0,0 +1,93 @@
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <string.h>
+#include <minix/com.h>
+#include <minix/callnr.h>
+
+#include "buf.h"
+#include "inode.h"
+#include "super.h"
+
+#include <minix/vfsif.h>
+
+static int panicking;
+
+/*===========================================================================*
+ *                             no_sys                                       *
+ *===========================================================================*/
+PUBLIC int no_sys()
+{
+/* Somebody has used an illegal system call number */
+  return(EINVAL);
+}
+
+/*===========================================================================*
+ *                             panic                                        *
+ *===========================================================================*/
+PUBLIC void panic(who, mess, num)
+char *who;                     /* who caused the panic */
+char *mess;                    /* panic message string */
+int num;                       /* number to go with it */
+{
+/* Something awful has happened.  Panics are caused when an internal
+ * inconsistency is detected, e.g., a programming error or illegal value of a
+ * defined constant.
+ */
+  if (panicking) return;       /* do not panic during a sync */
+  panicking = TRUE;            /* prevent another panic during the sync */
+
+  printf("FS panic (%s): %s ", who, mess);
+  if (num != NO_NUM) printf("%d",num); 
+  (void) fs_sync();            /* flush everything to the disk */
+  sys_exit(SELF);
+}
+
+/*===========================================================================*
+ *                             conv2                                        *
+ *===========================================================================*/
+PUBLIC unsigned conv2(norm, w)
+int norm;                      /* TRUE if no swap, FALSE for byte swap */
+int w;                         /* promotion of 16-bit word to be swapped */
+{
+/* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
+  if (norm) return( (unsigned) w & 0xFFFF);
+  return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
+}
+
+/*===========================================================================*
+ *                             conv4                                        *
+ *===========================================================================*/
+PUBLIC long conv4(norm, x)
+int norm;                      /* TRUE if no swap, FALSE for byte swap */
+long x;                                /* 32-bit long to be byte swapped */
+{
+/* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
+  unsigned lo, hi;
+  long l;
+  
+  if (norm) return(x);                 /* byte order was already ok */
+  lo = conv2(FALSE, (int) x & 0xFFFF); /* low-order half, byte swapped */
+  hi = conv2(FALSE, (int) (x>>16) & 0xFFFF);   /* high-order half, swapped */
+  l = ( (long) lo <<16) | hi;
+  return(l);
+}
+
+/*===========================================================================*
+ *                             clock_time                                   *
+ *===========================================================================*/
+PUBLIC time_t clock_time()
+{
+/* This routine returns the time in seconds since 1.1.1970.  MINIX is an
+ * astrophysically naive system that assumes the earth rotates at a constant
+ * rate and that such things as leap seconds do not exist.
+ */
+
+  register int k;
+  clock_t uptime;
+
+  if ( (k=getuptime(&uptime)) != OK) panic(__FILE__,"clock_time err", k);
+  return( (time_t) (boottime + (uptime/HZ)));
+}
+
+
similarity index 96%
rename from servers/fs/write.c
rename to servers/mfs/write.c
index d4075905ca9edf64c12f5b5d70f21b8fddca6e9d..c51cb0c79c0cdc19e8fd591512539fc7b06adca9 100644 (file)
@@ -1,3 +1,4 @@
+
 /* This file is the counterpart of "read.c".  It contains the code for writing
  * insofar as this is not contained in read_write().
  *
 #include "fs.h"
 #include <string.h>
 #include "buf.h"
-#include "file.h"
-#include "fproc.h"
 #include "inode.h"
 #include "super.h"
 
+
 FORWARD _PROTOTYPE( void wr_indir, (struct buf *bp, int index, zone_t zone) );
 FORWARD _PROTOTYPE( int empty_indir, (struct buf *, struct super_block *) );
 
-/*===========================================================================*
- *                             do_write                                     *
- *===========================================================================*/
-PUBLIC int do_write()
-{
-/* Perform the write(fd, buffer, nbytes) system call. */
-
-  return(read_write(WRITING));
-}
 
 /*===========================================================================*
  *                             write_map                                    *
@@ -45,8 +36,8 @@ int op;                               /* special actions */
  * Also free the double indirect block if that was the last entry in the
  * double indirect block.
  */
-  int scale, ind_ex = 0, new_ind, new_dbl,
-       zones, nr_indirects, single, zindex, ex;
+  int scale, ind_ex = 0, new_ind, new_dbl, 
+        zones, nr_indirects, single, zindex, ex;
   zone_t z, z1, z2 = NO_ZONE, old_zone;
   register block_t b;
   long excess, zone;
@@ -337,3 +328,4 @@ register struct buf *bp;    /* pointer to buffer to zero */
   memset(bp->b_data, 0, _MAX_BLOCK_SIZE);
   bp->b_dirt = DIRTY;
 }
+
index 140423bfec873502fb2975b26f1660e4e3fa19de..f47cf18c9904fa1db6661a22610ae0155a9c92b5 100644 (file)
@@ -17,7 +17,7 @@
 FORWARD _PROTOTYPE(void init_server, (void)                            );
 FORWARD _PROTOTYPE(void sig_handler, (void)                            );
 FORWARD _PROTOTYPE(void get_work, (message *m)                         );
-FORWARD _PROTOTYPE(void reply, (int whom, int result)                  );
+FORWARD _PROTOTYPE(void reply, (int whom, message *m_out)              );
 
 /* Data buffers to retrieve info during initialization. */
 PRIVATE struct boot_image image[NR_BOOT_PROCS];
@@ -99,7 +99,8 @@ PUBLIC int main(void)
 
           /* Finally send reply message, unless disabled. */
           if (result != EDONTREPLY) {
-              reply(who_e, result);
+             m.m_type = result;
+              reply(who_e, &m);
           }
       }
   }
@@ -191,17 +192,18 @@ message *m_in;                            /* pointer to message */
 /*===========================================================================*
  *                             reply                                        *
  *===========================================================================*/
-PRIVATE void reply(who, result)
+PRIVATE void reply(who, m_out)
 int who;                               /* replyee */
-int result;                            /* report result */
+message *m_out;                         /* reply message */
 {
-    message m_out;                     /* reply message */
+    /*message m_out;*/                 /* reply message */
     int s;                             /* send status */
 
-    m_out.m_type = result;             /* build reply message */
-    if (OK != (s=send(who, &m_out)))    /* send the message */
+    /*m_out.m_type = result;*/         /* build reply message */
+    if (OK != (s=send(who, m_out)))     /* send the message */
         panic("RS", "unable to send reply", s);
 }
 
 
 
+
index 048da7ab646e06410e83f802138290964de509c0..8513df17e590f71f73b386cb9e2da242da011817 100644 (file)
@@ -24,7 +24,8 @@ int nr_in_use;                                        /* number of services */
 extern int errno;                              /* error status */
 
 /* Prototypes for internal functions that do the hard work. */
-FORWARD _PROTOTYPE( int start_service, (struct rproc *rp, int flags) );
+FORWARD _PROTOTYPE( int start_service, (struct rproc *rp, int flags,
+       endpoint_t *ep) );
 FORWARD _PROTOTYPE( int stop_service, (struct rproc *rp,int how) );
 FORWARD _PROTOTYPE( int fork_nb, (void) );
 FORWARD _PROTOTYPE( int read_exec, (struct rproc *rp) );
@@ -56,6 +57,8 @@ int flags;                                    /* extra flags, if any */
   enum dev_style dev_style;                    /* device style */
   int s;                                       /* status variable */
   int len;                                     /* length of string */
+  int r;
+  endpoint_t ep;                               /* new endpoint no. */
 
   /* See if there is a free entry in the table with system processes. */
   if (nr_in_use >= NR_SYS_PROCS) return(EAGAIN); 
@@ -128,7 +131,10 @@ int flags;                                 /* extra flags, if any */
   rp->r_set_resources= 0;                      /* old style */
   
   /* All information was gathered. Now try to start the system service. */
-  return(start_service(rp, flags));
+
+  r = start_service(rp, flags, &ep);
+  m_ptr->RS_ENDPOINT = ep;
+  return r;
 }
 
 
@@ -149,6 +155,8 @@ message *m_ptr;                                     /* request message pointer */
   int s;                                       /* status variable */
   int len;                                     /* length of string */
   int i;
+  int r;
+  endpoint_t ep;
   struct rproc *tmp_rp;
   struct rs_start rs_start;
 
@@ -322,7 +330,9 @@ message *m_ptr;                                     /* request message pointer */
                                                 */
   
   /* All information was gathered. Now try to start the system service. */
-  return(start_service(rp, 0));
+  r = start_service(rp, 0, &ep);
+  m_ptr->RS_ENDPOINT = ep;
+  return r;
 }
 
 
@@ -380,8 +390,9 @@ PUBLIC int do_restart(message *m_ptr)
 {
   register struct rproc *rp;
   size_t len;
-  int s, proc;
+  int s, proc, r;
   char label[MAX_LABEL_LEN];
+  endpoint_t ep;
 
   len= m_ptr->RS_CMD_LEN;
   if (len >= sizeof(label))
@@ -404,8 +415,9 @@ PUBLIC int do_restart(message *m_ptr)
                return EBUSY;
          }
          rp->r_flags &= ~(RS_EXITING|RS_REFRESHING|RS_NOPINGREPLY);
-         start_service(rp, 0); 
-         return(OK);
+         r = start_service(rp, 0, &ep);        
+         m_ptr->RS_ENDPOINT = ep;
+         return(r);
       }
   }
 #if VERBOSE
@@ -491,7 +503,8 @@ PUBLIC void do_exit(message *m_ptr)
 {
   register struct rproc *rp;
   pid_t exit_pid;
-  int exit_status;
+  int exit_status, r;
+  endpoint_t ep;
 
 #if VERBOSE
   printf("RS: got SIGCHLD signal, doing wait to get exited child.\n");
@@ -538,8 +551,10 @@ PUBLIC void do_exit(message *m_ptr)
                      rp->r_restarts = -1;              /* reset counter */
                      if (rp->r_script[0] != '\0')
                        run_script(rp);
-                     else
-                       start_service(rp, 0);           /* direct restart */
+                     else {
+                       start_service(rp, 0, &ep); /* direct restart */
+                       m_ptr->RS_ENDPOINT = ep;
+                     }
              }
               else if (WIFEXITED(exit_status) &&
                      WEXITSTATUS(exit_status) == EXEC_FAILED) {
@@ -575,7 +590,11 @@ rp->r_restarts= 0;
                        rp->r_backoff= 1;
                  }
                  else {
-                     start_service(rp, 0);             /* direct restart */
+                     start_service(rp, 0, &ep);        /* direct restart */
+                     m_ptr->RS_ENDPOINT = ep;
+                       /* Do this even if no I/O happens with the ioctl, in
+                        * order to disambiguate requests with DEV_IOCTL_S.
+                        */
                  }
               }
              break;
@@ -593,6 +612,7 @@ message *m_ptr;
   register struct rproc *rp;
   clock_t now = m_ptr->NOTIFY_TIMESTAMP;
   int s;
+  endpoint_t ep;
 
   /* Search system services table. Only check slots that are in use. */
   for (rp=BEG_RPROC_ADDR; rp<END_RPROC_ADDR; rp++) {
@@ -605,7 +625,8 @@ message *m_ptr;
          if (rp->r_backoff > 0) {
               rp->r_backoff -= 1;
              if (rp->r_backoff == 0) {
-                 start_service(rp, 0);
+                 start_service(rp, 0, &ep);
+                 m_ptr->RS_ENDPOINT = ep;
              }
          }
 
@@ -661,9 +682,10 @@ message *m_ptr;
 /*===========================================================================*
  *                             start_service                                *
  *===========================================================================*/
-PRIVATE int start_service(rp, flags)
+PRIVATE int start_service(rp, flags, endpoint)
 struct rproc *rp;
 int flags;
+endpoint_t *endpoint;
 {
 /* Try to execute the given system service. Fork a new process. The child
  * process will be inhibited from running by the NO_PRIV flag. Only let the
@@ -771,6 +793,8 @@ int flags;
   getuptime(&rp->r_alive_tm);                  /* currently alive */
   rp->r_stop_tm = 0;                           /* not exiting yet */
   rproc_ptr[child_proc_nr_n] = rp;             /* mapping for fast access */
+
+  if(endpoint) *endpoint = child_proc_nr_e;    /* send back child endpoint */
   return(OK);
 }
 
similarity index 76%
rename from servers/fs/Makefile
rename to servers/vfs/Makefile
index 64bf4b26ce2dc7857b1ccf2c4482f1aa2d599efb..9d80d14d428e2c7aec65e771a2667765bcaa814c 100644 (file)
@@ -1,5 +1,5 @@
 # Makefile for File System (FS)
-SERVER = fs
+SERVER = vfs
 
 # directories
 u = /usr
@@ -14,9 +14,10 @@ LDFLAGS = -i
 LIBS = -lsys -lsysutil -ltimers
 
 OBJ =  main.o open.o read.o write.o pipe.o dmap.o \
-       device.o exec.o path.o mount.o link.o super.o inode.o \
-       cache.o cache2.o filedes.o stadir.o protect.o time.o \
-       lock.o misc.o utility.o select.o timers.o table.o
+       path.o device.o mount.o link.o exec.o \
+       filedes.o stadir.o protect.o time.o \
+       lock.o misc.o utility.o select.o timers.o table.o \
+       vnode.o vmnt.o request.o
 
 # build local binary 
 install all build:     $(SERVER)
diff --git a/servers/vfs/buf.h b/servers/vfs/buf.h
new file mode 100644 (file)
index 0000000..a175136
--- /dev/null
@@ -0,0 +1,75 @@
+/* Buffer (block) cache.  To acquire a block, a routine calls get_block(),
+ * telling which block it wants.  The block is then regarded as "in use"
+ * and has its 'b_count' field incremented.  All the blocks that are not
+ * in use are chained together in an LRU list, with 'front' pointing
+ * to the least recently used block, and 'rear' to the most recently used
+ * block.  A reverse chain, using the field b_prev is also maintained.
+ * Usage for LRU is measured by the time the put_block() is done.  The second
+ * parameter to put_block() can violate the LRU order and put a block on the
+ * front of the list, if it will probably not be needed soon.  If a block
+ * is modified, the modifying routine must set b_dirt to DIRTY, so the block
+ * will eventually be rewritten to the disk.
+ */
+
+#include <sys/dir.h>                   /* need struct direct */
+#include <dirent.h>
+
+EXTERN struct buf {
+  /* Data portion of the buffer. */
+  union {
+    char b__data[_MAX_BLOCK_SIZE];                  /* ordinary user data */
+/* directory block */
+    struct direct b__dir[NR_DIR_ENTRIES(_MAX_BLOCK_SIZE)];    
+/* V1 indirect block */
+    zone1_t b__v1_ind[V1_INDIRECTS];        
+/* V2 indirect block */
+    zone_t  b__v2_ind[V2_INDIRECTS(_MAX_BLOCK_SIZE)];       
+/* V1 inode block */
+    d1_inode b__v1_ino[V1_INODES_PER_BLOCK]; 
+/* V2 inode block */
+    d2_inode b__v2_ino[V2_INODES_PER_BLOCK(_MAX_BLOCK_SIZE)]; 
+/* bit map block */
+    bitchunk_t b__bitmap[FS_BITMAP_CHUNKS(_MAX_BLOCK_SIZE)];  
+  } b;
+
+  /* Header portion of the buffer. */
+  struct buf *b_next;          /* used to link all free bufs in a chain */
+  struct buf *b_prev;          /* used to link all free bufs the other way */
+  struct buf *b_hash;          /* used to link bufs on hash chains */
+  block_t b_blocknr;           /* block number of its (minor) device */
+  dev_t b_dev;                 /* major | minor device where block resides */
+  char b_dirt;                 /* CLEAN or DIRTY */
+  char b_count;                        /* number of users of this buffer */
+} buf[NR_BUFS];
+
+/* A block is free if b_dev == NO_DEV. */
+
+#define NIL_BUF ((struct buf *) 0)     /* indicates absence of a buffer */
+
+/* These defs make it possible to use to bp->b_data instead of bp->b.b__data */
+#define b_data   b.b__data
+#define b_dir    b.b__dir
+#define b_v1_ind b.b__v1_ind
+#define b_v2_ind b.b__v2_ind
+#define b_v1_ino b.b__v1_ino
+#define b_v2_ino b.b__v2_ino
+#define b_bitmap b.b__bitmap
+
+EXTERN struct buf *buf_hash[NR_BUF_HASH];      /* the buffer hash table */
+
+EXTERN struct buf *front;      /* points to least recently used free block */
+EXTERN struct buf *rear;       /* points to most recently used free block */
+EXTERN int bufs_in_use;                /* # bufs currently in use (not on free list)*/
+
+/* When a block is released, the type of usage is passed to put_block(). */
+#define WRITE_IMMED   0100 /* block should be written to disk now */
+#define ONE_SHOT      0200 /* set if block not likely to be needed soon */
+
+#define INODE_BLOCK        0                            /* inode block */
+#define DIRECTORY_BLOCK    1                            /* directory block */
+#define INDIRECT_BLOCK     2                            /* pointer block */
+#define MAP_BLOCK          3                            /* bit map */
+#define FULL_DATA_BLOCK    5                            /* data, fully used */
+#define PARTIAL_DATA_BLOCK 6                            /* data, partly used*/
+
+#define HASH_MASK (NR_BUF_HASH - 1)    /* mask for hashing block numbers */
similarity index 97%
rename from servers/fs/const.h
rename to servers/vfs/const.h
index d471e23124f2b14038f31f6dac70c3938a40fff3..479c8eae2d6a342d84ec955091d54f86ca8b3b69 100644 (file)
@@ -4,11 +4,16 @@
 #define V2_NR_DZONES       7   /* # direct zone numbers in a V2 inode */
 #define V2_NR_TZONES      10   /* total # zone numbers in a V2 inode */
 
-#define NR_FILPS         256   /* # slots in filp table */
+#define NR_FILPS         512   /* # slots in filp table */
 #define NR_INODES        256   /* # slots in "in core" inode table */
 #define NR_SUPERS         12   /* # slots in super block table */
 #define NR_LOCKS           8   /* # slots in the file locking table */
 
+
+#define NR_MNTS             8
+#define NR_VNODES         512
+
+
 /* 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.
similarity index 82%
rename from servers/fs/device.c
rename to servers/vfs/device.c
index e480eee2a22ac4a204c906666f28a6f936f39571..914af39b0b8dc57738a608ce36e5e76646a25b59 100644 (file)
@@ -14,7 +14,7 @@
  *   ctty_opcl:  perform controlling-tty-specific processing for open/close
  *   ctty_io:    perform controlling-tty-specific processing for I/O
  *   do_ioctl:  perform the IOCTL system call
- *   pm_setsid:         perform the SETSID system call (FS side)
+ *   do_setsid:         perform the SETSID system call (FS side)
  */
 
 #include "fs.h"
 #include <minix/com.h>
 #include <minix/endpoint.h>
 #include <minix/ioctl.h>
-#include <sys/ioc_tty.h>
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
 #include "param.h"
-#include "super.h"
 
 #define ELEMENTS(a) (sizeof(a)/sizeof((a)[0]))
 
@@ -42,6 +43,7 @@ FORWARD _PROTOTYPE( void safe_io_cleanup, (cp_grant_id_t, cp_grant_id_t *,
 extern int dmap_size;
 PRIVATE int dummyproc;
 
+
 /*===========================================================================*
  *                             dev_open                                     *
  *===========================================================================*/
@@ -67,6 +69,7 @@ int flags;                    /* mode bits and flags */
   return(r);
 }
 
+
 /*===========================================================================*
  *                             dev_close                                    *
  *===========================================================================*/
@@ -88,17 +91,17 @@ endpoint_t suspended_ep(endpoint_t driver, cp_grant_id_t g)
 /* A process is suspended on a driver for which FS issued
  * a grant. Find out which process it was.
  */
-       struct fproc *rfp;
-       for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
-               if(rfp->fp_pid == PID_FREE)
-                       continue;
-               if(rfp->fp_suspended == SUSPENDED &&
-                  rfp->fp_task == -driver && rfp->fp_grant == g) {
-                       return rfp->fp_endpoint;
-               }
-       }
-
-       return NONE;
+    struct fproc *rfp;
+    for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
+        if(rfp->fp_pid == PID_FREE)
+            continue;
+        if(rfp->fp_suspended == SUSPENDED &&
+                rfp->fp_task == -driver && rfp->fp_grant == g) {
+            return rfp->fp_endpoint;
+        }
+    }
+
+    return NONE;
 }
 
 /*===========================================================================*
@@ -246,6 +249,7 @@ off_t *pos;
                        else
                                size = _MINIX_IOCTL_SIZE(m_in.REQUEST);
 
+
                        /* Do this even if no I/O happens with the ioctl, in
                         * order to disambiguate requests with DEV_IOCTL_S.
                         */
@@ -491,6 +495,7 @@ int flags;                  /* special flags, like O_NONBLOCK */
        /* fp is uninitialized at init time. */
        if(!fp)
                panic(__FILE__,"SUSPEND on NULL fp", NO_NUM);
+
        if (flags & O_NONBLOCK) {
                /* Not supposed to block. */
                dev_mess.m_type = CANCEL;
@@ -634,14 +639,14 @@ PUBLIC int do_ioctl()
 /* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
 
   struct filp *f;
-  register struct inode *rip;
+  register struct vnode *vp;
   dev_t dev;
 
   if ( (f = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
-  rip = f->filp_ino;           /* get inode pointer */
-  if ( (rip->i_mode & I_TYPE) != I_CHAR_SPECIAL
-       && (rip->i_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
-  dev = (dev_t) rip->i_zone[0];
+  vp = f->filp_vno;            /* get vnode pointer */
+  if ( (vp->v_mode & I_TYPE) != I_CHAR_SPECIAL
+       && (vp->v_mode & I_TYPE) != I_BLOCK_SPECIAL) return(ENOTTY);
+  dev = (dev_t) vp->v_sdev;
 
   return(dev_io(DEV_IOCTL, dev, who_e, m_in.ADDRESS, 0L, 
        m_in.REQUEST, f->filp_flags));
@@ -728,6 +733,7 @@ message *mess_ptr;          /* pointer to message for task */
   return OK;
 }
 
+
 /*===========================================================================*
  *                             no_dev                                       *
  *===========================================================================*/
@@ -747,10 +753,12 @@ int flags;                        /* mode bits and flags */
 PUBLIC int no_dev_io(int proc, message *m)
 {
 /* Called when doing i/o on a nonexistent device. */
-  printf("FS: I/O on unmapped device number\n");
+  printf("VFS: I/O on unmapped device number\n");
   return EIO;
 }
 
+  
+
 /*===========================================================================*
  *                             clone_opcl                                   *
  *===========================================================================*/
@@ -797,24 +805,49 @@ int flags;                        /* mode bits and flags */
 
   if (op == DEV_OPEN && dev_mess.REP_STATUS >= 0) {
        if (dev_mess.REP_STATUS != minor) {
-               /* A new minor device number has been returned.  Create a
-                * temporary device file to hold it.
-                */
-               struct inode *ip;
-
-               /* Device number of the new device. */
+                struct vnode *vp;
+                struct vmnt *vmp;
+
+                struct clone_opcl_req req;
+                struct node_details res;
+               /* A new minor device number has been returned.
+                 * Request root FS to create a temporary device file to hold it. 
+                 */
+               
+                /* Device number of the new device. */
                dev = (dev & ~(BYTE << MINOR)) | (dev_mess.REP_STATUS << MINOR);
-
-               ip = alloc_inode(root_dev, ALL_MODES | I_CHAR_SPECIAL);
-               if (ip == NIL_INODE) {
-                       /* Oops, that didn't work.  Undo open. */
-                       (void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
-                       return(err_code);
+               
+                /* Fill in request */
+                req.fs_e = ROOT_FS_E;
+                req.dev = dev;
+
+                /* Issue request */
+                if ((r = req_clone_opcl(&req, &res)) != OK) {
+                    (void) clone_opcl(DEV_CLOSE, dev, proc_e, 0);
+                    return r;
+                }
+
+                /* Drop old node and use the new values */
+                vp = fp->fp_filp[m_in.fd]->filp_vno;
+               
+                put_vnode(vp);
+               if ((vp = get_free_vnode()) == NIL_VNODE) {
+                       printf("VFSclone_opcl: failed to get a free vnode..\n");
+                       vp = fp->fp_filp[m_in.fd]->filp_vno;
                }
-               ip->i_zone[0] = dev;
-
-               put_inode(fp->fp_filp[m_in.fd]->filp_ino);
-               fp->fp_filp[m_in.fd]->filp_ino = ip;
+               
+                vp->v_fs_e = res.fs_e;
+                if ((vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) 
+                    printf("VFSclone_opcl: no vmnt found\n");
+
+                vp->v_vmnt = vmp;
+                vp->v_dev = vmp->m_dev;
+                
+                vp->v_inode_nr = res.inode_nr;
+                vp->v_mode = res.fmode; 
+                vp->v_sdev = dev;
+                vp->v_count = 1;
+               fp->fp_filp[m_in.fd]->filp_vno = vp;
        }
        dev_mess.REP_STATUS = OK;
   }
@@ -826,63 +859,75 @@ int flags;                        /* mode bits and flags */
  *===========================================================================*/
 PUBLIC void dev_up(int maj)
 {
-       /* A new device driver has been mapped in. This function
-        * checks if any filesystems are mounted on it, and if so,
-        * dev_open()s them so the filesystem can be reused.
-        */
-       struct super_block *sb;
-       struct filp *fp;
-       int r;
-
-       /* Open a device once for every filp that's opened on it,
-        * and once for every filesystem mounted from it.
-        */
-
-       for(sb = super_block; sb < &super_block[NR_SUPERS]; sb++) {
-               int minor;
-               if(sb->s_dev == NO_DEV)
-                       continue;
-               if(((sb->s_dev >> MAJOR) & BYTE) != maj)
-                       continue;
-               minor = ((sb->s_dev >> MINOR) & BYTE);
-               printf("FS: remounting dev %d/%d\n", maj, minor);
-               if((r = dev_open(sb->s_dev, FS_PROC_NR,
-                  sb->s_rd_only ? R_BIT : (R_BIT|W_BIT))) != OK) {
-                       printf("FS: mounted dev %d/%d re-open failed: %d.\n",
-                               maj, minor, r);
-               }
-       }
-
-       for(fp = filp; fp < &filp[NR_FILPS]; fp++) {
-               struct inode *in;
-               int minor;
-
-               if(fp->filp_count < 1 || !(in=fp->filp_ino)) continue;
-               if(((in->i_zone[0] >> MAJOR) & BYTE) != maj) continue;
-               if(!(in->i_mode & (I_BLOCK_SPECIAL|I_CHAR_SPECIAL))) continue;
-               
-               minor = ((in->i_zone[0] >> MINOR) & BYTE);
-
-               printf("FS: reopening special %d/%d..\n", maj, minor);
-
-               if((r = dev_open(in->i_zone[0], FS_PROC_NR,
-                  in->i_mode & (R_BIT|W_BIT))) != OK) {
-                       int n;
-                       /* This function will set the fp_filp[]s of processes
-                        * holding that fp to NULL, but _not_ clear
-                        * fp_filp_inuse, so that fd can't be recycled until
-                        * it's close()d.
-                        */
-                       n = inval_filp(fp);
-                       if(n != fp->filp_count)
-                               printf("FS: warning: invalidate/count "
-                                "discrepancy (%d, %d)\n", n, fp->filp_count);
-                       fp->filp_count = 0;
-                       printf("FS: file on dev %d/%d re-open failed: %d; "
-                               "invalidated %d fd's.\n", maj, minor, r, n);
-               }
-       }
-
-       return;
+    /* A new device driver has been mapped in. This function
+     * checks if any filesystems are mounted on it, and if so,
+     * dev_open()s them so the filesystem can be reused.
+     */
+    struct filp *fp;
+    struct vmnt *vmp;
+    int r, new_driver_e;
+    message m;
+
+    /* Open a device once for every filp that's opened on it,
+     * and once for every filesystem mounted from it.
+     */
+    new_driver_e = dmap[maj].dmap_driver;
+
+    for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
+        int minor;
+        if (vmp->m_dev == NO_DEV) continue;
+        if ( ((vmp->m_dev >> MAJOR) & BYTE) != maj) continue;
+        minor = ((vmp->m_dev >> MINOR) & BYTE);
+        
+        printf("VFS: re-opening dev: %d/%d\n", maj, minor);
+        
+        if ((r = dev_open(vmp->m_dev, FS_PROC_NR,
+        vmp->m_flags ? R_BIT : (R_BIT|W_BIT))) != OK) {
+            printf("VFS: mounted dev %d/%d re-open failed: %d.\n",
+                maj, minor, r);
+        }
+
+        /* Send new driver endpoint */
+        printf("VFS: sending new dirver for dev: %d, endpoint: %d, FS_e: %d\n", 
+                vmp->m_dev, new_driver_e, vmp->m_fs_e);
+        
+        if (OK != req_newdriver(vmp->m_fs_e, vmp->m_dev, new_driver_e))
+printf("VFSdev_up: error sending new driver endpoint. FS_e: %d req_nr: %d\n", 
+                    vmp->m_fs_e, REQ_NEW_DRIVER);
+        else
+            vmp->m_driver_e = new_driver_e;
+    }
+
+    for (fp = filp; fp < &filp[NR_FILPS]; fp++) {
+        struct vnode *vp;
+        int minor;
+
+        if(fp->filp_count < 1 || !(vp = fp->filp_vno)) continue;
+        if(((vp->v_sdev >> MAJOR) & BYTE) != maj) continue;
+        if(!(vp->v_mode & (I_BLOCK_SPECIAL|I_CHAR_SPECIAL))) continue;
+
+        minor = ((vp->v_sdev >> MINOR) & BYTE);
+
+        printf("VFS: reopening special %d/%d..\n", maj, minor);
+
+        if((r = dev_open(vp->v_sdev, FS_PROC_NR,
+                        vp->v_mode & (R_BIT|W_BIT))) != OK) {
+            int n;
+            /* This function will set the fp_filp[]s of processes
+             * holding that fp to NULL, but _not_ clear
+             * fp_filp_inuse, so that fd can't be recycled until
+             * it's close()d.
+             */
+            n = inval_filp(fp);
+            if(n != fp->filp_count)
+                printf("VFS: warning: invalidate/count "
+                        "discrepancy (%d, %d)\n", n, fp->filp_count);
+            fp->filp_count = 0;
+            printf("VFS: file on dev %d/%d re-open failed: %d; "
+                    "invalidated %d fd's.\n", maj, minor, r, n);
+        }
+    }
+
+    return;
 }
 
similarity index 100%
rename from servers/fs/dmap.c
rename to servers/vfs/dmap.c
similarity index 58%
rename from servers/fs/exec.c
rename to servers/vfs/exec.c
index 39755f3d70092cbcdc359175b95edeb7c66d9f70..10ca92d900b775c1f3fba0271f66a58bb8d4eb51 100644 (file)
@@ -12,6 +12,9 @@
  *
  * The entry points into this file are:
  *   pm_exec:   perform the EXEC system call
+ *
+ * Changes for VFS:
+ *   Aug 2006 (Balazs Gerofi)
  */
 
 #include "fs.h"
 #include <a.out.h>
 #include <signal.h>
 #include <string.h>
-#include "buf.h"
+#include <dirent.h>
 #include "fproc.h"
-#include "inode.h"
 #include "param.h"
-#include "super.h"
+
+#include "vnode.h"
+#include "vmnt.h"
+#include <minix/vfsif.h>
 
 FORWARD _PROTOTYPE( int exec_newmem, (int proc_e, vir_bytes text_bytes,
        vir_bytes data_bytes, vir_bytes bss_bytes, vir_bytes tot_bytes,
@@ -34,17 +39,17 @@ FORWARD _PROTOTYPE( int exec_newmem, (int proc_e, vir_bytes text_bytes,
        Dev_t st_dev, ino_t st_ino, time_t st_ctime, char *progname,
        int new_uid, int new_gid,
        vir_bytes *stack_topp, int *load_textp, int *allow_setuidp)     );
-FORWARD _PROTOTYPE( int read_header, (struct inode *rip, int *sep_id,
+FORWARD _PROTOTYPE( int read_header, (struct vnode *vp, int *sep_id,
        vir_bytes *text_bytes, vir_bytes *data_bytes,
        vir_bytes *bss_bytes, phys_bytes *tot_bytes, vir_bytes *pc,
        int *hdrlenp)                                                   );
-FORWARD _PROTOTYPE( int patch_stack, (struct inode *rip,
+FORWARD _PROTOTYPE( int patch_stack, (struct vnode *vp,
        char stack[ARG_MAX], vir_bytes *stk_bytes)                      );
 FORWARD _PROTOTYPE( int insert_arg, (char stack[ARG_MAX],
        vir_bytes *stk_bytes, char *arg, int replace)                   );
 FORWARD _PROTOTYPE( void patch_ptr, (char stack[ARG_MAX],
                                                        vir_bytes base) );
-FORWARD _PROTOTYPE( int read_seg, (struct inode *rip, off_t off,
+FORWARD _PROTOTYPE( int read_seg, (struct vnode *vp, off_t off,
        int proc_e, int seg, phys_bytes seg_bytes)                      );
 FORWARD _PROTOTYPE( void clo_exec, (struct fproc *rfp)                 );
 
@@ -65,168 +70,218 @@ vir_bytes frame_len;
  * complete stack image, including pointers, args, environ, etc.  The stack
  * is copied to a buffer inside FS, and then to the new core image.
  */
-  int r, sep_id, round, proc_s, hdrlen, load_text, allow_setuid;
-  vir_bytes text_bytes, data_bytes, bss_bytes, pc;
-  phys_bytes tot_bytes;                /* total space for program, including gap */
-  vir_bytes stack_top, vsp;
-  off_t off;
-  uid_t new_uid;
-  gid_t new_gid;
-  struct fproc *rfp;
-  struct inode *rip;
-  char *cp;
-  char progname[PROC_NAME_LEN];
-
-  static char mbuf[ARG_MAX];   /* buffer for stack and zeroes */
-
-  okendpt(proc_e, &proc_s);
-  rfp= fp= &fproc[proc_s];
-  who_e= proc_e;
-  who_p= proc_s;
-  super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
-
-  /* Get the exec file name. */
-  r= fetch_name(path, path_len, 0);
-  if (r != OK)
-  {
-       printf("pm_exec: fetch_name failed\n");
-       return(r);      /* file name not in user data segment */
-  }
-
-  /* Fetch the stack from the user before destroying the old core image. */
-  if (frame_len > ARG_MAX)
-  {
-       printf("pm_exec: bad frame_len\n");
-       return(ENOMEM); /* stack too big */
-  }
-  r = sys_datacopy(proc_e, (vir_bytes) frame,
-                       SELF, (vir_bytes) mbuf, (phys_bytes)frame_len);
-  /* can't fetch stack (e.g. bad virtual addr) */
-  if (r != OK)
-  {
-       printf("pm_exec: sys_datacopy failed\n");
-       return(r);      
-  }
-
-  /* The default is the keep the original user and group IDs */
-  new_uid= rfp->fp_effuid;
-  new_gid= rfp->fp_effgid;
-
-  for (round= 0; round < 2; round++)
-       /* round = 0 (first attempt), or 1 (interpreted script) */
-  {
-       /* Save the name of the program */
-       (cp= strrchr(user_path, '/')) ? cp++ : (cp= user_path);
-
-       strncpy(progname, cp, PROC_NAME_LEN-1);
-       progname[PROC_NAME_LEN-1] = '\0';
-
-#if 0
-       printf("pm_exec: eat_path '%s'\n", user_path);
-#endif
-       rip= eat_path(user_path);
-       if (rip == NIL_INODE)
-       {
-               return(err_code);
-       }
-       if ((rip->i_mode & I_TYPE) != I_REGULAR)
-               r = ENOEXEC;
-       else
-               r = forbidden(rip, X_BIT); /* check if file is executable */
-       if (r != OK) {
-               put_inode(rip);
-               printf("pm_exec: bad executable\n");
-               return(r);
-       }
-
-       if (round == 0)
-       {
-               /* Deal with setuid/setgid executables */
-               if (rip->i_mode & I_SET_UID_BIT)
-                       new_uid = rip->i_uid;
-               if (rip->i_mode & I_SET_GID_BIT)
-                       new_gid = rip->i_gid;
-       }
-
-       /* Read the file header and extract the segment sizes. */
-       r = read_header(rip, &sep_id, &text_bytes, &data_bytes, &bss_bytes, 
-               &tot_bytes, &pc, &hdrlen);
-       if (r != ESCRIPT || round != 0)
-               break;
-
-       /* Get fresh copy of the file name. */
-       r= fetch_name(path, path_len, 0);
-       if (r != OK)
-       {
-               printf("pm_exec: 2nd fetch_name failed\n");
-               put_inode(rip);
-               return(r);      /* strange */
-       }
-       r= patch_stack(rip, mbuf, &frame_len);
-       put_inode(rip);
-       if (r != OK)
-       {
-               printf("pm_exec: patch stack\n");
+    int r, sep_id, round, proc_s, hdrlen, load_text, allow_setuid;
+    vir_bytes text_bytes, data_bytes, bss_bytes, pc;
+    phys_bytes tot_bytes;              /* total space for program, including gap */
+    vir_bytes stack_top, vsp;
+    off_t off;
+    uid_t new_uid;
+    gid_t new_gid;
+    struct fproc *rfp;
+    struct vnode vn;
+    struct vmnt *vmp;
+    time_t v_ctime;
+    uid_t v_uid;
+    gid_t v_gid;
+    char *cp;
+    char progname[PROC_NAME_LEN];
+    static char mbuf[ARG_MAX]; /* buffer for stack and zeroes */
+
+    /* Request and response structures */
+    struct lookup_req lookup_req;
+    struct access_req access_req;
+    struct open_req open_req;
+    struct node_details res;
+    
+    okendpt(proc_e, &proc_s);
+    rfp= fp= &fproc[proc_s];
+    who_e= proc_e;
+    who_p= proc_s;
+    super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
+
+    /* Get the exec file name. */
+    r= fetch_name(path, path_len, 0);
+    if (r != OK)
+    {
+        printf("pm_exec: fetch_name failed\n");
+        return(r);     /* file name not in user data segment */
+    }
+
+    /* Fetch the stack from the user before destroying the old core image. */
+    if (frame_len > ARG_MAX)
+    {
+        printf("pm_exec: bad frame_len\n");
+        return(ENOMEM);        /* stack too big */
+    }
+    r = sys_datacopy(proc_e, (vir_bytes) frame,
+            SELF, (vir_bytes) mbuf, (phys_bytes)frame_len);
+    /* can't fetch stack (e.g. bad virtual addr) */
+    if (r != OK)
+    {
+        printf("pm_exec: sys_datacopy failed\n");
+        return(r);     
+    }
+
+    /* The default is the keep the original user and group IDs */
+    new_uid= rfp->fp_effuid;
+    new_gid= rfp->fp_effgid;
+
+    for (round= 0; round < 2; round++)
+        /* round = 0 (first attempt), or 1 (interpreted script) */
+    {
+        /* Save the name of the program */
+        (cp= strrchr(user_fullpath, '/')) ? cp++ : (cp= user_fullpath);
+
+        strncpy(progname, cp, PROC_NAME_LEN-1);
+        progname[PROC_NAME_LEN-1] = '\0';
+
+        /* Fill in lookup request fields */
+        lookup_req.path = user_fullpath;
+        lookup_req.lastc = NULL;
+        lookup_req.flags = EAT_PATH;
+        
+        /* Request lookup */
+        if ((r = lookup(&lookup_req, &res)) != OK) return r;
+        
+        if ((res.fmode & I_TYPE) != I_REGULAR) {
+            return ENOEXEC;
+        }
+        else {
+            /* Fill in request fields */
+            access_req.fs_e = res.fs_e;
+            access_req.amode = X_BIT;
+            access_req.inode_nr = res.inode_nr;
+           access_req.uid = fp->fp_effuid;
+           access_req.gid = fp->fp_effgid;
+
+            
+           /* Issue request */
+           if ((r = req_access(&access_req)) != OK) {
+                printf("VFSexec: access failed\n");            
                return r;
+           }
+        }
+
+        /* Open request. */
+        open_req.inode_nr = res.inode_nr;
+        open_req.fs_e = res.fs_e;
+        open_req.oflags = 0;
+        open_req.omode = 0;
+        open_req.lastc = NULL;
+        open_req.uid = 0;
+        open_req.gid = 0;
+        
+        /* Issue request */
+        if ((r = req_open(&open_req, &res)) != OK) {
+            printf("VFSexec: open failed\n");          
+           return r;
        }
-  }
-
-  if (r != OK)
-  {
-       printf("pm_exec: returning ENOEXEC, r = %d\n", r);
-       return ENOEXEC;
-  }
-
-  r= exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes,
-       frame_len, sep_id, rip->i_dev, rip->i_num, rip->i_ctime, 
-       progname, new_uid, new_gid, &stack_top, &load_text, &allow_setuid);
-  if (r != OK)
-  {
-       printf("pm_exec: exec_newmap failed: %d\n", r);
-       put_inode(rip);
-       return r;
-  }
 
-  /* Patch up stack and copy it from FS to new core image. */
-  vsp = stack_top;
-  vsp -= frame_len;
-  patch_ptr(mbuf, vsp);
-  r = sys_datacopy(SELF, (vir_bytes) mbuf,
-               proc_e, (vir_bytes) vsp, (phys_bytes)frame_len);
-  if (r != OK) panic(__FILE__,"pm_exec stack copy err on", proc_e);
-
-  off = hdrlen;
-
-  /* Read in text and data segments. */
-  if (load_text) {
-       r= read_seg(rip, off, proc_e, T, text_bytes);
-  }
-  off += text_bytes;
-  if (r == OK)
-       r= read_seg(rip, off, proc_e, D, data_bytes);
-
-  put_inode(rip);
-
-  if (r != OK) return r;
-
-  clo_exec(rfp);
-
-  if (allow_setuid)
-  {
-       rfp->fp_effuid= new_uid;
-       rfp->fp_effgid= new_gid;
-  }
-
-  /* This child has now exec()ced. */
-  rfp->fp_execced = 1;
-
-  /* Check if this is a driver that can now be useful. */
-  dmap_endpt_up(rfp->fp_endpoint);
-
-  return OK;
+        /* Use the vnode to store file details */
+        vn.v_inode_nr = res.inode_nr;
+        vn.v_mode = res.fmode;
+        vn.v_index = res.inode_index;
+        vn.v_size = res.fsize;
+        vn.v_fs_e = res.fs_e;
+        vn.v_count = 1;
+        if ( (vmp = find_vmnt(vn.v_fs_e)) == NIL_VMNT)
+            printf("VFS: vmnt not found by exec()");
+      
+        vn.v_dev = vmp->m_dev;
+        vn.v_vmnt = vmp;
+        
+        v_ctime = res.ctime;
+        v_uid = res.uid;
+        v_gid = res.gid;
+        
+        if (round == 0)
+        {
+            /* Deal with setuid/setgid executables */
+            if (vn.v_mode & I_SET_UID_BIT)
+                new_uid = v_uid;
+            if (vn.v_mode & I_SET_GID_BIT)
+                new_gid = v_gid;
+        }
+
+        /* Read the file header and extract the segment sizes. */
+        r = read_header(&vn, &sep_id, &text_bytes, &data_bytes, &bss_bytes, 
+                &tot_bytes, &pc, &hdrlen);
+        if (r != ESCRIPT || round != 0)
+            break;
+
+        /* Get fresh copy of the file name. */
+        r= fetch_name(path, path_len, 0);
+        if (r != OK)
+        {
+            printf("pm_exec: 2nd fetch_name failed\n");
+            put_vnode(&vn);
+            return(r); /* strange */
+        }
+        r= patch_stack(&vn, mbuf, &frame_len);
+        put_vnode(&vn);
+        if (r != OK)
+        {
+            printf("pm_exec: patch stack\n");
+            return r;
+        }
+    }
+
+    if (r != OK)
+    {
+        printf("pm_exec: returning ENOEXEC, r = %d\n", r);
+        return ENOEXEC;
+    }
+
+    r= exec_newmem(proc_e, text_bytes, data_bytes, bss_bytes, tot_bytes,
+            frame_len, sep_id, vn.v_dev, vn.v_inode_nr, v_ctime, 
+            progname, new_uid, new_gid, &stack_top, &load_text, &allow_setuid);
+    if (r != OK)
+    {
+        printf("pm_exec: exec_newmap failed: %d\n", r);
+        put_vnode(&vn);
+        return r;
+    }
+
+    /* Patch up stack and copy it from FS to new core image. */
+    vsp = stack_top;
+    vsp -= frame_len;
+    patch_ptr(mbuf, vsp);
+    r = sys_datacopy(SELF, (vir_bytes) mbuf,
+            proc_e, (vir_bytes) vsp, (phys_bytes)frame_len);
+    if (r != OK) panic(__FILE__,"pm_exec stack copy err on", proc_e);
+
+    off = hdrlen;
+
+    /* Read in text and data segments. */
+    if (load_text) {
+        r= read_seg(&vn, off, proc_e, T, text_bytes);
+    }
+    off += text_bytes;
+    if (r == OK)
+        r= read_seg(&vn, off, proc_e, D, data_bytes);
+
+    put_vnode(&vn);
+
+    if (r != OK) return r;
+
+    clo_exec(rfp);
+
+    if (allow_setuid)
+    {
+        rfp->fp_effuid= new_uid;
+        rfp->fp_effgid= new_gid;
+    }
+
+    /* This child has now exec()ced. */
+    rfp->fp_execced = 1;
+
+    /* Check if this is a driver that can now be useful. */
+    dmap_endpt_up(rfp->fp_endpoint);
+
+/*printf("VFSpm_exec: %s OK\n", user_fullpath);*/
+    return OK;
 }
 
-
 /*===========================================================================*
  *                             exec_newmem                                  *
  *===========================================================================*/
@@ -291,9 +346,9 @@ int *allow_setuidp;
 /*===========================================================================*
  *                             read_header                                  *
  *===========================================================================*/
-PRIVATE int read_header(rip, sep_id, text_bytes, data_bytes, bss_bytes, 
+PRIVATE int read_header(vp, sep_id, text_bytes, data_bytes, bss_bytes, 
                                                tot_bytes, pc, hdrlenp)
-struct inode *rip;             /* inode for reading exec file */
+struct vnode *vp;              /* inode for reading exec file */
 int *sep_id;                   /* true iff sep I&D */
 vir_bytes *text_bytes;         /* place to return text size */
 vir_bytes *data_bytes;         /* place to return initialized data size */
@@ -304,8 +359,6 @@ int *hdrlenp;
 {
 /* Read the header and extract the text, data, bss and total sizes from it. */
   off_t pos;
-  block_t b;
-  struct buf *bp;
   struct exec hdr;             /* a.out header is read in here */
 
   /* Read the header and check the magic number.  The standard MINIX header 
@@ -335,25 +388,31 @@ int *hdrlenp;
    * is ignored here.
    */
 
+  struct readwrite_req req;
+  struct readwrite_res res;
+  int r;
+  
   pos= 0;      /* Read from the start of the file */
-  b = read_map(rip, pos);      /* get block number */
 
-  if (b == 0)  /* Hole */
-       return ENOEXEC;
+  /* Fill in request structure */
+  req.fs_e = vp->v_fs_e;
+  req.rw_flag = READING;
+  req.inode_nr = vp->v_inode_nr;
+  req.user_e = FS_PROC_NR;
+  req.seg = D;
+  req.pos = pos;
+  req.num_of_bytes = sizeof(hdr);
+  req.user_addr = (char*)&hdr;
+  req.inode_index = vp->v_index;
 
-  bp = get_block(rip->i_dev, b, NORMAL);       /* get block */
+  /* Issue request */
+  if ((r = req_readwrite(&req, &res)) != OK) return r;
 
   /* Interpreted script? */
-  if (bp->b_data[0] == '#' && bp->b_data[1] == '!' && rip->i_size >= 2)
-  {
-       put_block(bp, FULL_DATA_BLOCK);
+  if (((char*)&hdr)[0] == '#' && ((char*)&hdr)[1] == '!' && vp->v_size >= 2)
        return ESCRIPT;
-  }
 
-  memcpy(&hdr, bp->b_data, sizeof(hdr));
-  put_block(bp, FULL_DATA_BLOCK);
-
-  if (rip->i_size < A_MINHDR) return(ENOEXEC);
+  if (vp->v_size < A_MINHDR) return(ENOEXEC);
 
   /* Check magic number, cpu type, and flags. */
   if (BADMAG(hdr)) return(ENOEXEC);
@@ -388,8 +447,8 @@ int *hdrlenp;
 /*===========================================================================*
  *                             patch_stack                                  *
  *===========================================================================*/
-PRIVATE int patch_stack(rip, stack, stk_bytes)
-struct inode *rip;             /* pointer for open script file */
+PRIVATE int patch_stack(vp, stack, stk_bytes)
+struct vnode *vp;              /* pointer for open script file */
 char stack[ARG_MAX];           /* pointer to stack image within FS */
 vir_bytes *stk_bytes;          /* size of initial stack */
 {
@@ -398,50 +457,56 @@ vir_bytes *stk_bytes;             /* size of initial stack */
  * the interpreter.
  */
   enum { INSERT=FALSE, REPLACE=TRUE };
-  int n;
+  int n, r;
   off_t pos;
-  block_t b;
-  struct buf *bp;
   char *sp, *interp = NULL;
+  char buf[_MAX_BLOCK_SIZE];
+  struct readwrite_req req;
+  struct readwrite_res res;
 
   /* Make user_path the new argv[0]. */
-  if (!insert_arg(stack, stk_bytes, user_path, REPLACE)) return(ENOMEM);
-
-  pos= 0;      /* Read from the start of the file */
-  b = read_map(rip, pos);      /* get block number */
-  if (b == 0)  /* Hole */
-       return ENOEXEC;
-
-  bp = get_block(rip->i_dev, b, NORMAL);       /* get block */
-  n= rip->i_size;
-  if (n > rip->i_sp->s_block_size)
-       n= rip->i_sp->s_block_size;
-  if (n < 2)
-  {
-       put_block(bp, FULL_DATA_BLOCK);
-       return ENOEXEC;
-  }
-  sp= bp->b_data+2;                            /* just behind the #! */
+  if (!insert_arg(stack, stk_bytes, user_fullpath, REPLACE)) return(ENOMEM);
+
+  pos = 0;     /* Read from the start of the file */
+
+  /* Fill in request structure */
+  req.fs_e = vp->v_fs_e;
+  req.rw_flag = READING;
+  req.inode_nr = vp->v_inode_nr;
+  req.user_e = FS_PROC_NR;
+  req.seg = D;
+  req.pos = pos;
+  req.num_of_bytes = _MAX_BLOCK_SIZE;
+  req.user_addr = buf;
+  req.inode_index = vp->v_index;
+
+  /* Issue request */
+  if ((r = req_readwrite(&req, &res)) != OK) return r;
+  
+  n = vp->v_size;
+  if (n > vp->v_vmnt->m_block_size)
+       n = vp->v_vmnt->m_block_size;
+  if (n < 2) return ENOEXEC;
+  
+  sp = &(buf[2]);                              /* just behind the #! */
   n -= 2;
-  if (n > PATH_MAX)
-       n= PATH_MAX;
+  if (n > PATH_MAX) n = PATH_MAX;
 
   /* Use the user_path variable for temporary storage */
-  memcpy(user_path, sp, n);
-  put_block(bp, FULL_DATA_BLOCK);
+  memcpy(user_fullpath, sp, n);
 
-  if ((sp= memchr(user_path, '\n', n)) == NULL)        /* must be a proper line */
+  if ((sp = memchr(user_fullpath, '\n', n)) == NULL) /* must be a proper line */
        return(ENOEXEC);
 
   /* Move sp backwards through script[], prepending each string to stack. */
   for (;;) {
        /* skip spaces behind argument. */
-       while (sp > user_path && (*--sp == ' ' || *sp == '\t')) {}
-       if (sp == user_path) break;
+       while (sp > user_fullpath && (*--sp == ' ' || *sp == '\t')) {}
+       if (sp == user_fullpath) break;
 
        sp[1] = 0;
        /* Move to the start of the argument. */
-       while (sp > user_path && sp[-1] != ' ' && sp[-1] != '\t') --sp;
+       while (sp > user_fullpath && sp[-1] != ' ' && sp[-1] != '\t') --sp;
 
        interp = sp;
        if (!insert_arg(stack, stk_bytes, sp, INSERT)) return(ENOMEM);
@@ -450,8 +515,8 @@ vir_bytes *stk_bytes;               /* size of initial stack */
   /* Round *stk_bytes up to the size of a pointer for alignment contraints. */
   *stk_bytes= ((*stk_bytes + PTRSIZE - 1) / PTRSIZE) * PTRSIZE;
 
-  if (interp != user_path)
-       memmove(user_path, interp, strlen(interp)+1);
+  if (interp != user_fullpath)
+       memmove(user_fullpath, interp, strlen(interp)+1);
   return(OK);
 }
 
@@ -546,8 +611,8 @@ vir_bytes base;                     /* virtual address of stack base inside user */
 /*===========================================================================*
  *                             read_seg                                     *
  *===========================================================================*/
-PRIVATE int read_seg(rip, off, proc_e, seg, seg_bytes)
-struct inode *rip;             /* inode descriptor to read from */
+PRIVATE int read_seg(vp, off, proc_e, seg, seg_bytes)
+struct vnode *vp;              /* inode descriptor to read from */
 off_t off;                     /* offset in file */
 int proc_e;                    /* process number (endpoint) */
 int seg;                       /* T, D, or S */
@@ -558,46 +623,31 @@ phys_bytes seg_bytes;             /* how much is to be transferred? */
  * a segment is padded out to a click multiple, and the data segment is only
  * partially initialized.
  */
-
-  int r, block_size;
-  off_t n, o, b_off, seg_off;
-  block_t b;
-  struct buf *bp;
+  struct readwrite_req req;
+  struct readwrite_res res;
+  int r;
 
   /* Make sure that the file is big enough */
-  if (rip->i_size < off+seg_bytes)
-       return EIO;
-
-  block_size= rip->i_sp->s_block_size;
-  seg_off= 0;
-  for (o= off - (off % block_size); o < off+seg_bytes; o += block_size)
-  {
-       b= read_map(rip, o);
-       if (b == NO_BLOCK)
-       {
-               bp = get_block(NO_DEV, NO_BLOCK, NORMAL);    /* get a buffer */
-               zero_block(bp);
-       }
-       else
-               bp = get_block(rip->i_dev, b, NORMAL);  /* get block */
-       if (o < off)
-               b_off= off-o;
-       else
-               b_off= 0;
-       n= block_size-b_off;
-       if (o+b_off+n > off+seg_bytes)
-               n= off+seg_bytes-(o+b_off);
-       r= sys_vircopy(SELF, D, (vir_bytes)bp->b_data+b_off,
-               proc_e, seg, seg_off, n);
-       put_block(bp, FULL_DATA_BLOCK);
-
-       if (r != OK)
-               return r;
-
-       seg_off += n;
-  }
-
-  return OK;
+  if (vp->v_size < off+seg_bytes) return EIO;
+  
+  /* Fill in request structure */
+  req.fs_e = vp->v_fs_e;
+  req.rw_flag = READING;
+  req.inode_nr = vp->v_inode_nr;
+  req.user_e = proc_e;
+  req.seg = seg;
+  req.pos = off;
+  req.num_of_bytes = seg_bytes;
+  req.user_addr = 0;
+  req.inode_index = vp->v_index;
+
+  /* Issue request */
+  if ((r = req_readwrite(&req, &res)) != OK) return r;
+  
+  if (r == OK && res.cum_io != seg_bytes)
+      printf("VFSread_seg segment has not been read properly by exec() \n");
+
+  return r; 
 }
 
 
@@ -618,3 +668,4 @@ struct fproc *rfp;
 }
 
 
+
diff --git a/servers/vfs/file.h b/servers/vfs/file.h
new file mode 100644 (file)
index 0000000..4b1e692
--- /dev/null
@@ -0,0 +1,27 @@
+/* This is the filp table.  It is an intermediary between file descriptors and
+ * inodes.  A slot is free if filp_count == 0.
+ */
+
+EXTERN struct filp {
+  mode_t filp_mode;            /* RW bits, telling how file is opened */
+  int filp_flags;              /* flags from open and fcntl */
+  int filp_count;              /* how many file descriptors share this slot?*/
+/*  struct inode *filp_ino;*/  /* pointer to the inode */
+
+  struct vnode *filp_vno;
+  
+  off_t filp_pos;              /* file position */
+
+  /* the following fields are for select() and are owned by the generic
+   * select() code (i.e., fd-type-specific select() code can't touch these).
+   */
+  int filp_selectors;          /* select()ing processes blocking on this fd */
+  int filp_select_ops;         /* interested in these SEL_* operations */
+
+  /* following are for fd-type-specific select() */
+  int filp_pipe_select_ops;
+} filp[NR_FILPS];
+
+#define FILP_CLOSED    0       /* filp_mode: associated device closed */
+
+#define NIL_FILP (struct filp *) 0     /* indicates absence of a filp slot */
similarity index 88%
rename from servers/fs/filedes.c
rename to servers/vfs/filedes.c
index 48548bfef092bad45a32d8d1bb5eb59c8bf590f2..4b137c969aeb30d33539983b796f555f8da677c1 100644 (file)
@@ -13,7 +13,8 @@
 #include "fs.h"
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
+
+#include "vnode.h"
 
 /*===========================================================================*
  *                             get_fd                                       *
@@ -88,7 +89,7 @@ int fild;                     /* file descriptor */
 /*===========================================================================*
  *                             find_filp                                    *
  *===========================================================================*/
-PUBLIC struct filp *find_filp(register struct inode *rip, mode_t bits)
+PUBLIC struct filp *find_filp(register struct vnode *vp, mode_t bits)
 {
 /* Find a filp slot that refers to the inode 'rip' in a way as described
  * by the mode bit 'bits'. Used for determining whether somebody is still
@@ -100,7 +101,7 @@ PUBLIC struct filp *find_filp(register struct inode *rip, mode_t bits)
   register struct filp *f;
 
   for (f = &filp[0]; f < &filp[NR_FILPS]; f++) {
-       if (f->filp_count != 0 && f->filp_ino == rip && (f->filp_mode & bits)){
+       if (f->filp_count != 0 && f->filp_vno == vp && (f->filp_mode & bits)){
                return(f);
        }
   }
@@ -114,16 +115,16 @@ PUBLIC struct filp *find_filp(register struct inode *rip, mode_t bits)
  *===========================================================================*/
 PUBLIC int inval_filp(struct filp *fp)
 {
-       int f, fd, n = 0;
-       for(f = 0; f < NR_PROCS; f++) {
-               if(fproc[f].fp_pid == PID_FREE) continue;
-               for(fd = 0; fd < OPEN_MAX; fd++) {
-                       if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) {
-                               fproc[f].fp_filp[fd] = NIL_FILP;
-                               n++;
-                       }
-               }
-       }
-
-       return n;
+    int f, fd, n = 0;
+    for(f = 0; f < NR_PROCS; f++) {
+        if(fproc[f].fp_pid == PID_FREE) continue;
+        for(fd = 0; fd < OPEN_MAX; fd++) {
+            if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == fp) {
+                fproc[f].fp_filp[fd] = NIL_FILP;
+                n++;
+            }
+        }
+    }
+
+    return n;
 }
diff --git a/servers/vfs/fproc.h b/servers/vfs/fproc.h
new file mode 100644 (file)
index 0000000..1edfae9
--- /dev/null
@@ -0,0 +1,53 @@
+#include <sys/select.h>
+#include <minix/safecopies.h>
+
+/* This is the per-process information.  A slot is reserved for each potential
+ * process. Thus NR_PROCS must be the same as in the kernel. It is not 
+ * possible or even necessary to tell when a slot is free here.
+ */
+EXTERN struct fproc {
+  mode_t fp_umask;             /* mask set by umask system call */
+/*  struct inode *fp_workdir;*/        /* pointer to working directory's inode */
+/*  struct inode *fp_rootdir;*/        /* pointer to current root dir (see chroot) */
+
+  struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
+
+  struct vnode *fp_wd;
+  struct vnode *fp_rd;
+  
+  fd_set fp_filp_inuse;                /* which fd's are in use? */
+  uid_t fp_realuid;            /* real user id */
+  uid_t fp_effuid;             /* effective user id */
+  gid_t fp_realgid;            /* real group id */
+  gid_t fp_effgid;             /* effective group id */
+  dev_t fp_tty;                        /* major/minor of controlling tty */
+  int fp_fd;                   /* place to save fd if rd/wr can't finish */
+  char *fp_buffer;             /* place to save buffer if rd/wr can't finish*/
+  int  fp_nbytes;              /* place to save bytes if rd/wr can't finish */
+  int  fp_cum_io_partial;      /* partial byte count if rd/wr can't finish */
+  char fp_suspended;           /* set to indicate process hanging */
+  char fp_revived;             /* set to indicate process being revived */
+  int fp_task;                 /* which task is proc suspended on */
+  
+  endpoint_t fp_ioproc;                /* proc no. in suspended-on i/o message */
+  cp_grant_id_t fp_grant;      /* revoke this grant on unsuspend if > -1 */
+  
+  char fp_sesldr;              /* true if proc is a session leader */
+  char fp_execced;             /* true if proc has exec()ced after fork */
+  pid_t fp_pid;                        /* process id */
+  
+  fd_set fp_cloexec_set;       /* bit map for POSIX Table 6-2 FD_CLOEXEC */
+  endpoint_t fp_endpoint;      /* kernel endpoint number of this process */
+} fproc[NR_PROCS];
+
+/* Field values. */
+#define NOT_SUSPENDED      0   /* process is not suspended on pipe or task */
+#define SUSPENDED          1   /* process is suspended on pipe or task */
+#define NOT_REVIVING       0   /* process is not being revived */
+#define REVIVING           1   /* process is being revived from suspension */
+#define PID_FREE          0    /* process slot free */
+
+/* Check is process number is acceptable - includes system processes. */
+#define isokprocnr(n)  ((unsigned)((n)+NR_TASKS) < NR_PROCS + NR_TASKS)
+
diff --git a/servers/vfs/fs.h b/servers/vfs/fs.h
new file mode 100644 (file)
index 0000000..b9f16ff
--- /dev/null
@@ -0,0 +1,26 @@
+/* This is the master header for fs.  It includes some other files
+ * and defines the principal constants.
+ */
+#define _POSIX_SOURCE      1   /* tell headers to include POSIX stuff */
+#define _MINIX             1   /* tell headers to include MINIX stuff */
+#define _SYSTEM            1   /* tell headers that this is the kernel */
+
+#define VERBOSE                   0    /* show messages during initialization? */
+
+/* The following are so basic, all the *.c files get them automatically. */
+#include <minix/config.h>      /* MUST be first */
+#include <ansi.h>              /* MUST be second */
+#include <sys/types.h>
+#include <minix/const.h>
+#include <minix/type.h>
+#include <minix/dmap.h>
+
+#include <limits.h>
+#include <errno.h>
+
+#include <minix/syslib.h>
+#include <minix/sysutil.h>
+
+#include "const.h"
+#include "proto.h"
+#include "glo.h"
similarity index 75%
rename from servers/fs/glo.h
rename to servers/vfs/glo.h
index bcd16a868365201e380bea821c0e60579fc9a564..454425cd73dc8692fc9c95d89103040dd973643c 100644 (file)
@@ -10,9 +10,11 @@ EXTERN int super_user;               /* 1 if caller is super_user, else 0 */
 EXTERN int susp_count;         /* number of procs suspended on pipe */
 EXTERN int nr_locks;           /* number of locks currently in place */
 EXTERN int reviving;           /* number of pipe processes to be revived */
-EXTERN off_t rdahedpos;                /* position to read ahead */
-EXTERN struct inode *rdahed_inode;     /* pointer to inode to read ahead */
+
 EXTERN Dev_t root_dev;         /* device number of the root device */
+EXTERN int ROOT_FS_E;           /* kernel endpoint of the root FS proc */
+EXTERN int last_login_fs_e;     /* endpoint of the FS proc that logged in
+                                   before the corresponding mount request */
 EXTERN time_t boottime;                /* time in seconds at system boot */
 
 /* The parameters of the call are kept here. */
@@ -20,7 +22,10 @@ EXTERN message m_in;         /* the input message itself */
 EXTERN message m_out;          /* the output message used for reply */
 EXTERN int who_p, who_e;       /* caller's proc number, endpoint */
 EXTERN int call_nr;            /* system call number */
-EXTERN char user_path[PATH_MAX];/* storage for user path name */
+EXTERN message mount_m_in;     /* the input message itself */
+
+EXTERN char user_fullpath[PATH_MAX];    /* storage for user path name */
+EXTERN short cum_path_processed;        /* number of characters processed */
 
 /* The following variables are used for returning results to the caller. */
 EXTERN int err_code;           /* temporary storage for error number */
similarity index 100%
rename from servers/fs/inode.h
rename to servers/vfs/inode.h
diff --git a/servers/vfs/link.c b/servers/vfs/link.c
new file mode 100644 (file)
index 0000000..c616869
--- /dev/null
@@ -0,0 +1,413 @@
+/* This file handles the LINK and UNLINK system calls.  It also deals with
+ * deallocating the storage used by a file when the last UNLINK is done to a
+ * file and the blocks must be returned to the free block pool.
+ *
+ * The entry points into this file are
+ *   do_link:         perform the LINK system call
+ *   do_unlink:              perform the UNLINK and RMDIR system calls
+ *   do_rename:              perform the RENAME system call
+ *   do_truncate:     perform the TRUNCATE system call
+ *   do_ftruncate:    perform the FTRUNCATE system call
+ *   do_rdlink:       perform the RDLNK system call
+ *
+ * Changes for VFS:
+ *   Jul 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <string.h>
+#include <minix/com.h>
+#include <minix/callnr.h>
+#include <dirent.h>
+#include "file.h"
+#include "fproc.h"
+#include "param.h"
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+
+/*===========================================================================*
+ *                             do_link                                      *
+ *===========================================================================*/
+PUBLIC int do_link()
+{
+/* Perform the link(name1, name2) system call. */
+  int linked_fs_e;
+  int linked_inode_nr;
+  int link_lastdir_fs_e;
+  int link_lastdir_inode_nr;
+  char string[NAME_MAX];
+  struct link_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) 
+        return(err_code);
+        
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  linked_fs_e = res.fs_e;
+  req.linked_file = res.inode_nr;
+
+  /* Does the final directory of 'name2' exist? */
+  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
+       return(err_code);
+  }
+
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = string;
+  lookup_req.flags = LAST_DIR;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  link_lastdir_fs_e = res.fs_e;
+  req.link_parent = res.inode_nr;
+  
+  /* Check for links across devices. */
+  if (linked_fs_e != link_lastdir_fs_e) 
+        return EXDEV;
+
+  /* Send link request. */
+  req.fs_e = linked_fs_e;
+  /* Send the last component of the link name */
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  req.lastc = string;
+  
+  /* Issue request */
+  return req_link(&req);
+}
+
+
+
+/*===========================================================================*
+ *                             do_unlink                                    *
+ *===========================================================================*/
+PUBLIC int do_unlink()
+{
+/* Perform the unlink(name) or rmdir(name) system call. The code for these two
+ * is almost the same.  They differ only in some condition testing.  Unlink()
+ * may be used by the superuser to do dangerous things; rmdir() may not.
+ */
+  register struct fproc *rfp;
+  char string[NAME_MAX];
+  struct vnode *vp;
+  struct unlink_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+  string[0] = '\0';
+  
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH_OPAQUE;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  
+  /* If a directory file has to be removed the following conditions have to met:
+   *   - The directory must not be the root of a mounted file system
+   *   - The directory must not be anybody's root/working directory
+   */
+  if ((res.fmode & I_TYPE) == I_DIRECTORY) {
+      /* Only root can unlink a directory */
+      if (call_nr == UNLINK && !super_user) return EPERM; 
+
+      /* Can't remove a root directory */
+      if (res.inode_nr == ROOT_INODE) return EBUSY;
+
+      /* Can't remove anybody's working directory */
+      if ((vp = find_vnode(res.fs_e, res.inode_nr)) != 
+              NIL_VNODE) {
+          /* Check directories */
+          for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS]; 
+                  rfp++) {
+              if (rfp->fp_pid != PID_FREE && 
+                      (rfp->fp_wd == vp || rfp->fp_rd == vp))
+                  return(EBUSY); 
+          }
+      }
+  }
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = string;
+  lookup_req.flags = LAST_DIR;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  
+  /* Fill in request fields. */
+  req.fs_e = res.fs_e;
+  req.d_inode_nr = res.inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  req.lastc = string;
+  
+  /* Issue request */
+  return (call_nr == UNLINK) ? req_unlink(&req) : req_rmdir(&req);
+}
+
+
+/*===========================================================================*
+ *                             do_rename                                    *
+ *===========================================================================*/
+PUBLIC int do_rename()
+{
+/* Perform the rename(name1, name2) system call. */
+  int old_dir_inode;
+  int old_fs_e;
+  int new_dir_inode;
+  int new_fs_e;
+  char old_name[NAME_MAX];
+  char new_name[NAME_MAX];
+  struct vnode *vp;
+  struct fproc *rfp;
+  struct rename_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+  
+  /* See if 'name1' (existing file) exists.  Get dir and file inodes. */
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = old_name;
+  lookup_req.flags = LAST_DIR;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  
+  /* Remeber inode number and FS endpoint */
+  old_fs_e = res.fs_e;
+  req.old_dir = res.inode_nr;
+
+  /* See if 'name2' (new name) exists.  Get dir inode */
+  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) r = err_code;
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH_OPAQUE;
+        
+  /* Request lookup */
+  r = lookup(&lookup_req, &res);
+  
+  /* If a directory file has to be removed the following conditions have to met:
+   *   - The directory must not be the root of a mounted file system
+   *   - The directory must not be anybody's root/working directory
+   */
+  if (r == OK && ((res.fmode & I_TYPE) == I_DIRECTORY)) {
+      /* Can't remove a root directory */
+      if (res.inode_nr == ROOT_INODE) return EBUSY;
+
+      /* Can't remove anybody's working directory */
+      if ((vp = find_vnode(res.fs_e, res.inode_nr)) != 
+              NIL_VNODE) {
+          /* Check directories */
+          for (rfp = &fproc[INIT_PROC_NR + 1]; rfp < &fproc[NR_PROCS]; 
+                  rfp++) {
+              if (rfp->fp_pid != PID_FREE && 
+                      (rfp->fp_wd == vp || rfp->fp_rd == vp))
+                  return(EBUSY); 
+          }
+      }
+  }
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = new_name;
+  lookup_req.flags = LAST_DIR;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  
+  /* Remeber inode number and FS endpoint */
+  new_fs_e = res.fs_e;
+  req.new_dir = res.inode_nr;
+  
+  /* Both parent directories must be on the same device. */
+  if (old_fs_e != new_fs_e) return EXDEV;
+
+  /* Send actual rename request */
+  req.fs_e = old_fs_e;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  req.old_name = &old_name[0];
+  req.new_name = &new_name[0];
+  /* Issue request */
+  return req_rename(&req);
+}
+  
+
+/*===========================================================================*
+ *                             do_truncate                                  *
+ *===========================================================================*/
+PUBLIC int do_truncate()
+{
+/* truncate_inode() does the actual work of do_truncate() and do_ftruncate().
+ * do_truncate() and do_ftruncate() have to get hold of the inode, either
+ * by name or fd, do checks on it, and call truncate_inode() to do the
+ * work.
+ */
+  struct vnode *vp;
+  struct trunc_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+  
+  if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1) != OK) return err_code;
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  
+  /* Check whether the file is in use or not */
+  vp = find_vnode(res.fs_e, res.inode_nr);
+
+  /* Fill in request message fields.*/
+  req.fs_e = res.fs_e;
+  req.length = m_in.m2_l1;
+  req.inode_nr = res.inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  
+  /* Issue request */
+  if ((r = req_trunc(&req)) != OK) return r;
+         
+  /* Change vnode's size if found */
+  if (vp != NIL_VNODE)
+         vp->v_size = m_in.m2_l1;
+  
+  return OK;
+}
+
+
+
+/*===========================================================================*
+ *                             do_ftruncate                                 *
+ *===========================================================================*/
+PUBLIC int do_ftruncate()
+{
+/* As with do_truncate(), truncate_inode() does the actual work. */
+  int r;
+  struct filp *rfilp;
+  struct ftrunc_req req;
+  
+  if ( (rfilp = get_filp(m_in.m2_i1)) == NIL_FILP)
+        return err_code;
+  if ( (rfilp->filp_vno->v_mode & I_TYPE) != I_REGULAR)
+       return EINVAL;
+        
+  /* Fill in FS request */
+  req.fs_e = rfilp->filp_vno->v_fs_e; 
+  req.inode_nr = rfilp->filp_vno->v_inode_nr;
+  req.start = m_in.m2_l1;
+  req.end = 0;     /* Indicate trunc in fs_freesp_trunc */
+
+  /* Issue request */
+  if ((r = req_ftrunc(&req)) != OK) return r;
+         
+  rfilp->filp_vno->v_size = m_in.m2_l1;
+  return OK;
+}
+
+/*===========================================================================*
+ *                             do_slink                                             *
+ *===========================================================================*/
+PUBLIC int do_slink()
+{
+/* Perform the symlink(name1, name2) system call. */
+  char string[NAME_MAX];       /* last component of the new dir's path name */
+  struct slink_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+
+  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK)
+       return(err_code);
+
+  if (m_in.name1_length <= 1 || m_in.name1_length >= _MIN_BLOCK_SIZE)
+       return(ENAMETOOLONG);
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = string;
+  lookup_req.flags = LAST_DIR;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  /* Fill in request message */
+  req.fs_e = res.fs_e;
+  req.parent_dir = res.inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  req.lastc = string;
+  req.who_e = who_e;
+  req.path_addr = m_in.name1;
+  req.path_length = m_in.name1_length - 1;
+
+  /* Issue request */
+  return req_slink(&req);
+}
+
+/*===========================================================================*
+ *                             do_rdlink                                    *
+ *===========================================================================*/
+PUBLIC int do_rdlink()
+{
+/* Perform the readlink(name, buf) system call. */
+  int copylen;
+  struct rdlink_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+  
+  copylen = m_in.m1_i2;
+  if(copylen < 0) return EINVAL;
+
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH_OPAQUE;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  
+  /* Fill in request message */
+  req.fs_e = res.fs_e;
+  req.inode_nr = res.inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  req.who_e = who_e;
+  req.path_buffer = m_in.name2;
+  req.max_length = copylen;
+
+  /* Issue request */
+  return req_rdlink(&req);
+}
+
+
+
similarity index 95%
rename from servers/fs/lock.c
rename to servers/vfs/lock.c
index 737f88a9be7176169a8e1b27cfaa6f852ca361ac..d8e93cb49aafdaa6075f7d06f26c00033dba48a8 100644 (file)
 #include <unistd.h>
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
 #include "lock.h"
 #include "param.h"
 
+#include "vnode.h"
+
 /*===========================================================================*
  *                             lock_op                                      *
  *===========================================================================*/
@@ -42,7 +43,7 @@ int req;                      /* either F_SETLK or F_SETLKW */
   mo = f->filp_mode;
   if (ltype != F_UNLCK && ltype != F_RDLCK && ltype != F_WRLCK) return(EINVAL);
   if (req == F_GETLK && ltype == F_UNLCK) return(EINVAL);
-  if ( (f->filp_ino->i_mode & I_TYPE) != I_REGULAR) return(EINVAL);
+  if ( (f->filp_vno->v_mode & I_TYPE) != I_REGULAR) return(EINVAL);
   if (req != F_GETLK && ltype == F_RDLCK && (mo & R_BIT) == 0) return(EBADF);
   if (req != F_GETLK && ltype == F_WRLCK && (mo & W_BIT) == 0) return(EBADF);
 
@@ -50,7 +51,7 @@ int req;                      /* either F_SETLK or F_SETLKW */
   switch (flock.l_whence) {
        case SEEK_SET:  first = 0; break;
        case SEEK_CUR:  first = f->filp_pos; break;
-       case SEEK_END:  first = f->filp_ino->i_size; break;
+       case SEEK_END:  first = f->filp_vno->v_size; break;
        default:        return(EINVAL);
   }
   /* Check for overflow. */
@@ -70,7 +71,7 @@ int req;                      /* either F_SETLK or F_SETLKW */
                if (empty == (struct file_lock *) 0) empty = flp;
                continue;       /* 0 means unused slot */
        }
-       if (flp->lock_inode != f->filp_ino) continue;   /* different file */
+       if (flp->lock_vnode != f->filp_vno) continue;   /* different file */
        if (last < flp->lock_first) continue;   /* new one is in front */
        if (first > flp->lock_last) continue;   /* new one is afterwards */
        if (ltype == F_RDLCK && flp->lock_type == F_RDLCK) continue;
@@ -118,7 +119,7 @@ int req;                    /* either F_SETLK or F_SETLKW */
        flp2 = &file_lock[i];
        flp2->lock_type = flp->lock_type;
        flp2->lock_pid = flp->lock_pid;
-       flp2->lock_inode = flp->lock_inode;
+       flp2->lock_vnode = flp->lock_vnode;
        flp2->lock_first = last + 1;
        flp2->lock_last = flp->lock_last;
        flp->lock_last = first - 1;
@@ -152,7 +153,7 @@ int req;                    /* either F_SETLK or F_SETLKW */
   if (empty == (struct file_lock *) 0) return(ENOLCK); /* table full */
   empty->lock_type = ltype;
   empty->lock_pid = fp->fp_pid;
-  empty->lock_inode = f->filp_ino;
+  empty->lock_vnode = f->filp_vno;
   empty->lock_first = first;
   empty->lock_last = last;
   nr_locks++;
diff --git a/servers/vfs/lock.h b/servers/vfs/lock.h
new file mode 100644 (file)
index 0000000..e4453a7
--- /dev/null
@@ -0,0 +1,10 @@
+/* This is the file locking table.  Like the filp table, it points to the
+ * inode table, however, in this case to achieve advisory locking.
+ */
+EXTERN struct file_lock {
+  short lock_type;             /* F_RDLOCK or F_WRLOCK; 0 means unused slot */
+  pid_t lock_pid;              /* pid of the process holding the lock */
+  struct vnode *lock_vnode;
+  off_t lock_first;            /* offset of first byte locked */
+  off_t lock_last;             /* offset of last byte locked */
+} file_lock[NR_LOCKS];
similarity index 73%
rename from servers/fs/main.c
rename to servers/vfs/main.c
index 59c9dfcba9c290e5c49d1595dbdd5490ccdc5134..200e48d1b7b82cc90015af57b757fe4fbe283d93 100644 (file)
@@ -3,13 +3,13 @@
  * replies.
  *
  * The entry points into this file are:
- *   main:     main program of the File System
+ *   main:     main program of the Virtual File System
  *   reply:    send a reply to a process after the requested work is done
  *
+ * Changes for VFS:
+ *   Jul 2006 (Balazs Gerofi)
  */
 
-struct super_block;            /* proto.h needs to know this */
-
 #include "fs.h"
 #include <fcntl.h>
 #include <string.h>
@@ -26,12 +26,13 @@ struct super_block;         /* proto.h needs to know this */
 #include <minix/const.h>
 #include <minix/endpoint.h>
 #include <minix/safecopies.h>
-#include "buf.h"
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
 #include "param.h"
-#include "super.h"
+
+#include <minix/vfsif.h>
+#include "vmnt.h"
+#include "vnode.h"
 
 #if ENABLE_SYSCALL_STATS
 EXTERN unsigned long calls_stats[NCALLS];
@@ -42,6 +43,7 @@ FORWARD _PROTOTYPE( void get_work, (void)                             );
 FORWARD _PROTOTYPE( void init_root, (void)                             );
 FORWARD _PROTOTYPE( void service_pm, (void)                            );
 
+
 /*===========================================================================*
  *                             main                                         *
  *===========================================================================*/
@@ -55,6 +57,7 @@ PUBLIC int main()
 
   fs_init();
 
+
   /* This is the main loop that gets work, processes it, and sends replies. */
   while (TRUE) {
        get_work();             /* sets who and call_nr */
@@ -96,7 +99,7 @@ PUBLIC int main()
        default:
                /* Call the internal function that does the work. */
                if (call_nr < 0 || call_nr >= NCALLS) { 
-                       error = ENOSYS;
+                       error = SUSPEND;
                        /* Not supposed to happen. */
                        printf("FS, warning illegal %d system call by %d\n",
                                call_nr, who_e);
@@ -114,9 +117,7 @@ PUBLIC int main()
 
                /* Copy the results back to the user and send reply. */
                if (error != SUSPEND) { reply(who_e, error); }
-               if (rdahed_inode != NIL_INODE) {
-                       read_ahead(); /* do block read ahead */
-               }
+               
        }
   }
   return(OK);                          /* shouldn't come here */
@@ -179,32 +180,6 @@ PRIVATE void get_work()
   }
 }
 
-/*===========================================================================*
- *                             buf_pool                                     *
- *===========================================================================*/
-PRIVATE void buf_pool(void)
-{
-/* Initialize the buffer pool. */
-
-  register struct buf *bp;
-
-  bufs_in_use = 0;
-  front = &buf[0];
-  rear = &buf[NR_BUFS - 1];
-
-  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) {
-       bp->b_blocknr = NO_BLOCK;
-       bp->b_dev = NO_DEV;
-       bp->b_next = bp + 1;
-       bp->b_prev = bp - 1;
-  }
-  buf[0].b_prev = NIL_BUF;
-  buf[NR_BUFS - 1].b_next = NIL_BUF;
-
-  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++) bp->b_hash = bp->b_next;
-  buf_hash[0] = front;
-
-}
 
 /*===========================================================================*
  *                             reply                                        *
@@ -217,7 +192,7 @@ int result;                 /* result of the call (usually OK or error #) */
   int s;
   m_out.reply_type = result;
   s = send(whom, &m_out);
-  if (s != OK) printf("FS: couldn't send reply %d to %d: %d\n",
+  if (s != OK) printf("VFS: couldn't send reply %d to %d: %d\n",
        result, whom, s);
 }
 
@@ -232,6 +207,10 @@ PRIVATE void fs_init()
   message mess;
   int s;
 
+  /* Clear endpoint field */
+  last_login_fs_e = 0;
+  mount_m_in.m1_p3 = 0;
+
   /* Initialize the process table with help of the process manager messages. 
    * Expect one message for each system process with its slot number and pid. 
    * When no more processes follow, the magic process number NONE is sent. 
@@ -254,22 +233,25 @@ PRIVATE void fs_init()
    
   } while (TRUE);                      /* continue until process NONE */
   mess.m_type = OK;                    /* tell PM that we succeeded */
-  s=send(PM_PROC_NR, &mess);           /* send synchronization message */
+  s = send(PM_PROC_NR, &mess);         /* send synchronization message */
 
   /* All process table entries have been set. Continue with FS initialization.
    * Certain relations must hold for the file system to work at all. Some 
    * extra block_size requirements are checked at super-block-read-in time.
    */
   if (OPEN_MAX > 127) panic(__FILE__,"OPEN_MAX > 127", NO_NUM);
+  /*
   if (NR_BUFS < 6) panic(__FILE__,"NR_BUFS < 6", NO_NUM);
   if (V1_INODE_SIZE != 32) panic(__FILE__,"V1 inode size != 32", NO_NUM);
   if (V2_INODE_SIZE != 64) panic(__FILE__,"V2 inode size != 64", NO_NUM);
-
+  if (OPEN_MAX > 8 * sizeof(long))
+        panic(__FILE__,"Too few bits in fp_cloexec", NO_NUM);
+  */
+  
   /* The following initializations are needed to let dev_opcl succeed .*/
   fp = (struct fproc *) NULL;
   who_e = who_p = FS_PROC_NR;
 
-  buf_pool();                  /* initialize buffer pool */
   build_dmap();                        /* build device table and map boot driver */
   init_root();                 /* init root device and load super block */
   init_select();               /* init select() structures */
@@ -278,10 +260,10 @@ PRIVATE void fs_init()
   for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
        FD_ZERO(&(rfp->fp_filp_inuse));
        if (rfp->fp_pid != PID_FREE) {
-               rip = get_inode(root_dev, ROOT_INODE);
-               dup_inode(rip);
-               rfp->fp_rootdir = rip;
-               rfp->fp_workdir = rip;
+                
+                rfp->fp_rd = get_vnode(ROOT_FS_E, ROOT_INODE);
+                rfp->fp_wd = get_vnode(ROOT_FS_E, ROOT_INODE);
+               
        } else  rfp->fp_endpoint = NONE;
   }
 }
@@ -291,42 +273,96 @@ PRIVATE void fs_init()
  *===========================================================================*/
 PRIVATE void init_root()
 {
-  int bad;
-  register struct super_block *sp;
-  register struct inode *rip = NIL_INODE;
-  int s;
-
+  struct vmnt *vmp;
+  struct vnode *root_node;
+  struct dmap *dp;
+  message m;
+  int r = OK;
+  struct readsuper_req sreq;
+  struct readsuper_res sres;
+  
   /* Open the root device. */
   root_dev = DEV_IMGRD;
-  if ((s=dev_open(root_dev, FS_PROC_NR, R_BIT|W_BIT)) != OK)
-       panic(__FILE__,"Cannot open root device", s);
-
-#if ENABLE_CACHE2
-  /* The RAM disk is a second level block cache while not otherwise used. */
-  init_cache2(ram_size);
-#endif
-
-  /* Initialize the super_block table. */
-  for (sp = &super_block[0]; sp < &super_block[NR_SUPERS]; sp++)
-       sp->s_dev = NO_DEV;
-
-  /* Read in super_block for the root file system. */
-  sp = &super_block[0];
-  sp->s_dev = root_dev;
-
-  /* Check super_block for consistency. */
-  bad = (read_super(sp) != OK);
-  if (!bad) {
-       rip = get_inode(root_dev, ROOT_INODE);  /* inode for root dir */
-       if ( (rip->i_mode & I_TYPE) != I_DIRECTORY || rip->i_nlinks < 3) bad++;
+  ROOT_FS_E = MFS_PROC_NR;
+  
+  /* Wait FS login message */
+  if (last_login_fs_e != ROOT_FS_E) {
+         printf("VFS: Waiting for login from FS_e %d\n", ROOT_FS_E);
+         /* Wait FS login message */
+         if (receive(ROOT_FS_E, &m) != OK) {
+                 printf("VFS: Error receiving login request from FS_e %d\n", 
+                                 ROOT_FS_E);
+                 panic(__FILE__, "Error receiving login request from root filesystem\n", ROOT_FS_E);
+         }
+         if (m.m_type != FS_READY) {
+                 printf("VFS: Invalid login request from FS_e %d\n", 
+                                 ROOT_FS_E);
+                 panic(__FILE__, "Error receiving login request from root filesystem\n", ROOT_FS_E);
+         }
+         printf("VFS: FS_e %d logged in\n", ROOT_FS_E);
+  }
+  last_login_fs_e = 0;
+  
+  /* Initialize vmnt table */
+  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
+      vmp->m_dev = NO_DEV;
+  
+  vmp = &vmnt[0];
+  /* We'll need a vnode for the root inode, check whether there is one */
+  if ((root_node = get_free_vnode()) == NIL_VNODE) {
+       panic(__FILE__,"Cannot get free vnode", r);
+  }
+  
+  /* Get driver process' endpoint */  
+  dp = &dmap[(root_dev >> MAJOR) & BYTE];
+  if (dp->dmap_driver == NONE) {
+       panic(__FILE__,"No driver for root device", r);
   }
-  if (bad) panic(__FILE__,"Invalid root file system", NO_NUM);
 
-  sp->s_imount = rip;
-  dup_inode(rip);
-  sp->s_isup = rip;
-  sp->s_rd_only = 0;
-  return;
+  /* Open the device the file system lives on. */
+  if ((r = dev_open(root_dev, ROOT_FS_E, (R_BIT|W_BIT))) != OK) 
+       panic(__FILE__,"Cannot open root device", r);
+
+
+  /* Request for reading superblock and root inode */
+  sreq.fs_e = ROOT_FS_E;
+  sreq.readonly = 0;
+  sreq.boottime = boottime;
+  sreq.driver_e = dp->dmap_driver;
+  sreq.dev = root_dev;
+  sreq.slink_storage = user_fullpath;
+  sreq.isroot = 1;
+  /* Issue request */
+  if ((r = req_readsuper(&sreq, &sres)) != OK) {
+      dev_close(root_dev);
+      panic(__FILE__,"Cannot read superblock from root", r);
+  }
+  
+  /* Fill in root node's fields */
+  root_node->v_fs_e = sres.fs_e;
+  root_node->v_inode_nr = sres.inode_nr;
+  root_node->v_mode = sres.fmode;
+  root_node->v_size = sres.fsize;
+  root_node->v_sdev = NO_DEV;
+  root_node->v_count = 1;
+
+  /* Fill in max file size and blocksize for the vmnt */
+  vmp->m_fs_e = sres.fs_e;
+  vmp->m_dev = root_dev;
+  vmp->m_block_size = sres.blocksize;
+  vmp->m_max_file_size = sres.maxsize;
+  vmp->m_driver_e = dp->dmap_driver;
+  vmp->m_flags = 0;
+  
+  /* Root node is indeed on the partition */
+  root_node->v_vmnt = vmp;
+  root_node->v_dev = vmp->m_dev;
+
+  /* Root directory is mounted on itself */
+  vmp->m_mounted_on = root_node;
+  vmp->m_root_node = root_node;
 }
 
 /*===========================================================================*
@@ -335,6 +371,7 @@ PRIVATE void init_root()
 PRIVATE void service_pm()
 {
        int r, call;
+        struct vmnt *vmp;
        message m;
 
        /* Ask PM for work until there is nothing left to do */
@@ -344,7 +381,7 @@ PRIVATE void service_pm()
                r= sendrec(PM_PROC_NR, &m);
                if (r != OK)
                {
-                       panic("fs", "service_pm: sendrec failed", r);
+                       panic("VFS", "service_pm: sendrec failed", r);
                }
                if (m.m_type == PM_IDLE) {
                        break;
@@ -353,8 +390,13 @@ PRIVATE void service_pm()
                switch(call)
                {
                case PM_STIME:
-                       boottime= m.PM_STIME_TIME;
-
+                       boottime = m.PM_STIME_TIME;
+                       
+                        /* Send new time for all FS processes */
+                        for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { 
+                            if (vmp->m_fs_e)
+                                req_stime(vmp->m_fs_e, boottime);
+                        }
                        /* No need to report status to PM */
                        break;
                case PM_SETSID:
@@ -445,7 +487,8 @@ PRIVATE void service_pm()
                        break;
 
                default:
-                       panic("fs", "service_pm: unknown call", m.m_type);
+                       panic("VFS", "service_pm: unknown call", m.m_type);
                }
        }
 }
+
similarity index 64%
rename from servers/fs/misc.c
rename to servers/vfs/misc.c
index bc2a8196680d7096a32ec59eb891caa6bededcd6..7ad28ca5771361c9c09e729ee392c21e174e9b0e 100644 (file)
@@ -7,12 +7,12 @@
  *   do_fcntl:   perform the FCNTL system call
  *   do_sync:    perform the SYNC system call
  *   do_fsync:   perform the FSYNC system call
- *   pm_reboot:          sync disks and prepare for shutdown
- *   pm_fork:    adjust the tables after MM has performed a FORK system call
+ *   do_reboot:          sync disks and prepare for shutdown
+ *   do_fork:    adjust the tables after MM has performed a FORK system call
  *   do_exec:    handle files with FD_CLOEXEC on after MM has done an EXEC
  *   do_exit:    a process has exited; note that in the tables
- *   pm_setgid:          set group ids for some process
- *   pm_setuid:          set user ids for some process
+ *   do_set:     set uid or gid for some process
+ *   do_revive:          revive a process that was waiting for something (e.g. TTY)
  *   do_svrctl:          file system control
  *   do_getsysinfo:    request copy of FS data structure
  *   pm_dumpcore: create a core dump
 #include <minix/com.h>
 #include <sys/ptrace.h>
 #include <sys/svrctl.h>
-#include "buf.h"
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
 #include "param.h"
-#include "super.h"
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
 
 #define CORE_NAME      "core"
 #define CORE_MODE      0777    /* mode to use on core image files */
@@ -43,14 +44,17 @@ PUBLIC unsigned long calls_stats[NCALLS];
 #endif
 
 FORWARD _PROTOTYPE( void free_proc, (struct fproc *freed, int flags));
+/*
 FORWARD _PROTOTYPE( int dumpcore, (int proc_e, struct mem_map *seg_ptr));
 FORWARD _PROTOTYPE( int write_bytes, (struct inode *rip, off_t off,
        char *buf, size_t bytes));
 FORWARD _PROTOTYPE( int write_seg, (struct inode *rip, off_t off, int proc_e,
        int seg, off_t seg_off, phys_bytes seg_bytes));
+*/
 
 #define FP_EXITING     1
 
+
 /*===========================================================================*
  *                             do_getsysinfo                                *
  *===========================================================================*/
@@ -140,6 +144,8 @@ PUBLIC int do_dup()
   return(m_in.fd2);
 }
 
+
+
 /*===========================================================================*
  *                             do_fcntl                                     *
  *===========================================================================*/
@@ -149,11 +155,17 @@ PUBLIC int do_fcntl()
 
   register struct filp *f;
   int new_fd, r, fl;
+  long cloexec_mask;           /* bit map for the FD_CLOEXEC flag */
+  long clo_value;              /* FD_CLOEXEC flag in proper position */
   struct filp *dummy;
+  struct ftrunc_req req;
 
   /* Is the file descriptor valid? */
-  if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
-
+  if ((f = get_filp(m_in.fd)) == NIL_FILP) {
+/*printf("VFSfcntl: invalid filedesc %d\n", m_in.fd);   */
+         return(err_code);
+  }
+  
   switch (m_in.request) {
      case F_DUPFD:
        /* This replaces the old dup() system call. */
@@ -203,7 +215,7 @@ PUBLIC int do_fcntl()
        signed long offset;
 
        /* Check if it's a regular file. */
-       if((f->filp_ino->i_mode & I_TYPE) != I_REGULAR) {
+       if((f->filp_vno->v_mode & I_TYPE) != I_REGULAR) {
                return EINVAL;
        }
 
@@ -220,7 +232,7 @@ PUBLIC int do_fcntl()
        switch(flock_arg.l_whence) {
                case SEEK_SET: start = 0; if(offset < 0) return EINVAL; break;
                case SEEK_CUR: start = f->filp_pos; break;
-               case SEEK_END: start = f->filp_ino->i_size; break;
+               case SEEK_END: start = f->filp_vno->v_size; break;
                default: return EINVAL;
        }
 
@@ -233,11 +245,19 @@ PUBLIC int do_fcntl()
                if(end <= start) {
                        return EINVAL;
                }
-               r = freesp_inode(f->filp_ino, start, end);
-       } else {
-               r = truncate_inode(f->filp_ino, start);
+       } 
+        else {
+                end = 0;
        }
-       return r;
+  
+        /* Fill in FS request */
+        req.fs_e = f->filp_vno->v_fs_e; 
+        req.inode_nr = f->filp_vno->v_inode_nr;
+        req.start = start;
+        req.end = end;
+
+        /* Issue request */
+        return req_ftrunc(&req);
      }
 
      default:
@@ -245,28 +265,20 @@ PUBLIC int do_fcntl()
   }
 }
 
+
 /*===========================================================================*
  *                             do_sync                                      *
  *===========================================================================*/
 PUBLIC int do_sync()
 {
-/* Perform the sync() system call.  Flush all the tables. 
- * The order in which the various tables are flushed is critical.  The
- * blocks must be flushed last, since rw_inode() leaves its results in
- * the block cache.
- */
-  register struct inode *rip;
-  register struct buf *bp;
-
-  /* Write all the dirty inodes to the disk. */
-  for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
-       if (rip->i_count > 0 && rip->i_dirt == DIRTY) rw_inode(rip, WRITING);
-
-  /* Write all the dirty blocks to the disk, one drive at a time. */
-  for (bp = &buf[0]; bp < &buf[NR_BUFS]; bp++)
-       if (bp->b_dev != NO_DEV && bp->b_dirt == DIRTY) flushall(bp->b_dev);
-
-  return(OK);          /* sync() can't fail */
+  struct vmnt *vmp;
+  for (vmp = &vmnt[1]; vmp < &vmnt[NR_MNTS]; ++vmp) {
+         if (vmp->m_dev != NO_DEV) {
+                 /* Send sync request */ 
+                  req_sync(vmp->m_fs_e);
+         }
+  }
+  return OK;
 }
 
 /*===========================================================================*
@@ -288,8 +300,8 @@ PUBLIC void pm_reboot()
 {
   /* Perform the FS side of the reboot call. */
   int i;
-  struct super_block *sp;
-  struct inode dummy;
+  struct vnode vdummy;
+  struct vmnt *vmp;
 
   /* Do exit processing for all leftover processes and servers,
    * but don't actually exit them (if they were really gone, PM
@@ -302,22 +314,21 @@ PUBLIC void pm_reboot()
   /* The root file system is mounted onto itself, which keeps it from being
    * unmounted.  Pull an inode out of thin air and put the root on it.
    */
-  put_inode(super_block[0].s_imount);
-  super_block[0].s_imount= &dummy;
-  dummy.i_count = 2;                   /* expect one "put" */
+       
+  put_vnode(vmnt[0].m_mounted_on);
+  vmnt[0].m_mounted_on = &vdummy;
+  vmnt[0].m_root_node = &vdummy;
+  vdummy.v_count = 1;
 
   /* Unmount all filesystems.  File systems are mounted on other file systems,
    * so you have to pull off the loose bits repeatedly to get it all undone.
    */
   for (i= 0; i < NR_SUPERS; i++) {
        /* Unmount at least one. */
-       for (sp= &super_block[0]; sp < &super_block[NR_SUPERS]; sp++) {
-               if (sp->s_dev != NO_DEV) (void) unmount(sp->s_dev);
+       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
+               if (vmp->m_dev != NO_DEV) (void) unmount(vmp->m_dev);
        }
   }
-
-  /* Sync any unwritten buffers. */
-  do_sync();
 }
 
 /*===========================================================================*
@@ -331,7 +342,7 @@ int cpid;   /* Child process id */
 /* Perform those aspects of the fork() system call that relate to files.
  * In particular, let the child inherit its parent's file descriptors.
  * The parent and child parameters tell who forked off whom. The file
- * system uses the same slot numbers as the kernel.
+ * system uses the same slot numbers as the kernel.  Only MM makes this call.
  */
 
   register struct fproc *cp;
@@ -375,8 +386,8 @@ int cpid;   /* Child process id */
   cp->fp_execced = 0;
 
   /* Record the fact that both root and working dir have another user. */
-  dup_inode(cp->fp_rootdir);
-  dup_inode(cp->fp_workdir);
+  dup_vnode(cp->fp_rd);
+  dup_vnode(cp->fp_wd);
 }
 
 /*===========================================================================*
@@ -387,7 +398,7 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
   int i, task;
   register struct fproc *rfp;
   register struct filp *rfilp;
-  register struct inode *rip;
+  register struct vnode *vp;
   dev_t dev;
 
   fp = exiter;         /* get_filp() needs 'fp' */
@@ -405,11 +416,11 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
   }
 
   /* Release root and working directories. */
-  put_inode(fp->fp_rootdir);
-  put_inode(fp->fp_workdir);
-  fp->fp_rootdir = NIL_INODE;
-  fp->fp_workdir = NIL_INODE;
-
+  put_vnode(fp->fp_rd);
+  put_vnode(fp->fp_wd);
+  fp->fp_rd = NIL_VNODE;
+  fp->fp_wd = NIL_VNODE;
+  
   /* Check if any process is SUSPENDed on this driver.
    * If a driver exits, unmap its entries in the dmap table.
    * (unmapping has to be done after the first step, because the
@@ -440,9 +451,9 @@ PRIVATE void free_proc(struct fproc *exiter, int flags)
           for (i = 0; i < OPEN_MAX; i++) {
                if ((rfilp = rfp->fp_filp[i]) == NIL_FILP) continue;
                if (rfilp->filp_mode == FILP_CLOSED) continue;
-               rip = rfilp->filp_ino;
-               if ((rip->i_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
-               if ((dev_t) rip->i_zone[0] != dev) continue;
+               vp = rfilp->filp_vno;
+               if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue;
+               if ((dev_t) vp->v_sdev != dev) continue;
                dev_close(dev);
                rfilp->filp_mode = FILP_CLOSED;
           }
@@ -504,7 +515,6 @@ int ruid;
   tfp->fp_realuid = ruid;
 }
 
-
 /*===========================================================================*
  *                             do_svrctl                                    *
  *===========================================================================*/
@@ -562,7 +572,6 @@ PUBLIC int do_svrctl()
   }
 }
 
-
 /*===========================================================================*
  *                             pm_dumpcore                                  *
  *===========================================================================*/
@@ -571,267 +580,15 @@ int proc_e;
 struct mem_map *seg_ptr;
 {
        int r, proc_s;
-
-       r= dumpcore(proc_e, seg_ptr);
-
+       
        /* Terminate the process */
        okendpt(proc_e, &proc_s);
        free_proc(&fproc[proc_s], FP_EXITING);
-
-       return r;
-}
-
-/*===========================================================================*
- *                             dumpcore                                     *
- *===========================================================================*/
-PRIVATE int dumpcore(proc_e, seg_ptr)
-int proc_e;
-struct mem_map *seg_ptr;
-{
-       int r, seg, proc_s, exists;
-       mode_t omode;
-       vir_bytes len;
-       off_t off, seg_off;
-       long trace_off, trace_data;
-       struct fproc *rfp;
-       struct inode *rip, *ldirp;
-       struct mem_map segs[NR_LOCAL_SEGS];
-
-       okendpt(proc_e, &proc_s);
-       rfp= fp= &fproc[proc_s];
-       who_e= proc_e;
-       who_p= proc_s;
-       super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
-
-       /* We need the equivalent of
-        * open(CORE_NAME, O_WRONLY|O_CREAT|O_TRUNC|O_NONBLOCK, CORE_MODE)
-        */
-
-       /* Create a new inode by calling new_node(). */
-        omode = I_REGULAR | (CORE_MODE & ALL_MODES & rfp->fp_umask);
-       rip = new_node(&ldirp, CORE_NAME, omode, NO_ZONE, 0, NULL);
-       r = err_code;
-        put_inode(ldirp);
-       exists= (r == EEXIST);
-       if (r != OK && r != EEXIST) return(r); /* error */
-
-       /* Only do the normal open code if we didn't just create the file. */
-       if (exists) {
-               /* Check protections. */
-               r = forbidden(rip, W_BIT);
-               if (r != OK)
-               {
-                       put_inode(rip);
-                       return r;
-               }
-
-               /* Make sure it is a regular file */
-               switch (rip->i_mode & I_TYPE) {
-                  case I_REGULAR: 
-                       break;
-                  case I_DIRECTORY: 
-                       /* Directories may be read but not written. */
-                       r = EISDIR;
-                       break;
-
-                  case I_CHAR_SPECIAL:
-                  case I_BLOCK_SPECIAL:
-                  case I_NAMED_PIPE:
-                       r = EPERM;
-                       break;
-               }
-
-               if (r != OK)
-               {
-                       put_inode(rip);
-                       return r;
-               }
-
-               /* Truncate the file */
-               truncate_inode(rip, 0);
-               wipe_inode(rip);
-               /* Send the inode from the inode cache to the
-                * block cache, so it gets written on the next
-                * cache flush.
-                */
-               rw_inode(rip, WRITING);
-       }
-
-       /* Copy segments from PM */
-       r= sys_datacopy(PM_PROC_NR, (vir_bytes)seg_ptr,
-               SELF, (vir_bytes)segs, sizeof(segs));
-       if (r != OK) panic(__FILE__, "dumpcore: cannot copy segment info", r);
-
-       off= 0;
-       r= write_bytes(rip, off, (char *)segs, sizeof(segs));
-       if (r != OK)
-       {
-               put_inode(rip);
-               return r;
-       }
-       off += sizeof(segs);
-
-       /* Write out the whole kernel process table entry to get the regs. */
-       for (trace_off= 0;; trace_off += sizeof(long))
-       {
-               r= sys_trace(T_GETUSER, proc_e, trace_off, &trace_data);
-               if  (r != OK) 
-               {
-                       printf("dumpcore pid %d: sys_trace failed "
-                               "at offset %ld: %d\n",
-                               rfp->fp_pid, trace_off, r);
-                       break;
-               }
-               r= write_bytes(rip, off, (char *)&trace_data,
-                       sizeof(trace_data));
-               if (r != OK)
-               {
-                       put_inode(rip);
-                       return r;
-               }
-               off += sizeof(trace_data);
-       }
-
-       /* Loop through segments and write the segments themselves out. */
-       for (seg = 0; seg < NR_LOCAL_SEGS; seg++) {
-               len= segs[seg].mem_len << CLICK_SHIFT;
-               seg_off= segs[seg].mem_vir << CLICK_SHIFT;
-               r= write_seg(rip, off, proc_e, seg, seg_off, len);
-               if (r != OK)
-               {
-                       put_inode(rip);
-                       return r;
-               }
-               off += len;
-       }
-
-       rip->i_size= off;
-       rip->i_dirt = DIRTY;
-
-       put_inode(rip);
+        
+       printf("VFSdumpcore: not implemented\n");
        return OK;
 }
 
 
-/*===========================================================================*
- *                             write_bytes                                  *
- *===========================================================================*/
-PRIVATE int write_bytes(rip, off, buf, bytes)
-struct inode *rip;             /* inode descriptor to read from */
-off_t off;                     /* offset in file */
-char *buf;
-size_t bytes;                  /* how much is to be transferred? */
-{
-       int block_size;
-       off_t n, o, b_off;
-       block_t b;
-       struct buf *bp;
-
-       block_size= rip->i_sp->s_block_size;
-       for (o= off - (off % block_size); o < off+bytes; o += block_size)
-       {
-               if (o < off)
-                       b_off= off-o;
-               else
-                       b_off= 0;
-               n= block_size-b_off;
-               if (o+b_off+n > off+bytes)
-                       n= off+bytes-(o+b_off);
-
-               b = read_map(rip, o);
-
-               if (b == NO_BLOCK) {
-                       /* Writing to a nonexistent block. Create and enter
-                        * in inode.
-                        */
-                       if ((bp= new_block(rip, o)) == NIL_BUF)
-                               return(err_code);
-               } 
-               else
-               {
-                       /* Just read the block, no need to optimize for
-                        * writing entire blocks.
-                        */
-                       bp = get_block(rip->i_dev, b, NORMAL);
-               }
-
-               if (n != block_size && o >= rip->i_size && b_off == 0) {
-                       zero_block(bp);
-               }
-
-               /* Copy a chunk from user space to the block buffer. */
-               memcpy((bp->b_data+b_off), buf, n);
-               bp->b_dirt = DIRTY;
-               if (b_off + n == block_size)
-                       put_block(bp, FULL_DATA_BLOCK);
-               else
-                       put_block(bp, PARTIAL_DATA_BLOCK);
-
-               buf += n;
-       }
-
-       return OK;
-}
-
-/*===========================================================================*
- *                             write_seg                                    *
- *===========================================================================*/
-PRIVATE int write_seg(rip, off, proc_e, seg, seg_off, seg_bytes)
-struct inode *rip;             /* inode descriptor to read from */
-off_t off;                     /* offset in file */
-int proc_e;                    /* process number (endpoint) */
-int seg;                       /* T, D, or S */
-off_t seg_off;                 /* Offset in segment */
-phys_bytes seg_bytes;          /* how much is to be transferred? */
-{
-  int r, block_size, fl;
-  off_t n, o, b_off;
-  block_t b;
-  struct buf *bp;
-
-  block_size= rip->i_sp->s_block_size;
-  for (o= off - (off % block_size); o < off+seg_bytes; o += block_size)
-  {
-       if (o < off)
-               b_off= off-o;
-       else
-               b_off= 0;
-       n= block_size-b_off;
-       if (o+b_off+n > off+seg_bytes)
-               n= off+seg_bytes-(o+b_off);
-
-       b = read_map(rip, o);
-       if (b == NO_BLOCK) {
-               /* Writing to a nonexistent block. Create and enter in inode.*/
-               if ((bp= new_block(rip, o)) == NIL_BUF)
-                       return(err_code);
-       } else {
-               /* Normally an existing block to be partially overwritten is
-                * first read in.  However, a full block need not be read in.
-                * If it is already in the cache, acquire it, otherwise just
-                * acquire a free buffer.
-                */
-               fl = (n == block_size ? NO_READ : NORMAL);
-               bp = get_block(rip->i_dev, b, fl);
-       }
-
-       if (n != block_size && o >= rip->i_size && b_off == 0) {
-               zero_block(bp);
-       }
-
-       /* Copy a chunk from user space to the block buffer. */
-       r = sys_vircopy(proc_e, seg, (phys_bytes) seg_off,
-                       FS_PROC_NR, D, (phys_bytes) (bp->b_data+b_off),
-                       (phys_bytes) n);
-       bp->b_dirt = DIRTY;
-       fl = (b_off + n == block_size ? FULL_DATA_BLOCK : PARTIAL_DATA_BLOCK);
-       put_block(bp, fl);
-
-       seg_off += n;
-  }
-
-  return OK;
-}
 
 
diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c
new file mode 100644 (file)
index 0000000..fd59686
--- /dev/null
@@ -0,0 +1,602 @@
+/* This file performs the MOUNT and UMOUNT system calls.
+ *
+ * The entry points into this file are
+ *   do_mount:  perform the MOUNT system call
+ *   do_umount: perform the UMOUNT system call
+ *
+ * Changes for VFS:
+ *   Jul 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <fcntl.h>
+#include <string.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/keymap.h>
+#include <minix/const.h>
+#include <minix/endpoint.h>
+#include <minix/syslib.h>
+#include <unistd.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include "file.h"
+#include "fproc.h"
+#include "param.h"
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
+
+/* Allow the root to be replaced before the first 'real' mount. */
+PRIVATE int allow_newroot = 1;
+
+FORWARD _PROTOTYPE( dev_t name_to_dev, (void)                           );
+FORWARD _PROTOTYPE( int fs_exit, (endpoint_t fs_e)                      );
+FORWARD _PROTOTYPE( int mount_fs, (endpoint_t fs_e)                     );
+
+/*===========================================================================*
+ *                              do_fslogin                                   *
+ *===========================================================================*/
+PUBLIC int do_fslogin()
+{
+  /* Login before mount request */
+  if ((unsigned long)mount_m_in.m1_p3 != who_e) {
+      last_login_fs_e = who_e;
+printf("VFS: FS_e %d logged in\n", last_login_fs_e); 
+      return SUSPEND;
+  }
+  /* Login after a suspended mount */
+  else {
+      /* Copy back original mount request message */
+      m_in = mount_m_in;
+
+      /* Set up last login FS */
+      last_login_fs_e = who_e;
+
+      /* Set up endpoint and call nr */
+      who_e = m_in.m_source;
+      who_p = _ENDPOINT_P(who_e);
+      call_nr = m_in.m_type;
+      fp = &fproc[who_p];       /* pointer to proc table struct */
+      super_user = (fp->fp_effuid == SU_UID ? TRUE : FALSE);   /* su? */
+      
+      
+printf("VFS: FS_e %d logged in. Mount WAKEN UP\n", (unsigned int)m_in.m1_p3);
+      return do_mount();
+  }
+}
+
+/*===========================================================================*
+ *                              do_mount                                     *
+ *===========================================================================*/
+PUBLIC int do_mount()
+{
+  endpoint_t fs_e; 
+  int r;
+       
+  /* FS process' endpoint number */ 
+  fs_e = (unsigned long)m_in.m1_p3;
+  
+  /* Do the actual job */
+  r = mount_fs(fs_e);
+
+  /* If not OK and not suspended, bring down FS proc.. */
+  if (r != OK && r != SUSPEND) {
+      /* Ask RS to bring down FS */
+      if (-1 == fs_exit(fs_e)) {
+          printf("VFSmount: WARNING: couldn't stop FS endp: %d\n", fs_e);
+      }
+  }
+  
+  return r; 
+}
+
+
+/*===========================================================================*
+ *                              mount                                        *
+ *===========================================================================*/
+PRIVATE int mount_fs(endpoint_t fs_e)
+{
+/* Perform the mount(name, mfile, rd_only) system call. */
+  int rdir, mdir;               /* TRUE iff {root|mount} file is dir */
+  int i, r, found;
+  struct fproc *tfp;
+  struct dmap *dp;
+  dev_t dev;
+  message m;
+  struct vnode *vp, *root_node, *mounted_on, *bspec;
+  struct vmnt *vmp, *vmp2;
+  struct mountpoint_req mreq;
+  struct node_details res;
+  struct readsuper_req sreq;
+  struct readsuper_res sres;
+  struct lookup_req lookup_req;
+  
+  /* Only the super-user may do MOUNT. */
+  if (!super_user) return(EPERM);
+
+  /* If FS not yet logged in, save message and suspend mount */
+  if (last_login_fs_e != fs_e) {
+      mount_m_in = m_in; 
+      printf("VFS: FS_e %d not yet logged in. Mount SUSPENDED\n", fs_e); 
+      return SUSPEND;
+  }
+  
+  /* Mount request got after FS login or 
+   * FS login arrived after a suspended mount */
+  last_login_fs_e = 0;
+  
+  /* Clear endpoint field */
+  mount_m_in.m1_p3 = 0;
+
+  /* If 'name' is not for a block special file, return error. */
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  
+  /* Get free vnode for the mountpoint */
+  if ((mounted_on = get_free_vnode()) == NIL_VNODE) {
+        printf("VFSmount: not free vnode available\n");
+        return ENFILE;
+  }
+  
+  /* Mark it as used so that we won't find the same for the root_node */
+  mounted_on->v_count = 1;
+  
+  /* Convert name to device number */
+  if ((dev = name_to_dev()) == NO_DEV) return(err_code);
+
+  /* Check whether there is a block special file open which uses the 
+   * same device (partition) */
+  for (bspec = &vnode[0]; bspec < &vnode[NR_VNODES]; ++bspec) {
+      if (bspec->v_count > 0 && bspec->v_sdev == dev) {
+          /* Found, sync the buffer cache */
+printf("VFSmount: minor is opened as a block spec file, sync cache...\n");          
+          req_sync(bspec->v_fs_e);          
+          break;
+          /* Note: there are probably some blocks in the FS process' buffer
+           * cache which contain data on this minor, although they will be
+           * purged since the handling moves to the new FS process (if
+           * everything goes well with the mount...)
+           */ 
+      }
+  }
+  /* Didn't find? */
+  if (bspec == &vnode[NR_VNODES] && bspec->v_sdev != dev)
+      bspec = NULL;
+  
+  /* Scan vmnt table to see if dev already mounted, if not, 
+   * find a free slot.*/
+  found = FALSE; 
+  vmp = NIL_VMNT;
+  for (i = 0; i < NR_MNTS; ++i) {
+        if (vmnt[i].m_dev == dev) {
+            vmp = &vmnt[i];
+            found = TRUE;
+            break;
+        }
+        else if (!vmp && vmnt[i].m_dev == NO_DEV) {
+            vmp = &vmnt[i];
+        }
+  }
+
+  /* Partition was/is already mounted */
+  if (found) {
+      /* It is possible that we have an old root lying around that 
+       * needs to be remounted. */
+      if (vmp->m_mounted_on != vmp->m_root_node ||
+              vmp->m_mounted_on == fproc[FS_PROC_NR].fp_rd) {
+          /* Normally, m_mounted_on refers to the mount point. For a root
+           * filesystem, m_mounted_on is equal to the root vnode. We assume
+           * that the root of FS is always the real root. If the two
+           * vnodes are different or if the root of FS is equal two the
+           * root of the filesystem we found, we found a filesystem that
+           * is in use. */
+          mounted_on->v_count = 0;
+          return EBUSY;   /* already mounted */
+      }
+
+      if (root_dev == vmp->m_dev)
+          panic("fs", "inconsistency remounting old root", NO_NUM);
+
+      /* Now get the inode of the file to be mounted on. */
+      if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
+          return(err_code);
+      }
+
+      /* Fill in lookup request fields */
+      lookup_req.path = user_fullpath;
+      lookup_req.lastc = NULL;
+      lookup_req.flags = EAT_PATH;
+
+      /* Request lookup */
+      if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+      /* Fill in request message fields.*/
+      mreq.fs_e = res.fs_e;
+      mreq.inode_nr = res.inode_nr;
+      mreq.uid = fp->fp_effuid;
+      mreq.gid = fp->fp_effgid;
+
+      /* Issue request */
+      if ((r = req_mountpoint(&mreq, &res)) != OK) return r;
+
+      mounted_on->v_fs_e = res.fs_e;  
+      mounted_on->v_inode_nr = res.inode_nr;
+      mounted_on->v_mode = res.fmode;
+      mounted_on->v_size = res.fsize;
+      mounted_on->v_sdev = NO_DEV;
+      mounted_on->v_count = 1;
+
+      /* Find the vmnt for the vnode */
+      if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT)
+          printf("VFS: vmnt not found by mount()\n");
+      mounted_on->v_vmnt = vmp2; 
+      mounted_on->v_dev = vmp2->m_dev;  
+
+      /* Get the root inode of the mounted file system. */
+      root_node = vmp->m_root_node;
+
+      /* File types may not conflict. */
+      if (r == OK) {
+          mdir = ((mounted_on->v_mode & I_TYPE) == I_DIRECTORY); 
+          /* TRUE iff dir */
+          rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
+          if (!mdir && rdir) r = EISDIR;
+      }
+
+      /* If error, return the mount point. */
+      if (r != OK) {
+          put_vnode(mounted_on);
+
+          return(r);
+      }
+
+      /* Nothing else can go wrong.  Perform the mount. */
+      put_vnode(vmp->m_mounted_on);
+      vmp->m_mounted_on = mounted_on;
+      vmp->m_flags = m_in.rd_only;
+      allow_newroot = 0;              /* The root is now fixed */
+
+      return(OK);
+  }
+
+  /* We'll need a vnode for the root inode, check whether there is one */
+  if ((root_node = get_free_vnode()) == NIL_VNODE) {
+        printf("VFSmount: no free vnode available\n");
+        return ENFILE;
+  }
+  
+  /* Set it back to zero so that if st goes wrong it won't be kept in use */
+  mounted_on->v_count = 0;
+  
+  /* Fetch the name of the mountpoint */
+  if (fetch_name(m_in.name2, m_in.name2_length, M1) != OK) {
+        return(err_code);
+  }
+
+  /* Get driver process' endpoint */  
+  dp = &dmap[(dev >> MAJOR) & BYTE];
+  if (dp->dmap_driver == NONE) {
+        printf("VFSmount: no driver for dev %x\n", dev);
+        return(EINVAL);
+  }
+
+  /* Open the device the file system lives on. */
+  if (dev_open(dev, fs_e, m_in.rd_only ? R_BIT : (R_BIT|W_BIT)) != OK) {
+        return(EINVAL);
+  }
+
+printf("VFSmount: FS_e: %d mp: %s D_e: %d\n", fs_e, user_fullpath,
+                dp->dmap_driver); 
+
+  /* Request for reading superblock and root inode */
+  sreq.fs_e = fs_e;
+  sreq.readonly = m_in.rd_only;
+  sreq.boottime = boottime;
+  sreq.driver_e = dp->dmap_driver;
+  sreq.dev = dev;
+  sreq.slink_storage = user_fullpath;
+  
+  if (!strcmp(user_fullpath, "/")) sreq.isroot = 1;
+  else sreq.isroot = 0;
+  /* Issue request */
+  if ((r = req_readsuper(&sreq, &sres)) != OK) {
+printf("VFSmount: reading superb error dev: %d\n", dev);          
+      dev_close(dev);
+      return r;
+  }
+
+  /* Fill in root node's fields */
+  root_node->v_fs_e = sres.fs_e;
+  root_node->v_inode_nr = sres.inode_nr;
+  root_node->v_mode = sres.fmode;
+  root_node->v_size = sres.fsize;
+  root_node->v_sdev = NO_DEV;
+  root_node->v_count = 1;
+
+  /* Fill in max file size and blocksize for the vmnt */
+  vmp->m_fs_e = sres.fs_e;
+  vmp->m_dev = dev;
+  vmp->m_block_size = sres.blocksize;
+  vmp->m_max_file_size = sres.maxsize;
+  vmp->m_flags = m_in.rd_only;
+  vmp->m_driver_e = dp->dmap_driver;
+  
+  /* Root node is indeed on the partition */
+  root_node->v_vmnt = vmp;
+  root_node->v_dev = vmp->m_dev;
+  
+  if (strcmp(user_fullpath, "/") == 0 && allow_newroot) {
+      printf("Replacing root\n");
+
+      /* Superblock and root node already read. 
+       * Nothing else can go wrong. Perform the mount. */
+      vmp->m_root_node = root_node;
+      vmp->m_mounted_on = root_node;
+      root_dev = dev;
+      ROOT_FS_E = fs_e;
+
+      /* Replace all root and working directories */
+      for (i= 0, tfp= fproc; i<NR_PROCS; i++, tfp++) {
+          if (tfp->fp_pid == PID_FREE)
+              continue;
+
+          if (tfp->fp_rd == NULL)
+              panic("fs", "do_mount: null rootdir", i);
+          put_vnode(tfp->fp_rd);
+          dup_vnode(root_node);
+          tfp->fp_rd = root_node;
+
+          if (tfp->fp_wd == NULL)
+              panic("fs", "do_mount: null workdir", i);
+          put_vnode(tfp->fp_wd);
+          dup_vnode(root_node);
+          tfp->fp_wd = root_node;
+      }
+
+      return(OK);
+  }
+
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH;
+
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) {
+      put_vnode(root_node);
+      return r;
+  }
+
+  /* Fill in request fields.*/
+  mreq.fs_e = res.fs_e;
+  mreq.inode_nr = res.inode_nr;
+  mreq.uid = fp->fp_effuid;
+  mreq.gid = fp->fp_effgid;
+
+  /* Issue request */
+  if ((r = req_mountpoint(&mreq, &res)) != OK) {
+      put_vnode(root_node);
+      return r;
+  }
+  
+  /* Fill in vnode's fields */
+  mounted_on->v_fs_e = res.fs_e;  
+  mounted_on->v_inode_nr = res.inode_nr;
+  mounted_on->v_mode = res.fmode;
+  mounted_on->v_size = res.fsize;
+  mounted_on->v_sdev = NO_DEV;
+  mounted_on->v_count = 1;
+
+  /* Find the vmnt for the vnode */
+  if ( (vmp2 = find_vmnt(mounted_on->v_fs_e)) == NIL_VMNT)
+      printf("VFS: vmnt not found by mount()");
+  mounted_on->v_vmnt = vmp2; 
+  mounted_on->v_dev = vmp2->m_dev;
+
+  /* File types may not conflict. */
+  if (r == OK) {
+      mdir = ((mounted_on->v_mode & I_TYPE) == I_DIRECTORY);/* TRUE iff dir */
+      rdir = ((root_node->v_mode & I_TYPE) == I_DIRECTORY);
+      if (!mdir && rdir) r = EISDIR;
+  }
+
+  /* If error, return the super block and both inodes; release the vmnt. */
+  if (r != OK) {
+      put_vnode(mounted_on);
+      put_vnode(root_node);
+
+      vmp->m_dev = NO_DEV;
+      dev_close(dev);
+      return(r);
+  }
+
+  /* Nothing else can go wrong.  Perform the mount. */
+  vmp->m_mounted_on = mounted_on;
+  vmp->m_root_node = root_node;
+
+  /* The root is now fixed */
+  allow_newroot = 0;            
+
+  /* There was a block spec file open, and it should be handled by the 
+   * new FS proc now */
+  if (bspec) {
+      printf("VFSmount: moving opened block spec to new FS_e: %d...\n", fs_e);
+      bspec->v_bfs_e = fs_e; 
+  }
+  return(OK);
+}
+
+/*===========================================================================*
+ *                              do_umount                                    *
+ *===========================================================================*/
+PUBLIC int do_umount()
+{
+/* Perform the umount(name) system call. */
+  dev_t dev;
+
+  /* Only the super-user may do UMOUNT. */
+  if (!super_user) return(EPERM);
+
+  /* If 'name' is not for a block special file, return error. */
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+  if ( (dev = name_to_dev()) == NO_DEV) return(err_code);
+
+  return(unmount(dev));
+}
+
+
+/*===========================================================================*
+ *                              unmount                                      *
+ *===========================================================================*/
+PUBLIC int unmount(dev)
+Dev_t dev;
+{
+  struct vnode *vp;
+  struct vmnt *vmp;
+  struct dmap *dp;
+  int count, r;
+  int fs_e;
+
+  /* Find vmnt */
+  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
+      if (vmp->m_dev == dev) break;
+      else if (vmp == &vmnt[NR_MNTS])
+          return EINVAL;
+  }
+
+  /* See if the mounted device is busy.  Only 1 vnode using it should be
+   * open -- the root vnode -- and that inode only 1 time.
+   */
+  count = 0;
+  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
+      if (vp->v_count > 0 && vp->v_dev == dev) {
+          count += vp->v_count;
+      }
+  }
+
+  if (count > 1) {
+      printf("VFSunmount: %d filesystem is busy count: %d\n", dev, count);
+      return(EBUSY);    /* can't umount a busy file system */
+  }
+
+  /* Request FS the unmount */
+  if ((r = req_unmount(vmp->m_fs_e)) != OK) return r;
+
+  /* Close the device the file system lives on. */
+  dev_close(dev);
+
+  /* Is there a block special file that was handled by that partition? */
+  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
+      if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL && 
+              vp->v_bfs_e == vmp->m_fs_e) {
+
+          /* Get the driver endpoint of the block spec device */
+          dp = &dmap[(dev >> MAJOR) & BYTE];
+          if (dp->dmap_driver == NONE) {
+              printf("VFSblock_spec_open: driver not found for device %d\n", 
+                      dev);
+              /* What should be done, panic??? */
+              continue;
+          }
+
+          printf("VFSunmount: moving block spec %d to root FS\n", dev);
+          vp->v_bfs_e = ROOT_FS_E;
+          vp->v_blocksize = _MIN_BLOCK_SIZE;
+
+          /* Send the driver endpoint (even if it is known already...) */
+          if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver))
+                  != OK) {
+              printf("VFSunmount: error sending driver endpoint for block spec\n");
+          }
+      }
+  }
+
+  /* Root device is mounted on itself */
+  if (vmp->m_root_node != vmp->m_mounted_on) {
+      put_vnode(vmp->m_mounted_on);
+      vmp->m_root_node->v_count = 0;
+  }
+  else {
+      vmp->m_mounted_on->v_count--;
+  }
+
+  fs_e = vmp->m_fs_e;
+
+  vmp->m_root_node = NIL_VNODE;
+  vmp->m_mounted_on = NIL_VNODE;
+  vmp->m_dev = NO_DEV;
+  vmp->m_fs_e = 0;
+  vmp->m_driver_e = 0;
+
+  /* Ask RS to bring down FS */
+  if (-1 == fs_exit(fs_e)) {
+      printf("VFSunmount: WARNING: couldn't stop FS endp: %d\n", fs_e);
+  }
+
+  printf("VFSunmount: DEV: %d unmounted\n", dev);  
+  return(OK);
+}
+
+/*===========================================================================*
+ *                              name_to_dev                                  *
+ *===========================================================================*/
+PRIVATE dev_t name_to_dev()
+{
+/* Convert the block special file 'path' to a device number.  If 'path'
+ * is not a block special file, return error code in 'err_code'. */
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH;
+
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  if ((res.fmode & I_TYPE) != I_BLOCK_SPECIAL) {
+       err_code = ENOTBLK;
+       return NO_DEV;
+  }
+  
+  return res.dev;
+}
+
+
+/*===========================================================================*
+ *                              fs_exit                                      *
+ *===========================================================================*/
+PRIVATE int fs_exit(fs_e)
+endpoint_t fs_e;
+{
+/* Build a message for stoping a FS server and ask RS to do it */
+  message m;
+  pid_t fs_pid;
+  int r;
+
+  /* Don't need to stop the one in the bootimage */
+  if (fs_e == MFS_PROC_NR) return OK;
+  
+  /* Get pid for this endpoint */
+  if (-1 == (fs_pid = getnpid(fs_e))) {
+      printf("VFS: couldn't find pid for fs_e: %d\n", fs_e);
+      return -1;
+  }
+
+printf("VFSfs_exit: Bringing down FS endp: %d (pid: %d)\n", fs_e, fs_pid);  
+
+  /* Ask RS to stop process */
+  m.RS_PID = fs_pid;
+  if (OK != (r = _taskcall(RS_PROC_NR, RS_DOWN, &m))) {
+      printf("VFSfs_exit: couldn't bring FS down pid: %d\n", fs_pid);
+      return -1;
+  }
+
+  return OK;
+}
+
+
diff --git a/servers/vfs/open.c b/servers/vfs/open.c
new file mode 100644 (file)
index 0000000..4220ebc
--- /dev/null
@@ -0,0 +1,528 @@
+/* This file contains the procedures for creating, opening, closing, and
+ * seeking on files.
+ *
+ * The entry points into this file are
+ *   do_creat: perform the CREAT system call
+ *   do_open:  perform the OPEN system call
+ *   do_mknod: perform the MKNOD system call
+ *   do_mkdir: perform the MKDIR system call
+ *   do_close: perform the CLOSE system call
+ *   do_lseek:  perform the LSEEK system call
+ *
+ * Changes for VFS:
+ *   Jul 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include "file.h"
+#include "fproc.h"
+#include "lock.h"
+#include "param.h"
+#include <dirent.h>
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
+
+#define offset m2_l1
+
+PRIVATE char mode_map[] = {R_BIT, W_BIT, R_BIT|W_BIT, 0};
+
+FORWARD _PROTOTYPE( int common_open, (int oflags, mode_t omode)                );
+FORWARD _PROTOTYPE( int pipe_open, (struct vnode *vp,mode_t bits,int oflags));
+
+/*===========================================================================*
+ *                             do_creat                                     *
+ *===========================================================================*/
+PUBLIC int do_creat()
+{
+/* Perform the creat(name, mode) system call. */
+  int r;
+
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+  r = common_open(O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
+  return(r);
+}
+
+/*===========================================================================*
+ *                             do_open                                      *
+ *===========================================================================*/
+PUBLIC int do_open()
+{
+/* Perform the open(name, flags,...) system call. */
+  int create_mode = 0;         /* is really mode_t but this gives problems */
+  int r;
+
+  /* If O_CREAT is set, open has three parameters, otherwise two. */
+  if (m_in.mode & O_CREAT) {
+       create_mode = m_in.c_mode;      
+       r = fetch_name(m_in.c_name, m_in.name1_length, M1);
+  } else {
+       r = fetch_name(m_in.name, m_in.name_length, M3);
+  }
+
+  if (r != OK) {
+         return(err_code); /* name was bad */
+  }
+  r = common_open(m_in.mode, create_mode);
+  return(r);
+}
+
+/*===========================================================================*
+ *                             common_open                                  *
+ *===========================================================================*/
+PRIVATE int common_open(register int oflags, mode_t omode)
+{
+/* Common code from do_creat and do_open. */
+  int r, b, found;
+  dev_t dev;
+  mode_t bits;
+  off_t pos;
+  struct dmap *dp;
+  struct filp *fil_ptr, *filp2;
+  struct vnode *vp, *vp2;
+  struct vmnt *vmp;
+  char lastc[NAME_MAX];
+
+  /* Request and response structures */
+  struct lookup_req lookup_req;
+  struct open_req req;
+  struct node_details res;
+
+  /* Remap the bottom two bits of oflags. */
+  bits = (mode_t) mode_map[oflags & O_ACCMODE];
+
+  /* See if file descriptor and filp slots are available. */
+  if ((r = get_fd(0, bits, &m_in.fd, &fil_ptr)) != OK) return(r);
+
+  /* See if a free vnode is available */
+  if ((vp = get_free_vnode()) == NIL_VNODE) {
+      printf("VFS: no vnode available!\n");
+      return err_code;
+  }
+
+  /* If O_CREATE, set umask */ 
+  if (oflags & O_CREAT) {
+        omode = I_REGULAR | (omode & ALL_MODES & fp->fp_umask);
+  }
+
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = lastc;
+  lookup_req.flags = oflags&O_CREAT ? (oflags&O_EXCL ? LAST_DIR : 
+              LAST_DIR_EATSYM) : EAT_PATH;
+  
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  /* Lookup was okay, fill in request fields for 
+   * the actual open request. */
+  req.inode_nr = res.inode_nr;
+  req.fs_e = res.fs_e;
+  req.oflags = oflags;
+  req.omode = omode;
+  req.lastc = lastc;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+
+  /* Issue request */
+  if ((r = req_open(&req, &res)) != OK) return r;
+  
+  /* Check whether the vnode is already in use */
+  if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) != NIL_VNODE) {
+      vp = vp2;
+      vp->v_size = res.fsize;; /* In case of trunc... */
+      vp->v_count++;
+  }
+  /* Otherwise use the free one */
+  else {
+      vp->v_fs_e = res.fs_e;
+      if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
+          printf("VFS: vmnt not found by open()");
+      
+      vp->v_dev = vmp->m_dev;
+      vp->v_inode_nr = res.inode_nr;
+      vp->v_mode = res.fmode;
+      vp->v_size = res.fsize;
+      vp->v_sdev = res.dev; 
+      vp->v_count = 1;
+      vp->v_vmnt = vmp; 
+      vp->v_index = res.inode_index;
+  }
+
+  /* Claim the file descriptor and filp slot and fill them in. */
+  fp->fp_filp[m_in.fd] = fil_ptr;
+  FD_SET(m_in.fd, &fp->fp_filp_inuse);
+  fil_ptr->filp_count = 1;
+  fil_ptr->filp_flags = oflags;
+  fil_ptr->filp_vno = vp;
+  
+  switch (vp->v_mode & I_TYPE) {
+      case I_CHAR_SPECIAL:
+          /* Invoke the driver for special processing. */
+          r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE));
+          break;
+
+      case I_BLOCK_SPECIAL:
+          /* Invoke the driver for special processing. */
+          r = dev_open(vp->v_sdev, who_e, bits | (oflags & ~O_ACCMODE));
+          
+          /* Check whether the device is mounted or not */
+          found = 0;
+          if (r == OK) {
+printf("VFS: opening block spec %d, handled by ", vp->v_sdev); 
+              for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
+                  if (vmp->m_dev == vp->v_sdev) {
+                      found = 1;
+                      break;
+                  }
+              }
+             
+              /* Who is going to be responsible for this device? */
+              if (found) {
+printf("the FS of the mounted partition...\n"); 
+                  vp->v_bfs_e = vmp->m_fs_e;
+                  vp->v_blocksize - vmp->m_block_size;
+              }
+              else { /* To be handled in the root FS proc if not mounted */ 
+printf("the root FS...\n");
+                  vp->v_bfs_e = ROOT_FS_E;
+                  vp->v_blocksize = _MIN_BLOCK_SIZE;
+              }
+              
+              /* Get the driver endpoint of the block spec device */
+              dp = &dmap[(vp->v_sdev >> MAJOR) & BYTE];
+              if (dp->dmap_driver == NONE) {
+                  printf("VFSblock_spec_open: driver not found for device %d\n", 
+                          vp->v_sdev);
+                  r = EINVAL;
+                  break;
+              }
+
+              /* Send the driver endpoint (even if it is known already...) */
+              if ((r = req_newdriver(vp->v_bfs_e, vp->v_sdev, dp->dmap_driver))
+                      != OK) {
+                  printf("VFSblock_spec_open: error sending driver endpoint\n");
+              }
+          }
+          break;
+
+      case I_NAMED_PIPE:
+         vp->v_pipe = I_PIPE;
+          oflags |= O_APPEND;  /* force append mode */
+          fil_ptr->filp_flags = oflags;
+          r = pipe_open(vp, bits, oflags);
+          if (r != ENXIO) {
+              /* See if someone else is doing a rd or wt on
+               * the FIFO.  If so, use its filp entry so the
+               * file position will be automatically shared.
+               */
+              b = (bits & R_BIT ? R_BIT : W_BIT);
+              fil_ptr->filp_count = 0; /* don't find self */
+              if ((filp2 = find_filp(vp, b)) != NIL_FILP) {
+                  /* Co-reader or writer found. Use it.*/
+                  fp->fp_filp[m_in.fd] = filp2;
+                  filp2->filp_count++;
+                 filp2->filp_vno = vp;
+                  filp2->filp_flags = oflags;
+
+                  /* v_count was incremented after the vnode has 
+                   * been found, i_count was incremented incorrectly
+                   * by eatpath in FS, not knowing that we were going to 
+                   * use an existing filp entry.  Correct this error.
+                   */
+                  put_vnode(vp);
+             } else {
+                  /* Nobody else found.  Restore filp. */
+                  fil_ptr->filp_count = 1;
+                 if (fil_ptr->filp_mode == R_BIT)
+                       fil_ptr->filp_pos = vp->v_pipe_rd_pos; 
+                 else
+                       fil_ptr->filp_pos = vp->v_pipe_wr_pos;
+              }
+          }
+          break;
+  }
+
+  /* If error, release inode. */
+  if (r != OK) {
+       if (r == SUSPEND) return(r);            /* Oops, just suspended */
+       fp->fp_filp[m_in.fd] = NIL_FILP;
+       FD_CLR(m_in.fd, &fp->fp_filp_inuse);
+       fil_ptr->filp_count= 0;
+       put_vnode(vp);     
+       fil_ptr->filp_vno = NIL_VNODE;
+       return(r);
+  }
+  
+  return(m_in.fd);
+}
+
+
+
+/*===========================================================================*
+ *                             pipe_open                                    *
+ *===========================================================================*/
+PRIVATE int pipe_open(register struct vnode *vp, register mode_t bits,
+       register int oflags)
+{
+/*  This function is called from common_open. It checks if
+ *  there is at least one reader/writer pair for the pipe, if not
+ *  it suspends the caller, otherwise it revives all other blocked
+ *  processes hanging on the pipe.
+ */
+
+  vp->v_pipe = I_PIPE; 
+
+  if((bits & (R_BIT|W_BIT)) == (R_BIT|W_BIT)) {
+       printf("pipe opened RW.\n");
+       return ENXIO;
+  }
+
+  if (find_filp(vp, bits & W_BIT ? R_BIT : W_BIT) == NIL_FILP) { 
+       if (oflags & O_NONBLOCK) {
+               if (bits & W_BIT) return(ENXIO);
+       } else {
+               suspend(XPOPEN);        /* suspend caller */
+               return(SUSPEND);
+       }
+  } else if (susp_count > 0) {/* revive blocked processes */
+       release(vp, OPEN, susp_count);
+       release(vp, CREAT, susp_count);
+  }
+  return(OK);
+}
+
+
+
+
+/*===========================================================================*
+ *                             do_mknod                                     *
+ *===========================================================================*/
+PUBLIC int do_mknod()
+{
+/* Perform the mknod(name, mode, addr) system call. */
+  register mode_t bits, mode_bits;
+  char lastc[NAME_MAX];         /* last component of the path */
+  struct mknod_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+
+  /* Only the super_user may make nodes other than fifos. */
+  mode_bits = (mode_t) m_in.mk_mode;           /* mode of the inode */
+  if (!super_user && ((mode_bits & I_TYPE) != I_NAMED_PIPE)) return(EPERM);
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = lastc;
+  lookup_req.flags = LAST_DIR;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  /* Lookup was okay, fill in request fields for the actual
+   * mknod request. */
+  req.fs_e = res.fs_e;
+  req.inode_nr = res.inode_nr;
+  req.rmode = bits;
+  req.dev = m_in.mk_z0;
+  req.lastc = lastc;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+                                          
+  /* Issue request */
+  return req_mknod(&req);
+}
+
+
+/*===========================================================================*
+ *                             do_mkdir                                     *
+ *===========================================================================*/
+PUBLIC int do_mkdir()
+{
+/* Perform the mkdir(name, mode) system call. */
+  mode_t bits;                 /* mode bits for the new inode */
+  char lastc[NAME_MAX];
+  struct mkdir_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+
+/*printf("VFS: mkdir() START:");*/
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+
+  bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
+
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = lastc;
+  lookup_req.flags = LAST_DIR;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+  
+  /* Lookup was okay, fill in request message fields 
+   * for the actual mknod request. */
+  req.fs_e = res.fs_e;
+  req.d_inode_nr = res.inode_nr;
+  req.rmode = bits;
+  req.lastc = lastc;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+                                          
+  /* Issue request */
+  return req_mkdir(&req);
+}
+
+
+
+
+/*===========================================================================*
+ *                             do_lseek                                     *
+ *===========================================================================*/
+PUBLIC int do_lseek()
+{
+/* Perform the lseek(ls_fd, offset, whence) system call. */
+  register struct filp *rfilp;
+  register off_t pos;
+  struct node_req req;
+  int r;
+
+  /* Check to see if the file descriptor is valid. */
+  if ( (rfilp = get_filp(m_in.ls_fd)) == NIL_FILP) return(err_code);
+
+  /* No lseek on pipes. */
+  if (rfilp->filp_vno->v_pipe == I_PIPE) return(ESPIPE);
+
+  /* The value of 'whence' determines the start position to use. */
+  switch(m_in.whence) {
+      case SEEK_SET: pos = 0;  break;
+      case SEEK_CUR: pos = rfilp->filp_pos;    break;
+      case SEEK_END: pos = rfilp->filp_vno->v_size;    break;
+      default: return(EINVAL);
+  }
+
+  /* Check for overflow. */
+  if (((long)m_in.offset > 0) && ((long)(pos + m_in.offset) < (long)pos)) 
+      return(EINVAL);
+  if (((long)m_in.offset < 0) && ((long)(pos + m_in.offset) > (long)pos)) 
+      return(EINVAL);
+  pos = pos + m_in.offset;
+
+  if (pos != rfilp->filp_pos) {         /* Inhibit read ahead request */
+      /* Fill in request message */
+      req.fs_e = rfilp->filp_vno->v_fs_e;
+      req.inode_nr = rfilp->filp_vno->v_inode_nr;
+
+      /* Issue request */
+      if ((r = req_inhibread(&req)) != OK) return r;
+  }
+
+  rfilp->filp_pos = pos;
+  m_out.reply_l1 = pos;                /* insert the long into the output message */
+  return(OK);
+}
+
+
+/*===========================================================================*
+ *                             do_close                                     *
+ *===========================================================================*/
+PUBLIC int do_close()
+{
+/* Perform the close(fd) system call. */
+  return close_fd(fp, m_in.fd);
+}
+
+
+/*===========================================================================*
+ *                             close_fd                                     *
+ *===========================================================================*/
+PUBLIC int close_fd(rfp, fd_nr)
+struct fproc *rfp;
+int fd_nr;
+{
+/* Perform the close(fd) system call. */
+  register struct filp *rfilp;
+  register struct vnode *vp;
+  struct file_lock *flp;
+  int rw, mode_word, lock_count;
+  dev_t dev;
+
+  /* First locate the vnode that belongs to the file descriptor. */
+  if ( (rfilp = get_filp2(rfp, fd_nr)) == NIL_FILP) return(err_code);
+
+  vp = rfilp->filp_vno;
+
+  if (rfilp->filp_count - 1 == 0 && rfilp->filp_mode != FILP_CLOSED) {
+       /* Check to see if the file is special. */
+       mode_word = vp->v_mode & I_TYPE;
+       if (mode_word == I_CHAR_SPECIAL || mode_word == I_BLOCK_SPECIAL) {
+               dev = (dev_t) vp->v_sdev;
+               if (mode_word == I_BLOCK_SPECIAL)  {
+                       /* Invalidate cache entries unless special is mounted
+                        * or ROOT
+                        */
+                       req_sync(vp->v_bfs_e);
+printf("VFSclose: closed block spec %d\n", dev);               
+               }
+               /* Do any special processing on device close. */
+               dev_close(dev);
+       }
+  }
+
+  /* If the inode being closed is a pipe, release everyone hanging on it. */
+  if (vp->v_pipe == I_PIPE) {
+       rw = (rfilp->filp_mode & R_BIT ? WRITE : READ);
+       release(vp, rw, NR_PROCS);
+  }
+
+  /* If a write has been done, the inode is already marked as DIRTY. */
+  if (--rfilp->filp_count == 0) {
+       if (vp->v_pipe == I_PIPE && vp->v_count > 1) {
+               /* Save the file position in the v-node in case needed later.
+                * The read and write positions are saved separately.  
+                */
+               if (rfilp->filp_mode == R_BIT)
+                       vp->v_pipe_rd_pos = rfilp->filp_pos;
+               else
+                       vp->v_pipe_wr_pos = rfilp->filp_pos;
+               
+       }
+       else {
+               /* Otherwise zero the pipe position fields */
+               vp->v_pipe_rd_pos = 0;
+               vp->v_pipe_wr_pos = 0;
+       }
+               
+       put_vnode(rfilp->filp_vno);
+  }
+
+  FD_CLR(fd_nr, &rfp->fp_cloexec_set);
+  rfp->fp_filp[fd_nr] = NIL_FILP;
+  FD_CLR(fd_nr, &rfp->fp_filp_inuse);
+
+  /* Check to see if the file is locked.  If so, release all locks. */
+  if (nr_locks == 0) return(OK);
+  lock_count = nr_locks;       /* save count of locks */
+  for (flp = &file_lock[0]; flp < &file_lock[NR_LOCKS]; flp++) {
+       if (flp->lock_type == 0) continue;      /* slot not in use */
+       if (flp->lock_vnode == vp && flp->lock_pid == rfp->fp_pid) {
+               flp->lock_type = 0;
+               nr_locks--;
+       }
+  }
+  if (nr_locks < lock_count) lock_revive();    /* lock released */
+  return(OK);
+}
+
+
diff --git a/servers/vfs/param.h b/servers/vfs/param.h
new file mode 100644 (file)
index 0000000..2ea84d8
--- /dev/null
@@ -0,0 +1,65 @@
+/* The following names are synonyms for the variables in the input message. */
+#define acc_time      m2_l1
+#define addr         m1_i3
+#define buffer       m1_p1
+#define child_endpt      m1_i2
+#define co_mode              m1_i1
+#define eff_grp_id    m1_i3
+#define eff_user_id   m1_i3
+#define erki          m1_p1
+#define fd           m1_i1
+#define fd2          m1_i2
+#define ioflags       m1_i3
+#define group        m1_i3
+#define real_grp_id   m1_i2
+#define ls_fd        m2_i1
+#define mk_mode              m1_i2
+#define mk_z0        m1_i3
+#define mode         m3_i2
+#define c_mode        m1_i3
+#define c_name        m1_p1
+#define name         m3_p1
+#define name1        m1_p1
+#define name2        m1_p2
+#define        name_length   m3_i1
+#define name1_length  m1_i1
+#define name2_length  m1_i2
+#define nbytes        m1_i2
+#define owner        m1_i2
+#define parent_endpt      m1_i1
+#define pathname      m3_ca1
+#define pid          m1_i3
+#define ENDPT        m1_i1
+#define ctl_req       m4_l1
+#define driver_nr     m4_l2
+#define dev_nr       m4_l3
+#define dev_style     m4_l4
+#define m_force              m4_l5
+#define rd_only              m1_i3
+#define real_user_id  m1_i2
+#define request       m1_i2
+#define sig          m1_i2
+#define endpt1       m1_i1
+#define tp           m2_l1
+#define utime_actime  m2_l1
+#define utime_modtime m2_l2
+#define utime_file    m2_p1
+#define utime_length  m2_i1
+#define utime_strlen  m2_i2
+#define whence       m2_i2
+#define svrctl_req    m2_i1
+#define svrctl_argp   m2_p1
+#define pm_stime      m1_i1
+#define info_what     m1_i1
+#define info_where    m1_p1
+
+/* The following names are synonyms for the variables in the output message. */
+#define reply_type    m_type
+#define reply_l1      m2_l1
+#define reply_i1      m1_i1
+#define reply_i2      m1_i2
+#define reply_t1      m4_l1
+#define reply_t2      m4_l2
+#define reply_t3      m4_l3
+#define reply_t4      m4_l4
+#define reply_t5      m4_l5
diff --git a/servers/vfs/path.c b/servers/vfs/path.c
new file mode 100644 (file)
index 0000000..86e0608
--- /dev/null
@@ -0,0 +1,152 @@
+
+/* lookup() is the main routine that controls the path name lookup. It  
+ * handles mountpoints and symbolic links. The actual lookup requests
+ * are sent through the req_lookup wrapper function.
+ *
+ *  Jul 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <string.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/keymap.h>
+#include <minix/const.h>
+#include <minix/endpoint.h>
+#include <unistd.h>
+
+#include <minix/vfsif.h>
+#include "fproc.h"
+#include "vmnt.h"
+#include "vnode.h"
+#include "param.h"
+
+
+/*===========================================================================*
+ *                             lookup                                       *
+ *===========================================================================*/
+PUBLIC int lookup(lookup_req, node)
+lookup_req_t *lookup_req;
+node_details_t *node;
+{
+  struct vmnt *vmp;
+  struct vnode *start_node;
+  struct lookup_res res;
+  int r, symloop = 0;
+  int cum_path_processed = 0;
+  
+  /* Make a copy of the request so that the original values will be kept */ 
+  struct lookup_req req = *lookup_req; 
+  char *fullpath = lookup_req->path;
+
+  /* Empty (start) path? */
+  if (fullpath[0] == '\0') {
+      return ENOENT;
+  }
+
+  /* Set user and group ids according to the system call */
+  req.uid = (call_nr == ACCESS ? fp->fp_realuid : fp->fp_effuid); 
+  req.gid = (call_nr == ACCESS ? fp->fp_realgid : fp->fp_effgid); 
+
+  /* Set the starting directories inode number and FS endpoint */
+  start_node = (fullpath[0] == '/' ? fp->fp_rd : fp->fp_wd);
+  req.start_dir = start_node->v_inode_nr;
+  req.fs_e = start_node->v_fs_e;
+
+  /* Is the process' root directory on the same partition?,
+   * if so, set the chroot directory too. */
+  if (fp->fp_rd->v_dev == fp->fp_wd->v_dev)
+      req.root_dir = fp->fp_rd->v_inode_nr; 
+  else
+      req.root_dir = 0;
+
+  req.symloop = symloop;
+
+  /* Issue the request */
+  r = req_lookup(&req, &res);
+
+  /* While the response is related to mount control set the 
+   * new requests respectively */
+  while (r == EENTERMOUNT || r == ELEAVEMOUNT || r == ESYMLINK) {
+      
+      /* If a symlink was encountered during the lookup the 
+       * new path has been copied back and the number of characters 
+       * processed has been started over. */
+      if (r == ESYMLINK || res.symloop > symloop) {
+          /* The link's content is copied back to the user_fullpath
+           * array. Use it as the path argument from now on... */
+          fullpath = user_fullpath;
+          cum_path_processed = res.char_processed;
+      }
+      else {
+          /* Otherwise, cumulate the characters already processsed from 
+           * the path */
+          cum_path_processed += res.char_processed;
+      }
+
+      /* Remember the current value of the symloop counter */
+      symloop = res.symloop;
+
+      /* Symlink encountered with absolute path */
+      if (r == ESYMLINK) {
+          start_node = fp->fp_rd;
+      }
+      /* Entering a new partition */
+      else if (r == EENTERMOUNT) {
+          start_node = 0;
+          /* Start node is now the mounted partition's root node */
+          for (vmp = &vmnt[0]; vmp != &vmnt[NR_MNTS]; ++vmp) {
+              if (vmp->m_mounted_on->v_inode_nr == res.inode_nr
+                      && vmp->m_mounted_on->v_fs_e == res.fs_e) {
+                  start_node = vmp->m_root_node;
+                  break;
+              }
+          }
+          if (!start_node) {
+              printf("VFSlookup: mounted partition couldn't be found\n");
+              return ENOENT;
+          }
+
+      }
+      /* Climbing up mount */
+      else {
+          /* Find the vmnt that represents the partition on
+           * which we "climb up". */
+          if ((vmp = find_vmnt(res.fs_e)) == NIL_VMNT) {
+              printf("VFS: couldn't find vmnt during the climbup!\n");
+              return ENOENT;
+          }      
+          /* Start node is the vnode on which the partition is
+           * mounted */
+          start_node = vmp->m_mounted_on;
+      }
+      /* Fill in the request fields */
+      req.start_dir = start_node->v_inode_nr;
+      req.fs_e = start_node->v_fs_e;
+
+      /* Is the process' root directory on the same partition?*/
+      if (start_node->v_dev == fp->fp_rd->v_dev)
+          req.root_dir = fp->fp_rd->v_inode_nr;
+      else
+          req.root_dir = 0;
+
+      /* Fill in the current path name */
+      req.path = &fullpath[cum_path_processed];
+      req.symloop = symloop;
+      
+      /* Issue the request */
+      r = req_lookup(&req, &res);
+  }
+
+  /* If success, fill in response fields */
+  if (OK == r) {
+      node->inode_nr = res.inode_nr;
+      node->fmode = res.fmode;
+      node->fsize = res.fsize;
+      node->dev = res.dev;
+      node->fs_e = res.fs_e;
+  }
+  
+  return r;
+}
+
similarity index 82%
rename from servers/fs/pipe.c
rename to servers/vfs/pipe.c
index 57a8ebb1caa6d81b9e9b8c9416cef2b17dd8439b..430f97f610655f85e7da6d85e7ad0faa7e56c718 100644 (file)
@@ -13,6 +13,9 @@
  *   revive:     mark a suspended process as able to run again
  *   unsuspend_by_endpt: revive all processes blocking on a given process
  *   do_unpause:  a signal has been sent to a process; see if it suspended
+ *
+ * Changes for VFS:
+ *   Jul 2006 (Balazs Gerofi)
  */
 
 #include "fs.h"
 #include <sys/time.h>
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
 #include "param.h"
-#include "super.h"
 #include "select.h"
 
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
+
+
+
+
 /*===========================================================================*
  *                             do_pipe                                      *
  *===========================================================================*/
@@ -39,11 +47,22 @@ PUBLIC int do_pipe()
 /* Perform the pipe(fil_des) system call. */
 
   register struct fproc *rfp;
-  register struct inode *rip;
   int r;
   struct filp *fil_ptr0, *fil_ptr1;
   int fil_des[2];              /* reply goes here */
 
+  struct vnode *vp;
+  struct vmnt *vmp;
+
+  struct pipe_req req;
+  struct node_details res;
+
+  /* See if a free vnode is available */
+  if ( (vp = get_free_vnode()) == NIL_VNODE) {
+      printf("VFS: no vnode available!\n");
+      return err_code;
+  }
+
   /* Acquire two file descriptors. */
   rfp = fp;
   if ( (r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) return(r);
@@ -51,49 +70,69 @@ PUBLIC int do_pipe()
   FD_SET(fil_des[0], &rfp->fp_filp_inuse);
   fil_ptr0->filp_count = 1;
   if ( (r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
-       rfp->fp_filp[fil_des[0]] = NIL_FILP;
-       FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
-       fil_ptr0->filp_count = 0;
-       return(r);
+      rfp->fp_filp[fil_des[0]] = NIL_FILP;
+      FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
+      fil_ptr0->filp_count = 0;
+      return(r);
   }
   rfp->fp_filp[fil_des[1]] = fil_ptr1;
   FD_SET(fil_des[1], &rfp->fp_filp_inuse);
   fil_ptr1->filp_count = 1;
 
-  /* Make the inode on the pipe device. */
-  if ( (rip = alloc_inode(root_dev, I_REGULAR) ) == NIL_INODE) {
-       rfp->fp_filp[fil_des[0]] = NIL_FILP;
-       FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
-       fil_ptr0->filp_count = 0;
-       rfp->fp_filp[fil_des[1]] = NIL_FILP;
-       FD_CLR(fil_des[1], &rfp->fp_filp_inuse);
-       fil_ptr1->filp_count = 0;
-       return(err_code);
+  /* Fill in FS request */
+  req.fs_e = ROOT_FS_E;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+
+  /* Send request */
+  r = req_pipe(&req, &res);
+
+  /* Handle error */
+  if (r != OK) {
+      rfp->fp_filp[fil_des[0]] = NIL_FILP;
+      FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
+      fil_ptr0->filp_count = 0;
+      rfp->fp_filp[fil_des[1]] = NIL_FILP;
+      FD_CLR(fil_des[1], &rfp->fp_filp_inuse);
+      fil_ptr1->filp_count = 0;
+      return r;
+  }
+
+  /* Fill in vnode */
+  vp->v_fs_e = res.fs_e;
+  vp->v_inode_nr = res.inode_nr; 
+  vp->v_mode = res.fmode;
+  vp->v_index = res.inode_index;
+  vp->v_pipe = I_PIPE;
+  vp->v_count = 2;              /* Double usage */
+  vp->v_size = 0;
+
+  if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT) {
+      printf("VFS: vmnt not found by pipe() ==>> USING ROOT VMNT\n");
+      vp->v_vmnt = &vmnt[0];
+  }
+  else {
+      vp->v_vmnt = vmp; 
+      vp->v_dev = vmp->m_dev;
   }
 
-  if (read_only(rip) != OK) 
-       panic(__FILE__,"pipe device is read only", NO_NUM);
-  rip->i_pipe = I_PIPE;
-  rip->i_mode &= ~I_REGULAR;
-  rip->i_mode |= I_NAMED_PIPE; /* pipes and FIFOs have this bit set */
-  fil_ptr0->filp_ino = rip;
+  /* Fill in filp objects */
+  fil_ptr0->filp_vno = vp;
+  fil_ptr1->filp_vno = vp;
   fil_ptr0->filp_flags = O_RDONLY;
-  dup_inode(rip);              /* for double usage */
-  fil_ptr1->filp_ino = rip;
   fil_ptr1->filp_flags = O_WRONLY;
-  rw_inode(rip, WRITING);      /* mark inode as allocated */
+
   m_out.reply_i1 = fil_des[0];
   m_out.reply_i2 = fil_des[1];
-  rip->i_update = ATIME | CTIME | MTIME;
+
   return(OK);
 }
 
 /*===========================================================================*
  *                             pipe_check                                   *
  *===========================================================================*/
-PUBLIC int pipe_check(rip, rw_flag, oflags, bytes, position, canwrite, notouch)
-register struct inode *rip;    /* the inode of the pipe */
+PUBLIC int pipe_check(vp, rw_flag, oflags, bytes, position, canwrite, notouch)
+register struct vnode *vp;     /* the inode of the pipe */
 int rw_flag;                   /* READING or WRITING */
 int oflags;                    /* flags set by open or fcntl */
 register int bytes;            /* bytes to be read or written (all chunks) */
@@ -109,10 +148,10 @@ int notouch;                      /* check only */
 
   /* If reading, check for empty pipe. */
   if (rw_flag == READING) {
-       if (position >= rip->i_size) {
+       if (position >= vp->v_size) {
                /* Process is reading from an empty pipe. */
                int r = 0;
-               if (find_filp(rip, W_BIT) != NIL_FILP) {
+               if (find_filp(vp, W_BIT) != NIL_FILP) {
                        /* Writer exists */
                        if (oflags & O_NONBLOCK) {
                                r = EAGAIN;
@@ -123,13 +162,13 @@ int notouch;                      /* check only */
                        }
                        /* If need be, activate sleeping writers. */
                        if (susp_count > 0)
-                               release(rip, WRITE, susp_count);
+                               release(vp, WRITE, susp_count);
                }
                return(r);
        }
   } else {
        /* Process is writing to a pipe. */
-       if (find_filp(rip, R_BIT) == NIL_FILP) {
+       if (find_filp(vp, R_BIT) == NIL_FILP) {
                /* Tell kernel to generate a SIGPIPE signal. */
                if (!notouch) {
                        sys_kill(fp->fp_endpoint, SIGPIPE);
@@ -137,30 +176,31 @@ int notouch;                      /* check only */
                return(EPIPE);
        }
 
-       if (position + bytes > PIPE_SIZE(rip->i_sp->s_block_size)) {
+       if (position + bytes > PIPE_SIZE(vp->v_vmnt->m_block_size)) {
                if ((oflags & O_NONBLOCK)
-                && bytes <= PIPE_SIZE(rip->i_sp->s_block_size))
+                && bytes <= PIPE_SIZE(vp->v_vmnt->m_block_size)) {
                        return(EAGAIN);
+               }
                else if ((oflags & O_NONBLOCK)
-               && bytes > PIPE_SIZE(rip->i_sp->s_block_size)) {
-               if ( (*canwrite = (PIPE_SIZE(rip->i_sp->s_block_size) 
+               && bytes > PIPE_SIZE(vp->v_vmnt->m_block_size)) {
+               if ( (*canwrite = (PIPE_SIZE(vp->v_vmnt->m_block_size) 
                        - position)) > 0)  {
                                /* Do a partial write. Need to wakeup reader */
                                if (!notouch)
-                                       release(rip, READ, susp_count);
+                                       release(vp, READ, susp_count);
                                return(1);
                        } else {
                                return(EAGAIN);
                        }
                     }
-               if (bytes > PIPE_SIZE(rip->i_sp->s_block_size)) {
-                       if ((*canwrite = PIPE_SIZE(rip->i_sp->s_block_size) 
+               if (bytes > PIPE_SIZE(vp->v_vmnt->m_block_size)) {
+                       if ((*canwrite = PIPE_SIZE(vp->v_vmnt->m_block_size) 
                                - position) > 0) {
                                /* Do a partial write. Need to wakeup reader
                                 * since we'll suspend ourself in read_write()
                                 */
                                if (!notouch)
-                                       release(rip, READ, susp_count);
+                                       release(vp, READ, susp_count);
                                return(1);
                        }
                }
@@ -171,7 +211,7 @@ int notouch;                        /* check only */
 
        /* Writing to an empty pipe.  Search for suspended reader. */
        if (position == 0 && !notouch)
-               release(rip, READ, susp_count);
+               release(vp, READ, susp_count);
   }
 
   *canwrite = 0;
@@ -236,8 +276,8 @@ PUBLIC void unsuspend_by_endpt(int proc_e)
 /*===========================================================================*
  *                             release                                      *
  *===========================================================================*/
-PUBLIC void release(ip, call_nr, count)
-register struct inode *ip;     /* inode of pipe */
+PUBLIC void release(vp, call_nr, count)
+register struct vnode *vp;     /* inode of pipe */
 int call_nr;                   /* READ, WRITE, OPEN or CREAT */
 int count;                     /* max number of processes to release */
 {
@@ -260,7 +300,7 @@ int count;                  /* max number of processes to release */
                op = SEL_WR;
          for(f = &filp[0]; f < &filp[NR_FILPS]; f++) {
                if (f->filp_count < 1 || !(f->filp_pipe_select_ops & op) ||
-                  f->filp_ino != ip)
+                  f->filp_vno != vp)
                        continue;
                 select_callback(f, op);
                f->filp_pipe_select_ops &= ~op;
@@ -272,7 +312,7 @@ int count;                  /* max number of processes to release */
        if (rp->fp_pid != PID_FREE && rp->fp_suspended == SUSPENDED &&
                        rp->fp_revived == NOT_REVIVING &&
                        (rp->fp_fd & BYTE) == call_nr &&
-                       rp->fp_filp[rp->fp_fd>>8]->filp_ino == ip) {
+                       rp->fp_filp[rp->fp_fd>>8]->filp_vno == vp) {
                revive(rp->fp_endpoint, 0);
                susp_count--;   /* keep track of who is suspended */
                if (--count == 0) return;
@@ -337,6 +377,7 @@ int returned;                       /* if hanging on task, how many bytes read */
   }
 }
 
+
 /*===========================================================================*
  *                             do_unpause                                   *
  *===========================================================================*/
@@ -398,7 +439,7 @@ int proc_nr_e;
                if (fild < 0 || fild >= OPEN_MAX)
                        panic(__FILE__,"unpause err 2",NO_NUM);
                f = rfp->fp_filp[fild];
-               dev = (dev_t) f->filp_ino->i_zone[0];   /* device hung on */
+               dev = (dev_t) f->filp_vno->v_sdev;      /* device hung on */
                mess.TTY_LINE = (dev >> MINOR) & BYTE;
                mess.IO_ENDPT = rfp->fp_ioproc;
                mess.IO_GRANT = (char *) rfp->fp_grant;
@@ -424,6 +465,7 @@ int proc_nr_e;
   return(OK);
 }
 
+
 /*===========================================================================*
  *                             select_request_pipe                          *
  *===========================================================================*/
@@ -432,14 +474,14 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block)
        int orig_ops, r = 0, err, canwrite;
        orig_ops = *ops;
        if ((*ops & (SEL_RD|SEL_ERR))) {
-               if ((err = pipe_check(f->filp_ino, READING, 0,
+               if ((err = pipe_check(f->filp_vno, READING, 0,
                        1, f->filp_pos, &canwrite, 1)) != SUSPEND)
                        r |= SEL_RD;
                if (err < 0 && err != SUSPEND)
                        r |= SEL_ERR;
        }
        if ((*ops & (SEL_WR|SEL_ERR))) {
-               if ((err = pipe_check(f->filp_ino, WRITING, 0,
+               if ((err = pipe_check(f->filp_vno, WRITING, 0,
                        1, f->filp_pos, &canwrite, 1)) != SUSPEND)
                        r |= SEL_WR;
                if (err < 0 && err != SUSPEND)
@@ -462,8 +504,11 @@ PUBLIC int select_request_pipe(struct filp *f, int *ops, int block)
 PUBLIC int select_match_pipe(struct filp *f)
 {
        /* recognize either pipe or named pipe (FIFO) */
-       if (f && f->filp_ino && (f->filp_ino->i_mode & I_NAMED_PIPE))
+       if (f && f->filp_vno && (f->filp_vno->v_mode & I_NAMED_PIPE))
                return 1;
        return 0;
 }
 
+
+
+
diff --git a/servers/vfs/protect.c b/servers/vfs/protect.c
new file mode 100644 (file)
index 0000000..35173a7
--- /dev/null
@@ -0,0 +1,165 @@
+
+/* This file deals with protection in the file system.  It contains the code
+ * for four system calls that relate to protection.
+ *
+ * The entry points into this file are
+ *   do_chmod: perform the CHMOD and FCHMOD system calls
+ *   do_chown: perform the CHOWN and FCHOWN system calls
+ *   do_umask: perform the UMASK system call
+ *   do_access:        perform the ACCESS system call
+ *
+ * Changes for VFS:
+ *   Jul 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <unistd.h>
+#include <minix/callnr.h>
+#include "file.h"
+#include "fproc.h"
+#include "param.h"
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
+
+
+
+/*===========================================================================*
+ *                             do_chmod                                     *
+ *===========================================================================*/
+PUBLIC int do_chmod()
+{
+  struct filp *flp;
+  struct chmod_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+    
+  if (call_nr == CHMOD) {
+      /* Perform the chmod(name, mode) system call. */
+      if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+
+      /* Fill in lookup request fields */
+      lookup_req.path = user_fullpath;
+      lookup_req.lastc = NULL;
+      lookup_req.flags = EAT_PATH;
+
+      /* Request lookup */
+      if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+      req.inode_nr = res.inode_nr;
+      req.fs_e = res.fs_e;
+  } 
+  else if (call_nr == FCHMOD) {
+      if (!(flp = get_filp(m_in.m3_i1))) return err_code;
+      req.inode_nr = flp->filp_vno->v_inode_nr;
+      req.fs_e = flp->filp_vno->v_fs_e;
+  }
+  else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
+
+  /* Fill in request message fields.*/
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  req.rmode = m_in.mode;
+  
+  /* Issue request */
+  return req_chmod(&req);
+}
+
+/*===========================================================================*
+ *                             do_chown                                     *
+ *===========================================================================*/
+PUBLIC int do_chown()
+{
+  int inode_nr;
+  int fs_e;
+  struct filp *flp;
+  struct chown_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+  
+  if (call_nr == CHOWN) {
+      /* Perform the chmod(name, mode) system call. */
+      if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+      
+      /* Fill in lookup request fields */
+      lookup_req.path = user_fullpath;
+      lookup_req.lastc = NULL;
+      lookup_req.flags = EAT_PATH;
+
+      /* Request lookup */
+      if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+      req.inode_nr = res.inode_nr;
+      req.fs_e = res.fs_e;
+  } 
+  else if (call_nr == FCHOWN) {
+      if (!(flp = get_filp(m_in.m1_i1))) return err_code;
+      req.inode_nr = flp->filp_vno->v_inode_nr;
+      req.fs_e = flp->filp_vno->v_fs_e;
+  }
+  else panic(__FILE__, "do_chmod called with strange call_nr", call_nr);
+
+  /* Fill in request message fields.*/
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  req.newuid = m_in.owner;
+  req.newgid = m_in.group;
+  
+  /* Issue request */
+  return req_chown(&req);
+}
+
+
+/*===========================================================================*
+ *                             do_umask                                     *
+ *===========================================================================*/
+PUBLIC int do_umask()
+{
+/* Perform the umask(co_mode) system call. */
+  register mode_t r;
+
+  r = ~fp->fp_umask;           /* set 'r' to complement of old mask */
+  fp->fp_umask = ~(m_in.co_mode & RWX_MODES);
+  return(r);                   /* return complement of old mask */
+}
+
+
+/*===========================================================================*
+ *                             do_access                                    *
+ *===========================================================================*/
+PUBLIC int do_access()
+{
+/* Perform the access(name, mode) system call. */
+  struct access_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+    
+  /* First check to see if the mode is correct. */
+  if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
+       return(EINVAL);
+
+  if (fetch_name(m_in.name, m_in.name_length, M3) != OK) return(err_code);
+
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH;
+
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  /* Fill in request fields */
+  req.fs_e = res.fs_e;
+  req.amode = m_in.mode;
+  req.inode_nr = res.inode_nr;
+  req.uid = fp->fp_realuid;         /* real user and group id */
+  req.gid = fp->fp_realgid;
+  
+  /* Issue request */
+  return req_access(&req);
+}
+
diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h
new file mode 100644 (file)
index 0000000..9928e97
--- /dev/null
@@ -0,0 +1,224 @@
+/* Function prototypes. */
+
+#include "timers.h"
+#include "request.h"
+
+/* Structs used in prototypes must be declared as such first. */
+struct filp;           
+struct fproc;
+struct vmnt;
+struct vnode;
+
+/* device.c */
+_PROTOTYPE( int dev_open, (Dev_t dev, int proc, int flags)             );
+_PROTOTYPE( void dev_close, (Dev_t dev)                                        );
+_PROTOTYPE( int dev_bio, (int op, Dev_t dev, int proc, void *buf,
+                       off_t pos, int bytes)                           );
+_PROTOTYPE( int dev_io, (int op, Dev_t dev, int proc, void *buf,
+                       off_t pos, int bytes, int flags)                );
+_PROTOTYPE( int gen_opcl, (int op, Dev_t dev, int proc, int flags)     );
+_PROTOTYPE( int gen_io, (int task_nr, message *mess_ptr)               );
+_PROTOTYPE( int no_dev, (int op, Dev_t dev, int proc, int flags)       );
+_PROTOTYPE( int no_dev_io, (int, message *)                            );
+_PROTOTYPE( int tty_opcl, (int op, Dev_t dev, int proc, int flags)     );
+_PROTOTYPE( int ctty_opcl, (int op, Dev_t dev, int proc, int flags)    );
+_PROTOTYPE( int clone_opcl, (int op, Dev_t dev, int proc, int flags)   );
+_PROTOTYPE( int ctty_io, (int task_nr, message *mess_ptr)              );
+_PROTOTYPE( int do_ioctl, (void)                                       );
+_PROTOTYPE( void pm_setsid, (int proc_e)                               );
+_PROTOTYPE( void dev_status, (message *)                               );
+_PROTOTYPE( void dev_up, (int major)                                   );
+
+/* dmap.c */
+_PROTOTYPE( int do_devctl, (void)                                      );
+_PROTOTYPE( int fs_devctl, (int req, int dev, int proc_nr_e, int style,
+       int force)                                                      );
+_PROTOTYPE( void build_dmap, (void)                                    );
+_PROTOTYPE( int map_driver, (int major, int proc_nr, int dev_style,
+       int force)                                                      );
+_PROTOTYPE( int dmap_driver_match, (int proc, int major)               );
+_PROTOTYPE( void dmap_unmap_by_endpt, (int proc_nr)                    );
+_PROTOTYPE( void dmap_endpt_up, (int proc_nr)                          );
+
+/* exec.c */
+_PROTOTYPE( int pm_exec, (int proc_e, char *path, vir_bytes path_len,
+                               char *frame, vir_bytes frame_len)       );
+
+/* filedes.c */
+_PROTOTYPE( struct filp *find_filp, (struct vnode *vp, mode_t bits)    );
+_PROTOTYPE( int get_fd, (int start, mode_t bits, int *k, 
+            struct filp **fpt)                                          );
+_PROTOTYPE( struct filp *get_filp, (int fild)                          );
+_PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild)      );
+_PROTOTYPE( int inval_filp, (struct filp *)                            );
+
+/* link.c */
+_PROTOTYPE( int do_link, (void)                                                );
+_PROTOTYPE( int do_unlink, (void)                                      );
+_PROTOTYPE( int do_rename, (void)                                      );
+_PROTOTYPE( int do_truncate, (void)                                    );
+_PROTOTYPE( int do_ftruncate, (void)                                   );
+
+/* lock.c */
+_PROTOTYPE( int lock_op, (struct filp *f, int req)                     );
+_PROTOTYPE( void lock_revive, (void)                                   );
+
+/* main.c */
+_PROTOTYPE( int main, (void)                                           );
+_PROTOTYPE( void reply, (int whom, int result)                         );
+
+/* misc.c */
+_PROTOTYPE( int do_dup, (void)                                         );
+_PROTOTYPE( void pm_exit, (int proc)                                   );
+_PROTOTYPE( int do_fcntl, (void)                                       );
+_PROTOTYPE( void pm_fork, (int pproc, int cproc, int cpid)             );
+_PROTOTYPE( void pm_setgid, (int proc_e, int egid, int rgid)           );
+_PROTOTYPE( void pm_setuid, (int proc_e, int euid, int ruid)           );
+_PROTOTYPE( int do_sync, (void)                                                );
+_PROTOTYPE( int do_fsync, (void)                                       );
+_PROTOTYPE( void pm_reboot, (void)                                     );
+_PROTOTYPE( int do_svrctl, (void)                                      );
+_PROTOTYPE( int do_getsysinfo, (void)                                  );
+_PROTOTYPE( int pm_dumpcore, (int proc_e, struct mem_map *seg_ptr)     );
+
+/* mount.c */
+_PROTOTYPE( int do_fslogin, (void)                                      );
+_PROTOTYPE( int do_mount, (void)                                       );
+_PROTOTYPE( int do_umount, (void)                                      );
+_PROTOTYPE( int unmount, (Dev_t dev)                                   );
+
+/* open.c */
+_PROTOTYPE( int do_close, (void)                                       );
+_PROTOTYPE( int close_fd, (struct fproc *rfp, int fd_nr)               );
+_PROTOTYPE( int do_creat, (void)                                       );
+_PROTOTYPE( int do_lseek, (void)                                       );
+_PROTOTYPE( int do_mknod, (void)                                       );
+_PROTOTYPE( int do_mkdir, (void)                                       );
+_PROTOTYPE( int do_open, (void)                                                );
+_PROTOTYPE( int do_slink, (void)                                        );
+
+/* path.c */
+_PROTOTYPE( int lookup, (lookup_req_t *request, node_details_t *node)   );
+
+/* pipe.c */
+_PROTOTYPE( int do_pipe, (void)                                                );
+_PROTOTYPE( int do_unpause, (void)                                     );
+_PROTOTYPE( int unpause, (int proc_nr_e)                               );
+_PROTOTYPE( int pipe_check, (struct vnode *vp, int rw_flag,
+      int oflags, int bytes, off_t position, int *canwrite, int notouch));
+_PROTOTYPE( void release, (struct vnode *vp, int call_nr, int count)   );
+_PROTOTYPE( void revive, (int proc_nr, int bytes)                      );
+_PROTOTYPE( void suspend, (int task)                                   );
+_PROTOTYPE( int select_request_pipe, (struct filp *f, int *ops, int bl)        );
+_PROTOTYPE( int select_cancel_pipe, (struct filp *f)                   );
+_PROTOTYPE( int select_match_pipe, (struct filp *f)                    );
+_PROTOTYPE( void unsuspend_by_endpt, (int)                             );
+
+/* protect.c */
+_PROTOTYPE( int do_access, (void)                                      );
+_PROTOTYPE( int do_chmod, (void)                                       );
+_PROTOTYPE( int do_chown, (void)                                       );
+_PROTOTYPE( int do_umask, (void)                                       );
+
+/* read.c */
+_PROTOTYPE( int do_read, (void)                                                );
+_PROTOTYPE( int read_write, (int rw_flag)                              );
+
+/* request.c */
+_PROTOTYPE( int fs_sendrec, (endpoint_t fs_e, message *reqm)            );
+_PROTOTYPE( int req_getnode, (node_req_t *req, node_details_t *res)     );
+_PROTOTYPE( int req_putnode, (node_req_t *req)                          );
+_PROTOTYPE( int req_open, (open_req_t *req, node_details_t *res)        ); 
+_PROTOTYPE( int req_readwrite, (readwrite_req_t *req, 
+            readwrite_res_t *res)                                       );
+_PROTOTYPE( int req_pipe, (pipe_req_t *req, node_details_t *res)        );
+_PROTOTYPE( int req_clone_opcl, (clone_opcl_req_t *req, 
+            node_details_t *res)                                        );
+_PROTOTYPE( int req_ftrunc, (ftrunc_req_t *req)                         );
+_PROTOTYPE( int req_chown, (chown_req_t *req)                           );
+_PROTOTYPE( int req_chmod, (chmod_req_t *req)                           );
+_PROTOTYPE( int req_access, (access_req_t *req)                         );
+_PROTOTYPE( int req_mknod, (mknod_req_t *req)                           );
+_PROTOTYPE( int req_mkdir, (mkdir_req_t *req)                           );
+_PROTOTYPE( int req_inhibread, (node_req_t *req)                        );
+_PROTOTYPE( int req_stat, (stat_req_t *req)                             );
+_PROTOTYPE( int req_fstat, (stat_req_t *req)                            );
+_PROTOTYPE( int req_fstatfs, (stat_req_t *req)                          );
+_PROTOTYPE( int req_unlink, (unlink_req_t *req)                         );
+_PROTOTYPE( int req_rmdir, (unlink_req_t *req)                          );
+_PROTOTYPE( int req_utime, (utime_req_t *req)                           );
+_PROTOTYPE( int req_stime, (endpoint_t fs_e, time_t boottime)           );
+_PROTOTYPE( int req_sync, (endpoint_t fs_e)                             );
+_PROTOTYPE( int req_getdir, (getdir_req_t *req, node_details_t *res)    );
+_PROTOTYPE( int req_link, (link_req_t *req)                             );
+_PROTOTYPE( int req_slink, (slink_req_t *req)                           );
+_PROTOTYPE( int req_rdlink, (rdlink_req_t *req)                         );
+_PROTOTYPE( int req_rename, (rename_req_t *req)                         );
+_PROTOTYPE( int req_mountpoint, (mountpoint_req_t *req, 
+            node_details_t *res)                                        );
+_PROTOTYPE( int req_readsuper, (readsuper_req_t *req, 
+            readsuper_res_t *res)                                       );
+_PROTOTYPE( int req_unmount, (endpoint_t fs_e)                          );
+_PROTOTYPE( int req_trunc, (trunc_req_t *req)                           );
+_PROTOTYPE( int req_lookup, (lookup_req_t *req, lookup_res_t *res)      );
+_PROTOTYPE( int req_newdriver, (endpoint_t fs_e, Dev_t dev, 
+            endpoint_t driver_e)                                        );
+_PROTOTYPE( int req_breadwrite, (breadwrite_req_t *req, 
+            readwrite_res_t *res)                                       );
+
+/* stadir.c */
+_PROTOTYPE( int do_chdir, (void)                                       );
+_PROTOTYPE( int do_fchdir, (void)                                      );
+_PROTOTYPE( int do_chroot, (void)                                      );
+_PROTOTYPE( int do_fstat, (void)                                       );
+_PROTOTYPE( int do_stat, (void)                                                );
+_PROTOTYPE( int do_fstatfs, (void)                                     );
+_PROTOTYPE( int do_rdlink, (void)                                      );
+_PROTOTYPE( int do_lstat, (void)                                       );
+
+/* time.c */
+_PROTOTYPE( int do_stime, (void)                                       );
+_PROTOTYPE( int do_utime, (void)                                       );
+
+/* utility.c */
+_PROTOTYPE( time_t clock_time, (void)                                  );
+_PROTOTYPE( unsigned conv2, (int norm, int w)                          );
+_PROTOTYPE( long conv4, (int norm, long x)                             );
+_PROTOTYPE( int fetch_name, (char *path, int len, int flag)            );
+_PROTOTYPE( int no_sys, (void)                                         );
+_PROTOTYPE( int isokendpt_f, (char *f, int l, int e, int *p, int ft));
+_PROTOTYPE( void panic, (char *who, char *mess, int num)               );
+
+#define okendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 1)
+#define isokendpt(e, p) isokendpt_f(__FILE__, __LINE__, (e), (p), 0)
+
+/* vmnt.c */
+_PROTOTYPE( struct vmnt *get_free_vmnt, (short *index)                  );
+_PROTOTYPE( struct vmnt *find_vmnt, (int fs_e)                          );
+
+/* vnode.c */
+_PROTOTYPE( struct vnode *get_free_vnode, (void)                        );
+_PROTOTYPE( struct vnode *find_vnode, (int fs_e, int numb)              );
+_PROTOTYPE( void dup_vnode, (struct vnode *vp)                          );
+_PROTOTYPE( void put_vnode, (struct vnode *vp)                          );
+_PROTOTYPE( struct vnode *get_vnode, (int fs_e, int inode_nr)           );
+
+/* write.c */
+_PROTOTYPE( int do_write, (void)                                       );
+
+/* select.c */
+_PROTOTYPE( int do_select, (void)                                      );
+_PROTOTYPE( int select_callback, (struct filp *, int ops)              );
+_PROTOTYPE( void select_forget, (int fproc)                            );
+_PROTOTYPE( void select_timeout_check, (timer_t *)                     );
+_PROTOTYPE( void init_select, (void)                                   );
+_PROTOTYPE( void select_unsuspend_by_endpt, (int proc)                 );
+_PROTOTYPE( int select_notified, (int major, int minor, int ops)       );
+
+/* timers.c */
+_PROTOTYPE( void fs_set_timer, (timer_t *tp, int delta, 
+            tmr_func_t watchdog, int arg)                               );
+_PROTOTYPE( void fs_expire_timers, (clock_t now)                       );
+_PROTOTYPE( void fs_cancel_timer, (timer_t *tp)                                );
+_PROTOTYPE( void fs_init_timer, (timer_t *tp)                          );
+
diff --git a/servers/vfs/read.c b/servers/vfs/read.c
new file mode 100644 (file)
index 0000000..84e3618
--- /dev/null
@@ -0,0 +1,292 @@
+/* This file contains the heart of the mechanism used to read (and write)
+ * files.  Read and write requests are split up into chunks that do not cross
+ * block boundaries.  Each chunk is then processed in turn.  Reads on special
+ * files are also detected and handled.
+ *
+ * The entry points into this file are
+ *   do_read:   perform the READ system call by calling read_write
+ *   read_write: actually do the work of READ and WRITE
+ *
+ * Changes for VFS:
+ *   Jul 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <fcntl.h>
+#include <unistd.h>
+#include <minix/com.h>
+#include "file.h"
+#include "fproc.h"
+#include "param.h"
+#include <dirent.h>
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
+
+
+/*===========================================================================*
+ *                             do_read                                      *
+ *===========================================================================*/
+PUBLIC int do_read()
+{
+  return(read_write(READING));
+}
+
+
+/*===========================================================================*
+ *                             read_write                                   *
+ *===========================================================================*/
+PUBLIC int read_write(rw_flag)
+int rw_flag;                   /* READING or WRITING */
+{
+/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
+  register struct filp *f;
+  register struct vnode *vp;
+  off_t bytes_left, f_size, position;
+  unsigned int off, cum_io;
+  int op, oflags, r, chunk, usr, seg, block_spec, char_spec;
+  int regular, partial_pipe = 0, partial_cnt = 0;
+  mode_t mode_word;
+  struct filp *wf;
+  phys_bytes p;
+  struct dmap *dp;
+
+  /* Request and response structures */
+  struct readwrite_req req;
+  struct readwrite_res res;
+
+  /* For block spec files */
+  struct breadwrite_req breq;
+
+  /* PM loads segments by putting funny things in other bits of the
+   * message, indicated by a high bit in fd. */
+  if (who_e == PM_PROC_NR && (m_in.fd & _PM_SEG_FLAG)) {
+      seg = (int) m_in.m1_p2;
+      usr = (int) m_in.m1_p3;
+      m_in.fd &= ~(_PM_SEG_FLAG);      /* get rid of flag bit */
+  } 
+  else {
+      usr = who_e;             /* normal case */
+      seg = D;
+  }
+
+  /* If the file descriptor is valid, get the vnode, size and mode. */
+  if (m_in.nbytes < 0) return(EINVAL);
+  if ((f = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+  if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
+      return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
+  }
+
+  if (m_in.nbytes == 0)
+      return(0);       /* so char special files need not check for 0*/
+
+  /* check if user process has the memory it needs.
+   * if not, copying will fail later.
+   * do this after 0-check above because umap doesn't want to map 0 bytes. */
+  if ((r = sys_umap(usr, seg, (vir_bytes) m_in.buffer, m_in.nbytes, &p)) != OK) {
+      printf("VFS: read_write: umap failed for process %d\n", usr);
+      return r;
+  }
+  position = f->filp_pos;
+  oflags = f->filp_flags;
+
+  vp = f->filp_vno;
+  f_size = vp->v_size;
+
+  r = OK;
+  if (vp->v_pipe == I_PIPE) {
+      /* fp->fp_cum_io_partial is only nonzero when doing partial writes */
+      cum_io = fp->fp_cum_io_partial; 
+  } 
+  else {
+      cum_io = 0;
+  }
+
+  op = (rw_flag == READING ? DEV_READ : DEV_WRITE);
+  mode_word = vp->v_mode & I_TYPE;
+  regular = mode_word == I_REGULAR || mode_word == I_NAMED_PIPE;
+
+  if ((char_spec = (mode_word == I_CHAR_SPECIAL ? 1 : 0))) {
+      if (vp->v_sdev == NO_DEV)
+          panic(__FILE__,"read_write tries to read from "
+                  "character device NO_DEV", NO_NUM);
+  }
+
+  if ((block_spec = (mode_word == I_BLOCK_SPECIAL ? 1 : 0))) {
+      f_size = ULONG_MAX;
+      if (vp->v_sdev == NO_DEV)
+          panic(__FILE__,"read_write tries to read from "
+                  " block device NO_DEV", NO_NUM);
+  }
+
+  /* Character special files. */
+  if (char_spec) {
+      dev_t dev;
+      /*dev = (dev_t) f->filp_ino->i_zone[0];*/
+      dev = (dev_t) vp->v_sdev;
+      r = dev_io(op, dev, usr, m_in.buffer, position, m_in.nbytes, oflags);
+      if (r >= 0) {
+          cum_io = r;
+          position += r;
+          r = OK;
+      }
+  } 
+  /* Block special files. */
+  else if (block_spec) {
+      /* Fill in the fields of the request */
+      breq.rw_flag = rw_flag;
+      breq.fs_e = vp->v_bfs_e;
+      breq.blocksize = vp->v_blocksize;
+      breq.dev = vp->v_sdev;
+      breq.user_e = usr;
+      breq.pos = position;
+      breq.num_of_bytes = m_in.nbytes;
+      breq.user_addr = m_in.buffer;
+
+      /* Issue request */
+      r = req_breadwrite(&breq, &res);
+
+      position = res.new_pos;
+      cum_io += res.cum_io;
+  }
+  /* Regular files */
+  else {
+      if (rw_flag == WRITING && block_spec == 0) {
+          /* Check in advance to see if file will grow too big. */
+          if (position > vp->v_vmnt->m_max_file_size - m_in.nbytes) 
+              return(EFBIG);
+
+          /* Check for O_APPEND flag. */
+          if (oflags & O_APPEND) position = f_size;
+      }
+
+      /* Pipes are a little different. Check. */
+      if (vp->v_pipe == I_PIPE) {
+          r = pipe_check(vp, rw_flag, oflags,
+                  m_in.nbytes, position, &partial_cnt, 0);
+          if (r <= 0) return(r);
+      }
+
+      if (partial_cnt > 0) {
+          /* So taht we don't need to deal with partial count 
+           * in the FS process */
+          m_in.nbytes = MIN(m_in.nbytes, partial_cnt);
+          partial_pipe = 1;
+      }
+
+      /* Fill in request structure */
+      req.fs_e = vp->v_fs_e;
+      req.rw_flag = rw_flag;
+      req.inode_nr = vp->v_inode_nr;
+      req.user_e = usr;
+      req.seg = seg;
+      req.pos = position;
+      req.num_of_bytes = m_in.nbytes;
+      req.user_addr = m_in.buffer;
+      req.inode_index = vp->v_index;
+
+      /* Issue request */
+      r = req_readwrite(&req, &res);
+
+      position = res.new_pos;
+      cum_io += res.cum_io;
+  }
+
+  /* On write, update file size and access time. */
+  if (rw_flag == WRITING) {
+      if (regular || mode_word == I_DIRECTORY) {
+          if (position > f_size) vp->v_size = position;
+      }
+  }
+  else {
+      if (vp->v_pipe == I_PIPE) {
+          if (position >= vp->v_size) {
+              /* Reset pipe pointers */
+              vp->v_size = 0;
+              position = 0;
+              wf = find_filp(vp, W_BIT);
+              if (wf != NIL_FILP) wf->filp_pos = 0;
+          }
+      }
+  }
+
+  f->filp_pos = position;
+
+  if (r == OK) {
+      if (partial_pipe) {
+          partial_pipe = 0;
+          /* partial write on pipe with */
+          /* O_NONBLOCK, return write count */
+          if (!(oflags & O_NONBLOCK)) {
+              fp->fp_cum_io_partial = cum_io;
+              suspend(XPIPE);   /* partial write on pipe with */
+              return(SUSPEND);  /* nbyte > PIPE_SIZE - non-atomic */
+          }
+      }
+      fp->fp_cum_io_partial = 0;
+      return cum_io;
+  }
+
+  return r;
+}
+
+
+/* Original "uncached" code for block spec files */
+#if 0      
+  else if (block_spec) {
+        char buf[_MIN_BLOCK_SIZE];
+        block_t b;
+        int bleft = m_in.nbytes;
+       dev_t dev = vp->v_sdev;
+        
+        b = position / _MIN_BLOCK_SIZE;
+        off = position % _MIN_BLOCK_SIZE;
+       
+        while (bleft) {
+            /* First read the whole block */
+            r = dev_bio(DEV_READ, dev, FS_PROC_NR, buf, b * _MIN_BLOCK_SIZE, 
+                    _MIN_BLOCK_SIZE);
+
+            if (r != _MIN_BLOCK_SIZE)
+                break;
+
+            /* How many bytes to copy? */
+            chunk = MIN(bleft, _MIN_BLOCK_SIZE - off);
+
+            if (rw_flag == READING) {
+                /* Copy a chunk from the buffer to user space. */
+                r = sys_vircopy(FS_PROC_NR, D, (phys_bytes) (&buf[off]),
+                        usr, seg, (phys_bytes) m_in.buffer,
+                        (phys_bytes) chunk);
+            } 
+            else {
+                /* Copy a chunk from user space to the buffer. */
+                r = sys_vircopy(usr, seg, (phys_bytes) m_in.buffer,
+                        FS_PROC_NR, D, (phys_bytes) (&buf[off]),
+                        (phys_bytes) chunk);
+            }
+
+            /* Write back if WRITE */
+            if (rw_flag == WRITING) {
+                r = dev_bio(DEV_WRITE, dev, FS_PROC_NR, buf, 
+                       b * _MIN_BLOCK_SIZE, _MIN_BLOCK_SIZE);
+                
+                if (r != _MIN_BLOCK_SIZE)
+                    break;
+            }
+           
+            bleft -= chunk;
+            m_in.buffer += chunk;
+           
+            /* 0 offset in the next block */
+            b++;
+            off = 0;
+        } 
+        
+        cum_io = m_in.nbytes - bleft;
+        position += cum_io;
+       r = OK;
+  }        
+#endif        
+
diff --git a/servers/vfs/request.c b/servers/vfs/request.c
new file mode 100644 (file)
index 0000000..6849fdb
--- /dev/null
@@ -0,0 +1,954 @@
+
+/* This file contains the wrapper functions for issueing a request
+ * and receiving response from FS processes.
+ * Each function builds a request message according to the request
+ * parameter, calls the most low-level fs_sendrec and copies
+ * back the response.
+ * The low-level fs_sendrec handles the recovery mechanism from
+ * a dead driver and reissues the request.
+ *
+ *  Sep 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <string.h>
+#include <minix/callnr.h>
+#include <minix/com.h>
+#include <minix/keymap.h>
+#include <minix/const.h>
+#include <minix/endpoint.h>
+#include <unistd.h>
+
+#include <minix/vfsif.h>
+#include "fproc.h"
+#include "vmnt.h"
+#include "vnode.h"
+#include "param.h"
+
+
+/*===========================================================================*
+ *                             req_getnode                                  *
+ *===========================================================================*/
+PUBLIC int req_getnode(req, res)
+node_req_t *req; 
+node_details_t *res;
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_GETNODE;
+    m.REQ_INODE_NR = req->inode_nr;
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+
+    /* Fill in response structure */
+    res->fs_e = m.m_source;
+    res->inode_nr = m.RES_INODE_NR;
+    res->fmode = m.RES_MODE;
+    res->fsize = m.RES_FILE_SIZE;
+    res->dev = m.RES_DEV;
+
+    return OK;
+}
+
+
+/*===========================================================================*
+ *                             req_putnode                                  *
+ *===========================================================================*/
+PUBLIC int req_putnode(req)
+node_req_t *req; 
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_PUTNODE;
+    m.REQ_INODE_NR = req->inode_nr;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+/*===========================================================================*
+ *                             req_open                                     *
+ *===========================================================================*/
+int req_open(req, res)
+open_req_t *req; 
+node_details_t *res; 
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_OPEN;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_FLAGS = req->oflags;
+    m.REQ_MODE = req->omode;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_PATH = req->lastc;
+    m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+
+    /* Fill in response structure */
+    res->fs_e = m.m_source;
+    res->inode_nr = m.RES_INODE_NR;
+    res->fmode = m.RES_MODE;
+    res->fsize = m.RES_FILE_SIZE;
+    res->dev = m.RES_DEV;
+    res->inode_index = m.RES_INODE_INDEX;
+    /* For exec */
+    res->uid = m.RES_UID;
+    res->gid = m.RES_GID;
+    res->ctime = m.RES_CTIME;
+
+    return OK;
+}
+
+
+/*===========================================================================*
+ *                             req_readwrite                                *
+ *===========================================================================*/
+int req_readwrite(req, res)
+readwrite_req_t *req; 
+readwrite_res_t *res; 
+{
+    int r;
+    message m;
+    
+    /* Fill in request message */
+    m.m_type = req->rw_flag == READING ? REQ_READ : REQ_WRITE;
+    m.REQ_FD_INODE_NR = req->inode_nr;
+    m.REQ_FD_WHO_E = req->user_e;
+    m.REQ_FD_SEG = req->seg;
+    m.REQ_FD_POS = req->pos;
+    m.REQ_FD_NBYTES = req->num_of_bytes;
+    m.REQ_FD_USER_ADDR = req->user_addr;
+    m.REQ_FD_INODE_INDEX = req->inode_index;
+    
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+
+    /* Fill in response structure */
+    res->new_pos = m.RES_FD_POS;
+    res->cum_io = m.RES_FD_CUM_IO;
+
+    return OK;
+}
+
+
+
+/*===========================================================================*
+ *                             req_pipe                                     *
+ *===========================================================================*/
+PUBLIC int req_pipe(req, res)
+pipe_req_t *req; 
+node_details_t *res;
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_PIPE;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+
+    /* Fill in response structure */
+    res->fs_e = m.m_source;
+    res->inode_nr = m.RES_INODE_NR;
+    res->fmode = m.RES_MODE;
+    res->fsize = m.RES_FILE_SIZE;
+    res->dev = m.RES_DEV;
+    res->inode_index = m.RES_INODE_INDEX;
+    
+    return OK;
+}
+
+
+/*===========================================================================*
+ *                             req_clone_opcl                               *
+ *===========================================================================*/
+PUBLIC int req_clone_opcl(req, res)
+clone_opcl_req_t *req;
+node_details_t *res;
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_CLONE_OPCL;
+    m.REQ_DEV = req->dev;
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+    
+    /* Fill in response structure */
+    res->fs_e = m.m_source;
+    res->inode_nr = m.RES_INODE_NR;
+    res->fmode = m.RES_MODE;
+    res->fsize = m.RES_FILE_SIZE;
+    res->dev = m.RES_DEV;
+    res->inode_index = m.RES_INODE_INDEX;
+    
+    return OK;
+}
+
+
+
+/*===========================================================================*
+ *                             req_ftrunc                                   *
+ *===========================================================================*/
+PUBLIC int req_ftrunc(req)
+ftrunc_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_FTRUNC;
+    m.REQ_FD_INODE_NR = req->inode_nr;
+    m.REQ_FD_START = req->start;
+    m.REQ_FD_END = req->end;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_chmod                                    *
+ *===========================================================================*/
+PUBLIC int req_chmod(req)
+chmod_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_CHMOD;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_MODE = req->rmode;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_chown                                    *
+ *===========================================================================*/
+PUBLIC int req_chown(req)
+chown_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_CHOWN;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_NEW_UID = req->newuid;
+    m.REQ_NEW_GID = req->newgid;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_access                                   *
+ *===========================================================================*/
+PUBLIC int req_access(req)
+access_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_ACCESS;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_MODE = req->amode;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_mknod                                    *
+ *===========================================================================*/
+PUBLIC int req_mknod(req)
+mknod_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_MKNOD;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_MODE = req->rmode;
+    m.REQ_DEV = req->dev;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_PATH = req->lastc;
+    m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_mkdir                                    *
+ *===========================================================================*/
+PUBLIC int req_mkdir(req)
+mkdir_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_MKDIR;
+    m.REQ_INODE_NR = req->d_inode_nr;
+    m.REQ_MODE = req->rmode;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_PATH = req->lastc;
+    m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+
+/*===========================================================================*
+ *                             req_inhibread                                *
+ *===========================================================================*/
+PUBLIC int req_inhibread(req)
+node_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_INHIBREAD;
+    m.REQ_INODE_NR = req->inode_nr;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_stat                                     *
+ *===========================================================================*/
+PUBLIC int req_stat(req)
+stat_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_STAT;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_WHO_E = req->who_e;
+    m.REQ_USER_ADDR = req->buf;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_fstat                                    *
+ *===========================================================================*/
+PUBLIC int req_fstat(req)
+stat_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_FSTAT;
+    m.REQ_FD_INODE_NR = req->inode_nr;
+    m.REQ_FD_WHO_E = req->who_e;
+    m.REQ_FD_USER_ADDR = req->buf;
+    m.REQ_FD_POS = req->pos;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_fstatfs                                  *
+ *===========================================================================*/
+PUBLIC int req_fstatfs(req)
+stat_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_FSTATFS;
+    m.REQ_FD_INODE_NR = req->inode_nr;
+    m.REQ_FD_WHO_E = req->who_e;
+    m.REQ_FD_USER_ADDR = req->buf;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_unlink                                   *
+ *===========================================================================*/
+PUBLIC int req_unlink(req)
+unlink_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_UNLINK;
+    m.REQ_INODE_NR = req->d_inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_PATH = req->lastc;
+    m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_rmdir                                    *
+ *===========================================================================*/
+PUBLIC int req_rmdir(req)
+unlink_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_RMDIR;
+    m.REQ_INODE_NR = req->d_inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_PATH = req->lastc;
+    m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_utime                                    *
+ *===========================================================================*/
+PUBLIC int req_utime(req)
+utime_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_UTIME;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_ACTIME = req->actime;
+    m.REQ_MODTIME = req->modtime;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_stime                                    *
+ *===========================================================================*/
+PUBLIC int req_stime(fs_e, boottime)
+endpoint_t fs_e; 
+time_t boottime;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_STIME;
+    m.REQ_BOOTTIME = boottime;
+    
+    /* Send/rec request */
+    return fs_sendrec(fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_sync                                     *
+ *===========================================================================*/
+PUBLIC int req_sync(fs_e)
+endpoint_t fs_e; 
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_SYNC;
+    
+    /* Send/rec request */
+    return fs_sendrec(fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_getdir                                   *
+ *===========================================================================*/
+PUBLIC int req_getdir(req, res)
+getdir_req_t *req; 
+node_details_t *res;
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_GETDIR;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+
+    /* Fill in response structure */
+    res->fs_e = m.m_source;
+    res->inode_nr = m.RES_INODE_NR;
+    res->fmode = m.RES_MODE;
+    res->fsize = m.RES_FILE_SIZE;
+
+    return OK;
+}
+
+
+/*===========================================================================*
+ *                             req_link                                     *
+ *===========================================================================*/
+PUBLIC int req_link(req)
+link_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_LINK;
+    m.REQ_LINKED_FILE = req->linked_file;
+    m.REQ_LINK_PARENT = req->link_parent;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_PATH = req->lastc;
+    m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+    
+
+/*===========================================================================*
+ *                             req_slink                                    *
+ *===========================================================================*/
+PUBLIC int req_slink(req)
+slink_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_SLINK;
+    m.REQ_INODE_NR = req->parent_dir;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_PATH = req->lastc;
+    m.REQ_PATH_LEN = strlen(req->lastc) + 1;
+    m.REQ_WHO_E = req->who_e;
+    m.REQ_USER_ADDR = req->path_addr;
+    m.REQ_SLENGTH = req->path_length;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_rdlink                                   *
+ *===========================================================================*/
+PUBLIC int req_rdlink(req)
+rdlink_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_RDLINK;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_WHO_E = req->who_e;
+    m.REQ_USER_ADDR = req->path_buffer;
+    m.REQ_SLENGTH = req->max_length;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_rename                                   *
+ *===========================================================================*/
+PUBLIC int req_rename(req)
+rename_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_RENAME;
+    m.REQ_OLD_DIR = req->old_dir;
+    m.REQ_NEW_DIR = req->new_dir;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_PATH = req->old_name;
+    m.REQ_PATH_LEN = strlen(req->old_name) + 1;
+    m.REQ_USER_ADDR = req->new_name;
+    m.REQ_SLENGTH = strlen(req->new_name) + 1;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_mountpoint                               *
+ *===========================================================================*/
+PUBLIC int req_mountpoint(req, res)
+mountpoint_req_t *req; 
+node_details_t *res;
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_MOUNTPOINT;
+    m.REQ_INODE_NR = req->inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+
+    /* Fill in response structure */
+    res->fs_e = m.m_source;
+    res->inode_nr = m.RES_INODE_NR;
+    res->fmode = m.RES_MODE;
+    res->fsize = m.RES_FILE_SIZE;
+
+    return OK;
+}
+
+
+/*===========================================================================*
+ *                             req_readsuper                                *
+ *===========================================================================*/
+PUBLIC int req_readsuper(req, res)
+readsuper_req_t *req; 
+readsuper_res_t *res;
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_READSUPER;
+    m.REQ_READONLY = req->readonly;
+    m.REQ_BOOTTIME = req->boottime;
+    m.REQ_DRIVER_E = req->driver_e;
+    m.REQ_DEV = req->dev;
+    m.REQ_SLINK_STORAGE = req->slink_storage;
+    m.REQ_ISROOT = req->isroot;
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+
+    /* Fill in response structure */
+    res->fs_e = m.m_source;
+    res->inode_nr = m.RES_INODE_NR;
+    res->fmode = m.RES_MODE;
+    res->fsize = m.RES_FILE_SIZE;
+    res->blocksize = m.RES_BLOCKSIZE;
+    res->maxsize = m.RES_MAXSIZE;
+
+    return OK;
+}
+
+
+/*===========================================================================*
+ *                             req_unmount                                  *
+ *===========================================================================*/
+PUBLIC int req_unmount(fs_e)
+endpoint_t fs_e; 
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_UNMOUNT;
+    
+    /* Send/rec request */
+    return fs_sendrec(fs_e, &m);
+}
+
+
+/*===========================================================================*
+ *                             req_trunc                                    *
+ *===========================================================================*/
+PUBLIC int req_trunc(req)
+trunc_req_t *req;
+{
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_TRUNC;
+    m.REQ_FD_INODE_NR = req->inode_nr;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_LENGTH = req->length;
+
+    /* Send/rec request */
+    return fs_sendrec(req->fs_e, &m);
+}
+
+
+
+/*===========================================================================*
+ *                             req_newdriver                                *
+ *===========================================================================*/
+PUBLIC int req_newdriver(fs_e, dev, driver_e)
+endpoint_t fs_e;
+Dev_t dev;
+endpoint_t driver_e;
+{
+/* Note: this is the only request function that doesn't use the 
+ * fs_sendrec internal routine, since we want to avoid the dead
+ * driver recovery mechanism here. This function is actually called 
+ * during the recovery.
+ */
+    message m;
+    int r;
+
+    /* Fill in request message */
+    m.m_type = REQ_NEW_DRIVER;
+    m.REQ_DEV = dev;
+    m.REQ_DRIVER_E = driver_e;
+
+    /* Issue request */
+    if ((r = sendrec(fs_e, &m)) != OK) {
+        printf("VFSreq_newdriver: error sending message to %d\n", fs_e);
+        return r;
+    }
+
+    return OK;
+}
+
+
+/*===========================================================================*
+ *                             req_lookup                                   *
+ *===========================================================================*/
+PUBLIC int req_lookup(req, res)
+lookup_req_t *req; 
+lookup_res_t *res;
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+    m.m_type = REQ_LOOKUP;
+    m.REQ_PATH = req->path;
+    m.REQ_PATH_LEN = strlen(req->path) + 1;
+    m.REQ_USER_ADDR = req->lastc;
+    m.REQ_FLAGS = req->flags;
+    
+    m.REQ_INODE_NR = req->start_dir;
+    m.REQ_CHROOT_NR = req->root_dir;
+    m.REQ_UID = req->uid;
+    m.REQ_GID = req->gid;
+    m.REQ_SYMLOOP = req->symloop;
+
+    /* Send/rec request */
+    r = fs_sendrec(req->fs_e, &m);
+
+    /* Fill in response according to the return value */
+    res->fs_e = m.m_source;
+    switch (r) {
+        case OK:
+            res->inode_nr = m.RES_INODE_NR;
+            res->fmode = m.RES_MODE;
+            res->fsize = m.RES_FILE_SIZE;
+            res->dev = m.RES_DEV;
+            break;
+        case EENTERMOUNT:
+            res->inode_nr = m.RES_INODE_NR;
+        case ELEAVEMOUNT:
+        case ESYMLINK:
+            res->char_processed = m.RES_OFFSET;
+            res->symloop = m.RES_SYMLOOP;
+            break;
+    }
+
+    return r;
+}
+
+
+/*===========================================================================*
+ *                     req_breadwrite                                       *
+ *===========================================================================*/
+int req_breadwrite(req, res)
+breadwrite_req_t *req; 
+readwrite_res_t *res; 
+{
+    int r;
+    message m;
+    
+    /* Fill in request message */
+    m.m_type = req->rw_flag == READING ? REQ_BREAD : REQ_BWRITE;
+    m.REQ_FD_BDEV = req->dev;
+    m.REQ_FD_BLOCK_SIZE = req->blocksize;
+    m.REQ_FD_WHO_E = req->user_e;
+    m.REQ_FD_POS = req->pos;
+    m.REQ_FD_NBYTES = req->num_of_bytes;
+    m.REQ_FD_USER_ADDR = req->user_addr;
+    
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+
+    /* Fill in response structure */
+    res->new_pos = m.RES_FD_POS;
+    res->cum_io = m.RES_FD_CUM_IO;
+
+    return OK;
+}
+
+
+
+
+#if 0           
+/*                 Wrapper pattern:                                          */
+/*===========================================================================*
+ *                             req_                                 *
+ *===========================================================================*/
+PUBLIC int req_(req, res)
+_req_t *req;
+_t *res;
+{
+    int r;
+    message m;
+
+    /* Fill in request message */
+
+
+    /* Send/rec request */
+    if ((r = fs_sendrec(req->fs_e, &m)) != OK) return r;
+    
+    /* Fill in response structure */
+
+
+    return OK;
+}
+#endif 
+
+
+
+
+/*===========================================================================*
+ *                             fs_sendrec                                   *
+ *===========================================================================*/
+PUBLIC int fs_sendrec(endpoint_t fs_e, message *reqm)
+{
+/* This is the low level function that sends requests to FS processes.
+ * It also handles driver recovery mechanism and reissuing the
+ * request which failed due to a dead driver.
+ */
+  int r, old_driver_e, new_driver_e;
+  message origm, m;
+  struct vmnt *vmp;
+  
+  /* Make a copy of the request so that we can load it back in
+   * case of a dead driver */
+  origm = *reqm;
+  
+  for (;;) {
+      /* Do the actual send, receive */
+      if (OK != sendrec(fs_e, reqm)) {
+          printf("VFS: error sending message. FS_e: %d req_nr: %d\n", 
+                  fs_e, reqm->m_type);
+      }
+
+      /* Get response type */
+      r = reqm->m_type;
+
+      /* Dead driver */
+      if (r == EDEADSRCDST || r == EDSTDIED || r == ESRCDIED) {
+          old_driver_e = 0;
+          /* Find old driver enpoint */
+          for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
+              if (vmp->m_fs_e == reqm->m_source) {   /* found FS */
+                  old_driver_e = vmp->m_driver_e;
+                  dmap_unmap_by_endpt(old_driver_e); /* unmap driver */
+                  break;
+              }
+          }
+         
+          /* No FS ?? */
+          if (!old_driver_e) {
+              panic(__FILE__, "VFSdead_driver: couldn't find FS\n", 
+                             old_driver_e);
+          }
+
+          /* Wait for a new driver. */
+          for (;;) {
+              new_driver_e = 0;
+              printf("VFSdead_driver: waiting for new driver\n");
+              r = receive(RS_PROC_NR, &m);
+              if (r != OK) {
+                  panic(__FILE__, "VFSdead_driver: unable to receive from RS", 
+                                 r);
+              }
+              if (m.m_type == DEVCTL) {
+                  /* Map new driver */
+                  r = fs_devctl(m.ctl_req, m.dev_nr, m.driver_nr,
+                          m.dev_style, m.m_force);
+                  if (m.ctl_req == DEV_MAP && r == OK) {
+                      new_driver_e = m.driver_nr;
+                      printf("VFSdead_driver: new driver endpoint: %d\n",
+                              new_driver_e);
+                  }
+              }
+              else {
+                  panic(__FILE__, "VFSdead_driver: got message from RS, type", 
+                          m.m_type);
+              }
+              m.m_type = r;
+              if ((r = send(RS_PROC_NR, &m)) != OK) {
+                  panic(__FILE__, "VFSdead_driver: unable to send to RS",
+                          r);
+              }
+              /* New driver is ready */
+              if (new_driver_e) break;
+          }
+          
+          /* Copy back original request */
+          *reqm = origm;  
+          continue;
+      }
+      
+      /* Sendrec was okay */
+      break;
+  }
+  /* Return message type */
+  return r;
+}
+
+
+
diff --git a/servers/vfs/request.h b/servers/vfs/request.h
new file mode 100644 (file)
index 0000000..16795f3
--- /dev/null
@@ -0,0 +1,321 @@
+
+/* Low level request messages are built and sent by wrapper functions.
+ * This file contains the request and response structures for accessing
+ * those wrappers functions.
+ */
+
+#include <sys/types.h>
+
+
+/* Structure for REQ_GETNODE and REQ_PUTNODE requests */
+typedef struct node_req {
+       endpoint_t fs_e;
+       ino_t inode_nr;
+} node_req_t;
+
+
+/* Structure for response that contains inode details */
+typedef struct node_details {
+       endpoint_t fs_e;
+       ino_t inode_nr;
+       mode_t fmode;
+       off_t fsize;
+       unsigned short inode_index;
+       /* For char/block special files */
+       dev_t dev;
+       
+       /* Fields used by the exec() syscall */
+       uid_t uid;
+       gid_t gid;
+       time_t ctime;
+} node_details_t;
+
+
+/* Structure for REQ_OPEN request */
+typedef struct open_req {
+        endpoint_t fs_e;
+        ino_t inode_nr;
+       char *lastc;
+       int oflags;
+       mode_t omode;   
+       uid_t uid;
+       gid_t gid;
+} open_req_t;
+
+
+/* Structure for REQ_READ and REQ_WRITE request */
+typedef struct readwrite_req {
+       int rw_flag;
+       endpoint_t fs_e;
+        endpoint_t user_e;
+       ino_t inode_nr;
+       unsigned short inode_index;
+       int seg;
+       off_t pos;
+       unsigned int num_of_bytes;
+       char *user_addr;
+} readwrite_req_t;
+
+
+/* Structure for response of REQ_READ and REQ_WRITE */
+typedef struct readwrite_res {
+       off_t new_pos;
+       unsigned int cum_io;
+} readwrite_res_t;
+
+
+/* Structure for REQ_PIPE request */
+typedef struct pipe_req {
+        int fs_e;
+        uid_t uid;
+        gid_t gid;
+} pipe_req_t;
+
+
+/* Structure for REQ_CLONE_OPCL request */
+typedef struct clone_opcl_req {
+        int fs_e;
+        dev_t dev;
+} clone_opcl_req_t;
+
+
+/* Structure for REQ_FTRUNC request */
+typedef struct ftrunc_req {
+        int fs_e;
+        ino_t inode_nr;
+        off_t start;
+        off_t end;
+} ftrunc_req_t;
+
+
+/* Structure for REQ_CHOWN request */
+typedef struct chown_req {
+        int fs_e;
+        ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+        uid_t newuid;
+        gid_t newgid;
+} chown_req_t;
+
+
+/* Structure for REQ_CHMOD request */
+typedef struct chmod_req {
+        int fs_e;
+        ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+        mode_t rmode;
+} chmod_req_t;
+
+
+/* Structure for REQ_ACCESS request */
+typedef struct access_req {
+        int fs_e;
+        ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+        mode_t amode;
+} access_req_t;
+
+
+/* Structure for REQ_MKNOD request */
+typedef struct mknod_req {
+        int fs_e;
+        ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+        mode_t rmode;
+        dev_t dev;
+        char *lastc;
+} mknod_req_t;
+
+
+/* Structure for REQ_MKDIR request */
+typedef struct mkdir_req {
+        int fs_e;
+        ino_t d_inode_nr;
+        uid_t uid;
+        gid_t gid;
+        mode_t rmode;
+        char *lastc;
+} mkdir_req_t;
+
+
+/* Structure for REQ_STAT, REQ_FSTAT, REQ_FSTATFS requests */
+typedef struct stat_req {
+        int fs_e;
+        ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+        int who_e;
+        char *buf;
+        int pos;
+} stat_req_t;
+
+/* Structure for REQ_UNLINK request */
+typedef struct unlink_req {
+        int fs_e;
+        ino_t d_inode_nr;
+        uid_t uid;
+        gid_t gid;
+        char *lastc;
+} unlink_req_t;
+
+
+/* Structure for REQ_UTIME request */
+typedef struct utime_req {
+        int fs_e;
+        ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+        time_t actime;
+        time_t modtime;
+} utime_req_t;
+
+
+/* Structure for REQ_GETDIR request */
+typedef struct getdir_req {
+       endpoint_t fs_e;
+       ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+} getdir_req_t;
+
+
+/* Structure for REQ_LINK request */
+typedef struct link_req {
+       endpoint_t fs_e;
+        ino_t linked_file;
+        ino_t link_parent;
+        uid_t uid;
+        gid_t gid;
+        char *lastc;
+} link_req_t;
+
+
+/* Structure for REQ_SLINK request */
+typedef struct slink_req {
+       endpoint_t fs_e;
+        ino_t parent_dir;
+        uid_t uid;
+        gid_t gid;
+        char *lastc;
+        endpoint_t who_e;
+        char *path_addr;
+        unsigned short path_length;
+} slink_req_t;
+
+
+/* Structure for REQ_RDLINK request */
+typedef struct rdlink_req {
+       endpoint_t fs_e;
+        ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+        endpoint_t who_e;
+        char *path_buffer;
+        unsigned short max_length;
+} rdlink_req_t;
+
+
+/* Structure for REQ_RENAME request */
+typedef struct rename_req {
+       endpoint_t fs_e;
+        ino_t old_dir;
+        ino_t new_dir;
+        uid_t uid;
+        gid_t gid;
+        char *old_name;
+        char *new_name;
+} rename_req_t;
+
+
+/* Structure for REQ_MOUNTPOINT request */
+typedef struct mountpoint_req {
+       endpoint_t fs_e;
+        ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+} mountpoint_req_t;
+
+
+/* Structure for REQ_READSUPER request */
+typedef struct readsuper_req {
+       endpoint_t fs_e;
+        time_t boottime;
+        endpoint_t driver_e;
+        dev_t dev;
+        char *slink_storage;
+        char isroot;
+        char readonly;
+} readsuper_req_t;
+
+/* Structure for response of READSUPER request */
+typedef struct readsuper_res {
+       endpoint_t fs_e;
+       ino_t inode_nr;
+       mode_t fmode;
+       off_t fsize;
+        int blocksize;
+        off_t maxsize;
+} readsuper_res_t;
+
+        
+/* Structure for REQ_TRUNC request */
+typedef struct trunc_req {
+       endpoint_t fs_e;
+       ino_t inode_nr;
+        uid_t uid;
+        gid_t gid;
+        off_t length;
+} trunc_req_t;
+
+
+/* Structure for REQ_LOOKUP request */
+typedef struct lookup_req {
+        /* Fields filled in by the caller */
+        char *path;
+        char *lastc;
+        int flags;
+       /* Fields filled in by the path name traversal method */
+        endpoint_t fs_e;
+        ino_t start_dir;
+        ino_t root_dir;     /* process' root directory */
+        uid_t uid;
+        gid_t gid;
+        unsigned char symloop;
+} lookup_req_t;
+
+
+/* Structure for a lookup response */
+typedef struct lookup_res {
+       endpoint_t fs_e;
+       ino_t inode_nr;
+       mode_t fmode;
+       off_t fsize;
+       /* For char/block special files */
+       dev_t dev;
+       
+       /* Fields used for handling mount point and symbolic links */
+       int char_processed;
+       unsigned char symloop;
+} lookup_res_t;
+
+
+/* Structure for REQ_BREAD and REQ_BWRITE request (block spec files) */
+typedef struct breadwrite_req {
+       int rw_flag;
+        short blocksize;
+       endpoint_t fs_e;
+        endpoint_t user_e;
+        endpoint_t driver_e;
+        dev_t dev;
+       off_t pos;
+       unsigned int num_of_bytes;
+       char *user_addr;
+} breadwrite_req_t;
+
+
+
+/* Structure for REQ_ request */
similarity index 92%
rename from servers/fs/select.c
rename to servers/vfs/select.c
index 066e17e9be8cedd757931838439dcbc736ae7196..44dd00a67988642c5fdd7591bae5a19ece728a83 100644 (file)
@@ -15,7 +15,7 @@
 #include "fs.h"
 #include "select.h"
 #include "file.h"
-#include "inode.h"
+#include "vnode.h"
 
 #include <sys/time.h>
 #include <sys/select.h>
@@ -38,7 +38,6 @@ PRIVATE struct selectentry {
        timer_t timer;  /* if expiry > 0 */
 } selecttab[MAXSELECTS];
 
-
 FORWARD _PROTOTYPE(int select_reevaluate, (struct filp *fp));
 
 FORWARD _PROTOTYPE(int select_request_file,
@@ -92,7 +91,7 @@ PRIVATE int select_request_file(struct filp *f, int *ops, int block)
  *===========================================================================*/
 PRIVATE int select_match_file(struct filp *file)
 {
-       if (file && file->filp_ino && (file->filp_ino->i_mode & I_REGULAR))
+       if (file && file->filp_vno && (file->filp_vno->v_mode & I_REGULAR))
                return 1;
        return 0;
 }
@@ -104,7 +103,7 @@ PRIVATE int select_request_general(struct filp *f, int *ops, int block)
 {
        int rops = *ops;
        if (block) rops |= SEL_NOTIFY;
-       *ops = dev_io(DEV_SELECT, f->filp_ino->i_zone[0], rops, NULL, 0, 0, 0);
+       *ops = dev_io(DEV_SELECT, f->filp_vno->v_sdev, rops, NULL, 0, 0, 0);
        if (*ops < 0)
                return SEL_ERR;
        return SEL_OK;
@@ -116,10 +115,10 @@ PRIVATE int select_request_general(struct filp *f, int *ops, int block)
 PRIVATE int select_major_match(int match_major, struct filp *file)
 {
        int major;
-       if (!(file && file->filp_ino &&
-               (file->filp_ino->i_mode & I_TYPE) == I_CHAR_SPECIAL))
+       if (!(file && file->filp_vno &&
+               (file->filp_vno->v_mode & I_TYPE) == I_CHAR_SPECIAL))
                return 0;
-       major = (file->filp_ino->i_zone[0] >> MAJOR) & BYTE;
+       major = (file->filp_vno->v_sdev >> MAJOR) & BYTE;
        if (major == match_major)
                return 1;
        return 0;
@@ -164,22 +163,23 @@ PRIVATE void ops2tab(int ops, int fd, struct selectentry *e)
  *===========================================================================*/
 PRIVATE void copy_fdsets(struct selectentry *e)
 {
-       int fd_setsize;
-       if(e->nfds < 0 || e->nfds > OPEN_MAX)
-               panic(__FILE__, "select copy_fdsets: e->nfds wrong", e->nfds);
-
-       /* Only copy back as many bits as the user expects. */
-       fd_setsize = _FDSETWORDS(e->nfds)*_FDSETBITSPERWORD/8;
-
-       if (e->vir_readfds)
-               sys_vircopy(SELF, D, (vir_bytes) &e->ready_readfds,
-               e->req_endpt, D, (vir_bytes) e->vir_readfds, fd_setsize);
-       if (e->vir_writefds)
-               sys_vircopy(SELF, D, (vir_bytes) &e->ready_writefds,
-               e->req_endpt, D, (vir_bytes) e->vir_writefds, fd_setsize);
-       if (e->vir_errorfds)
-               sys_vircopy(SELF, D, (vir_bytes) &e->ready_errorfds,
-               e->req_endpt, D, (vir_bytes) e->vir_errorfds, fd_setsize);
+       int fd_setsize;
+       if(e->nfds < 0 || e->nfds > OPEN_MAX)
+               panic(__FILE__, "select copy_fdsets: e->nfds wrong", e->nfds);
+
+       /* Only copy back as many bits as the user expects. */
+       fd_setsize = _FDSETWORDS(e->nfds)*_FDSETBITSPERWORD/8;
+
+        if (e->vir_readfds)
+               sys_vircopy(SELF, D, (vir_bytes) &e->ready_readfds,
+               e->req_endpt, D, (vir_bytes) e->vir_readfds, fd_setsize);
+        if (e->vir_writefds)
+               sys_vircopy(SELF, D, (vir_bytes) &e->ready_writefds,
+               e->req_endpt, D, (vir_bytes) e->vir_writefds, fd_setsize);
+        if (e->vir_errorfds)
+               sys_vircopy(SELF, D, (vir_bytes) &e->ready_errorfds,
+               e->req_endpt, D, (vir_bytes) e->vir_errorfds, fd_setsize);
+
 
        return;
 }
@@ -221,11 +221,12 @@ PUBLIC int do_select(void)
        selecttab[s].vir_writefds = (fd_set *) m_in.SEL_WRITEFDS;
        selecttab[s].vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS;
 
-       /* Copy args. Our storage size is zeroed above. Only copy
-        * as many bits as user has supplied (nfds).
-        * Could be compiled with a different OPEN_MAX or FD_SETSIZE.
-        * If nfds is too large, we have already returned above.
-        */
+
+       /* Copy args. Our storage size is zeroed above. Only copy
+        * as many bits as user has supplied (nfds).
+        * Could be compiled with a different OPEN_MAX or FD_SETSIZE.
+        * If nfds is too large, we have already returned above.
+        */
 
        fd_setsize = _FDSETWORDS(nfds)*_FDSETBITSPERWORD/8;
        if (selecttab[s].vir_readfds
@@ -589,7 +590,7 @@ PUBLIC int select_notified(int major, int minor, int selected_ops)
                                continue;
                        ops = tab2ops(f, &selecttab[s]);
                        s_minor =
-                       (selecttab[s].filps[f]->filp_ino->i_zone[0] >> MINOR)
+                       (selecttab[s].filps[f]->filp_vno->v_sdev >> MINOR)
                                & BYTE;
                        if ((s_minor == minor) &&
                                (selected_ops & ops)) {
@@ -691,9 +692,9 @@ PUBLIC void select_unsuspend_by_endpt(int proc_e)
                  continue;
          for(fd = 0; fd < selecttab[s].nfds; fd++) {
            int maj;
-           if (!selecttab[s].filps[fd] || !selecttab[s].filps[fd]->filp_ino)
+           if (!selecttab[s].filps[fd] || !selecttab[s].filps[fd]->filp_vno)
                continue;
-           maj = (selecttab[s].filps[fd]->filp_ino->i_zone[0] >> MAJOR)&BYTE;
+           maj = (selecttab[s].filps[fd]->filp_vno->v_sdev >> MAJOR)&BYTE;
            if(dmap_driver_match(proc_e, maj)) {
                        select_return(&selecttab[s], EAGAIN);
            }
diff --git a/servers/vfs/select.h b/servers/vfs/select.h
new file mode 100644 (file)
index 0000000..5e2cc8e
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef _FS_SELECT_H
+#define _FS_SELECT_H 1
+
+/* return codes for select_request_* and select_cancel_* */
+#define SEL_OK         0       /* ready */
+#define SEL_ERROR      1       /* failed */
+
+#endif
+
diff --git a/servers/vfs/stadir.c b/servers/vfs/stadir.c
new file mode 100644 (file)
index 0000000..91d2ee4
--- /dev/null
@@ -0,0 +1,334 @@
+/* This file contains the code for performing four system calls relating to
+ * status and directories.
+ *
+ * The entry points into this file are
+ *   do_chdir: perform the CHDIR system call
+ *   do_chroot:        perform the CHROOT system call
+ *   do_stat:  perform the STAT system call
+ *   do_fstat: perform the FSTAT system call
+ *   do_fstatfs: perform the FSTATFS system call
+ *   do_lstat:  perform the LSTAT system call
+ *
+ * Changes for VFS:
+ *   Jul 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include <sys/stat.h>
+#include <sys/statfs.h>
+#include <minix/com.h>
+#include <string.h>
+#include "file.h"
+#include "fproc.h"
+#include "param.h"
+
+#include <minix/vfsif.h>
+#include "vnode.h"
+#include "vmnt.h"
+
+FORWARD _PROTOTYPE( int change, (struct vnode **iip, char *name_ptr, int len));
+FORWARD _PROTOTYPE( int change_into, (struct vnode **iip, struct vnode *vp));
+
+/*===========================================================================*
+ *                             do_fchdir                                    *
+ *===========================================================================*/
+PUBLIC int do_fchdir()
+{
+  /* Change directory on already-opened fd. */
+  struct filp *rfilp;
+  struct getdir_req req;
+  struct node_details res;
+  int r;
+
+  /* Is the file descriptor valid? */
+  if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+
+  /* Is it a dir? */
+  if ((rfilp->filp_vno->v_mode & I_TYPE) != I_DIRECTORY)
+      return ENOTDIR;
+  
+  /* Fill in request message fields.*/
+  req.fs_e = rfilp->filp_vno->v_fs_e;
+  req.inode_nr = rfilp->filp_vno->v_inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  
+  /* Issue request and handle error */
+  if ((r = req_getdir(&req, &res)) != OK) return r;
+  
+  /* GETDIR increased the counter in the FS proc */
+  rfilp->filp_vno->v_count++;
+  
+  return change_into(&fp->fp_wd, rfilp->filp_vno);
+}
+
+/*===========================================================================*
+ *                             do_chdir                                     *
+ *===========================================================================*/
+PUBLIC int do_chdir()
+{
+/* Change directory.  This function is  also called by MM to simulate a chdir
+ * in order to do EXEC, etc.  It also changes the root directory, the uids and
+ * gids, and the umask. 
+ */
+  int r;
+  register struct fproc *rfp;
+
+  if (who_e == PM_PROC_NR) {
+       int slot;
+       if(isokendpt(m_in.endpt1, &slot) != OK)
+               return EINVAL;
+       rfp = &fproc[slot];
+        
+        put_vnode(fp->fp_rd);
+        dup_vnode(fp->fp_rd = rfp->fp_rd);
+        put_vnode(fp->fp_wd);
+        dup_vnode(fp->fp_wd = rfp->fp_wd);
+        
+       /* MM uses access() to check permissions.  To make this work, pretend
+        * that the user's real ids are the same as the user's effective ids.
+        * FS calls other than access() do not use the real ids, so are not
+        * affected.
+        */
+       fp->fp_realuid =
+       fp->fp_effuid = rfp->fp_effuid;
+       fp->fp_realgid =
+       fp->fp_effgid = rfp->fp_effgid;
+       fp->fp_umask = rfp->fp_umask;
+       return(OK);
+  }
+
+  /* Perform the chdir(name) system call. */
+  r = change(&fp->fp_wd, m_in.name, m_in.name_length);
+  return(r);
+}
+
+/*===========================================================================*
+ *                             do_chroot                                    *
+ *===========================================================================*/
+PUBLIC int do_chroot()
+{
+/* Perform the chroot(name) system call. */
+
+  register int r;
+
+  if (!super_user) return(EPERM);      /* only su may chroot() */
+  
+  r = change(&fp->fp_rd, m_in.name, m_in.name_length);
+  return(r);
+}
+
+
+/*===========================================================================*
+ *                             change                                       *
+ *===========================================================================*/
+PRIVATE int change(iip, name_ptr, len)
+struct vnode **iip;            /* pointer to the inode pointer for the dir */
+char *name_ptr;                        /* pointer to the directory name to change to */
+int len;                       /* length of the directory name string */
+{
+/* Do the actual work for chdir() and chroot(). */
+  struct vnode *vp, *vp2;
+  struct vmnt *vmp;
+  struct getdir_req req;
+  struct node_details res;
+  struct lookup_req lookup_req;
+  int r;
+
+  if (fetch_name(name_ptr, len, M3) != OK) return(err_code);
+  
+  /* See if free vnode is available */
+  if ((vp = get_free_vnode()) == NIL_VNODE) {
+      printf("VFSchange: no free vnode available\n");
+      return EINVAL;
+  }
+
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  /* Is it a dir? */
+  if ((res.fmode & I_TYPE) != I_DIRECTORY)
+      return ENOTDIR;
+  
+  /* Fill in request message fields.*/
+  req.fs_e = res.fs_e;
+  req.inode_nr = res.inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  /* Issue request */
+  if ((r = req_getdir(&req, &res)) != OK) return r;
+  
+  /* Check whether vnode is already in use or not */
+  if ((vp2 = find_vnode(res.fs_e, res.inode_nr)) 
+          != NIL_VNODE) {
+        vp2->v_count++;
+        vp = vp2;
+  }
+  else {
+        /* Fill in the free vnode's fields */
+        vp->v_fs_e = res.fs_e;
+        vp->v_inode_nr = res.inode_nr;
+        vp->v_mode = res.fmode;
+        vp->v_size = res.fsize;
+
+          if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
+              printf("VFSchange: vmnt not found");
+
+        vp->v_vmnt = vmp; 
+        vp->v_dev = vmp->m_dev;
+        vp->v_count = 1;
+  }
+
+  return change_into(iip, vp);
+}
+
+
+/*===========================================================================*
+ *                             change_into                                  *
+ *===========================================================================*/
+PRIVATE int change_into(iip, vp)
+struct vnode **iip;            /* pointer to the inode pointer for the dir */
+struct vnode *vp;              /* this is what the inode has to become */
+{
+  /* Everything is OK.  Make the change. */
+  put_vnode(*iip);             /* release the old directory */
+  *iip = vp;                   /* acquire the new one */
+
+  return(OK);
+}
+
+
+/*===========================================================================*
+ *                             do_stat                                      *
+ *===========================================================================*/
+PUBLIC int do_stat()
+{
+/* Perform the stat(name, buf) system call. */
+  struct stat_req req;
+  struct node_details res;
+  struct lookup_req lookup_req;
+  int r;
+    
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  /* Fill in request message fields.*/
+  req.fs_e = res.fs_e;
+  req.who_e = who_e;
+  req.buf = m_in.name2;
+  req.inode_nr = res.inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  
+  /* Issue request */
+  return req_stat(&req);
+}
+
+
+
+/*===========================================================================*
+ *                             do_fstat                                     *
+ *===========================================================================*/
+PUBLIC int do_fstat()
+{
+/* Perform the fstat(fd, buf) system call. */
+  register struct filp *rfilp;
+  int pipe_pos = 0;
+  struct stat_req req;
+
+  /* Is the file descriptor valid? */
+  if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) {
+         return(err_code);
+  }
+  
+  /* If we read from a pipe, send position too */
+  if (rfilp->filp_vno->v_pipe == I_PIPE) {
+       if (rfilp->filp_mode & R_BIT) 
+               pipe_pos = rfilp->filp_pos;
+  }
+
+  /* Fill in request message */
+  req.fs_e = rfilp->filp_vno->v_fs_e;
+  req.inode_nr = rfilp->filp_vno->v_inode_nr;
+  req.pos = pipe_pos;
+  req.who_e = who_e;
+  req.buf = m_in.buffer;
+
+  /* Issue request */
+  return req_fstat(&req);
+}
+
+
+
+/*===========================================================================*
+ *                             do_fstatfs                                   *
+ *===========================================================================*/
+PUBLIC int do_fstatfs()
+{
+  /* Perform the fstatfs(fd, buf) system call. */
+  register struct filp *rfilp;
+  struct stat_req req;
+
+  /* Is the file descriptor valid? */
+  if ( (rfilp = get_filp(m_in.fd)) == NIL_FILP) return(err_code);
+
+  /* Send FS request */
+  req.fs_e = rfilp->filp_vno->v_fs_e;
+  req.inode_nr = rfilp->filp_vno->v_inode_nr;
+  req.who_e = who_e;
+  req.buf = m_in.buffer;
+  
+  /* Issue request */
+  return req_fstatfs(&req);
+}
+
+
+
+/*===========================================================================*
+ *                             do_lstat                                      *
+ *===========================================================================*/
+PUBLIC int do_lstat()
+{
+/* Perform the lstat(name, buf) system call. */
+  struct stat_req req;
+  struct node_details res;
+  struct lookup_req lookup_req;
+  int r;
+
+  if (fetch_name(m_in.name1, m_in.name1_length, M1) != OK) return(err_code);
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH_OPAQUE;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
+
+  /* Fill in request message fields.*/
+  req.fs_e = res.fs_e;
+  req.who_e = who_e;
+  req.buf = m_in.name2;
+  req.inode_nr = res.inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  
+  /* Issue request */
+  return req_stat(&req);
+}
+
+
+
similarity index 100%
rename from servers/fs/super.h
rename to servers/vfs/super.h
similarity index 96%
rename from servers/fs/table.c
rename to servers/vfs/table.c
index 262d7f4b508dbe66521c25e571e75edba6416137..f347ac3356c978dd8b92f19b5cb1d7a62b2f955d 100644 (file)
@@ -7,12 +7,13 @@
 #include "fs.h"
 #include <minix/callnr.h>
 #include <minix/com.h>
-#include "buf.h"
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
 #include "lock.h"
-#include "super.h"
+
+#include "vnode.h"
+#include "vmnt.h"
+
 
 PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        no_sys,         /*  0 = unused  */
@@ -72,7 +73,7 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        do_ioctl,       /* 54 = ioctl   */
        do_fcntl,       /* 55 = fcntl   */
        no_sys,         /* 56 = (mpx)   */
-       no_sys,         /* 57 = unused  */
+       do_fslogin,     /* 57 = FS proc login */
        no_sys,         /* 58 = unused  */
        no_sys,         /* 59 = (execve) */
        do_umask,       /* 60 = umask   */
@@ -114,7 +115,8 @@ PUBLIC _PROTOTYPE (int (*call_vec[]), (void) ) = {
        do_ftruncate,   /* 94 = truncate */
        do_chmod,       /* 95 = fchmod */
        do_chown,       /* 96 = fchown */
-       no_sys,         /* 97 = (getsysinfo_up) */
+       no_sys,         /* 97 = getsysinfo_up */
 };
 /* This should not fail with "array size is negative": */
 extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];
+
similarity index 52%
rename from servers/fs/time.c
rename to servers/vfs/time.c
index 39fa3c54648a3f72e62fd5fde9a3a5c353240b19..806fee9a24e6b99c5106b75376934272c4b6a19c 100644 (file)
 #include <minix/com.h>
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
 #include "param.h"
 
+#include <minix/vfsif.h>
+#include "vmnt.h"
+
 /*===========================================================================*
  *                             do_utime                                     *
  *===========================================================================*/
 PUBLIC int do_utime()
 {
 /* Perform the utime(name, timep) system call. */
-
-  register struct inode *rip;
-  register int len, r;
-
+  register int len;
+  struct utime_req req;
+  struct lookup_req lookup_req;
+  struct node_details res;
+  int r;
+  
   /* Adjust for case of 'timep' being NULL;
    * utime_strlen then holds the actual size: strlen(name)+1.
    */
   len = m_in.utime_length;
   if (len == 0) len = m_in.utime_strlen;
 
-  /* Temporarily open the file. */
   if (fetch_name(m_in.utime_file, len, M1) != OK) return(err_code);
-  if ( (rip = eat_path(user_path)) == NIL_INODE) return(err_code);
+  
+  /* Fill in lookup request fields */
+  lookup_req.path = user_fullpath;
+  lookup_req.lastc = NULL;
+  lookup_req.flags = EAT_PATH;
+        
+  /* Request lookup */
+  if ((r = lookup(&lookup_req, &res)) != OK) return r;
 
-  /* Only the owner of a file or the super_user can change its time. */
-  r = OK;
-  if (rip->i_uid != fp->fp_effuid && !super_user) r = EPERM;
-  if (m_in.utime_length == 0 && r != OK) r = forbidden(rip, W_BIT);
-  if (read_only(rip) != OK) r = EROFS; /* not even su can touch if R/O */
-  if (r == OK) {
-       if (m_in.utime_length == 0) {
-               rip->i_atime = clock_time();
-               rip->i_mtime = rip->i_atime;
-       } else {
-               rip->i_atime = m_in.utime_actime;
-               rip->i_mtime = m_in.utime_modtime;
-       }
-       rip->i_update = CTIME;  /* discard any stale ATIME and MTIME flags */
-       rip->i_dirt = DIRTY;
+  /* Fill in request fields.*/
+  if (m_in.utime_length == 0) {
+        req.actime = 0;        
+        req.modtime = clock_time();
+  } else {
+        req.actime = m_in.utime_actime;
+        req.modtime = m_in.utime_modtime;
   }
-
-  put_inode(rip);
-  return(r);
+  req.fs_e = res.fs_e;
+  req.inode_nr = res.inode_nr;
+  req.uid = fp->fp_effuid;
+  req.gid = fp->fp_effgid;
+  
+  /* Issue request */
+  return req_utime(&req);
 }
 
+
 /*===========================================================================*
  *                             do_stime                                     *
  *===========================================================================*/
 PUBLIC int do_stime()
 {
-/* Perform the stime(tp) system call. */
+  struct vmnt *vmp;
+  /* Perform the stime(tp) system call. */
   boottime = (long) m_in.pm_stime; 
-  return(OK);
+    
+  /* Send new time for all FS processes */
+  for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { 
+      if (vmp->m_fs_e) req_stime(vmp->m_fs_e, boottime);
+  }
+
+  return OK;
 }
 
similarity index 100%
rename from servers/fs/timers.c
rename to servers/vfs/timers.c
diff --git a/servers/vfs/type.h b/servers/vfs/type.h
new file mode 100644 (file)
index 0000000..19749fe
--- /dev/null
@@ -0,0 +1,23 @@
+/* Declaration of the V1 inode as it is on the disk (not in core). */
+typedef struct {               /* V1.x disk inode */
+  mode_t d1_mode;              /* file type, protection, etc. */
+  uid_t d1_uid;                        /* user id of the file's owner */
+  off_t d1_size;               /* current file size in bytes */
+  time_t d1_mtime;             /* when was file data last changed */
+  u8_t d1_gid;                 /* group number */
+  u8_t d1_nlinks;              /* how many links to this file */
+  u16_t d1_zone[V1_NR_TZONES]; /* block nums for direct, ind, and dbl ind */
+} d1_inode;
+
+/* Declaration of the V2 inode as it is on the disk (not in core). */
+typedef struct {               /* V2.x disk inode */
+  mode_t d2_mode;              /* file type, protection, etc. */
+  u16_t d2_nlinks;             /* how many links to this file. HACK! */
+  uid_t d2_uid;                        /* user id of the file's owner. */
+  u16_t d2_gid;                        /* group number HACK! */
+  off_t d2_size;               /* current file size in bytes */
+  time_t d2_atime;             /* when was file data last accessed */
+  time_t d2_mtime;             /* when was file data last changed */
+  time_t d2_ctime;             /* when was inode data last changed */
+  zone_t d2_zone[V2_NR_TZONES];        /* block nums for direct, ind, and dbl ind */
+} d2_inode;
similarity index 66%
rename from servers/fs/utility.c
rename to servers/vfs/utility.c
index 50821f072dc28fe7da24c26569bd3d25d831e9d8..a73442088e7c7f6f745bcba55e650db3ca05d862 100644 (file)
 #include <minix/com.h>
 #include <minix/endpoint.h>
 #include <unistd.h>
-#include "buf.h"
 #include "file.h"
 #include "fproc.h"
-#include "inode.h"
 #include "param.h"
 
 PRIVATE int panicking;         /* inhibits recursive panics during sync */
 
-/*===========================================================================*
- *                             clock_time                                   *
- *===========================================================================*/
-PUBLIC time_t clock_time()
-{
-/* This routine returns the time in seconds since 1.1.1970.  MINIX is an
- * astrophysically naive system that assumes the earth rotates at a constant
- * rate and that such things as leap seconds do not exist.
- */
-
-  register int k;
-  clock_t uptime;
-
-  if ( (k=getuptime(&uptime)) != OK) panic(__FILE__,"clock_time err", k);
-  return( (time_t) (boottime + (uptime/HZ)));
-}
-
 /*===========================================================================*
  *                             fetch_name                                   *
  *===========================================================================*/
@@ -67,15 +48,16 @@ int flag;                   /* M3 means path may be in message */
 
   if (flag == M3 && len <= M3_STRING) {
        /* Just copy the path from the message to 'user_path'. */
-       rpu = &user_path[0];
+       rpu = &user_fullpath[0];
        rpm = m_in.pathname;            /* contained in input message */
        do { *rpu++ = *rpm++; } while (--len);
        r = OK;
   } else {
        /* String is not contained in the message.  Get it from user space. */
        r = sys_datacopy(who_e, (vir_bytes) path,
-               FS_PROC_NR, (vir_bytes) user_path, (phys_bytes) len);
+               FS_PROC_NR, (vir_bytes) user_fullpath, (phys_bytes) len);
   }
+
   return(r);
 }
 
@@ -85,8 +67,8 @@ int flag;                     /* M3 means path may be in message */
 PUBLIC int no_sys()
 {
 /* Somebody has used an illegal system call number */
-  printf("FS: in no_sys: call %d from %d\n", call_nr, who_e);
-  return(EINVAL);
+  printf("VFSno_sys: call %d from %d\n", call_nr, who_e);
+  return(SUSPEND);
 }
 
 /*===========================================================================*
@@ -110,57 +92,46 @@ int num;                   /* number to go with it */
   sys_exit(SELF);
 }
 
-/*===========================================================================*
- *                             conv2                                        *
- *===========================================================================*/
-PUBLIC unsigned conv2(norm, w)
-int norm;                      /* TRUE if no swap, FALSE for byte swap */
-int w;                         /* promotion of 16-bit word to be swapped */
-{
-/* Possibly swap a 16-bit word between 8086 and 68000 byte order. */
-  if (norm) return( (unsigned) w & 0xFFFF);
-  return( ((w&BYTE) << 8) | ( (w>>8) & BYTE));
-}
 
 /*===========================================================================*
- *                             conv4                                        *
+ *                             isokendpt_f                                  *
  *===========================================================================*/
-PUBLIC long conv4(norm, x)
-int norm;                      /* TRUE if no swap, FALSE for byte swap */
-long x;                                /* 32-bit long to be byte swapped */
+PUBLIC int isokendpt_f(char *file, int line, int endpoint, int *proc, int fatal)
 {
-/* Possibly swap a 32-bit long between 8086 and 68000 byte order. */
-  unsigned lo, hi;
-  long l;
-  
-  if (norm) return(x);                 /* byte order was already ok */
-  lo = conv2(FALSE, (int) x & 0xFFFF); /* low-order half, byte swapped */
-  hi = conv2(FALSE, (int) (x>>16) & 0xFFFF);   /* high-order half, swapped */
-  l = ( (long) lo <<16) | hi;
-  return(l);
+    int failed = 0;
+    *proc = _ENDPOINT_P(endpoint);
+    if(*proc < 0 || *proc >= NR_PROCS) {
+        printf("FS:%s:%d: proc (%d) from endpoint (%d) out of range\n",
+                file, line, *proc, endpoint);
+        failed = 1;
+    } else if(fproc[*proc].fp_endpoint != endpoint) {
+        printf("FS:%s:%d: proc (%d) from endpoint (%d) doesn't match "
+                "known endpoint (%d)\n",
+                file, line, *proc, endpoint, fproc[*proc].fp_endpoint);
+        failed = 1;
+    }
+
+    if(failed && fatal)
+        panic(__FILE__, "isokendpt_f failed", NO_NUM);
+
+    return failed ? EDEADSRCDST : OK;
 }
 
 /*===========================================================================*
- *                             isokendpt_f                                  *
+ *                             clock_time                                   *
  *===========================================================================*/
-PUBLIC int isokendpt_f(char *file, int line, int endpoint, int *proc, int fatal)
+PUBLIC time_t clock_time()
 {
-       int failed = 0;
-       *proc = _ENDPOINT_P(endpoint);
-       if(*proc < 0 || *proc >= NR_PROCS) {
-               printf("FS:%s:%d: proc (%d) from endpoint (%d) out of range\n",
-                       file, line, *proc, endpoint);
-               failed = 1;
-       } else if(fproc[*proc].fp_endpoint != endpoint) {
-               printf("FS:%s:%d: proc (%d) from endpoint (%d) doesn't match "
-                       "known endpoint (%d)\n",
-                       file, line, *proc, endpoint, fproc[*proc].fp_endpoint);
-               failed = 1;
-       }
-
-       if(failed && fatal)
-               panic(__FILE__, "isokendpt_f failed", NO_NUM);
-
-       return failed ? EDEADSRCDST : OK;
+/* This routine returns the time in seconds since 1.1.1970.  MINIX is an
+ * astrophysically naive system that assumes the earth rotates at a constant
+ * rate and that such things as leap seconds do not exist.
+ */
+
+  register int k;
+  clock_t uptime;
+
+  if ( (k=getuptime(&uptime)) != OK) panic(__FILE__,"clock_time err", k);
+  return( (time_t) (boottime + (uptime/HZ)));
 }
 
+
diff --git a/servers/vfs/vmnt.c b/servers/vfs/vmnt.c
new file mode 100644 (file)
index 0000000..9b92743
--- /dev/null
@@ -0,0 +1,37 @@
+/* Virtual mount table related routines.
+ *
+ *   Jul 2006 (Balazs Gerofi)
+ */
+
+#include "fs.h"
+#include "vmnt.h"
+
+
+/*===========================================================================*
+ *                             get_free_vmnt                                *
+ *===========================================================================*/
+PUBLIC struct vmnt *get_free_vmnt(short *index)
+{
+  struct vmnt *vp;
+  *index = 0;
+  for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp, ++(*index)) {
+      if (vp->m_dev == NO_DEV) return vp;
+  }
+
+  return NIL_VMNT;
+}
+
+/*===========================================================================*
+ *                             find_vmnt                                    *
+ *===========================================================================*/
+PUBLIC struct vmnt *find_vmnt(int fs_e) 
+{
+  struct vmnt *vp;
+  for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) {
+      if (vp->m_fs_e == fs_e) return vp;
+  }
+
+  return NIL_VMNT;
+}
+
+
diff --git a/servers/vfs/vmnt.h b/servers/vfs/vmnt.h
new file mode 100644 (file)
index 0000000..f1916fc
--- /dev/null
@@ -0,0 +1,14 @@
+
+
+EXTERN struct vmnt {
+  int m_fs_e;                   /* FS process' kernel endpoint */
+  dev_t m_dev;                  /* device number */
+  int m_driver_e;               /* device driver process' kernel endpoint */
+  int m_flags;                  /* mount flags */
+  int m_max_file_size;          /* maximum file size on partition */
+  unsigned short m_block_size;  /* block size */
+  struct vnode *m_mounted_on;   /* the vnode on which the partition is mounted */
+  struct vnode *m_root_node;    /* root vnode */
+} vmnt[NR_MNTS];
+
+#define NIL_VMNT (struct vmnt *) 0
diff --git a/servers/vfs/vnode.c b/servers/vfs/vnode.c
new file mode 100644 (file)
index 0000000..0646bc4
--- /dev/null
@@ -0,0 +1,161 @@
+
+/* This file contains the routines related to vnodes.
+ * The entry points are:
+ *      
+ *  get_vnode - increase counter and get details of an inode
+ *  get_free_vnode - get a pointer to a free vnode obj
+ *  find_vnode - find a vnode according to the FS endpoint and the inode num.  
+ *  dup_vnode - duplicate vnode (i.e. increase counter)
+ *  put_vnode - drop vnode (i.e. decrease counter)  
+ *  
+ *  Jul 2006 (Balazs Gerofi)
+ */
+#include "fs.h"
+#include "vnode.h"
+#include "vmnt.h"
+
+#include <minix/vfsif.h>
+
+/*===========================================================================*
+ *                             get_vnode                                    *
+ *===========================================================================*/
+PUBLIC struct vnode *get_vnode(int fs_e, int inode_nr)
+{
+/* get_vnode() is called to get the details of the specified inode.
+ * Note that inode's usage counter in the FS is supposed to be incremented.
+ */
+  struct vnode *vp, *vp2;
+  struct vmnt *vmp;
+
+  /* Request & response structures */
+  struct node_req req;
+  struct node_details res;
+  
+  /* Check whether a free vnode is avaliable */
+  if ((vp = get_free_vnode()) == NIL_VNODE) {
+        printf("VFSget_vnode: no vnode available\n");
+        return NIL_VNODE;
+  }
+  
+  /* Fill req struct */
+  req.inode_nr = inode_nr;
+  req.fs_e = fs_e;
+
+  /* Send request to FS */
+  if (req_getnode(&req, &res) != OK) {
+        printf("VFSget_vnode: couldn't find vnode\n"); 
+        return NIL_VNODE;
+  }
+
+  /* Fill in the free vnode's fields and return it */
+  vp->v_fs_e = res.fs_e;
+  vp->v_inode_nr = res.inode_nr;
+  vp->v_mode = res.fmode;
+  vp->v_size = res.fsize;
+  vp->v_sdev = res.dev;
+  
+  /* Find corresponding virtual mount object */
+  if ( (vmp = find_vmnt(vp->v_fs_e)) == NIL_VMNT)
+        printf("VFS: vmnt not found by get_vnode()\n");
+  
+  vp->v_vmnt = vmp; 
+  vp->v_dev = vmp->m_dev;
+  vp->v_count = 1;
+  
+  return vp; 
+}
+
+
+/*===========================================================================*
+ *                             get_free_vnode                               *
+ *===========================================================================*/
+PUBLIC struct vnode *get_free_vnode()
+{
+/* Find a free vnode slot in the vnode table */    
+  struct vnode *vp;
+
+  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
+      if (vp->v_count == 0) return vp;
+  
+  err_code = ENFILE;
+  return NIL_VNODE;
+}
+
+/*===========================================================================*
+ *                             find_vnode                                   *
+ *===========================================================================*/
+PUBLIC struct vnode *find_vnode(int fs_e, int numb)
+{
+/* Find a specified (FS endpoint and inode number) vnode in the
+ * vnode table */
+  struct vnode *vp;
+
+  for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
+      if (vp->v_count > 0 && vp->v_inode_nr == numb
+              && vp->v_fs_e == fs_e) return vp;
+  
+  return NIL_VNODE;
+}
+
+
+/*===========================================================================*
+ *                             dup_vnode                                    *
+ *===========================================================================*/
+PUBLIC void dup_vnode(struct vnode *vp)
+{
+/* dup_vnode() is called to increment the vnode and therefore the
+ * referred inode's counter.
+ */
+  struct node_req req;
+  struct node_details res;
+  
+  if (vp == NIL_VNODE) {
+      printf("VFSdup_vnode NIL_VNODE\n");
+      return;
+  }
+
+  /* Fill req struct */
+  req.inode_nr = vp->v_inode_nr;
+  req.fs_e = vp->v_fs_e;
+
+  /* Send request to FS */
+  if (req_getnode(&req, &res) != OK)
+        printf("VFSdup_vnode Warning: inode doesn't exist\n"); 
+  else
+        vp->v_count++;
+}
+
+
+/*===========================================================================*
+ *                             put_vnode                                    *
+ *===========================================================================*/
+PUBLIC void put_vnode(struct vnode *vp)
+{
+/* Decrease vnode's usage counter and decrease inode's usage counter in the 
+ * corresponding FS process.
+ */
+  struct node_req req;
+  
+  if (vp == NIL_VNODE) {
+        /*printf("VFSput_vnode NIL_VNODE\n");*/
+        return;
+  }
+
+  /* Fill in request fields */
+  req.fs_e = vp->v_fs_e;
+  req.inode_nr = vp->v_inode_nr;
+
+  /* Send request */
+  if (req_putnode(&req) == OK) {
+      /* Decrease counter */
+      if (--vp->v_count == 0) {
+          vp->v_pipe = NO_PIPE;
+          vp->v_sdev = NO_DEV;
+          vp->v_index = 0;
+      }
+  }
+  else 
+      printf("VFSput_vnode Warning: inode doesn't exist\n"); 
+}
+
+
diff --git a/servers/vfs/vnode.h b/servers/vfs/vnode.h
new file mode 100644 (file)
index 0000000..afd8565
--- /dev/null
@@ -0,0 +1,34 @@
+
+
+EXTERN struct vnode {
+  endpoint_t v_fs_e;            /* FS process' endpoint number */
+  ino_t v_inode_nr;            /* inode number on its (minor) device */
+  mode_t v_mode;               /* file type, protection, etc. */
+  off_t v_size;                        /* current file size in bytes */
+  int v_count;                 /* # times vnode used; 0 means slot is free */
+  char v_pipe;                 /* set to I_PIPE if pipe */
+  off_t v_pipe_rd_pos;
+  off_t v_pipe_wr_pos;
+  endpoint_t v_bfs_e;          /* endpoint number for the FS proces in case
+                                  of a block special file */
+  
+  dev_t v_dev;                  /* device number on which the corresponding 
+                                   inode resides */
+  
+  Dev_t v_sdev;                 /* device number for special files */
+  int v_blocksize;              /* block size of the filesys */
+  unsigned short v_index;       /* inode's index in the FS inode table */
+  struct vmnt *v_vmnt;          /* vmnt object of the partition */
+} vnode[NR_VNODES];
+
+#define NIL_VNODE (struct vnode *) 0   /* indicates absence of vnode slot */
+
+/* Field values.  Note that CLEAN and DIRTY are defined in "const.h" */
+#define NO_PIPE            0   /* i_pipe is NO_PIPE if inode is not a pipe */
+#define I_PIPE             1   /* i_pipe is I_PIPE if inode is a pipe */
+#define NO_MOUNT           0   /* i_mount is NO_MOUNT if file not mounted on*/
+#define I_MOUNT            1   /* i_mount is I_MOUNT if file mounted on */
+#define NO_SEEK            0   /* i_seek = NO_SEEK if last op was not SEEK */
+#define ISEEK              1   /* i_seek = ISEEK if last op was SEEK */
+
+
diff --git a/servers/vfs/write.c b/servers/vfs/write.c
new file mode 100644 (file)
index 0000000..4a8390b
--- /dev/null
@@ -0,0 +1,22 @@
+/* This file is the counterpart of "read.c".  It contains the code for writing
+ * insofar as this is not contained in read_write().
+ *
+ * The entry points into this file are
+ *   do_write:     call read_write to perform the WRITE system call
+ */
+
+#include "fs.h"
+#include <string.h>
+#include "file.h"
+#include "fproc.h"
+
+
+/*===========================================================================*
+ *                             do_write                                     *
+ *===========================================================================*/
+PUBLIC int do_write()
+{
+/* Perform the write(fd, buffer, nbytes) system call. */
+  return(read_write(WRITING));
+}
+
index 2b55376810682295df8a2e1853ca958c2796ae82..9d3d2ba835f97c04f95bd674297b5a95d9e849e2 100755 (executable)
@@ -8,12 +8,13 @@ MDEC= /usr/mdec
 # Specify the programs that are part of the system image.
 PROGRAMS=      ../kernel/kernel \
        ../servers/pm/pm \
-       ../servers/fs/fs \
+       ../servers/vfs/vfs \
        ../servers/rs/rs \
        ../servers/ds/ds \
        ../drivers/tty/tty \
        ../drivers/memory/memory \
        ../drivers/log/log \
+       ../servers/mfs/mfs \
        ../servers/init/init
 
 usage: