#define BYTE 0377 /* mask for 8 bits */
#define READING 0 /* copy data to user */
#define WRITING 1 /* copy data from user */
+#define PEEKING 2 /* retrieve FS data without copying */
#define HAVE_SCATTERED_IO 1 /* scattered I/O is now standard */
/* Memory is allocated in clicks. */
#define REQ_RDLINK (VFS_BASE + 30)
#define REQ_GETDENTS (VFS_BASE + 31)
#define REQ_STATVFS (VFS_BASE + 32)
+#define REQ_PEEK (VFS_BASE + 33)
-#define NREQS 33
+#define NREQS 34
#define IS_VFS_RQ(type) (((type) & ~0xff) == VFS_BASE)
no_sys, /* 30 rdlink */
do_getdents, /* 31 getdents */
do_statvfs, /* 32 statvfs */
+ no_sys, /* 33 peek */
};
/* This should not fail with "array size is negative": */
fs_rdlink, /* 30 rdlink */
fs_getdents, /* 31 getdents */
fs_statvfs, /* 32 statvfs */
+ no_sys, /* 33 peek */
};
/* This should not fail with "array size is negative": */
if (f_size < 0) f_size = MAX_FILE_POS;
}
- /* Get the values from the request message */
rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
+ switch(fs_m_in.m_type) {
+ case REQ_READ: rw_flag = READING; break;
+ case REQ_WRITE: rw_flag = WRITING; break;
+ case REQ_PEEK: rw_flag = PEEKING; break;
+ default: panic("odd request");
+ }
gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
position = (off_t) fs_m_in.REQ_SEEK_POS_LO;
nrbytes = (size_t) fs_m_in.REQ_NBYTES;
unsigned off; /* off within the current block */
unsigned int chunk; /* number of bytes to read or write */
unsigned left; /* max number of bytes wanted after position */
-int rw_flag; /* READING or WRITING */
+int rw_flag; /* READING, WRITING or PEEKING */
cp_grant_id_t gid; /* grant */
unsigned buf_off; /* offset in grant */
unsigned int block_size; /* block size of FS operating on */
{
/* Read or write (part of) a block. */
- register struct buf *bp;
+ register struct buf *bp = NULL;
register int r = OK;
int n, block_spec;
block_t b;
dev_t dev;
+ /* rw_flag:
+ * READING: read from FS, copy to user
+ * WRITING: copy from user, write to FS
+ * PEEKING: try to get all the blocks into the cache, no copying
+ */
+
*completed = 0;
block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
}
return r;
} else {
- /* Writing to a nonexistent block. Create and enter in inode.*/
+ /* Writing to or peeking a nonexistent block.
+ * Create and enter in inode.
+ */
if ((bp = new_block(rip, (off_t) ex64lo(position))) == NULL)
return(err_code);
}
- } else if (rw_flag == READING) {
+ } else if (rw_flag == READING || rw_flag == PEEKING) {
/* Read and read ahead if convenient. */
bp = rahead(rip, b, position, left);
} else {
/* Copy a chunk from the block buffer to user space. */
r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) buf_off,
(vir_bytes) (b_data(bp)+off), (size_t) chunk);
- } else {
+ } else if(rw_flag == WRITING) {
/* Copy a chunk from user space to the block buffer. */
r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) buf_off,
(vir_bytes) (b_data(bp)+off), (size_t) chunk);
fs_rdlink, /* 30 */
fs_getdents, /* 31 */
fs_statvfs, /* 32 */
+ fs_readwrite, /* 33 */
};
int fs_getdents(void);
int read_chunk(struct dir_record *rip, u64_t position, unsigned off, int
chunk, unsigned left, cp_grant_id_t gid, unsigned buf_off, int
- block_size, int *completed);
+ block_size, int *completed, int rw);
/* stadir.c */
int fs_stat(void);
unsigned int off, cum_io;
int completed;
struct dir_record *dir;
+ int rw;
+
+ switch(fs_m_in.m_type) {
+ case REQ_READ: rw = READING;
+ case REQ_PEEK: rw = PEEKING;
+ default: panic("odd m_type");
+ }
r = OK;
/* Read or write 'chunk' bytes. */
r = read_chunk(dir, cvul64(position), off, chunk, (unsigned) nrbytes,
- gid, cum_io, block_size, &completed);
+ gid, cum_io, block_size, &completed, rw);
if (r != OK) break; /* EOF reached */
if (rdwt_err < 0) break;
/* Read 'chunk' bytes. */
r = read_chunk(dir, position, off, chunk, (unsigned) nrbytes,
- gid, cum_io, block_size, &completed);
+ gid, cum_io, block_size, &completed, READING);
if (r != OK) break; /* EOF reached */
if (rdwt_err < 0) break;
/*===========================================================================*
* read_chunk *
*===========================================================================*/
-int read_chunk(dir, position, off, chunk, left, gid, buf_off, block_size, completed)
+int read_chunk(dir, position, off, chunk, left, gid, buf_off, block_size, completed, rw)
register struct dir_record *dir;/* pointer to inode for file to be rd/wr */
u64_t position; /* position within file to read or write */
unsigned off; /* off within the current block */
unsigned buf_off; /* offset in grant */
int block_size; /* block size of FS operating on */
int *completed; /* number of bytes copied */
+int rw; /* READING or PEEKING */
{
register struct buf *bp;
panic("bp not valid in rw_chunk; this can't happen");
}
- r = sys_safecopyto(VFS_PROC_NR, gid, buf_off,
+ if(rw == READING) {
+ r = sys_safecopyto(VFS_PROC_NR, gid, buf_off,
(vir_bytes) (b_data(bp)+off), (phys_bytes) chunk);
+ }
put_block(bp);
no_sys, /* 30: not used */
fs_getdents, /* 31 */
fs_statvfs, /* 32 */
+ fs_read /* 33 */
};
}
/* Get the values from the request message */
- rw_flag = (fs_m_in.m_type == REQ_READ ? READING : WRITING);
+ switch(fs_m_in.m_type) {
+ case REQ_READ: rw_flag = READING; break;
+ case REQ_WRITE: rw_flag = WRITING; break;
+ case REQ_PEEK: rw_flag = PEEKING; break;
+ default: panic("odd request");
+ }
gid = (cp_grant_id_t) fs_m_in.REQ_GRANT;
position = (off_t) fs_m_in.REQ_SEEK_POS_LO;
nrbytes = (size_t) fs_m_in.REQ_NBYTES;
unsigned off; /* off within the current block */
unsigned int chunk; /* number of bytes to read or write */
unsigned left; /* max number of bytes wanted after position */
-int rw_flag; /* READING or WRITING */
+int rw_flag; /* READING, WRITING or PEEKING */
cp_grant_id_t gid; /* grant */
unsigned buf_off; /* offset in grant */
unsigned int block_size; /* block size of FS operating on */
{
/* Read or write (part of) a block. */
- register struct buf *bp;
+ register struct buf *bp = NULL;
register int r = OK;
int n, block_spec;
block_t b;
dev_t dev;
+ /* rw_flag:
+ * READING: read from FS, copy to user
+ * WRITING: copy from user, write to FS
+ * PEEKING: try to get all the blocks into the cache, no copying
+ */
+
*completed = 0;
block_spec = (rip->i_mode & I_TYPE) == I_BLOCK_SPECIAL;
}
return r;
} else {
- /* Writing to a nonexistent block. Create and enter in inode.*/
+ /* Writing to or peeking a nonexistent block.
+ * Create and enter in inode.
+ */
if ((bp = new_block(rip, (off_t) ex64lo(position))) == NULL)
return(err_code);
}
- } else if (rw_flag == READING) {
+ } else if (rw_flag == READING || rw_flag == PEEKING) {
/* Read and read ahead if convenient. */
bp = rahead(rip, b, position, left);
} else {
}
/* In all cases, bp now points to a valid buffer. */
- if (bp == NULL)
- panic("bp not valid in rw_chunk; this can't happen");
+ assert(bp);
if (rw_flag == WRITING && chunk != block_size && !block_spec &&
(off_t) ex64lo(position) >= rip->i_size && off == 0) {
/* Copy a chunk from the block buffer to user space. */
r = sys_safecopyto(VFS_PROC_NR, gid, (vir_bytes) buf_off,
(vir_bytes) (b_data(bp)+off), (size_t) chunk);
- } else {
+ } else if(rw_flag == WRITING) {
/* Copy a chunk from user space to the block buffer. */
r = sys_safecopyfrom(VFS_PROC_NR, gid, (vir_bytes) buf_off,
(vir_bytes) (b_data(bp)+off), (size_t) chunk);
fs_rdlink, /* 30 */
fs_getdents, /* 31 */
fs_statvfs, /* 32 */
+ fs_readwrite, /* 33 */
};
void lock_bsf(void);
void unlock_bsf(void);
void check_bsf_lock(void);
-int do_read_write(int rw_flag);
+int do_read_write_peek(int rw_flag, int fd, char *buf, size_t bytes);
int read_write(int rw_flag, struct filp *f, char *buffer, size_t nbytes,
endpoint_t for_e);
int rw_pipe(int rw_flag, endpoint_t usr, struct filp *f, char *buf,
*===========================================================================*/
int do_read()
{
- return(do_read_write(READING));
+ return(do_read_write_peek(READING, job_m_in.fd,
+ job_m_in.buffer, (size_t) job_m_in.nbytes));
}
}
/*===========================================================================*
- * do_read_write *
+ * do_read_write_peek *
*===========================================================================*/
-int do_read_write(rw_flag)
-int rw_flag; /* READING or WRITING */
+int do_read_write_peek(int rw_flag, int io_fd, char *io_buf, size_t io_nbytes)
{
/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
struct filp *f;
tll_access_t locktype;
int r;
+ int ro = 1;
- scratch(fp).file.fd_nr = job_m_in.fd;
- scratch(fp).io.io_buffer = job_m_in.buffer;
- scratch(fp).io.io_nbytes = (size_t) job_m_in.nbytes;
+ if(rw_flag == WRITING) ro = 0;
- locktype = (rw_flag == READING) ? VNODE_READ : VNODE_WRITE;
+ scratch(fp).file.fd_nr = io_fd;
+ scratch(fp).io.io_buffer = io_buf;
+ scratch(fp).io.io_nbytes = io_nbytes;
+
+ locktype = ro ? VNODE_READ : VNODE_WRITE;
if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
return(err_code);
- if (((f->filp_mode) & (rw_flag == READING ? R_BIT : W_BIT)) == 0) {
+ if (((f->filp_mode) & (ro ? R_BIT : W_BIT)) == 0) {
unlock_filp(f);
return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
}
r = OK;
cum_io = 0;
+ assert(rw_flag == READING || rw_flag == WRITING || rw_flag == PEEKING);
+
if (size > SSIZE_MAX) return(EINVAL);
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
if (fp->fp_cum_io_partial != 0) {
panic("VFS: read_write: fp_cum_io_partial not clear");
}
+ if(rw_flag == PEEKING) return EINVAL;
r = rw_pipe(rw_flag, for_e, f, buf, size);
} else if (S_ISCHR(vp->v_mode)) { /* Character special files. */
dev_t dev;
int suspend_reopen;
+ int op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
+
+ if(rw_flag == PEEKING) return EINVAL;
if (vp->v_sdev == NO_DEV)
panic("VFS: read_write tries to access char dev NO_DEV");
if (vp->v_sdev == NO_DEV)
panic("VFS: read_write tries to access block dev NO_DEV");
+ if(rw_flag == PEEKING) return EINVAL;
+
lock_bsf();
r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position, size,
unsigned int *cum_iop;
{
int r;
- cp_grant_id_t grant_id;
+ cp_grant_id_t grant_id = -1;
message m;
+ int type = -1;
+ int grantflag = -1;
+
+ /* rw_flag:
+ * READING: do i/o from FS, copy into userspace
+ * WRITING: do i/o from userspace, copy into FS
+ * PEEKING: do i/o in FS, just get the blocks into the cache, no copy
+ */
if (ex64hi(pos) != 0)
panic("req_readwrite: pos too large");
- grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr, num_of_bytes,
- (rw_flag==READING ? CPF_WRITE:CPF_READ));
- if (grant_id == -1)
- panic("req_readwrite: cpf_grant_magic failed");
+ assert(rw_flag == READING || rw_flag == WRITING || rw_flag == PEEKING);
+
+ switch(rw_flag) {
+ case READING:
+ type = REQ_READ;
+ grantflag = CPF_WRITE;
+ /* fallthrough */
+ case WRITING:
+ if(type < 0) { type = REQ_WRITE; grantflag = CPF_READ; }
+ grant_id = cpf_grant_magic(fs_e, user_e, (vir_bytes) user_addr,
+ num_of_bytes, grantflag);
+ if (grant_id == -1)
+ panic("req_readwrite: cpf_grant_magic failed");
+ break;
+ case PEEKING:
+ type = REQ_PEEK;
+ break;
+ default:
+ panic("odd rw_flag");
+ }
/* Fill in request message */
- m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE;
+ m.m_type = type;
m.REQ_INODE_NR = inode_nr;
m.REQ_GRANT = grant_id;
m.REQ_SEEK_POS_LO = ex64lo(pos);
#include "fs.h"
#include "file.h"
+#include "param.h"
/*===========================================================================*
int do_write()
{
/* Perform the write(fd, buffer, nbytes) system call. */
- return(do_read_write(WRITING));
+ return(do_read_write_peek(WRITING, job_m_in.fd,
+ job_m_in.buffer, (size_t) job_m_in.nbytes));
}