]> Zhao Yanbai Git Server - minix.git/commitdiff
Implement support for getvfsstat(2) 32/932/2
authorDavid van Moolenbroek <david@minix3.org>
Mon, 19 Aug 2013 23:39:47 +0000 (01:39 +0200)
committerLionel Sambuc <lionel@minix3.org>
Tue, 18 Feb 2014 10:25:02 +0000 (11:25 +0100)
Change-Id: I99b697919d411c57105de561105beefc7d1d309a

26 files changed:
distrib/sets/lists/minix/mi
include/minix/callnr.h
include/minix/com.h
include/minix/sysinfo.h
lib/libc/include/namespace.h
lib/libc/sys-minix/MISSING_SYSCALLS
lib/libc/sys-minix/Makefile.inc
lib/libc/sys-minix/getvfsstat.c [new file with mode: 0644]
lib/libc/sys/Makefile.inc
lib/libminc/Makefile
servers/pm/table.c
servers/procfs/Makefile
servers/procfs/mounts.c [deleted file]
servers/procfs/mounts.h [deleted file]
servers/procfs/root.c
servers/vfs/README
servers/vfs/comm.h [deleted file]
servers/vfs/fs.h
servers/vfs/misc.c
servers/vfs/mount.c
servers/vfs/proto.h
servers/vfs/stadir.c
servers/vfs/table.c
servers/vfs/type.h [new file with mode: 0644]
servers/vfs/vmnt.h
sys/sys/statvfs.h

index 62c5dc3e9605aaf91539260eefa529a4d87a6e37..3ab7dc0ec79e359ffa436bf60910b5cc127ca34b 100644 (file)
 ./usr/man/man2/getsockopt.2            minix-sys
 ./usr/man/man2/gettimeofday.2          minix-sys
 ./usr/man/man2/getuid.2                        minix-sys
+./usr/man/man2/getvfsstat.2            minix-sys
 ./usr/man/man2/intro.2                 minix-sys
 ./usr/man/man2/ioctl.2                 minix-sys
 ./usr/man/man2/kill.2                  minix-sys
index db2372e2fc98b8580261ea089311e79a9e1d0a77..69685decb599060c95d29e320fbc5fde906c89f3 100644 (file)
@@ -74,6 +74,7 @@
 #define SYSUNAME         78
 #define GETDENTS_321     80    /* to VFS */
 #define LLSEEK           81    /* to VFS */
+#define GETVFSSTAT       82    /* to VFS */
 #define STATVFS          83    /* to VFS */
 #define FSTATVFS         84    /* to VFS */
 #define SELECT            85   /* to VFS */
index a38bbb2d59b1597ceefca39148b5528dd979896d..8ad57eea156064e10ef43ccf91a680bdf9dba6f4 100644 (file)
 #define SEL_ERRORFDS   m8_p3
 #define SEL_TIMEOUT    m8_p4
 
+/* Field names for the getvfsstat(2) call. */
+#define VFS_GETVFSSTAT_BUF     m1_p1
+#define VFS_GETVFSSTAT_SIZE    m1_i1
+#define VFS_GETVFSSTAT_FLAGS   m1_i2
+
 /* Field names for the fstatvfs call */
 #define FSTATVFS_FD m1_i1
 #define FSTATVFS_BUF m1_p1
index 88f9d6fcf788d03a0b242a9d92066a0159d9b7a9..e63bb006e59d4520e0af46421249b2d780a9d2b8 100644 (file)
@@ -13,7 +13,6 @@ int getsysinfo(endpoint_t who, int what, void *where, size_t size);
 #define SI_DATA_STORE     5    /* get copy of data store mappings */
 #define SI_CALL_STATS     9    /* system call statistics */
 #define SI_PROCPUB_TAB    11   /* copy of public entries of process table */
-#define SI_VMNT_TAB        12   /* get vmnt table */
 
 #endif
 
index f7627610f4bcf09bdd3d8fa0f2c026c3f4656516..3a1f9faac0e43099e0f0d2286b79272326198ba7 100644 (file)
 #define getttyent              _getttyent
 #define getttynam              _getttynam
 #define getusershell           _getusershell
