Align "struct statvfs" with NetBSD
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
This commit is contained in:
parent
f10229eafb
commit
61ed526374
10 changed files with 97 additions and 48 deletions
|
@ -83,6 +83,8 @@ int fs_statvfs()
|
||||||
int r;
|
int r;
|
||||||
struct statvfs st;
|
struct statvfs st;
|
||||||
|
|
||||||
|
memset(&st, 0, sizeof(st));
|
||||||
|
|
||||||
if (global_pu->pu_ops.puffs_fs_statvfs(global_pu, &st) != 0) {
|
if (global_pu->pu_ops.puffs_fs_statvfs(global_pu, &st) != 0) {
|
||||||
lpuffs_debug("statvfs failed\n");
|
lpuffs_debug("statvfs failed\n");
|
||||||
return(EINVAL);
|
return(EINVAL);
|
||||||
|
|
|
@ -43,17 +43,13 @@ int do_statvfs()
|
||||||
/* Returning zero for unknown values seems to be the convention. However, we
|
/* 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.
|
* 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_bsize = BLOCK_SIZE;
|
||||||
statvfs.f_frsize = BLOCK_SIZE;
|
statvfs.f_frsize = BLOCK_SIZE;
|
||||||
|
statvfs.f_iosize = BLOCK_SIZE;
|
||||||
statvfs.f_blocks = div64u(total, BLOCK_SIZE);
|
statvfs.f_blocks = div64u(total, BLOCK_SIZE);
|
||||||
statvfs.f_bfree = div64u(free, BLOCK_SIZE);
|
statvfs.f_bfree = div64u(free, BLOCK_SIZE);
|
||||||
statvfs.f_bavail = statvfs.f_bfree;
|
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;
|
statvfs.f_namemax = NAME_MAX;
|
||||||
|
|
||||||
return sys_safecopyto(m_in.m_source, m_in.REQ_GRANT, 0,
|
return sys_safecopyto(m_in.m_source, m_in.REQ_GRANT, 0,
|
||||||
|
|
|
@ -65,8 +65,7 @@ int fs_statvfs(void)
|
||||||
|
|
||||||
memset(&statvfs, 0, sizeof(statvfs));
|
memset(&statvfs, 0, sizeof(statvfs));
|
||||||
|
|
||||||
statvfs.f_fsid = fs_dev;
|
statvfs.f_flag = ST_NOTRUNC;
|
||||||
statvfs.f_flag = ST_RDONLY | ST_NOTRUNC;
|
|
||||||
statvfs.f_namemax = PNAME_MAX;
|
statvfs.f_namemax = PNAME_MAX;
|
||||||
|
|
||||||
return sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0,
|
return sys_safecopyto(fs_m_in.m_source, fs_m_in.REQ_GRANT, 0,
|
||||||
|
|
|
@ -84,19 +84,20 @@ int fs_statvfs()
|
||||||
struct super_block *sp;
|
struct super_block *sp;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
memset(&st, 0, sizeof(st));
|
||||||
|
|
||||||
sp = get_super(fs_dev);
|
sp = get_super(fs_dev);
|
||||||
|
|
||||||
|
st.f_flag = ST_NOTRUNC;
|
||||||
st.f_bsize = sp->s_block_size;
|
st.f_bsize = sp->s_block_size;
|
||||||
st.f_frsize = 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_blocks = sp->s_blocks_count;
|
||||||
st.f_bfree = sp->s_free_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_bavail = sp->s_free_blocks_count - sp->s_r_blocks_count;
|
||||||
st.f_files = sp->s_inodes_count;
|
st.f_files = sp->s_inodes_count;
|
||||||
st.f_ffree = sp->s_free_inodes_count;
|
st.f_ffree = sp->s_free_inodes_count;
|
||||||
st.f_favail = 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;
|
st.f_namemax = NAME_MAX;
|
||||||
|
|
||||||
/* Copy the struct to user space. */
|
/* Copy the struct to user space. */
|
||||||
|
|
|
@ -100,17 +100,12 @@ int fs_statvfs()
|
||||||
struct statvfs st;
|
struct statvfs st;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
memset(&st, 0, sizeof(st));
|
||||||
|
|
||||||
st.f_bsize = v_pri.logical_block_size_l;
|
st.f_bsize = v_pri.logical_block_size_l;
|
||||||
st.f_frsize = st.f_bsize;
|
st.f_frsize = st.f_bsize;
|
||||||
|
st.f_iosize = st.f_bsize;
|
||||||
st.f_blocks = v_pri.volume_space_size_l;
|
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;
|
st.f_namemax = NAME_MAX;
|
||||||
|
|
||||||
/* Copy the struct to user space. */
|
/* Copy the struct to user space. */
|
||||||
|
|
|
@ -99,16 +99,17 @@ int fs_statvfs()
|
||||||
|
|
||||||
scale = sp->s_log_zone_size;
|
scale = sp->s_log_zone_size;
|
||||||
|
|
||||||
|
memset(&st, 0, sizeof(st));
|
||||||
|
|
||||||
fs_blockstats(&st.f_blocks, &st.f_bfree, &used);
|
fs_blockstats(&st.f_blocks, &st.f_bfree, &used);
|
||||||
st.f_bavail = st.f_bfree;
|
st.f_bavail = st.f_bfree;
|
||||||
|
|
||||||
st.f_bsize = sp->s_block_size << scale;
|
st.f_bsize = sp->s_block_size << scale;
|
||||||
st.f_frsize = sp->s_block_size;
|
st.f_frsize = sp->s_block_size;
|
||||||
|
st.f_iosize = st.f_frsize;
|
||||||
st.f_files = sp->s_ninodes;
|
st.f_files = sp->s_ninodes;
|
||||||
st.f_ffree = count_free_bits(sp, IMAP);
|
st.f_ffree = count_free_bits(sp, IMAP);
|
||||||
st.f_favail = st.f_ffree;
|
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;
|
st.f_namemax = MFS_DIRSIZ;
|
||||||
|
|
||||||
/* Copy the struct to user space. */
|
/* Copy the struct to user space. */
|
||||||
|
|
|
@ -238,7 +238,7 @@ int req_chown(endpoint_t fs_e, ino_t inode_nr, uid_t newuid, gid_t newgid,
|
||||||
int req_create(endpoint_t fs_e, ino_t inode_nr, int omode, uid_t uid,
|
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);
|
gid_t gid, char *path, node_details_t *res);
|
||||||
int req_flush(endpoint_t fs_e, dev_t dev);
|
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_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,
|
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);
|
size_t size, off_t *new_pos, int direct, int getdents_321);
|
||||||
|
|
|
@ -226,16 +226,16 @@ int req_flush(endpoint_t fs_e, dev_t dev)
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* req_statvfs *
|
* 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;
|
int r;
|
||||||
cp_grant_id_t grant_id;
|
cp_grant_id_t grant_id;
|
||||||
message m;
|
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);
|
CPF_WRITE);
|
||||||
if(grant_id == GRANT_INVALID)
|
if(grant_id == GRANT_INVALID)
|
||||||
panic("req_statvfs: cpf_grant_magic failed");
|
panic("req_statvfs: cpf_grant_direct failed");
|
||||||
|
|
||||||
/* Fill in request message */
|
/* Fill in request message */
|
||||||
m.m_type = REQ_STATVFS;
|
m.m_type = REQ_STATVFS;
|
||||||
|
|
|
@ -208,12 +208,43 @@ int do_fstat(message *UNUSED(m_out))
|
||||||
return(r);
|
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 *
|
* do_statvfs *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_statvfs(message *UNUSED(m_out))
|
int do_statvfs(message *UNUSED(m_out))
|
||||||
{
|
{
|
||||||
/* Perform the stat(name, buf) system call. */
|
/* Perform the statvfs(name, buf) system call. */
|
||||||
int r;
|
int r;
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
struct vmnt *vmp;
|
struct vmnt *vmp;
|
||||||
|
@ -232,7 +263,7 @@ int do_statvfs(message *UNUSED(m_out))
|
||||||
|
|
||||||
if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
|
if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
|
||||||
if ((vp = eat_path(&resolve, fp)) == NULL) 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_vnode(vp);
|
||||||
unlock_vmnt(vmp);
|
unlock_vmnt(vmp);
|
||||||
|
@ -246,7 +277,7 @@ int do_statvfs(message *UNUSED(m_out))
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int do_fstatvfs(message *UNUSED(m_out))
|
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;
|
register struct filp *rfilp;
|
||||||
int r, rfd;
|
int r, rfd;
|
||||||
vir_bytes statbuf;
|
vir_bytes statbuf;
|
||||||
|
@ -256,7 +287,7 @@ int do_fstatvfs(message *UNUSED(m_out))
|
||||||
|
|
||||||
/* Is the file descriptor valid? */
|
/* Is the file descriptor valid? */
|
||||||
if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
|
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);
|
unlock_filp(rfilp);
|
||||||
|
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include <sys/stdint.h>
|
#include <sys/stdint.h>
|
||||||
#include <machine/ansi.h>
|
#include <machine/ansi.h>
|
||||||
#include <sys/ansi.h>
|
#include <sys/ansi.h>
|
||||||
|
#include <sys/fstypes.h>
|
||||||
|
|
||||||
#define _VFS_NAMELEN 32
|
#define _VFS_NAMELEN 32
|
||||||
#define _VFS_MNAMELEN 1024
|
#define _VFS_MNAMELEN 1024
|
||||||
|
@ -63,28 +64,51 @@ typedef _BSD_SIZE_T_ size_t;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
struct statvfs {
|
struct statvfs {
|
||||||
unsigned long f_bsize; /* File system block size. */
|
unsigned long f_flag; /* copy of mount exported flags */
|
||||||
unsigned long f_frsize; /* Fundamental file system block size. */
|
unsigned long f_bsize; /* file system block size */
|
||||||
fsblkcnt_t f_blocks; /* Total number of blocks on file system */
|
unsigned long f_frsize; /* fundamental file system block size */
|
||||||
/* in units of f_frsize. */
|
unsigned long f_iosize; /* optimal file system block size */
|
||||||
fsblkcnt_t f_bfree; /* Total number of free blocks. */
|
|
||||||
fsblkcnt_t f_bavail; /* Number of free blocks available to */
|
/* The following are in units of f_frsize */
|
||||||
/* non-privileged process. */
|
fsblkcnt_t f_blocks; /* number of blocks in file system, */
|
||||||
fsfilcnt_t f_files; /* Total number of file serial numbers. */
|
fsblkcnt_t f_bfree; /* free blocks avail in file system */
|
||||||
fsfilcnt_t f_ffree; /* Total number of free file serial numbers. */
|
fsblkcnt_t f_bavail; /* free blocks avail to non-root */
|
||||||
fsfilcnt_t f_favail; /* Number of file serial numbers available */
|
fsblkcnt_t f_bresvd; /* blocks reserved for root */
|
||||||
/* to non-privileged process. */
|
|
||||||
unsigned long f_fsid; /* File system ID. */
|
fsfilcnt_t f_files; /* total file nodes in file system */
|
||||||
unsigned long f_flag; /* Bit mask of f_flag values. */
|
fsfilcnt_t f_ffree; /* free file nodes in file system */
|
||||||
unsigned long f_namemax; /* Maximum filename length. */
|
fsfilcnt_t f_favail; /* free file nodes avail to non-root */
|
||||||
unsigned char __padding[32]; /* Padding for future compatibility */
|
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 */
|
#if defined(_NETBSD_SOURCE) && !defined(_POSIX_SOURCE) && \
|
||||||
#define ST_RDONLY 0x1
|
!defined(_XOPEN_SOURCE)
|
||||||
#define ST_NOSUID 0x2
|
#define VFS_NAMELEN _VFS_NAMELEN
|
||||||
|
#define VFS_MNAMELEN _VFS_MNAMELEN
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ST_RDONLY MNT_RDONLY
|
||||||
|
#define ST_NOSUID MNT_NOSUID
|
||||||
#ifdef __minix
|
#ifdef __minix
|
||||||
#define ST_NOTRUNC 0x4
|
#define ST_NOTRUNC __MNT_UNUSED1
|
||||||
#endif /* !__minix*/
|
#endif /* !__minix*/
|
||||||
|
|
||||||
__BEGIN_DECLS
|
__BEGIN_DECLS
|
||||||
|
@ -92,4 +116,4 @@ int statvfs(const char *__restrict, struct statvfs *__restrict);
|
||||||
int fstatvfs(int, struct statvfs *);
|
int fstatvfs(int, struct statvfs *);
|
||||||
__END_DECLS
|
__END_DECLS
|
||||||
|
|
||||||
#endif /* _SYS_STATVFS_H_ */
|
#endif /* !_SYS_STATVFS_H_ */
|
||||||
|
|
Loading…
Reference in a new issue