Implement support for getvfsstat(2)
Change-Id: I99b697919d411c57105de561105beefc7d1d309a
This commit is contained in:
		
							parent
							
								
									7113bcb896
								
							
						
					
					
						commit
						266239fe64
					
				@ -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…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user