+#define getvfsstat             _getvfsstat
 #define glob                   _glob
 #define globfree               _globfree
 #define gmtime_r               _gmtime_r
index 98ee058c0d63074dace880110bc2b1859133242b..2d50827e7f05b650e45541c0efe9efb92707c805 100644 (file)
@@ -14,7 +14,6 @@ getpgid
 setrlimit
 getrusage
 getsid
-getvfsstat
 issetugid /* WARNING: Always returns 0 in this impl. */
 kevent
 kqueue
index 890b66d876036ecf75567b6b734c1198cf104e50..38ef33de876c4713d2ffcfae2685c63d9e081df4 100644 (file)
@@ -8,6 +8,7 @@ SRCS+=  accept.c access.c adjtime.c bind.c brk.c sbrk.c m_closefrom.c getsid.c \
        getgroups.c getitimer.c setitimer.c __getlogin.c getpeername.c \
        getpgrp.c getpid.c getppid.c priority.c getrlimit.c getsockname.c \
        getsockopt.c setsockopt.c gettimeofday.c geteuid.c getuid.c \
+       getvfsstat.c \
        ioctl.c issetugid.c kill.c link.c listen.c loadname.c lseek.c \
        minix_rs.c mkdir.c mkfifo.c mknod.c mmap.c mount.c nanosleep.c \
        open.c pathconf.c pipe.c poll.c pread.c ptrace.c pwrite.c \
diff --git a/lib/libc/sys-minix/getvfsstat.c b/lib/libc/sys-minix/getvfsstat.c
new file mode 100644 (file)
index 0000000..69a0864
--- /dev/null
@@ -0,0 +1,19 @@
+#include <sys/cdefs.h>
+#include <lib.h>
+#include "namespace.h"
+
+#include <sys/statvfs.h>
+
+#ifdef __weak_alias
+__weak_alias(getvfsstat, _getvfsstat)
+#endif
+
+int getvfsstat(struct statvfs *buf, size_t bufsize, int flags)
+{
+  message m;
+
+  m.VFS_GETVFSSTAT_BUF = (char *) buf;
+  m.VFS_GETVFSSTAT_SIZE = bufsize;
+  m.VFS_GETVFSSTAT_FLAGS = flags;
+  return(_syscall(VFS_PROC_NR, GETVFSSTAT, &m));
+}
index 2fa88dfd573ada298d196c2ef4d63f87cb16ac12..239ff1aeafed88692a37deca876b2848ae073fa3 100644 (file)
@@ -226,7 +226,7 @@ MAN+=       accept.2 access.2 acct.2 bind.2 brk.2 chdir.2 \
        connect.2 dup.2 execve.2 _exit.2 extattr_get_file.2 \
        fcntl.2 fdatasync.2 fhopen.2 \
        flock.2 fork.2 fsync.2 getcontext.2 getdents.2 \
-       getfh.2 getvfsstat.2 getgid.2 getgroups.2 \
+       getfh.2 getgid.2 getgroups.2 \
        getitimer.2 getlogin.2 getpeername.2 getpgrp.2 getpid.2 \
        getpriority.2 getrlimit.2 getsid.2 getsockname.2 \
        getsockopt.2 gettimeofday.2 getuid.2 intro.2 ioctl.2 issetugid.2 \
@@ -244,7 +244,7 @@ MAN+=       accept.2 access.2 acct.2 bind.2 brk.2 chdir.2 \
        mprotect.2 mremap.2 msgctl.2 msgget.2 msgrcv.2 msgsnd.2 msync.2 \
        munmap.2 nanosleep.2 nfssvc.2 ntp_adjtime.2 open.2 pathconf.2 pipe.2 
 .else
-MAN+=  adjtime.2 clock_settime.2 pipe.2 getrusage.2
+MAN+=  adjtime.2 clock_settime.2 getvfsstat.2 pipe.2 getrusage.2
 .endif # !defined(__MINIX)
 .if !defined(__MINIX)
 MAN+=  pmc_control.2 poll.2 posix_fadvise.2 profil.2 ptrace.2 __quotactl.2 \
