This is a requirement for implementing calls such as getmntinfo(3).
VFS is now responsible for filling in some of the structure's fields.
Change-Id: I0c1fa78019587efefd2949b3be38cd9a7ddc2ced
int r;
struct statvfs st;
+ memset(&st, 0, sizeof(st));
+
if (global_pu->pu_ops.puffs_fs_statvfs(global_pu, &st) != 0) {
lpuffs_debug("statvfs failed\n");
return(EINVAL);
/* Returning zero for unknown values seems to be the convention. However, we
* do have to use a nonzero block size, even though it is entirely arbitrary.
*/
+ statvfs.f_flag = ST_NOTRUNC;
statvfs.f_bsize = BLOCK_SIZE;
statvfs.f_frsize = BLOCK_SIZE;
+ statvfs.f_iosize = BLOCK_SIZE;
statvfs.f_blocks = div64u(total, BLOCK_SIZE);
statvfs.f_bfree = div64u(free, BLOCK_SIZE);
statvfs.f_bavail = statvfs.f_bfree;
- statvfs.f_files = 0;
- statvfs.f_ffree = 0;
- statvfs.f_favail = 0;
- statvfs.f_fsid = state.s_dev;
- statvfs.f_flag = state.s_read_only ? ST_RDONLY : 0;
- statvfs.f_flag |= ST_NOTRUNC;
statvfs.f_namemax = NAME_MAX;
return sys_safecopyto(m_in.m_source, m_in.REQ_GRANT, 0,
memset(&statvfs, 0, sizeof(statvfs));
- statvfs.f_fsid = fs_dev;
- statvfs.f_flag = ST_RDONLY | ST_NOTRUNC;
+ statvfs.f_flag = ST_NOTRUNC;
statvfs.f_namemax = PNAME_MAX;
return sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0,
struct super_block *sp;
int r;
+ memset(&st, 0, sizeof(st));
+
sp = get_super(fs_dev);
+ st.f_flag = ST_NOTRUNC;
st.f_bsize = sp->s_block_size;
st.f_frsize = sp->s_block_size;
+ st.f_iosize = sp->s_block_size;
st.f_blocks = sp->s_blocks_count;
st.f_bfree = sp->s_free_blocks_count;
st.f_bavail = sp->s_free_blocks_count - sp->s_r_blocks_count;
st.f_files = sp->s_inodes_count;
st.f_ffree = sp->s_free_inodes_count;
st.f_favail = sp->s_free_inodes_count;
- st.f_fsid = fs_dev;
- st.f_flag = (sp->s_rd_only == 1 ? ST_RDONLY : 0);
- st.f_flag |= ST_NOTRUNC;
st.f_namemax = NAME_MAX;
/* Copy the struct to user space. */
struct statvfs st;
int r;
+ memset(&st, 0, sizeof(st));
st.f_bsize = v_pri.logical_block_size_l;
st.f_frsize = st.f_bsize;
+ st.f_iosize = st.f_bsize;
st.f_blocks = v_pri.volume_space_size_l;
- st.f_bfree = 0;
- st.f_bavail = 0;
- st.f_files = 0;
- st.f_ffree = 0;
- st.f_favail = 0;
- st.f_fsid = fs_dev;
- st.f_flag = ST_RDONLY;
st.f_namemax = NAME_MAX;
/* Copy the struct to user space. */
scale = sp->s_log_zone_size;
+ memset(&st, 0, sizeof(st));
+
fs_blockstats(&st.f_blocks, &st.f_bfree, &used);
st.f_bavail = st.f_bfree;
st.f_bsize = sp->s_block_size << scale;
st.f_frsize = sp->s_block_size;
+ st.f_iosize = st.f_frsize;
st.f_files = sp->s_ninodes;
st.f_ffree = count_free_bits(sp, IMAP);
st.f_favail = st.f_ffree;
- st.f_fsid = fs_dev;
- st.f_flag = (sp->s_rd_only == 1 ? ST_RDONLY : 0);
st.f_namemax = MFS_DIRSIZ;
/* Copy the struct to user space. */
int req_create(endpoint_t fs_e, ino_t inode_nr, int omode, uid_t uid,
gid_t gid, char *path, node_details_t *res);
int req_flush(endpoint_t fs_e, dev_t dev);
-int req_statvfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf);
+int req_statvfs(endpoint_t fs_e, struct statvfs *buf);
int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end);
int req_getdents(endpoint_t fs_e, ino_t inode_nr, off_t pos, char *buf,
size_t size, off_t *new_pos, int direct, int getdents_321);
/*===========================================================================*
* req_statvfs *
*===========================================================================*/
-int req_statvfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf)
+int req_statvfs(endpoint_t fs_e, struct statvfs *buf)
{
int r;
cp_grant_id_t grant_id;
message m;
- grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct statvfs),
+ grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, sizeof(struct statvfs),
CPF_WRITE);
if(grant_id == GRANT_INVALID)
- panic("req_statvfs: cpf_grant_magic failed");
+ panic("req_statvfs: cpf_grant_direct failed");
/* Fill in request message */
m.m_type = REQ_STATVFS;
return(r);
}
+/*===========================================================================*
+ * fill_statvfs *
+ *===========================================================================*/
+static int fill_statvfs(struct vnode *vp, endpoint_t endpt, vir_bytes buf_addr)
+{
+/* 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;
+ int r;
+
+ vmp = vp->v_vmnt;
+
+ if ((r = req_statvfs(vp->v_fs_e, &buf)) != OK)
+ return r;
+
+ if (vmp->m_flags & VMNT_READONLY)
+ buf.f_flag |= ST_RDONLY;
+
+ buf.f_fsid = vmp->m_dev;
+
+ strlcpy(buf.f_fstypename, "", sizeof(buf.f_fstypename)); /* FIXME */
+ strlcpy(buf.f_mntonname, vmp->m_mount_path, sizeof(buf.f_mntonname));
+ strlcpy(buf.f_mntfromname, vmp->m_mount_dev, sizeof(buf.f_mntfromname));
+
+ return sys_datacopy(SELF, (vir_bytes) &buf, endpt, buf_addr, sizeof(buf));
+}
+
/*===========================================================================*
* do_statvfs *
*===========================================================================*/
int do_statvfs(message *UNUSED(m_out))
{
-/* Perform the stat(name, buf) system call. */
+/* Perform the statvfs(name, buf) system call. */
int r;
struct vnode *vp;
struct vmnt *vmp;
if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
- r = req_statvfs(vp->v_fs_e, who_e, statbuf);
+ r = fill_statvfs(vp, who_e, statbuf);
unlock_vnode(vp);
unlock_vmnt(vmp);
*===========================================================================*/
int do_fstatvfs(message *UNUSED(m_out))
{
-/* Perform the fstat(fd, buf) system call. */
+/* Perform the fstatvfs(fd, buf) system call. */
register struct filp *rfilp;
int r, rfd;
vir_bytes statbuf;
/* Is the file descriptor valid? */
if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
- r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, statbuf);
+ r = fill_statvfs(rfilp->filp_vno, who_e, statbuf);
unlock_filp(rfilp);
#include <sys/stdint.h>
#include <machine/ansi.h>
#include <sys/ansi.h>
+#include <sys/fstypes.h>
#define _VFS_NAMELEN 32
#define _VFS_MNAMELEN 1024
#endif
struct statvfs {
- unsigned long f_bsize; /* File system block size. */
- unsigned long f_frsize; /* Fundamental file system block size. */
- fsblkcnt_t f_blocks; /* Total number of blocks on file system */
- /* in units of f_frsize. */
- fsblkcnt_t f_bfree; /* Total number of free blocks. */
- fsblkcnt_t f_bavail; /* Number of free blocks available to */
- /* non-privileged process. */
- fsfilcnt_t f_files; /* Total number of file serial numbers. */
- fsfilcnt_t f_ffree; /* Total number of free file serial numbers. */
- fsfilcnt_t f_favail; /* Number of file serial numbers available */
- /* to non-privileged process. */
- unsigned long f_fsid; /* File system ID. */
- unsigned long f_flag; /* Bit mask of f_flag values. */
- unsigned long f_namemax; /* Maximum filename length. */
- unsigned char __padding[32]; /* Padding for future compatibility */
+ 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 */
+
+ /* The following are in units of f_frsize */
+ 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 */
+
+ fsid_t f_fsidx; /* NetBSD compatible fsid */
+ unsigned long f_fsid; /* Posix compatible fsid */
+ unsigned long f_namemax; /* maximum filename length */
+ uid_t f_owner; /* user that mounted the file system */
+
+ uint32_t f_spare[4]; /* spare space */
+
+ char f_fstypename[_VFS_NAMELEN]; /* fs type name */
+ char f_mntonname[_VFS_MNAMELEN]; /* directory on which mounted */
+ char f_mntfromname[_VFS_MNAMELEN]; /* mounted file system */
+
};
-/* Possible values for statvfs->f_flag */
-#define ST_RDONLY 0x1
-#define ST_NOSUID 0x2
+#if defined(_NETBSD_SOURCE) && !defined(_POSIX_SOURCE) && \
+ !defined(_XOPEN_SOURCE)
+#define VFS_NAMELEN _VFS_NAMELEN
+#define VFS_MNAMELEN _VFS_MNAMELEN
+#endif
+
+#define ST_RDONLY MNT_RDONLY
+#define ST_NOSUID MNT_NOSUID
#ifdef __minix
-#define ST_NOTRUNC 0x4
+#define ST_NOTRUNC __MNT_UNUSED1
#endif /* !__minix*/
__BEGIN_DECLS
int fstatvfs(int, struct statvfs *);
__END_DECLS
-#endif /* _SYS_STATVFS_H_ */
+#endif /* !_SYS_STATVFS_H_ */