]> Zhao Yanbai Git Server - minix.git/commitdiff
VFS, FSes: add REQ_PEEK request type 82/382/2
authorBen Gras <ben@minix3.org>
Sun, 13 Jan 2013 21:44:38 +0000 (21:44 +0000)
committerBen Gras <ben@minix3.org>
Thu, 7 Mar 2013 10:57:38 +0000 (10:57 +0000)
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

15 files changed:
include/minix/const.h
include/minix/vfsif.h
lib/libsffs/table.c
lib/libvtreefs/table.c
servers/ext2/read.c
servers/ext2/table.c
servers/iso9660fs/proto.h
servers/iso9660fs/read.c
servers/iso9660fs/table.c
servers/mfs/read.c
servers/mfs/table.c
servers/vfs/proto.h
servers/vfs/read.c
servers/vfs/request.c
servers/vfs/write.c

index 0afebcf6cfe603d4908b258e068ee51cecd7c1f1..65378668c5fb7130871f6879c42efaa5e2a512fe 100644 (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. */
index 00d703074c28dce933852b811e5e2d64b5343c87..f4aac02ccb1552a8aa4c3df3604f0ce0f620912e 100644 (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)
 
index 1744fcbfd0b17e373ef253d614addf81809fa0db..2573fb97d5caa0e5c8819b09244a6cac922c3bfb 100644 (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": */
index 4aef223a05b1b8f25c1b74f05070f1e1fbfc7269..8f73c1098bb047afa26ac05b5bde8457a0ebcd47 100644 (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": */
index 3597acf2655c6c915b1f6ff0d4b0f75b768b92c6..50cc875cb1fed03a60a9dc2ba9d4db377c19db77 100644 (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);
index 6c384a3d653a26c731e295d6edf858025bfd74ae..2ebfcbce283a51b42c11136c369716c61674a004 100644 (file)
@@ -46,4 +46,5 @@ int (*fs_call_vec[])(void) = {
     fs_rdlink,          /* 30  */
     fs_getdents,        /* 31  */
     fs_statvfs,                /* 32  */
+    fs_readwrite,       /* 33  */
 };
index dcc92ce1fff0ce097fd0cc8e033d1c7d30b47d19..f99d570937dcd44f0a49390931c77e469e448e99 100644 (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);
index bd097581f5bed9256b8ef63431c5101debeb6aa9..2e6073a6cbd96f91366ce1e932ed9b280338c6de 100644 (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);
 
index 307ff4cda4166cde0d0f46332aba69a1997840af..e6cb5d387a4f36db31bac5f5ce85f058c9c69b99 100644 (file)
@@ -41,4 +41,5 @@ int (*fs_call_vec[])(void) = {
   no_sys,                      /* 30: not used */
   fs_getdents,                 /* 31 */
   fs_statvfs,                  /* 32 */
+  fs_read                      /* 33 */
 };
index 408359ad3d59183e030a41b08e38cd3d6073407e..3e016e72c08951293b888a0ffc185753f5e6cea6 100644 (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);
index 42fee46ee97a4143b23b2a24832d63f19a5c7163..d54c91558151715f9ed2722e5eba1e600eff66ed 100644 (file)
@@ -44,5 +44,6 @@ int (*fs_call_vec[])(void) = {
         fs_rdlink,         /* 30  */
         fs_getdents,       /* 31  */
         fs_statvfs,         /* 32  */
+        fs_readwrite,       /* 33  */
 };
 
index ee3df9f25c7f9031212a54a3135d87d2a605ed53..7bfff497adee85d8bb7027a6ef3f30eea40aa3e6 100644 (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,
index 90e8c4a72b707bc0881fb9d4dd7eea888916638c..e85531a19f5cd6fe1891408634c27a2f87042e85 100644 (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,
index de25c4c4179eecb856650fa64fdbbc7747bc8acc..443ba69053e0fc38b802de83c79b2d75dc1b0530 100644 (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);
index 80975b15020a7a86de329a568793372c220bfe56..6d9e939e4b80729a001cb3ec35cefcbfa5a145e6 100644 (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));
 }