index 35e644d8d9a80f808cc2b5c1b012abed03d9edc7..18da0cf027187abd9b20b58b8e6cf366e2ffe57e 100644 (file)
@@ -144,8 +144,8 @@ CPPFLAGS.${i}+= -I${LIBCDIR}/locale
 
 # Import from sys-minix
 .for i in access.c brk.c close.c environ.c execve.c fork.c \
-       getgid.c getpid.c geteuid.c getuid.c gettimeofday.c loadname.c \
-       link.c _mcontext.c mknod.c mmap.c nanosleep.c open.c \
+       getgid.c getpid.c geteuid.c getuid.c gettimeofday.c getvfsstat.c \
+       link.c loadname.c _mcontext.c mknod.c mmap.c nanosleep.c open.c \
        read.c reboot.c sbrk.c select.c setuid.c sigprocmask.c stat.c \
        stime.c syscall.c _ucontext.c umask.c unlink.c waitpid.c \
        brksize.S _ipc.S _senda.S ucontext.S mmap.c init.c
index 6873ff2b797f8ac7bfb2486934e95aa08368385b..8660b5449b66b427d5dbcf513cae116f8cd144ff 100644 (file)
@@ -93,7 +93,7 @@ int (*call_vec[])(void) = {
        no_sys,         /* 79 = unused */
        no_sys,         /* 80 = (getdents) */
        no_sys,         /* 81 = unused */
-       no_sys,         /* 82 = unused */
+       no_sys,         /* 82 = (getvfsstat) */
        no_sys,         /* 83 = unused */
        no_sys,         /* 84 = unused */
        no_sys,         /* 85 = (select) */
index 52d79cbbed247c94ad9a0bdba0d9ed51b20f61c8..cd426ebc6d7eb2df0710b7020b90e3f2b5a5ff3f 100644 (file)
@@ -4,7 +4,7 @@
 .include <bsd.own.mk>
 
 PROG=  procfs
-SRCS=  buf.c main.c pid.c root.c tree.c util.c cpuinfo.c mounts.c
+SRCS=  buf.c main.c pid.c root.c tree.c util.c cpuinfo.c
 
 CPPFLAGS+= -I${NETBSDSRCDIR} -I${NETBSDSRCDIR}/servers
 
diff --git a/servers/procfs/mounts.c b/servers/procfs/mounts.c
deleted file mode 100644 (file)
index cfd4f26..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#include "inc.h"
-#include "vfs/vmnt.h"
-
-extern struct mproc mproc[NR_PROCS];
-
-/*===========================================================================*
- *                              root_mtab                                    *
- *===========================================================================*/
-void
-root_mounts(void)
-{
-       struct vmnt vmnt[NR_MNTS];
-       struct vmnt *vmp;
-       struct mproc *rmp;
-        int slot;
-
-        if (getsysinfo(VFS_PROC_NR, SI_VMNT_TAB, vmnt, sizeof(vmnt)) != OK)
-                return;
-
-        for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
-                if (vmp->m_dev == NO_DEV)
-                        continue;
-               if (vmp->m_fs_e == PFS_PROC_NR)
-                       continue; /* Skip (special case) */
-
-               slot = _ENDPOINT_P(vmp->m_fs_e);
-               if (slot < 0 || slot >= NR_PROCS)
-                       continue;
-               rmp = &mproc[slot];
-                buf_printf("%s on %s type %s (%s)\n", vmp->m_mount_dev,
-                       vmp->m_mount_path, rmp->mp_name,
-                       (vmp->m_flags & VMNT_READONLY) ? "ro" : "rw");
-        }
-}
diff --git a/servers/procfs/mounts.h b/servers/procfs/mounts.h
deleted file mode 100644 (file)
index ca5712b..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-#ifndef __PROCFS_MOUNTS_H
-#define __PROCFS_MOUNTS_H__
-
-void root_mounts(void);
-
-#endif /* __PROCFS_MOUNTS_H__ */
index 7629c0ad6fb4f52c77cd549601d670878eda0cd5..6f121a844d0411ff5b0f9a98ee2d0249b4a93dad 100644 (file)
@@ -7,7 +7,6 @@
 #endif
 #include <minix/dmap.h>
 #include "cpuinfo.h"
