From: Thomas Veerman Date: Tue, 11 Dec 2012 19:46:09 +0000 (+0000) Subject: VFS/PFS: remove notion of position in pipes X-Git-Tag: v3.2.1~127 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/zlib_tech.html?a=commitdiff_plain;h=3de8d1cf6e52dbd6edb8331b6a6b186e6c860646;p=minix.git VFS/PFS: remove notion of position in pipes Because pipes have no file position. VFS maintained (file) offsets into a buffer internal to PFS and stored them in vnodes for simplicity, mixing the responsibilities of filp and vnode objects. With this patch PFS ignores the position field in REQ_READ and REQ_WRITE requests making VFS' job a lot simpler. --- diff --git a/servers/pfs/read.c b/servers/pfs/read.c index 691c0fddc..d80647b58 100644 --- a/servers/pfs/read.c +++ b/servers/pfs/read.c @@ -32,23 +32,34 @@ int fs_readwrite(message *fs_m_in, message *fs_m_out) /* Get the values from the request message */ rw_flag = (fs_m_in->m_type == REQ_READ ? READING : WRITING); gid = (cp_grant_id_t) fs_m_in->REQ_GRANT; - position = fs_m_in->REQ_SEEK_POS_LO; nrbytes = (unsigned) fs_m_in->REQ_NBYTES; /* We can't read beyond the max file position */ if (nrbytes > MAX_FILE_POS) return(EFBIG); - if (rw_flag == WRITING) { - /* Check in advance to see if file will grow too big. */ - /* Casting nrbytes to signed is safe, because it's guaranteed not to - be beyond max signed value (i.e., MAX_FILE_POS). */ - if (position > PIPE_BUF - (signed) nrbytes) return(EFBIG); - } - /* Mark inode in use */ if ((get_inode(rip->i_dev, rip->i_num)) == NULL) return(err_code); if ((bp = get_block(rip->i_dev, rip->i_num)) == NULL) return(err_code); + if (rw_flag == WRITING) { + /* Check in advance to see if file will grow too big. */ + /* Casting nrbytes to signed is safe, because it's guaranteed not to + * be beyond max signed value (i.e., MAX_FILE_POS). + */ + position = rip->i_size; + if (position > PIPE_BUF - (signed) nrbytes) { + put_inode(rip); + put_block(rip->i_dev, rip->i_num); + return(EFBIG); + } + } else { + position = bp->b_bytes; + if (nrbytes > rip->i_size - position) { + /* There aren't that many bytes to read */ + nrbytes = rip->i_size - position; + } + } + if (rw_flag == READING) { /* Copy a chunk from the block buffer to user space. */ r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0, @@ -78,10 +89,12 @@ int fs_readwrite(message *fs_m_in, message *fs_m_out) } } - bp->b_bytes = position; + if (rw_flag == READING) + bp->b_bytes = position; if (rw_flag == READING) rip->i_update |= ATIME; if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME; fs_m_out->RES_NBYTES = (size_t) cum_io; + put_inode(rip); put_block(rip->i_dev, rip->i_num); diff --git a/servers/vfs/open.c b/servers/vfs/open.c index 0bc7690ff..cc386f6a8 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -248,8 +248,6 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode) r = map_vnode(vp, PFS_PROC_NR); if (r == OK) { if (vp->v_ref_count == 1) { - vp->v_pipe_rd_pos = 0; - vp->v_pipe_wr_pos = 0; if (vp->v_size != 0) r = truncate_vnode(vp, 0); } diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index 494f229df..0ad1c471b 100644 --- a/servers/vfs/pipe.c +++ b/servers/vfs/pipe.c @@ -108,8 +108,6 @@ int do_pipe() vp->v_inode_nr = res.inode_nr; vp->v_mapinode_nr = res.inode_nr; vp->v_mode = res.fmode; - vp->v_pipe_rd_pos= 0; - vp->v_pipe_wr_pos= 0; vp->v_fs_count = 1; vp->v_mapfs_count = 1; vp->v_ref_count = 1; @@ -175,13 +173,13 @@ endpoint_t map_to_fs_e; /*===========================================================================* * pipe_check * *===========================================================================*/ -int pipe_check(vp, rw_flag, oflags, bytes, position, notouch) -register struct vnode *vp; /* the inode of the pipe */ -int rw_flag; /* READING or WRITING */ -int oflags; /* flags set by open or fcntl */ -register int bytes; /* bytes to be read or written (all chunks) */ -u64_t position; /* current file position */ -int notouch; /* check only */ +int pipe_check( +struct vnode *vp, /* the inode of the pipe */ +int rw_flag, /* READING or WRITING */ +int oflags, /* flags set by open or fcntl */ +int bytes, /* bytes to be read or written (all chunks) */ +int notouch /* check only */ +) { /* Pipes are a little different. If a process reads from an empty pipe for * which a writer still exists, suspend the reader. If the pipe is empty @@ -191,13 +189,15 @@ int notouch; /* check only */ off_t pos; int r = OK; - if (ex64hi(position) != 0) - panic("pipe_check: position too large in pipe"); - pos = ex64lo(position); + /* Reads start at the beginning; writes append to pipes */ + if (rw_flag == READING) + pos = 0; + else + pos = vp->v_size; /* If reading, check for empty pipe. */ if (rw_flag == READING) { - if (pos >= vp->v_size) { + if (vp->v_size == 0) { /* Process is reading from an empty pipe. */ if (find_filp(vp, W_BIT) != NULL) { /* Writer exists */ diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 4b1f2f220..b98d7420d 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -187,7 +187,7 @@ int do_pipe(void); int map_vnode(struct vnode *vp, endpoint_t fs_e); void unpause(endpoint_t proc_e); int pipe_check(struct vnode *vp, int rw_flag, int oflags, int bytes, - u64_t position, int notouch); + int notouch); void release(struct vnode *vp, int op, int count); void revive(endpoint_t proc_e, int returned); void suspend(int why); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index 59cbd2b7a..65722ab41 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -264,7 +264,7 @@ size_t req_size; int r, oflags, partial_pipe = 0; size_t size, cum_io, cum_io_incr; struct vnode *vp; - u64_t position, new_pos; + u64_t position, new_pos; /* Must make sure we're operating on locked filp and vnode */ assert(tll_locked_by_me(&f->filp_vno->v_lock)); @@ -272,12 +272,12 @@ size_t req_size; oflags = f->filp_flags; vp = f->filp_vno; - position = cvu64((rw_flag == READING) ? vp->v_pipe_rd_pos : - vp->v_pipe_wr_pos); + position = cvu64(0); /* Not actually used */ + /* fp->fp_cum_io_partial is only nonzero when doing partial writes */ cum_io = fp->fp_cum_io_partial; - r = pipe_check(vp, rw_flag, oflags, req_size, position, 0); + r = pipe_check(vp, rw_flag, oflags, req_size, 0); if (r <= 0) { if (r == SUSPEND) pipe_suspend(f, buf, req_size); return(r); @@ -287,16 +287,8 @@ size_t req_size; if (size < req_size) partial_pipe = 1; /* Truncate read request at size. */ - if((rw_flag == READING) && - cmp64ul(add64ul(position, size), vp->v_size) > 0) { - /* Position always should fit in an off_t (LONG_MAX). */ - off_t pos32; - - assert(cmp64ul(position, LONG_MAX) <= 0); - pos32 = cv64ul(position); - assert(pos32 >= 0); - assert(pos32 <= LONG_MAX); - size = vp->v_size - pos32; + if (rw_flag == READING && size > vp->v_size) { + size = vp->v_size; } if (vp->v_mapfs_e == 0) @@ -309,7 +301,6 @@ size_t req_size; if (ex64hi(new_pos)) panic("rw_pipe: bad new pos"); - position = new_pos; cum_io += cum_io_incr; buf += cum_io_incr; req_size -= cum_io_incr; @@ -317,27 +308,19 @@ size_t req_size; /* On write, update file size and access time. */ if (rw_flag == WRITING) { - if (cmp64ul(position, vp->v_size) > 0) { - if (ex64hi(position) != 0) { + if (cmp64ul(new_pos, vp->v_size) > 0) { + if (ex64hi(new_pos) != 0) { panic("read_write: file size too big for v_size"); } - vp->v_size = ex64lo(position); + vp->v_size = ex64lo(new_pos); } } else { - if (cmp64ul(position, vp->v_size) >= 0) { - /* Reset pipe pointers */ + if (cmp64ul(new_pos, vp->v_size) >= 0) { + /* Pipe emtpy; reset size */ vp->v_size = 0; - vp->v_pipe_rd_pos= 0; - vp->v_pipe_wr_pos= 0; - position = cvu64(0); } } - if (rw_flag == READING) - vp->v_pipe_rd_pos= cv64ul(position); - else - vp->v_pipe_wr_pos= cv64ul(position); - if (r == OK) { if (partial_pipe) { /* partial write on pipe with */ diff --git a/servers/vfs/select.c b/servers/vfs/select.c index 089822931..8c3a13ce7 100644 --- a/servers/vfs/select.c +++ b/servers/vfs/select.c @@ -451,7 +451,8 @@ static int select_request_pipe(struct filp *f, int *ops, int block) orig_ops = *ops; if ((*ops & (SEL_RD|SEL_ERR))) { - err = pipe_check(f->filp_vno, READING, 0, 1, f->filp_pos, 1); + /* Check if we can read 1 byte */ + err = pipe_check(f->filp_vno, READING, 0, 1, 1 /* Check only */); if (err != SUSPEND) r |= SEL_RD; @@ -466,7 +467,8 @@ static int select_request_pipe(struct filp *f, int *ops, int block) } if ((*ops & (SEL_WR|SEL_ERR))) { - err = pipe_check(f->filp_vno, WRITING, 0, 1, f->filp_pos, 1); + /* Check if we can write 1 byte */ + err = pipe_check(f->filp_vno, WRITING, 0, 1, 1 /* Check only */); if (err != SUSPEND) r |= SEL_WR; diff --git a/servers/vfs/vnode.h b/servers/vfs/vnode.h index bcea1f063..2f01d7379 100644 --- a/servers/vfs/vnode.h +++ b/servers/vfs/vnode.h @@ -16,8 +16,6 @@ EXTERN struct vnode { #if 0 int v_ref_check; /* for consistency checks */ #endif - off_t v_pipe_rd_pos; - off_t v_pipe_wr_pos; endpoint_t v_bfs_e; /* endpoint number for the FS proces in case of a block special file */ dev_t v_dev; /* device number on which the corresponding