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:
Ben Gras 2013-01-13 21:44:38 +00:00
parent 1ba514e19c
commit a9f55a2e46
15 changed files with 116 additions and 37 deletions

View file

@ -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. */

View file

@ -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)

View file

@ -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": */

View file

@ -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": */

View file

@ -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);

View file

@ -46,4 +46,5 @@ int (*fs_call_vec[])(void) = {
fs_rdlink, /* 30 */
fs_getdents, /* 31 */
fs_statvfs, /* 32 */
fs_readwrite, /* 33 */
};

View file

@ -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);

View file

@ -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");
}
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);

View file

@ -41,4 +41,5 @@ int (*fs_call_vec[])(void) = {
no_sys, /* 30: not used */
fs_getdents, /* 31 */
fs_statvfs, /* 32 */
fs_read /* 33 */
};

View file

@ -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);

View file

@ -44,5 +44,6 @@ int (*fs_call_vec[])(void) = {
fs_rdlink, /* 30 */
fs_getdents, /* 31 */
fs_statvfs, /* 32 */
fs_readwrite, /* 33 */
};

View file

@ -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,

View file

@ -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,

View file

@ -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));
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);

View file

@ -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));
}