-#include "mounts.h"
 
 static void root_hz(void);
 static void root_uptime(void);
@@ -19,6 +18,7 @@ static void root_pci(void);
 #endif
 static void root_dmap(void);
 static void root_ipcvecs(void);
+static void root_mounts(void);
 
 struct file root_files[] = {
        { "hz",         REG_ALL_MODE,   (data_t) root_hz        },
@@ -209,3 +209,21 @@ static void root_ipcvecs(void)
        PRINT_ENTRYPOINT(do_kernel_call);
 }
 
+/*===========================================================================*
+ *                             root_mounts                                  *
+ *===========================================================================*/
+static void
+root_mounts(void)
+{
+       struct statvfs buf[NR_MNTS];
+       int i, count;
+
+       if ((count = getvfsstat(buf, sizeof(buf), ST_NOWAIT)) < 0)
+               return;
+
+       for (i = 0; i < count; i++) {
+               buf_printf("%s on %s type %s (%s)\n", buf[i].f_mntfromname,
+                       buf[i].f_mntonname, buf[i].f_fstypename,
+                       (buf[i].f_flag & ST_RDONLY) ? "ro" : "rw");
+        }
+}
index bb9751a59db9110e6c6d1f42a93804463a5aab91..76b675c0df6340963d430f4e8319ec59075d8c27 100644 (file)
@@ -38,7 +38,7 @@ it supports a few calls necessary for libc. The following system calls are
 handled by VFS:
 
 access, chdir, chmod, chown, chroot, close, creat, fchdir, fcntl, fstat,
-fstatvfs, fsync, ftruncate getdents, ioctl, link, llseek, lseek,
+fstatvfs, fsync, ftruncate, getdents, getvfsstat, ioctl, link, llseek, lseek,
 lstat, mkdir, mknod, mount, open, pipe, read, readlink, rename, rmdir, select,
 stat, statvfs, symlink, sync, truncate, umask, umount, unlink, utime, write.
 
@@ -355,7 +355,7 @@ requests) do need a vmnt lock.
 | a file descriptor | getdents, ioctl, llseek, pipe, read, select, write      |
 | argument          |                                                         |
 +-------------------+---------------------------------------------------------+
-| System calls with | fsync++, sync, umask                                    |
+| System calls with | fsync++, getvfsstat, sync, umask                        |
 | other or no       |                                                         |
 | arguments         |                                                         |
 -------------------------------------------------------------------------------
@@ -452,11 +452,12 @@ as used by VFS.
 | File rename | rename       | VMNT_EXCL  | Identical to file unlink          |
 | ops.        |              |            | operations                        |
 +-------------+--------------+------------+-----------------------------------+
-| Non-file    | sync, umask  | VMNT_READ  | umask does not involve the file   |
-| ops.        |              | or none    | system, so it does not need       |
+| Non-file    | sync, umask, | VMNT_READ  | umask does not involve the file   |
+| ops.        | getvfsstat   | or none    | system, so it does not need       |
 |             |              |            | locks. sync does not alter state  |
 |             |              |            | in VFS and  is atomic at the FS   |
-|             |              |            | level                             |
+|             |              |            | level. getvfsstat caches stats    |
+|             |              |            | only and requires no exclusion.   |
 -------------------------------------------------------------------------------
 }}}
 Table 5: System call without file descriptor argument sub-categorization
diff --git a/servers/vfs/comm.h b/servers/vfs/comm.h
deleted file mode 100644 (file)
index 4e0d00c..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-#ifndef __VFS_COMM_H__
-#define __VFS_COMM_H__
-
-/* VFS<->FS communication */
-
-typedef struct {
-  int c_max_reqs;      /* Max requests an FS can handle simultaneously */
-  int c_cur_reqs;      /* Number of requests the FS is currently handling */
-  struct worker_thread *c_req_queue;/* Queue of procs waiting to send a message */
-} comm_t;
-
-#endif
index 3c95e26d5886a9101472f274edf0e78e2e7727c1..a96a8894331c0f45777f7a291d7dfcbd8afb7532 100644 (file)
@@ -28,7 +28,7 @@
 #include "proto.h"
 #include "threads.h"
 #include "glo.h"
