VFS: simplify stat for pipes
According to POSIX the st_size field of struct stat is undefined for fifos and anonymous pipes. Thus we can do anything we want. We save a copy by not being accurate on pipe sizes.
This commit is contained in:
parent
db8198d99d
commit
7b81254069
5 changed files with 25 additions and 47 deletions
|
@ -8,7 +8,6 @@
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
struct stat {
|
struct stat {
|
||||||
big_dev_t st_dev; /* inode's device */
|
big_dev_t st_dev; /* inode's device */
|
||||||
big_mode_t st_mode; /* inode protection mode */
|
big_mode_t st_mode; /* inode protection mode */
|
||||||
|
@ -40,7 +39,6 @@ struct stat {
|
||||||
u32_t st_spare[2];
|
u32_t st_spare[2];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct minix_prev_stat {
|
struct minix_prev_stat {
|
||||||
short st_dev; /* major/minor device number */
|
short st_dev; /* major/minor device number */
|
||||||
ino_t st_ino; /* i-node number */
|
ino_t st_ino; /* i-node number */
|
||||||
|
@ -55,20 +53,17 @@ struct minix_prev_stat {
|
||||||
time_t st_ctime; /* time of last file status change */
|
time_t st_ctime; /* time of last file status change */
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if defined(_NETBSD_SOURCE)
|
#if defined(_NETBSD_SOURCE)
|
||||||
/* XXX after updating stat struct we don't want to update all the code */
|
|
||||||
#define st_atime st_atimespec.tv_sec
|
#define st_atime st_atimespec.tv_sec
|
||||||
#define st_mtime st_mtimespec.tv_sec
|
|
||||||
#define st_ctime st_ctimespec.tv_sec
|
|
||||||
#define st_birthtime st_birthtimespec.tv_sec
|
|
||||||
#define st_atimensec st_atimespec.tv_nsec
|
#define st_atimensec st_atimespec.tv_nsec
|
||||||
|
#define st_mtime st_mtimespec.tv_sec
|
||||||
#define st_mtimensec st_mtimespec.tv_nsec
|
#define st_mtimensec st_mtimespec.tv_nsec
|
||||||
|
#define st_ctime st_ctimespec.tv_sec
|
||||||
#define st_ctimensec st_ctimespec.tv_nsec
|
#define st_ctimensec st_ctimespec.tv_nsec
|
||||||
|
#define st_birthtime st_birthtimespec.tv_sec
|
||||||
#define st_birthtimensec st_birthtimespec.tv_nsec
|
#define st_birthtimensec st_birthtimespec.tv_nsec
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define S_ISUID 0004000 /* set user id on execution */
|
#define S_ISUID 0004000 /* set user id on execution */
|
||||||
#define S_ISGID 0002000 /* set group id on execution */
|
#define S_ISGID 0002000 /* set group id on execution */
|
||||||
#if defined(_NETBSD_SOURCE)
|
#if defined(_NETBSD_SOURCE)
|
||||||
|
|
|
@ -155,7 +155,7 @@ static int get_read_vp(struct exec_info *execi, char *fullpath,
|
||||||
return r;
|
return r;
|
||||||
else
|
else
|
||||||
r = req_stat(execi->vp->v_fs_e, execi->vp->v_inode_nr,
|
r = req_stat(execi->vp->v_fs_e, execi->vp->v_inode_nr,
|
||||||
VFS_PROC_NR, (vir_bytes) &(execi->sb), 0, 0);
|
VFS_PROC_NR, (vir_bytes) &(execi->sb), 0);
|
||||||
|
|
||||||
if (r != OK) return r;
|
if (r != OK) return r;
|
||||||
|
|
||||||
|
|
|
@ -253,7 +253,7 @@ int req_rmdir(endpoint_t fs_e, ino_t inode_nr, char *lastc);
|
||||||
int req_slink(endpoint_t fs_e, ino_t inode_nr, char *lastc, endpoint_t proc_e,
|
int req_slink(endpoint_t fs_e, ino_t inode_nr, char *lastc, endpoint_t proc_e,
|
||||||
vir_bytes path_addr, size_t path_length, uid_t uid, gid_t gid);
|
vir_bytes path_addr, size_t path_length, uid_t uid, gid_t gid);
|
||||||
int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf,
|
int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf,
|
||||||
int pos, int stat_version);
|
int old_stat);
|
||||||
int req_sync(endpoint_t fs_e);
|
int req_sync(endpoint_t fs_e);
|
||||||
int req_unlink(endpoint_t fs_e, ino_t inode_nr, char *lastc);
|
int req_unlink(endpoint_t fs_e, ino_t inode_nr, char *lastc);
|
||||||
int req_unmount(endpoint_t fs_e);
|
int req_unmount(endpoint_t fs_e);
|
||||||
|
|
|
@ -923,7 +923,7 @@ int req_slink(
|
||||||
* req_stat *
|
* req_stat *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf,
|
int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf,
|
||||||
int pos, int stat_version)
|
int old_stat)
|
||||||
{
|
{
|
||||||
cp_grant_id_t grant_id;
|
cp_grant_id_t grant_id;
|
||||||
int r;
|
int r;
|
||||||
|
@ -931,12 +931,17 @@ int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf,
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
struct minix_prev_stat old_sb; /* for backward compatibility */
|
struct minix_prev_stat old_sb; /* for backward compatibility */
|
||||||
|
|
||||||
if (pos != 0 || stat_version != 0)
|
if (old_stat == 1) {
|
||||||
grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb,
|
/* We're dealing with the old stat() call. First copy stat structure
|
||||||
sizeof(struct stat), CPF_WRITE);
|
* to VFS so we can convert the new struct stat to the old version.
|
||||||
else
|
*/
|
||||||
|
grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb, sizeof(struct stat),
|
||||||
|
CPF_WRITE);
|
||||||
|
} else {
|
||||||
|
/* Grant FS access to copy straight into user provided buffer */
|
||||||
grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat),
|
grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat),
|
||||||
CPF_WRITE);
|
CPF_WRITE);
|
||||||
|
}
|
||||||
|
|
||||||
if (grant_id < 0)
|
if (grant_id < 0)
|
||||||
panic("req_stat: cpf_grant_* failed");
|
panic("req_stat: cpf_grant_* failed");
|
||||||
|
@ -950,29 +955,16 @@ int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf,
|
||||||
r = fs_sendrec(fs_e, &m);
|
r = fs_sendrec(fs_e, &m);
|
||||||
cpf_revoke(grant_id);
|
cpf_revoke(grant_id);
|
||||||
|
|
||||||
if (r != OK || (pos == 0 && stat_version == 0))
|
if (r != OK || old_stat == 0)
|
||||||
return(r);
|
return(r);
|
||||||
|
|
||||||
if (pos != 0)
|
#if defined(_NETBSD_SOURCE)
|
||||||
sb.st_size -= pos;
|
|
||||||
if (stat_version == 0) {
|
|
||||||
r = sys_vircopy(SELF, D, (vir_bytes) &sb, proc_e, D, buf,
|
|
||||||
sizeof(struct stat));
|
|
||||||
return(r);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* User needs old struct stat.
|
|
||||||
* Just 1 prev version at this moment */
|
|
||||||
assert(stat_version == 1);
|
|
||||||
|
|
||||||
/* XXX until that st_Xtime macroses used, we have to undefine them,
|
|
||||||
* because of minix_prev_stat
|
|
||||||
*/
|
|
||||||
#undef st_atime
|
#undef st_atime
|
||||||
#undef st_ctime
|
#undef st_ctime
|
||||||
#undef st_mtime
|
#undef st_mtime
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Copy field by field because of st_gid type mismath and
|
/* Copy field by field because of st_gid type mismatch and
|
||||||
* difference in order after atime.
|
* difference in order after atime.
|
||||||
*/
|
*/
|
||||||
old_sb.st_dev = sb.st_dev;
|
old_sb.st_dev = sb.st_dev;
|
||||||
|
|
|
@ -181,7 +181,7 @@ int do_stat()
|
||||||
|
|
||||||
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_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat);
|
r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, old_stat);
|
||||||
|
|
||||||
unlock_vnode(vp);
|
unlock_vnode(vp);
|
||||||
unlock_vmnt(vmp);
|
unlock_vmnt(vmp);
|
||||||
|
@ -197,7 +197,7 @@ int do_fstat()
|
||||||
{
|
{
|
||||||
/* Perform the fstat(fd, buf) system call. */
|
/* Perform the fstat(fd, buf) system call. */
|
||||||
register struct filp *rfilp;
|
register struct filp *rfilp;
|
||||||
int r, pipe_pos = 0, old_stat = 0, rfd;
|
int r, old_stat = 0, rfd;
|
||||||
vir_bytes statbuf;
|
vir_bytes statbuf;
|
||||||
|
|
||||||
statbuf = (vir_bytes) job_m_in.buffer;
|
statbuf = (vir_bytes) job_m_in.buffer;
|
||||||
|
@ -209,17 +209,8 @@ int do_fstat()
|
||||||
/* 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);
|
||||||
|
|
||||||
/* If we read from a pipe, send position too */
|
|
||||||
if (S_ISFIFO(rfilp->filp_vno->v_mode)) {
|
|
||||||
if (rfilp->filp_mode & R_BIT)
|
|
||||||
if (ex64hi(rfilp->filp_pos) != 0) {
|
|
||||||
panic("do_fstat: bad position in pipe");
|
|
||||||
}
|
|
||||||
pipe_pos = ex64lo(rfilp->filp_pos);
|
|
||||||
}
|
|
||||||
|
|
||||||
r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
|
r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
|
||||||
who_e, statbuf, pipe_pos, old_stat);
|
who_e, statbuf, old_stat);
|
||||||
|
|
||||||
unlock_filp(rfilp);
|
unlock_filp(rfilp);
|
||||||
|
|
||||||
|
@ -331,7 +322,7 @@ int do_lstat()
|
||||||
old_stat = 1;
|
old_stat = 1;
|
||||||
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_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat);
|
r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, old_stat);
|
||||||
|
|
||||||
unlock_vnode(vp);
|
unlock_vnode(vp);
|
||||||
unlock_vmnt(vmp);
|
unlock_vmnt(vmp);
|
||||||
|
|
Loading…
Reference in a new issue