From 44f34e53d57e040e3eb0d230c42ceb6b28dc4fbf Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Sat, 16 Mar 2013 04:09:36 +0000 Subject: [PATCH] VFS: Implement REQ_BPEEK. This commit introduces a new request type called REQ_BPEEK. It requests minor device blocks from the FS. Analogously to REQ_PEEK, it requests the filesystem to get the requested blocks into its cache, without actually copying the result anywhere. Change-Id: If1d06645b0e17553a64b3167091e9d12efeb3d6f --- include/minix/vfsif.h | 3 +- lib/libminixfs/cache.c | 30 ++++++++++++++++ lib/libpuffs/table.c | 2 ++ lib/libsffs/table.c | 1 + lib/libvtreefs/table.c | 1 + servers/mfs/misc.c | 5 +++ servers/mfs/proto.h | 1 + servers/mfs/table.c | 3 ++ servers/vfs/mount.c | 7 ++++ servers/vfs/proto.h | 2 ++ servers/vfs/request.c | 80 ++++++++++++++++++++++++++---------------- servers/vfs/vmnt.h | 1 + 12 files changed, 105 insertions(+), 31 deletions(-) diff --git a/include/minix/vfsif.h b/include/minix/vfsif.h index 35fc94e7d..10a8568f4 100644 --- a/include/minix/vfsif.h +++ b/include/minix/vfsif.h @@ -117,8 +117,9 @@ typedef struct { #define REQ_GETDENTS (VFS_BASE + 31) #define REQ_STATVFS (VFS_BASE + 32) #define REQ_PEEK (VFS_BASE + 33) +#define REQ_BPEEK (VFS_BASE + 34) -#define NREQS 34 +#define NREQS 35 #define IS_VFS_RQ(type) (((type) & ~0xff) == VFS_BASE) diff --git a/lib/libminixfs/cache.c b/lib/libminixfs/cache.c index eb55bc808..579a02cfe 100644 --- a/lib/libminixfs/cache.c +++ b/lib/libminixfs/cache.c @@ -855,3 +855,33 @@ int lmfs_rdwt_err(void) return rdwt_err; } +int lmfs_do_bpeek(message *m) +{ + block_t startblock, b, limitblock; + dev_t dev = m->REQ_DEV2; + u64_t extra, pos = make64(m->REQ_SEEK_POS_LO, m->REQ_SEEK_POS_HI); + size_t len = m->REQ_NBYTES; + struct buf *bp; + + assert(m->m_type == REQ_BPEEK); + assert(fs_block_size > 0); + assert(dev != NO_DEV); + + if((extra=(pos % fs_block_size))) { + pos -= extra; + len += extra; + } + + len = roundup(len, fs_block_size); + + startblock = pos/fs_block_size; + limitblock = startblock + len/fs_block_size; + + for(b = startblock; b < limitblock; b++) { + bp = lmfs_get_block(dev, b, NORMAL); + assert(bp); + lmfs_put_block(bp, FULL_DATA_BLOCK); + } + + return OK; +} diff --git a/lib/libpuffs/table.c b/lib/libpuffs/table.c index 50f5bddb6..b28cf6766 100644 --- a/lib/libpuffs/table.c +++ b/lib/libpuffs/table.c @@ -43,4 +43,6 @@ int (*fs_call_vec[])(void) = { fs_rdlink, /* 30 */ fs_getdents, /* 31 */ fs_statvfs, /* 32 */ + no_sys, /* 33 peek */ + no_sys, /* 34 bpeek */ }; diff --git a/lib/libsffs/table.c b/lib/libsffs/table.c index 2573fb97d..35e778dec 100644 --- a/lib/libsffs/table.c +++ b/lib/libsffs/table.c @@ -42,6 +42,7 @@ int (*call_vec[])(void) = { do_getdents, /* 31 getdents */ do_statvfs, /* 32 statvfs */ no_sys, /* 33 peek */ + no_sys, /* 33 bpeek */ }; /* This should not fail with "array size is negative": */ diff --git a/lib/libvtreefs/table.c b/lib/libvtreefs/table.c index 8f73c1098..d3f20fac5 100644 --- a/lib/libvtreefs/table.c +++ b/lib/libvtreefs/table.c @@ -38,6 +38,7 @@ int (*fs_call_vec[])(void) = { fs_getdents, /* 31 getdents */ fs_statvfs, /* 32 statvfs */ no_sys, /* 33 peek */ + no_sys, /* 34 bpeek */ }; /* This should not fail with "array size is negative": */ diff --git a/servers/mfs/misc.c b/servers/mfs/misc.c index 326e86f28..036d84cda 100644 --- a/servers/mfs/misc.c +++ b/servers/mfs/misc.c @@ -79,3 +79,8 @@ int fs_new_driver(void) return(OK); } + +int fs_bpeek(void) +{ + return lmfs_do_bpeek(&fs_m_in); +} diff --git a/servers/mfs/proto.h b/servers/mfs/proto.h index e7634f615..38e4fc5d5 100644 --- a/servers/mfs/proto.h +++ b/servers/mfs/proto.h @@ -41,6 +41,7 @@ int truncate_inode(struct inode *rip, off_t len); int fs_flush(void); int fs_sync(void); int fs_new_driver(void); +int fs_bpeek(void); /* mount.c */ int fs_mountpoint(void); diff --git a/servers/mfs/table.c b/servers/mfs/table.c index d54c91558..1fb73334e 100644 --- a/servers/mfs/table.c +++ b/servers/mfs/table.c @@ -3,6 +3,8 @@ * routines that perform them. */ +#include + #define _TABLE #include "fs.h" @@ -45,5 +47,6 @@ int (*fs_call_vec[])(void) = { fs_getdents, /* 31 */ fs_statvfs, /* 32 */ fs_readwrite, /* 33 */ + fs_bpeek, /* 34 */ }; diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index 51517ef46..6db6b379d 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -282,6 +282,13 @@ char mount_label[LABEL_MAX] ) r = req_readsuper(fs_e, label, dev, rdonly, isroot, &res, &con_reqs); new_vmp->m_flags &= ~VMNT_MOUNTING; + if(req_peek(fs_e, 1, 0, PAGE_SIZE) != OK || + req_bpeek(fs_e, dev, 0, PAGE_SIZE) != OK) { + new_vmp->m_haspeek = 0; + } else { + new_vmp->m_haspeek = 1; + } + if (r != OK) { mark_vmnt_free(new_vmp); unlock_vnode(root_node); diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 5eec16aee..a2fe8728b 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -254,6 +254,8 @@ int req_readsuper(endpoint_t fs_e, char *driver_name, dev_t dev, int readonly, int req_readwrite(endpoint_t fs_e, ino_t inode_nr, u64_t pos, int rw_flag, endpoint_t user_e, char *user_addr, unsigned int num_of_bytes, u64_t *new_posp, unsigned int *cum_iop); +int req_bpeek(endpoint_t fs_e, dev_t dev, u64_t pos, unsigned int num_of_bytes); +int req_peek(endpoint_t fs_e, ino_t inode_nr, u64_t pos, unsigned int bytes); int req_rename(endpoint_t fs_e, ino_t old_dir, char *old_name, ino_t new_dir, char *new_name); int req_rmdir(endpoint_t fs_e, ino_t inode_nr, char *lastc); diff --git a/servers/vfs/request.c b/servers/vfs/request.c index 4eab2791e..d1cd0b02e 100644 --- a/servers/vfs/request.c +++ b/servers/vfs/request.c @@ -69,6 +69,27 @@ int req_breadwrite( return(OK); } +/*===========================================================================* + * req_bpeek * + *===========================================================================*/ +int req_bpeek(endpoint_t fs_e, dev_t dev, u64_t pos, unsigned int num_of_bytes) +{ + message m; + + memset(&m, 0, sizeof(m)); + + /* Fill in request message */ + m.m_type = REQ_BPEEK; + m.REQ_DEV2 = dev; + m.REQ_SEEK_POS_LO = ex64lo(pos); + m.REQ_SEEK_POS_HI = ex64hi(pos); + m.REQ_NBYTES = num_of_bytes; + + /* Send/rec request */ + return fs_sendrec(fs_e, &m); + + return(OK); +} /*===========================================================================* * req_chmod * @@ -762,43 +783,19 @@ u64_t *new_posp; unsigned int *cum_iop; { int r; - cp_grant_id_t grant_id = -1; + cp_grant_id_t grant_id; 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"); - 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"); - } + 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"); /* Fill in request message */ - m.m_type = type; + m.m_type = rw_flag == READING ? REQ_READ : REQ_WRITE; m.REQ_INODE_NR = inode_nr; m.REQ_GRANT = grant_id; m.REQ_SEEK_POS_LO = ex64lo(pos); @@ -818,6 +815,29 @@ unsigned int *cum_iop; return(r); } +/*===========================================================================* + * req_peek * + *===========================================================================*/ +int req_peek(endpoint_t fs_e, ino_t inode_nr, u64_t pos, unsigned int bytes) +{ + message m; + + memset(&m, 0, sizeof(m)); + + if (ex64hi(pos) != 0) + panic("req_peek: pos too large"); + + /* Fill in request message */ + m.m_type = REQ_PEEK; + m.REQ_INODE_NR = inode_nr; + m.REQ_GRANT = -1; + m.REQ_SEEK_POS_LO = ex64lo(pos); + m.REQ_SEEK_POS_HI = 0; /* Not used for now, so clear it. */ + m.REQ_NBYTES = bytes; + + /* Send/rec request */ + return fs_sendrec(fs_e, &m); +} /*===========================================================================* * req_rename * diff --git a/servers/vfs/vmnt.h b/servers/vfs/vmnt.h index 2d3156e5f..40c032a3f 100644 --- a/servers/vfs/vmnt.h +++ b/servers/vfs/vmnt.h @@ -15,6 +15,7 @@ EXTERN struct vmnt { char m_label[LABEL_MAX]; /* label of the file system process */ char m_mount_path[PATH_MAX]; /* path on which vmnt is mounted */ char m_mount_dev[PATH_MAX]; /* path on which vmnt is mounted */ + int m_haspeek; /* supports REQ_PEEK, REQ_BPEEK */ } vmnt[NR_MNTS]; /* vmnt flags */