VFS, FSes: add REQ_PEEK request type
REQ_PEEK behaves just like REQ_READ except that it does not copy data anywhere, just obtains the blocks from the FS into the cache. To be used by the future mmap implementation. Change-Id: I1b56de304f0a7152b69a72c8962d04258adb44f9
This commit is contained in:
parent
1ba514e19c
commit
a9f55a2e46
15 changed files with 116 additions and 37 deletions
|
@ -72,6 +72,7 @@
|
|||
#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. */
|
||||
|
|
|
@ -114,8 +114,9 @@ typedef struct {
|
|||
#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)
|
||||
|
||||
|
|
|
@ -41,6 +41,7 @@ int (*call_vec[])(void) = {
|
|||
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": */
|
||||
|
|
|
@ -37,6 +37,7 @@ int (*fs_call_vec[])(void) = {
|
|||
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": */
|
||||
|
|
|
@ -60,8 +60,13 @@ int fs_readwrite(void)
|
|||
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;
|
||||
|
@ -206,7 +211,7 @@ u64_t position; /* position within file to read or write */
|
|||
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 */
|
||||
|
@ -214,12 +219,18 @@ int *completed; /* number of bytes copied */
|
|||
{
|
||||
/* 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;
|
||||
|
@ -244,11 +255,13 @@ int *completed; /* number of bytes copied */
|
|||
}
|
||||
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 {
|
||||
|
@ -275,7 +288,7 @@ int *completed; /* number of bytes copied */
|
|||
/* 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);
|
||||
|
|
|
@ -46,4 +46,5 @@ int (*fs_call_vec[])(void) = {
|
|||
fs_rdlink, /* 30 */
|
||||
fs_getdents, /* 31 */
|
||||
fs_statvfs, /* 32 */
|
||||
fs_readwrite, /* 33 */
|
||||
};
|
||||
|
|
|
@ -50,7 +50,7 @@ int fs_bread(void);
|
|||
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);
|
||||
|
|
|
@ -19,6 +19,13 @@ int fs_read(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;
|
||||
|
||||
|
@ -48,7 +55,7 @@ int fs_read(void) {
|
|||
|
||||
/* 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;
|
||||
|
@ -106,7 +113,7 @@ int fs_bread(void)
|
|||
|
||||
/* 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;
|
||||
|
@ -280,7 +287,7 @@ int fs_getdents(void) {
|
|||
/*===========================================================================*
|
||||
* 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 */
|
||||
|
@ -290,6 +297,7 @@ cp_grant_id_t gid; /* grant */
|
|||
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;
|
||||
|
@ -325,8 +333,10 @@ int *completed; /* number of bytes copied */
|
|||
panic("bp not valid in rw_chunk; this can't happen");
|
||||
}
|
||||
|
||||
if(rw == READING) {
|
||||
r = sys_safecopyto(VFS_PROC_NR, gid, buf_off,
|
||||
(vir_bytes) (b_data(bp)+off), (phys_bytes) chunk);
|
||||
}
|
||||
|
||||
put_block(bp);
|
||||
|
||||
|
|
|
@ -41,4 +41,5 @@ int (*fs_call_vec[])(void) = {
|
|||
no_sys, /* 30: not used */
|
||||
fs_getdents, /* 31 */
|
||||
fs_statvfs, /* 32 */
|
||||
fs_read /* 33 */
|
||||
};
|
||||
|
|
|
@ -53,7 +53,12 @@ int fs_readwrite(void)
|
|||
}
|
||||
|
||||
/* 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;
|
||||
|
@ -215,7 +220,7 @@ u64_t position; /* position within file to read or write */
|
|||
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 */
|
||||
|
@ -223,12 +228,18 @@ int *completed; /* number of bytes copied */
|
|||
{
|
||||
/* 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;
|
||||
|
@ -253,11 +264,13 @@ int *completed; /* number of bytes copied */
|
|||
}
|
||||
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 {
|
||||
|
@ -272,8 +285,7 @@ int *completed; /* number of bytes copied */
|
|||
}
|
||||
|
||||
/* 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) {
|
||||
|
@ -284,7 +296,7 @@ int *completed; /* number of bytes copied */
|
|||
/* 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);
|
||||
|
|
|
@ -44,5 +44,6 @@ int (*fs_call_vec[])(void) = {
|
|||
fs_rdlink, /* 30 */
|
||||
fs_getdents, /* 31 */
|
||||
fs_statvfs, /* 32 */
|
||||
fs_readwrite, /* 33 */
|
||||
};
|
||||
|
||||
|
|
|
@ -210,7 +210,7 @@ int do_getdents(void);
|
|||
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,
|
||||
|
|
|
@ -31,7 +31,8 @@
|
|||
*===========================================================================*/
|
||||
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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -82,24 +83,26 @@ void check_bsf_lock(void)
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* 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);
|
||||
}
|
||||
|
@ -131,6 +134,8 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
|||
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);
|
||||
|
@ -139,10 +144,14 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
|||
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");
|
||||
|
@ -161,6 +170,8 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
|||
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,
|
||||
|
|
|
@ -762,19 +762,43 @@ u64_t *new_posp;
|
|||
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));
|
||||
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);
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
|
||||
#include "fs.h"
|
||||
#include "file.h"
|
||||
#include "param.h"
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -15,5 +16,6 @@
|
|||
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));
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue