]> Zhao Yanbai Git Server - minix.git/commitdiff
MFS: annotate cache blocks with inode metadata 06/406/7
authorBen Gras <ben@minix3.org>
Sat, 16 Mar 2013 02:29:32 +0000 (02:29 +0000)
committerBen Gras <ben@minix3.org>
Wed, 24 Apr 2013 10:18:16 +0000 (10:18 +0000)
. use lmfs_* cache functions that provide the cache with inode
  metadata whenever applicable, i.e. tell the cache code which
  inode number and in-inode offset a particular cache block
  corresponds to.
. needed for mmap implementation

Change-Id: Ic7d3c0c49029880f86a31368278722e907bc2896

servers/mfs/link.c
servers/mfs/path.c
servers/mfs/proto.h
servers/mfs/read.c
servers/mfs/table.c
servers/mfs/write.c

index d148d5214da86a0fc7f19e1d6f9e4ef7c2257e07..621d3c432de779da0e3732ffe18ca5576155acba 100644 (file)
@@ -6,6 +6,7 @@
 #include "inode.h"
 #include "super.h"
 #include <minix/vfsif.h>
+#include <sys/param.h>
 
 #define SAME 1000
 
@@ -172,7 +173,6 @@ int fs_unlink()
  *===========================================================================*/
 int fs_rdlink()
 {
-  block_t b;                   /* block containing link text */
   struct buf *bp;              /* buffer containing link text */
   register struct inode *rip;  /* target inode */
   register int r;              /* return value */
@@ -186,14 +186,13 @@ int fs_rdlink()
 
   if(!S_ISLNK(rip->i_mode))
          r = EACCES;
-  else if ((b = read_map(rip, (off_t) 0)) == NO_BLOCK)
-       r = EIO;
   else {
+       if(!(bp = get_block_map(rip, 0)))
+               return EIO;
        /* Passed all checks */
        /* We can safely cast to unsigned, because copylen is guaranteed to be
           below max file size */
        copylen = min( copylen, (unsigned) rip->i_size);
-       bp = get_block(rip->i_dev, b, NORMAL);
        r = sys_safecopyto(VFS_PROC_NR, (cp_grant_id_t) fs_m_in.REQ_GRANT,
                           (vir_bytes) 0, (vir_bytes) b_data(bp),
                           (size_t) copylen);
@@ -677,7 +676,6 @@ off_t len;
 {
 /* Zero an arbitrary byte range in a zone, possibly spanning multiple blocks.
  */
-  block_t b;
   struct buf *bp;
   off_t offset;
   unsigned short block_size;
@@ -686,10 +684,10 @@ off_t len;
   block_size = rip->i_sp->s_block_size;
 
   if(!len) return; /* no zeroing to be done. */
-  if( (b = read_map(rip, pos)) == NO_BLOCK) return;
+
   while (len > 0) {
-       if( (bp = get_block(rip->i_dev, b, NORMAL)) == NULL)
-               panic("zerozone_range: no block");
+       if( (bp = get_block_map(rip, rounddown(pos, block_size))) == NULL)
+               return;
        offset = pos % block_size;
        bytes = block_size - offset;
        if (bytes > (size_t) len)
@@ -700,7 +698,6 @@ off_t len;
 
        pos += bytes;
        len -= bytes;
-       b++;
   }
 }
 
index f558c89c4a10a7258d20df0dc6a411bb046f10d7..1e876aade6c335e228eddc673a0af00d576f1a55 100644 (file)
@@ -287,16 +287,13 @@ char *suffix;                     /* current remaining path. Has to point in the
  * new pathname.
  */
   
-  block_t blink;       /* block containing link text */
   size_t llen;         /* length of link */
   size_t slen;         /* length of suffix */
   struct buf *bp;      /* buffer containing link text */
   char *sp;            /* start of link text */
 
-  if ((blink = read_map(rip, (off_t) 0)) == NO_BLOCK)
+  if(!(bp = get_block_map(rip, 0)))
        return(EIO);
-
-  bp = get_block(rip->i_dev, blink, NORMAL);
   llen = (size_t) rip->i_size;
   sp = b_data(bp);
   slen = strlen(suffix);
@@ -485,7 +482,6 @@ int check_permissions;               /* check permissions when flag is !IS_EMPTY */
   mode_t bits;
   off_t pos;
   unsigned new_slots, old_slots;
-  block_t b;
   struct super_block *sp;
   int extended = 0;
 
@@ -524,12 +520,14 @@ int check_permissions;             /* check permissions when flag is !IS_EMPTY */
   }
 
   for (; pos < ldir_ptr->i_size; pos += ldir_ptr->i_sp->s_block_size) {
-       b = read_map(ldir_ptr, pos);    /* get block number */
+       assert(ldir_ptr->i_dev != NO_DEV);
 
        /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
-       bp = get_block(ldir_ptr->i_dev, b, NORMAL);     /* get a dir block */
+       bp = get_block_map(ldir_ptr, pos);
 
+       assert(ldir_ptr->i_dev != NO_DEV);
        assert(bp != NULL);
+       assert(lmfs_dev(bp) != NO_DEV);
 
        /* Search a directory block. */
        for (dp = &b_dir(bp)[0];
@@ -573,6 +571,7 @@ int check_permissions;               /* check permissions when flag is !IS_EMPTY */
                                *numb = (ino_t) conv4(sp->s_native,
                                                      (int) dp->mfs_d_ino);
                        }
+                       assert(lmfs_dev(bp) != NO_DEV);
                        put_block(bp, DIRECTORY_BLOCK);
                        return(r);
                }
@@ -586,6 +585,7 @@ int check_permissions;               /* check permissions when flag is !IS_EMPTY */
 
        /* The whole block has been searched or ENTER has a free slot. */
        if (e_hit) break;       /* e_hit set if ENTER can be performed now */
+       assert(lmfs_dev(bp) != NO_DEV);
        put_block(bp, DIRECTORY_BLOCK); /* otherwise, continue searching dir */
   }
 