-#include "comm.h"
+#include "type.h"
 #include "vmnt.h"
 
 #endif
index f557bd5e8610381d07b64f0053646e0b7ddf64e5..e30f800843b65767c7b4df05277d393e0bcbde64 100644 (file)
@@ -91,11 +91,6 @@ int do_getsysinfo()
        len = sizeof(calls_stats);
        break;
 #endif
-    case SI_VMNT_TAB:
-       fetch_vmnt_paths();
-       src_addr = (vir_bytes) vmnt;
-       len = sizeof(struct vmnt) * NR_MNTS;
-       break;
     default:
        return(EINVAL);
   }
index 5b25ebe1663c34e4ab029bbb1f7ba404dac168bb..da00663a5b1e8ae1758189e1ffbf34bb1bb4f951 100644 (file)
@@ -183,6 +183,7 @@ char mount_label[LABEL_MAX] )
   char *label;
   struct node_details res;
   struct lookup resolve;
+  struct statvfs statvfs_buf;
 
   /* Look up block device driver label when dev is not a pseudo-device */
   label = "";
@@ -290,6 +291,10 @@ char mount_label[LABEL_MAX] )
        new_vmp->m_haspeek = 1;
   }
 
+  /* Fill the statvfs cache with initial values. */
+  if (r == OK)
+       r = update_statvfs(new_vmp, &statvfs_buf);
+
   if (r != OK) {
        mark_vmnt_free(new_vmp);
        unlock_vnode(root_node);
@@ -323,6 +328,9 @@ char mount_label[LABEL_MAX] )
        new_vmp->m_comm.c_max_reqs = VFS_FS_PROTO_CONREQS(new_vmp->m_proto);
   new_vmp->m_comm.c_cur_reqs = 0;
 
+  /* No more blocking operations, so we can now report on this file system. */
+  new_vmp->m_flags |= VMNT_CANSTAT;
+
   if (mount_root) {
        /* Superblock and root node already read.
         * Nothing else can go wrong. Perform the mount. */
@@ -501,6 +509,9 @@ int unmount(
        return(EBUSY);    /* can't umount a busy file system */
   }
 
+  /* This FS will now disappear, so stop listing it in statistics. */
+  vmp->m_flags &= ~VMNT_CANSTAT;
+
   /* Tell FS to drop all inode references for root inode except 1. */
   vnode_clean_refs(vmp->m_root_node);
 
index b4d57037b7feeeaa3d8cefcbb3aae66894d05875..0c5549e38c36754e31cfc05924c00bca5de89445 100644 (file)
@@ -287,8 +287,10 @@ int do_fstat(message *m_out);
 int do_stat(message *m_out);
 int do_statvfs(message *m_out);
 int do_fstatvfs(message *m_out);
+int do_getvfsstat(message *m_out);
 int do_rdlink(message *m_out);
 int do_lstat(message *m_out);
+int update_statvfs(struct vmnt *vmp, struct statvfs *buf);
 
 /* time.c */
 int do_utime(message *);
index 138fe06f6af255b3295962c468566c31a3925128..ab718c7dd7f76729f1efdd67b64ad1a642ad84dd 100644 (file)
@@ -9,6 +9,7 @@
  *   do_fstat: perform the FSTAT system call
  *   do_statvfs: perform the STATVFS system call
  *   do_fstatvfs: perform the FSTATVFS system call
+ *   do_getvfsstat: perform the GETVFSSTAT system call
  */
 
 #include "fs.h"
@@ -208,24 +209,87 @@ int do_fstat(message *UNUSED(m_out))
   return(r);
 }
 
