Implement support for getvfsstat(2)
Change-Id: I99b697919d411c57105de561105beefc7d1d309a
This commit is contained in:
parent
7113bcb896
commit
266239fe64
26 changed files with 267 additions and 88 deletions
|
@ -2228,6 +2228,7 @@
|
|||
./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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -902,6 +902,11 @@
|
|||
#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
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -366,6 +366,7 @@
|
|||
#define getttyent _getttyent
|
||||
#define getttynam _getttynam
|
||||
#define getusershell _getusershell
|
||||
#define getvfsstat _getvfsstat
|
||||
#define glob _glob
|
||||
#define globfree _globfree
|
||||
#define gmtime_r _gmtime_r
|
||||
|
|
|
@ -14,7 +14,6 @@ getpgid
|
|||
setrlimit
|
||||
getrusage
|
||||
getsid
|
||||
getvfsstat
|
||||
issetugid /* WARNING: Always returns 0 in this impl. */
|
||||
kevent
|
||||
kqueue
|
||||
|
|
|
@ -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 \
|
||||
|
|
19
lib/libc/sys-minix/getvfsstat.c
Normal file
19
lib/libc/sys-minix/getvfsstat.c
Normal file
|
@ -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));
|
||||
}
|
|
@ -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 \
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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) */
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
|
@ -1,6 +0,0 @@
|
|||
#ifndef __PROCFS_MOUNTS_H
|
||||
#define __PROCFS_MOUNTS_H__
|
||||
|
||||
void root_mounts(void);
|
||||
|
||||
#endif /* __PROCFS_MOUNTS_H__ */
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -28,7 +28,7 @@
|
|||
#include "proto.h"
|
||||
#include "threads.h"
|
||||
#include "glo.h"
|
||||
#include "comm.h"
|
||||
#include "type.h"
|
||||
#include "vmnt.h"
|
||||
|
||||
#endif
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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 *);
|
||||
|
|
|
@ -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"
|
||||
|
@ -209,24 +210,87 @@ int do_fstat(message *UNUSED(m_out))
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* fill_statvfs *
|
||||
* update_statvfs *
|
||||
*===========================================================================*/
|
||||
static int fill_statvfs(struct vnode *vp, endpoint_t endpt, vir_bytes buf_addr)
|
||||
int update_statvfs(struct vmnt *vmp, struct statvfs *buf)
|
||||
{
|
||||
/* 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.
|
||||
*/
|
||||
struct statvfs buf;
|
||||
struct vmnt *vmp;
|
||||
/* Get statistics from a file system, and cache part of the results. */
|
||||
int r;
|
||||
|
||||
vmp = vp->v_vmnt;
|
||||
|
||||
if ((r = req_statvfs(vp->v_fs_e, &buf)) != OK)
|
||||
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 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 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;
|
||||
|
||||
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));
|
||||
|
||||
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 *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -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 */
|
||||
|
|
41
servers/vfs/type.h
Normal file
41
servers/vfs/type.h
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
|
@ -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_ */
|
||||
|
|
Loading…
Reference in a new issue