index 403a39780eb77b28a08717007bdf219abb76b2e1..e7634f615e4f1d7bcd2078fed035a2966c155086 100644 (file)
@@ -73,7 +73,8 @@ int read_only(struct inode *ip);
 int fs_breadwrite(void);
 int fs_readwrite(void);
 void read_ahead(void);
-block_t read_map(struct inode *rip, off_t pos);
+block_t read_map(struct inode *rip, off_t pos, int opportunistic);
+struct buf *get_block_map(register struct inode *rip, u64_t position);
 zone_t rd_indir(struct buf *bp, int index);
 
 /* stadir.c */
index 3e016e72c08951293b888a0ffc185753f5e6cea6..0146f5bed8b9a31ad7ac90d64101c850b53595bb 100644 (file)
@@ -8,6 +8,7 @@
 #include "inode.h"
 #include "super.h"
 #include <minix/vfsif.h>
+#include <sys/param.h>
 #include <assert.h>
 
 
@@ -62,7 +63,7 @@ int fs_readwrite(void)
   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;
-  
+
   lmfs_reset_rdwt_err();
 
   /* If this is file i/o, check we can write */
@@ -233,6 +234,8 @@ int *completed;                     /* number of bytes copied */
   int n, block_spec;
   block_t b;
   dev_t dev;
+  ino_t ino = VMC_NO_INODE;
+  u64_t ino_off = rounddown(position, block_size);
 
   /* rw_flag:
    *   READING: read from FS, copy to user
@@ -250,8 +253,10 @@ int *completed;                    /* number of bytes copied */
   } else {
        if (ex64hi(position) != 0)
                panic("rw_chunk: position too high");
-       b = read_map(rip, (off_t) ex64lo(position));
+       b = read_map(rip, (off_t) ex64lo(position), 0);
        dev = rip->i_dev;
+       ino = rip->i_num;
+       assert(ino != VMC_NO_INODE);
   }
 
   if (!block_spec && b == NO_BLOCK) {
@@ -281,7 +286,14 @@ int *completed;                    /* number of bytes copied */
        n = (chunk == block_size ? NO_READ : NORMAL);
        if (!block_spec && off == 0 && (off_t) ex64lo(position) >= rip->i_size) 
                n = NO_READ;
-       bp = get_block(dev, b, n);
+       if(block_spec) {
+               assert(ino == VMC_NO_INODE);
+               bp = get_block(dev, b, n);
+       } else {
+               assert(ino != VMC_NO_INODE);
+               assert(!(ino_off % block_size));
+               bp = lmfs_get_block_ino(dev, b, n, ino, ino_off);
+       }
   }
 
   /* In all cases, bp now points to a valid buffer. */