+/*===========================================================================*
+ *                             update_statvfs                               *
+ *===========================================================================*/
+int update_statvfs(struct vmnt *vmp, struct statvfs *buf)
+{
+/* Get statistics from a file system, and cache part of the results. */
+  int r;
+
+  if ((r = req_statvfs(vmp->m_fs_e, buf)) != OK)
+       return r;
+
+  vmp->m_stats.f_flag = buf->f_flag;
+  vmp->m_stats.f_bsize = buf->f_bsize;
+  vmp->m_stats.f_frsize = buf->f_frsize;
+  vmp->m_stats.f_iosize = buf->f_iosize;
+
+  vmp->m_stats.f_blocks = buf->f_blocks;
+  vmp->m_stats.f_bfree = buf->f_bfree;
+  vmp->m_stats.f_bavail = buf->f_bavail;
+  vmp->m_stats.f_bresvd = buf->f_bresvd;
+
+  vmp->m_stats.f_files = buf->f_files;
+  vmp->m_stats.f_ffree = buf->f_ffree;
+  vmp->m_stats.f_favail = buf->f_favail;
+  vmp->m_stats.f_fresvd = buf->f_fresvd;
+
+  vmp->m_stats.f_syncreads = buf->f_syncreads;
+  vmp->m_stats.f_syncwrites = buf->f_syncwrites;
+
+  vmp->m_stats.f_asyncreads = buf->f_asyncreads;
+  vmp->m_stats.f_asyncwrites = buf->f_asyncwrites;
+
+  vmp->m_stats.f_namemax = buf->f_namemax;
+
+  return OK;
+}
+
 /*===========================================================================*
  *                             fill_statvfs                                 *
  *===========================================================================*/
-static int fill_statvfs(struct vnode *vp, endpoint_t endpt, vir_bytes buf_addr)
+static int fill_statvfs(struct vmnt *vmp, endpoint_t endpt, vir_bytes buf_addr,
+       int flags)
 {
 /* Fill a statvfs structure in a userspace process.  First let the target file
- * server (as identified by the given vnode) fill in most fields.  Then fill in
- * some remaining fields with local information.  Finally, copy the result to
- * user space.
+ * server fill in most fields, or use the cached copy if ST_NOWAIT is given.
+ * Then fill in some remaining fields with local information.  Finally, copy
+ * the result to user space.
  */
   struct statvfs buf;
-  struct vmnt *vmp;
-  int r;
 
-  vmp = vp->v_vmnt;
+  if (!(flags & ST_NOWAIT)) {
+       /* Get fresh statistics from the file system. */
+       if (update_statvfs(vmp, &buf) != OK)
+               return EIO;
+  } else {
+       /* Use the cached statistics. */
+       memset(&buf, 0, sizeof(buf));
 
-  if ((r = req_statvfs(vp->v_fs_e, &buf)) != OK)
-       return r;
+       buf.f_flag = vmp->m_stats.f_flag;
+       buf.f_bsize = vmp->m_stats.f_bsize;
+       buf.f_frsize = vmp->m_stats.f_frsize;
+       buf.f_iosize = vmp->m_stats.f_iosize;
+
+       buf.f_blocks = vmp->m_stats.f_blocks;
+       buf.f_bfree = vmp->m_stats.f_bfree;
+       buf.f_bavail = vmp->m_stats.f_bavail;
+       buf.f_bresvd = vmp->m_stats.f_bresvd;
+
+       buf.f_files = vmp->m_stats.f_files;
+       buf.f_ffree = vmp->m_stats.f_ffree;
+       buf.f_favail = vmp->m_stats.f_favail;
+       buf.f_fresvd = vmp->m_stats.f_fresvd;
+
+       buf.f_syncreads = vmp->m_stats.f_syncreads;
+       buf.f_syncwrites = vmp->m_stats.f_syncwrites;
+
+       buf.f_asyncreads = vmp->m_stats.f_asyncreads;
+       buf.f_asyncwrites = vmp->m_stats.f_asyncwrites;
+
+       buf.f_namemax = vmp->m_stats.f_namemax;
+  }
 
   if (vmp->m_flags & VMNT_READONLY)
        buf.f_flag |= ST_RDONLY;
@@ -265,7 +329,7 @@ int do_statvfs(message *UNUSED(m_out))
 
   if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
   if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
-  r = fill_statvfs(vp, who_e, statbuf);
+  r = fill_statvfs(vp->v_vmnt, who_e, statbuf, ST_WAIT);
 
   unlock_vnode(vp);
   unlock_vmnt(vmp);
@@ -289,13 +353,80 @@ int do_fstatvfs(message *UNUSED(m_out))
 
   /* Is the file descriptor valid? */
   if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
-  r = fill_statvfs(rfilp->filp_vno, who_e, statbuf);
+  r = fill_statvfs(rfilp->filp_vno->v_vmnt, who_e, statbuf, ST_WAIT);
 
   unlock_filp(rfilp);
 
   return(r);
 }
 
