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.
This commit is contained in:
parent
7c8b3ddfed
commit
3de8d1cf6e
7 changed files with 51 additions and 57 deletions
|
@ -32,23 +32,34 @@ int fs_readwrite(message *fs_m_in, message *fs_m_out)
|
||||||
/* Get the values from the request message */
|
/* Get the values from the request message */
|
||||||
rw_flag = (fs_m_in->m_type == REQ_READ ? READING : WRITING);
|
rw_flag = (fs_m_in->m_type == REQ_READ ? READING : WRITING);
|
||||||
gid = (cp_grant_id_t) fs_m_in->REQ_GRANT;
|
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;
|
nrbytes = (unsigned) fs_m_in->REQ_NBYTES;
|
||||||
|
|
||||||
/* We can't read beyond the max file position */
|
/* We can't read beyond the max file position */
|
||||||
if (nrbytes > MAX_FILE_POS) return(EFBIG);
|
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 */
|
/* Mark inode in use */
|
||||||
if ((get_inode(rip->i_dev, rip->i_num)) == NULL) return(err_code);
|
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 ((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) {
|
if (rw_flag == READING) {
|
||||||
/* Copy a chunk from the block buffer to user space. */
|
/* Copy a chunk from the block buffer to user space. */
|
||||||
r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) 0,
|
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 == READING) rip->i_update |= ATIME;
|
||||||
if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
|
if (rw_flag == WRITING) rip->i_update |= CTIME | MTIME;
|
||||||
fs_m_out->RES_NBYTES = (size_t) cum_io;
|
fs_m_out->RES_NBYTES = (size_t) cum_io;
|
||||||
|
|
||||||
put_inode(rip);
|
put_inode(rip);
|
||||||
put_block(rip->i_dev, rip->i_num);
|
put_block(rip->i_dev, rip->i_num);
|
||||||
|
|
||||||
|
|
|
@ -248,8 +248,6 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode)
|
||||||
r = map_vnode(vp, PFS_PROC_NR);
|
r = map_vnode(vp, PFS_PROC_NR);
|
||||||
if (r == OK) {
|
if (r == OK) {
|
||||||
if (vp->v_ref_count == 1) {
|
if (vp->v_ref_count == 1) {
|
||||||
vp->v_pipe_rd_pos = 0;
|
|
||||||
vp->v_pipe_wr_pos = 0;
|
|
||||||
if (vp->v_size != 0)
|
if (vp->v_size != 0)
|
||||||
r = truncate_vnode(vp, 0);
|
r = truncate_vnode(vp, 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -108,8 +108,6 @@ int do_pipe()
|
||||||
vp->v_inode_nr = res.inode_nr;
|
vp->v_inode_nr = res.inode_nr;
|
||||||
vp->v_mapinode_nr = res.inode_nr;
|
vp->v_mapinode_nr = res.inode_nr;
|
||||||
vp->v_mode = res.fmode;
|
vp->v_mode = res.fmode;
|
||||||
vp->v_pipe_rd_pos= 0;
|
|
||||||
vp->v_pipe_wr_pos= 0;
|
|
||||||
vp->v_fs_count = 1;
|
vp->v_fs_count = 1;
|
||||||
vp->v_mapfs_count = 1;
|
vp->v_mapfs_count = 1;
|
||||||
vp->v_ref_count = 1;
|
vp->v_ref_count = 1;
|
||||||
|
@ -175,13 +173,13 @@ endpoint_t map_to_fs_e;
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* pipe_check *
|
* pipe_check *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
int pipe_check(vp, rw_flag, oflags, bytes, position, notouch)
|
int pipe_check(
|
||||||
register struct vnode *vp; /* the inode of the pipe */
|
struct vnode *vp, /* the inode of the pipe */
|
||||||
int rw_flag; /* READING or WRITING */
|
int rw_flag, /* READING or WRITING */
|
||||||
int oflags; /* flags set by open or fcntl */
|
int oflags, /* flags set by open or fcntl */
|
||||||
register int bytes; /* bytes to be read or written (all chunks) */
|
int bytes, /* bytes to be read or written (all chunks) */
|
||||||
u64_t position; /* current file position */
|
int notouch /* check only */
|
||||||
int notouch; /* check only */
|
)
|
||||||
{
|
{
|
||||||
/* Pipes are a little different. If a process reads from an empty pipe for
|
/* 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
|
* which a writer still exists, suspend the reader. If the pipe is empty
|
||||||
|
@ -191,13 +189,15 @@ int notouch; /* check only */
|
||||||
off_t pos;
|
off_t pos;
|
||||||
int r = OK;
|
int r = OK;
|
||||||
|
|
||||||
if (ex64hi(position) != 0)
|
/* Reads start at the beginning; writes append to pipes */
|
||||||
panic("pipe_check: position too large in pipe");
|
if (rw_flag == READING)
|
||||||
pos = ex64lo(position);
|
pos = 0;
|
||||||
|
else
|
||||||
|
pos = vp->v_size;
|
||||||
|
|
||||||
/* If reading, check for empty pipe. */
|
/* If reading, check for empty pipe. */
|
||||||
if (rw_flag == READING) {
|
if (rw_flag == READING) {
|
||||||
if (pos >= vp->v_size) {
|
if (vp->v_size == 0) {
|
||||||
/* Process is reading from an empty pipe. */
|
/* Process is reading from an empty pipe. */
|
||||||
if (find_filp(vp, W_BIT) != NULL) {
|
if (find_filp(vp, W_BIT) != NULL) {
|
||||||
/* Writer exists */
|
/* Writer exists */
|
||||||
|
|
|
@ -187,7 +187,7 @@ int do_pipe(void);
|
||||||
int map_vnode(struct vnode *vp, endpoint_t fs_e);
|
int map_vnode(struct vnode *vp, endpoint_t fs_e);
|
||||||
void unpause(endpoint_t proc_e);
|
void unpause(endpoint_t proc_e);
|
||||||
int pipe_check(struct vnode *vp, int rw_flag, int oflags, int bytes,
|
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 release(struct vnode *vp, int op, int count);
|
||||||
void revive(endpoint_t proc_e, int returned);
|
void revive(endpoint_t proc_e, int returned);
|
||||||
void suspend(int why);
|
void suspend(int why);
|
||||||
|
|
|
@ -264,7 +264,7 @@ size_t req_size;
|
||||||
int r, oflags, partial_pipe = 0;
|
int r, oflags, partial_pipe = 0;
|
||||||
size_t size, cum_io, cum_io_incr;
|
size_t size, cum_io, cum_io_incr;
|
||||||
struct vnode *vp;
|
struct vnode *vp;
|
||||||
u64_t position, new_pos;
|
u64_t position, new_pos;
|
||||||
|
|
||||||
/* Must make sure we're operating on locked filp and vnode */
|
/* Must make sure we're operating on locked filp and vnode */
|
||||||
assert(tll_locked_by_me(&f->filp_vno->v_lock));
|
assert(tll_locked_by_me(&f->filp_vno->v_lock));
|
||||||
|
@ -272,12 +272,12 @@ size_t req_size;
|
||||||
|
|
||||||
oflags = f->filp_flags;
|
oflags = f->filp_flags;
|
||||||
vp = f->filp_vno;
|
vp = f->filp_vno;
|
||||||
position = cvu64((rw_flag == READING) ? vp->v_pipe_rd_pos :
|
position = cvu64(0); /* Not actually used */
|
||||||
vp->v_pipe_wr_pos);
|
|
||||||
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
|
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
|
||||||
cum_io = fp->fp_cum_io_partial;
|
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 <= 0) {
|
||||||
if (r == SUSPEND) pipe_suspend(f, buf, req_size);
|
if (r == SUSPEND) pipe_suspend(f, buf, req_size);
|
||||||
return(r);
|
return(r);
|
||||||
|
@ -287,16 +287,8 @@ size_t req_size;
|
||||||
if (size < req_size) partial_pipe = 1;
|
if (size < req_size) partial_pipe = 1;
|
||||||
|
|
||||||
/* Truncate read request at size. */
|
/* Truncate read request at size. */
|
||||||
if((rw_flag == READING) &&
|
if (rw_flag == READING && size > vp->v_size) {
|
||||||
cmp64ul(add64ul(position, size), vp->v_size) > 0) {
|
size = vp->v_size;
|
||||||
/* 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 (vp->v_mapfs_e == 0)
|
if (vp->v_mapfs_e == 0)
|
||||||
|
@ -309,7 +301,6 @@ size_t req_size;
|
||||||
if (ex64hi(new_pos))
|
if (ex64hi(new_pos))
|
||||||
panic("rw_pipe: bad new pos");
|
panic("rw_pipe: bad new pos");
|
||||||
|
|
||||||
position = new_pos;
|
|
||||||
cum_io += cum_io_incr;
|
cum_io += cum_io_incr;
|
||||||
buf += cum_io_incr;
|
buf += cum_io_incr;
|
||||||
req_size -= cum_io_incr;
|
req_size -= cum_io_incr;
|
||||||
|
@ -317,27 +308,19 @@ size_t req_size;
|
||||||
|
|
||||||
/* On write, update file size and access time. */
|
/* On write, update file size and access time. */
|
||||||
if (rw_flag == WRITING) {
|
if (rw_flag == WRITING) {
|
||||||
if (cmp64ul(position, vp->v_size) > 0) {
|
if (cmp64ul(new_pos, vp->v_size) > 0) {
|
||||||
if (ex64hi(position) != 0) {
|
if (ex64hi(new_pos) != 0) {
|
||||||
panic("read_write: file size too big for v_size");
|
panic("read_write: file size too big for v_size");
|
||||||
}
|
}
|
||||||
vp->v_size = ex64lo(position);
|
vp->v_size = ex64lo(new_pos);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (cmp64ul(position, vp->v_size) >= 0) {
|
if (cmp64ul(new_pos, vp->v_size) >= 0) {
|
||||||
/* Reset pipe pointers */
|
/* Pipe emtpy; reset size */
|
||||||
vp->v_size = 0;
|
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 (r == OK) {
|
||||||
if (partial_pipe) {
|
if (partial_pipe) {
|
||||||
/* partial write on pipe with */
|
/* partial write on pipe with */
|
||||||
|
|
|
@ -451,7 +451,8 @@ static int select_request_pipe(struct filp *f, int *ops, int block)
|
||||||
orig_ops = *ops;
|
orig_ops = *ops;
|
||||||
|
|
||||||
if ((*ops & (SEL_RD|SEL_ERR))) {
|
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)
|
if (err != SUSPEND)
|
||||||
r |= SEL_RD;
|
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))) {
|
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)
|
if (err != SUSPEND)
|
||||||
r |= SEL_WR;
|
r |= SEL_WR;
|
||||||
|
|
|
@ -16,8 +16,6 @@ EXTERN struct vnode {
|
||||||
#if 0
|
#if 0
|
||||||
int v_ref_check; /* for consistency checks */
|
int v_ref_check; /* for consistency checks */
|
||||||
#endif
|
#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
|
endpoint_t v_bfs_e; /* endpoint number for the FS proces in case
|
||||||
of a block special file */
|
of a block special file */
|
||||||
dev_t v_dev; /* device number on which the corresponding
|
dev_t v_dev; /* device number on which the corresponding
|
||||||
|
|
Loading…
Reference in a new issue