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
					
				@ -8,7 +8,6 @@
 | 
			
		||||
#include <sys/time.h>
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct stat {
 | 
			
		||||
  big_dev_t     st_dev;               /* inode's device */
 | 
			
		||||
  big_mode_t    st_mode;              /* inode protection mode */
 | 
			
		||||
@ -40,7 +39,6 @@ struct stat {
 | 
			
		||||
  u32_t     st_spare[2];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct minix_prev_stat {
 | 
			
		||||
  short st_dev;			/* major/minor device 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 */
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#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_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_mtime		st_mtimespec.tv_sec
 | 
			
		||||
#define st_mtimensec            st_mtimespec.tv_nsec
 | 
			
		||||
#define st_ctime		st_ctimespec.tv_sec
 | 
			
		||||
#define st_ctimensec            st_ctimespec.tv_nsec
 | 
			
		||||
#define st_birthtime            st_birthtimespec.tv_sec
 | 
			
		||||
#define st_birthtimensec        st_birthtimespec.tv_nsec
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#define	S_ISUID	0004000			/* set user id on execution */
 | 
			
		||||
#define	S_ISGID	0002000			/* set group id on execution */
 | 
			
		||||
#if defined(_NETBSD_SOURCE)
 | 
			
		||||
 | 
			
		||||
@ -155,7 +155,7 @@ static int get_read_vp(struct exec_info *execi, char *fullpath,
 | 
			
		||||
		return r;
 | 
			
		||||
	else
 | 
			
		||||
		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;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
	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 pos, int stat_version);
 | 
			
		||||
	int old_stat);
 | 
			
		||||
int req_sync(endpoint_t fs_e);
 | 
			
		||||
int req_unlink(endpoint_t fs_e, ino_t inode_nr, char *lastc);
 | 
			
		||||
int req_unmount(endpoint_t fs_e);
 | 
			
		||||
 | 
			
		||||
@ -923,7 +923,7 @@ int req_slink(
 | 
			
		||||
 *				req_stat	       			     *
 | 
			
		||||
 *===========================================================================*/
 | 
			
		||||
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;
 | 
			
		||||
  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 minix_prev_stat old_sb; /* for backward compatibility */
 | 
			
		||||
 | 
			
		||||
  if (pos != 0 || stat_version != 0)
 | 
			
		||||
	  grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb,
 | 
			
		||||
				      sizeof(struct stat), CPF_WRITE);
 | 
			
		||||
  else
 | 
			
		||||
  if (old_stat == 1) {
 | 
			
		||||
	/* We're dealing with the old stat() call. First copy stat structure
 | 
			
		||||
	 * to VFS so we can convert the new struct stat to the old version.
 | 
			
		||||
	 */
 | 
			
		||||
	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),
 | 
			
		||||
				   CPF_WRITE);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  if (grant_id < 0)
 | 
			
		||||
	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);
 | 
			
		||||
  cpf_revoke(grant_id);
 | 
			
		||||
 | 
			
		||||
  if (r != OK || (pos == 0 && stat_version == 0))
 | 
			
		||||
  if (r != OK || old_stat == 0)
 | 
			
		||||
	return(r);
 | 
			
		||||
 | 
			
		||||
  if (pos != 0)
 | 
			
		||||
	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
 | 
			
		||||
 */
 | 
			
		||||
#if defined(_NETBSD_SOURCE)
 | 
			
		||||
#undef st_atime
 | 
			
		||||
#undef st_ctime
 | 
			
		||||
#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.
 | 
			
		||||
 */
 | 
			
		||||
  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 ((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_vmnt(vmp);
 | 
			
		||||
@ -197,7 +197,7 @@ int do_fstat()
 | 
			
		||||
{
 | 
			
		||||
/* Perform the fstat(fd, buf) system call. */
 | 
			
		||||
  register struct filp *rfilp;
 | 
			
		||||
  int r, pipe_pos = 0, old_stat = 0, rfd;
 | 
			
		||||
  int r, old_stat = 0, rfd;
 | 
			
		||||
  vir_bytes statbuf;
 | 
			
		||||
 | 
			
		||||
  statbuf = (vir_bytes) job_m_in.buffer;
 | 
			
		||||
@ -209,17 +209,8 @@ int do_fstat()
 | 
			
		||||
  /* Is the file descriptor valid? */
 | 
			
		||||
  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,
 | 
			
		||||
	       who_e, statbuf, pipe_pos, old_stat);
 | 
			
		||||
	       who_e, statbuf, old_stat);
 | 
			
		||||
 | 
			
		||||
  unlock_filp(rfilp);
 | 
			
		||||
 | 
			
		||||
@ -331,7 +322,7 @@ int do_lstat()
 | 
			
		||||
	old_stat = 1;
 | 
			
		||||
  if (fetch_name(vname1, vname1_length, fullpath) != OK) 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_vmnt(vmp);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user