+/*===========================================================================*
+ *                             do_getvfsstat                                *
+ *===========================================================================*/
+int do_getvfsstat(message *UNUSED(m_out))
+{
+/* Perform the getvfsstat(buf, bufsize, flags) system call. */
+  struct vmnt *vmp;
+  vir_bytes buf;
+  size_t bufsize;
+  int r, flags, count, do_lock;
+
+  buf = (vir_bytes) job_m_in.VFS_GETVFSSTAT_BUF;
+  bufsize = job_m_in.VFS_GETVFSSTAT_SIZE;
+  flags = job_m_in.VFS_GETVFSSTAT_FLAGS;
+
+  count = 0;
+
+  if (buf != 0) {
+       /* We only need to lock target file systems if we are going to query
+        * them.  This will only happen if ST_NOWAIT is not given.  If we do
+        * not lock, we rely on the VMNT_CANSTAT flag to protect us from
+        * concurrent (un)mount operations.  Note that procfs relies on
+        * ST_NOWAIT calls being lock free, as it is a file system itself.
+        */
+       do_lock = !(flags & ST_NOWAIT);
+
+       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
+               /* If there is no more space, return the count so far. */
+               if (bufsize < sizeof(struct statvfs))
+                       break;
+
+               /* Lock the file system before checking any fields. */
+               if (do_lock && (r = lock_vmnt(vmp, VMNT_READ)) != OK)
+                       return r;
+
+               /* Obtain information for this file system, if it is in use and
+                * can be reported.  File systems that are being (un)mounted
+                * are skipped, as is PFS.  The fill call will block only if
+                * ST_NOWAIT was not given.
+                */
+               if (vmp->m_dev != NO_DEV && (vmp->m_flags & VMNT_CANSTAT)) {
+                       if ((r = fill_statvfs(vmp, who_e, buf, flags)) != OK) {
+                               if (do_lock)
+                                       unlock_vmnt(vmp);
+
+                               return r;
+                       }
+
+                       count++;
+                       buf += sizeof(struct statvfs);
+                       bufsize -= sizeof(struct statvfs);
+               }
+
+               if (do_lock)
+                       unlock_vmnt(vmp);
+       }
+  } else {
+       /* Just report a file system count.  No need to lock, as above. */
+       for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
+               if (vmp->m_dev != NO_DEV && (vmp->m_flags & VMNT_CANSTAT))
+                       count++;
+       }
+  }
+
+  return count;
+}
+
 /*===========================================================================*
  *                             do_lstat                                             *
  *===========================================================================*/