@@ -313,9 +325,10 @@ int *completed;                    /* number of bytes copied */
 /*===========================================================================*
  *                             read_map                                     *
  *===========================================================================*/
-block_t read_map(rip, position)
+block_t read_map(rip, position, opportunistic)
 register struct inode *rip;    /* ptr to inode to map from */
 off_t position;                        /* position in file whose blk wanted */
+int opportunistic;             /* if nonzero, only use cache for metadata */
 {
 /* Given an inode and a position within the corresponding file, locate the
  * block (not zone) number in which that position is to be found and return it.
@@ -327,7 +340,10 @@ off_t position;                    /* position in file whose blk wanted */
   unsigned int dzones, nr_indirects;
   block_t b;
   unsigned long excess, zone, block_pos;
-  
+  int iomode = NORMAL;
+
+  if(opportunistic) iomode = PREFETCH;
+
   scale = rip->i_sp->s_log_zone_size;  /* for block-zone conversion */
   block_pos = position/rip->i_sp->s_block_size;        /* relative blk # in file */
   zone = block_pos >> scale;   /* position's zone */
@@ -359,7 +375,11 @@ off_t position;                    /* position in file whose blk wanted */
        index = (int) (excess/nr_indirects);
        if ((unsigned int) index > rip->i_nindirs)
                return(NO_BLOCK);       /* Can't go beyond double indirects */
-       bp = get_block(rip->i_dev, b, NORMAL);  /* get double indirect block */
+       bp = get_block(rip->i_dev, b, iomode); /* get double indirect block */
+       if(opportunistic && lmfs_dev(bp) == NO_DEV) {
+               put_block(bp, INDIRECT_BLOCK);
+               return NO_BLOCK;
+       }
        ASSERT(lmfs_dev(bp) != NO_DEV);
        ASSERT(lmfs_dev(bp) == rip->i_dev);
        z = rd_indir(bp, index);                /* z= zone for single*/
@@ -370,7 +390,11 @@ off_t position;                    /* position in file whose blk wanted */
   /* 'z' is zone num for single indirect block; 'excess' is index into it. */
   if (z == NO_ZONE) return(NO_BLOCK);
   b = (block_t) z << scale;                    /* b is blk # for single ind */
-  bp = get_block(rip->i_dev, b, NORMAL);       /* get single indirect block */
+  bp = get_block(rip->i_dev, b, iomode);       /* get single indirect block */
+  if(opportunistic && lmfs_dev(bp) == NO_DEV) {
+       put_block(bp, INDIRECT_BLOCK);
+       return NO_BLOCK;
+  }
   z = rd_indir(bp, (int) excess);              /* get block pointed to */
   put_block(bp, INDIRECT_BLOCK);               /* release single indir blk */
   if (z == NO_ZONE) return(NO_BLOCK);
@@ -378,6 +402,16 @@ off_t position;                    /* position in file whose blk wanted */
   return(b);
 }
 
+struct buf *get_block_map(register struct inode *rip, u64_t position)
+{
+       block_t b = read_map(rip, position, 0); /* get block number */
+       int block_size = get_block_size(rip->i_dev);
+       if(b == NO_BLOCK)
+               return NULL;
+       position = rounddown(position, block_size);
+       assert(rip->i_num != VMC_NO_INODE);
+       return lmfs_get_block_ino(rip->i_dev, b, NORMAL, rip->i_num, position);
+}
 
 /*===========================================================================*
  *                             rd_indir                                     *
@@ -442,6 +476,7 @@ unsigned bytes_ahead;               /* bytes beyond position for immediate use */
   struct buf *bp;
   static unsigned int readqsize = 0;
   static struct buf **read_q;