index 3492aae38ec7a6bb4b916e753a8b4f19067d6da2..5afc110afdbe1ed98270033c74f8690e7c6342dd 100644 (file)
@@ -97,7 +97,7 @@ int (*call_vec[])(message *m_out) = {
        no_sys,         /* 79 = unused */
        do_getdents,    /* 80 = getdents_321 (to be phased out) */
        do_lseek,       /* 81 = llseek */
-       no_sys,         /* 82 = unused */
+       do_getvfsstat,  /* 82 = getvfsstat */
        do_statvfs,     /* 83 = fstatvfs */
        do_fstatvfs,    /* 84 = statvfs */
        do_select,      /* 85 = select */
diff --git a/servers/vfs/type.h b/servers/vfs/type.h
new file mode 100644 (file)
index 0000000..673be5f
--- /dev/null
@@ -0,0 +1,41 @@
+#ifndef __VFS_TYPE_H__
+#define __VFS_TYPE_H__
+
+/* VFS<->FS communication */
+
+typedef struct {
+  int c_max_reqs;      /* Max requests an FS can handle simultaneously */
+  int c_cur_reqs;      /* Number of requests the FS is currently handling */
+  struct worker_thread *c_req_queue;/* Queue of procs waiting to send a message */
+} comm_t;
+
+/*
+ * Cached statvfs fields.  We are not using struct statvfs itself because that
+ * would add over 2K of unused memory per mount table entry.
+ */
+struct statvfs_cache {
+  unsigned long        f_flag;         /* copy of mount exported flags */
+  unsigned long        f_bsize;        /* file system block size */
+  unsigned long        f_frsize;       /* fundamental file system block size */
+  unsigned long        f_iosize;       /* optimal file system block size */
+
+  fsblkcnt_t   f_blocks;       /* number of blocks in file system, */
+  fsblkcnt_t   f_bfree;        /* free blocks avail in file system */
+  fsblkcnt_t   f_bavail;       /* free blocks avail to non-root */
+  fsblkcnt_t   f_bresvd;       /* blocks reserved for root */
+
+  fsfilcnt_t   f_files;        /* total file nodes in file system */
+  fsfilcnt_t   f_ffree;        /* free file nodes in file system */
+  fsfilcnt_t   f_favail;       /* free file nodes avail to non-root */
+  fsfilcnt_t   f_fresvd;       /* file nodes reserved for root */
+
+  uint64_t     f_syncreads;    /* count of sync reads since mount */
+  uint64_t     f_syncwrites;   /* count of sync writes since mount */
+
+  uint64_t     f_asyncreads;   /* count of async reads since mount */
+  uint64_t     f_asyncwrites;  /* count of async writes since mount */
+
+  unsigned long        f_namemax;      /* maximum filename length */
+};
+
+#endif
index a49792c4fe5d6f9cf2fe0a8e8c0ed973d3ea236d..16e7c955d6aa757c558d44f21067581fbf0d0a81 100644 (file)
@@ -2,7 +2,7 @@
 #define __VFS_VMNT_H__
 
 #include "tll.h"
-#include "comm.h"
+#include "type.h"
 
 EXTERN struct vmnt {
   int m_fs_e;                  /* FS process' kernel endpoint */
@@ -18,6 +18,7 @@ EXTERN struct vmnt {
   char m_mount_dev[PATH_MAX];  /* device from which vmnt is mounted */
   char m_fstype[FSTYPE_MAX];   /* file system type */
   int m_haspeek;               /* supports REQ_PEEK, REQ_BPEEK */
+  struct statvfs_cache m_stats;        /* cached file system statistics */
 } vmnt[NR_MNTS];
 
 /* vmnt flags */
@@ -25,6 +26,7 @@ EXTERN struct vmnt {
 #define VMNT_CALLBACK          02      /* FS did back call */
 #define VMNT_MOUNTING          04      /* Device is being mounted */
 #define VMNT_FORCEROOTBSF      010     /* Force usage of none-device */
+#define VMNT_CANSTAT           020     /* Include FS in getvfsstat output */
 
 /* vmnt lock types mapping */
 #define VMNT_READ TLL_READ
index c1cd4df6a187cf59dfddbb5f49781c1f08b5d8de..8809c640989e25e69427272323d28212e24201ed 100644 (file)
@@ -111,9 +111,13 @@ struct statvfs {
 #define        ST_NOTRUNC      __MNT_UNUSED1
 #endif /* !__minix*/
 
+#define        ST_WAIT         MNT_WAIT
+#define        ST_NOWAIT       MNT_NOWAIT
+
 __BEGIN_DECLS
 int    statvfs(const char *__restrict, struct statvfs *__restrict);
 int    fstatvfs(int, struct statvfs *);
+int    getvfsstat(struct statvfs *, size_t, int);
 __END_DECLS
 
 #endif /* !_SYS_STATVFS_H_ */