+  u64_t position_running;
 
   if(readqsize != nr_bufs) {
        if(readqsize > 0) {
@@ -458,11 +493,24 @@ unsigned bytes_ahead;             /* bytes beyond position for immediate use */
        dev = (dev_t) rip->i_zone[0];
   else 
        dev = rip->i_dev;
+
+  assert(dev != NO_DEV);
   
   block_size = get_block_size(dev);
 
   block = baseblock;
-  bp = get_block(dev, block, PREFETCH);
+
+  fragment = position % block_size;
+  position -= fragment;
+  position_running = position;
+  bytes_ahead += fragment;
+  blocks_ahead = (bytes_ahead + block_size - 1) / block_size;
+
+  if(block_spec)
+         bp = get_block(dev, block, PREFETCH);
+  else
+         bp = lmfs_get_block_ino(dev, block, PREFETCH, rip->i_num, position);
+
   assert(bp != NULL);
   if (lmfs_dev(bp) != NO_DEV) return(bp);
 
@@ -486,12 +534,6 @@ unsigned bytes_ahead;              /* bytes beyond position for immediate use */
    * indirect blocks (but don't call read_map!).
    */
 
-  fragment = rem64u(position, block_size);
-  position = sub64u(position, fragment);
-  bytes_ahead += fragment;
-
-  blocks_ahead = (bytes_ahead + block_size - 1) / block_size;
-
   if (block_spec && rip->i_size == 0) {
        blocks_left = (block_t) NR_IOREQS;
   } else {
@@ -524,6 +566,7 @@ unsigned bytes_ahead;               /* bytes beyond position for immediate use */
 
   /* Acquire block buffers. */
   for (;;) {
+       block_t thisblock;
        read_q[read_q_size++] = bp;
 
        if (--blocks_ahead == 0) break;
@@ -532,8 +575,14 @@ unsigned bytes_ahead;              /* bytes beyond position for immediate use */
        if (lmfs_bufs_in_use() >= nr_bufs - 4) break;
 
        block++;
+       position_running += block_size;
 
-       bp = get_block(dev, block, PREFETCH);
+       if(!block_spec && 
+         (thisblock = read_map(rip, (off_t) ex64lo(position_running), 1)) != NO_BLOCK) {
+               bp = lmfs_get_block_ino(dev, thisblock, PREFETCH, rip->i_num, position_running);
+       } else {
+               bp = get_block(dev, block, PREFETCH);
+       }
        if (lmfs_dev(bp) != NO_DEV) {
                /* Oops, block already in the cache, get out. */
                put_block(bp, FULL_DATA_BLOCK);
@@ -541,7 +590,10 @@ unsigned bytes_ahead;              /* bytes beyond position for immediate use */
        }
   }
   lmfs_rw_scattered(dev, read_q, read_q_size, READING);
-  return(get_block(dev, baseblock, NORMAL));
+
+  if(block_spec)
+         return get_block(dev, baseblock, NORMAL);
+  return(lmfs_get_block_ino(dev, baseblock, NORMAL, rip->i_num, position));
 }
 
 
@@ -557,7 +609,6 @@ int fs_getdents(void)
   int o, r, done;
   unsigned int block_size, len, reclen;
   ino_t ino;
-  block_t b;
   cp_grant_id_t gid;
   size_t size, tmpbuf_off, userbuf_off;
   off_t pos, off, block_pos, new_pos, ent_pos;
@@ -592,11 +643,8 @@ int fs_getdents(void)
   new_pos = rip->i_size;
 
   for(; block_pos < rip->i_size; block_pos += block_size) {
-       b = read_map(rip, block_pos);   /* get block number */
-         
-       /* Since directories don't have holes, 'b' cannot be NO_BLOCK. */
-       bp = get_block(rip->i_dev, b, NORMAL);  /* get a dir block */
-
+       /* Since directories don't have holes, 'bp' cannot be NULL. */
+       bp = get_block_map(rip, block_pos);     /* get a dir block */
        assert(bp != NULL);
 
          /* Search a directory block. */
index 8d19c3b8abd905d5cfc495ebec4b252f29ab5540..d54c91558151715f9ed2722e5eba1e600eff66ed 100644 (file)
@@ -44,6 +44,6 @@ int (*fs_call_vec[])(void) = {
         fs_rdlink,         /* 30  */
         fs_getdents,       /* 31  */
         fs_statvfs,         /* 32  */
-        no_sys,             /* 33  */          /* peek not supported */
+        fs_readwrite,       /* 33  */
 };
 
index 1e7e5729f813b52fbaa9c3753af82ed5de7361db..0dbacbc3bf36deb4d75629f6384d4eb37f604981 100644 (file)
@@ -11,6 +11,8 @@
 
 #include "fs.h"
 #include <string.h>
+#include <assert.h>
+#include <sys/param.h>
 #include "buf.h"
 #include "inode.h"
 #include "super.h"
@@ -99,7 +101,8 @@ int op;                              /* special actions */
                z1 = NO_ZONE;
        } else {
                b = (block_t) z << scale;
-               bp_dindir = get_block(rip->i_dev, b, (new_dbl?NO_READ:NORMAL));
+               bp_dindir = get_block(rip->i_dev, b,
+                       (new_dbl?NO_READ:NORMAL));
                if (new_dbl) zero_block(bp_dindir);
                z1 = rd_indir(bp_dindir, ind_ex);
        }
@@ -239,31 +242,12 @@ int flag;                 /* 1 if called by new_block, 0 otherwise */
  * a byte in the first block to be zeroed.  Clearzone() is called from 
  * fs_readwrite(), truncate_inode(), and new_block().
  */
-
-  struct buf *bp;
-  block_t b, blo, bhi;
-  off_t next;
-  int scale, zone_size;
+  int scale;
 
   /* If the block size and zone size are the same, clear_zone() not needed. */
   scale = rip->i_sp->s_log_zone_size;
-  if (scale == 0) return;
-
-  zone_size = rip->i_sp->s_block_size << scale;
-  if (flag == 1) pos = (off_t) ((pos/zone_size) * zone_size);
-  next = pos + rip->i_sp->s_block_size - 1;
-
-  /* If 'pos' is in the last block of a zone, do not clear the zone. */
-  if (next/zone_size != pos/zone_size) return;
-  if ( (blo = read_map(rip, next)) == NO_BLOCK) return;
-  bhi = (block_t) (  ((blo>>scale)+1) << scale)   - 1;
-
-  /* Clear all the blocks between 'blo' and 'bhi'. */
-  for (b = blo; b <= bhi; b++) {
-       bp = get_block(rip->i_dev, b, NO_READ);
-       zero_block(bp);
-       put_block(bp, FULL_DATA_BLOCK);
-  }
+  assert(scale == 0);
+  return;
 }
 
 
@@ -286,7 +270,7 @@ off_t position;                     /* file pointer */
   int scale, r;
 
   /* Is another block available in the current zone? */
-  if ( (b = read_map(rip, position)) == NO_BLOCK) {
+  if ( (b = read_map(rip, position, 0)) == NO_BLOCK) {
        if (rip->i_zsearch == NO_ZONE) {
                /* First search for this file. Start looking from
                 * the file's first data zone to prevent fragmentation
@@ -316,7 +300,8 @@ off_t position;                     /* file pointer */
        b = base_block + (block_t)((position % zone_size)/rip->i_sp->s_block_size);
   }
 
-  bp = get_block(rip->i_dev, b, NO_READ);
+  bp = lmfs_get_block_ino(rip->i_dev, b, NO_READ, rip->i_num,
+       rounddown(position, rip->i_sp->s_block_size));
   zero_block(bp);
   return(bp);
 }