]> Zhao Yanbai Git Server - minix.git/commitdiff
libminixfs, mfs, ext2: may re-evaluate cache size 29/529/1
authorBen Gras <ben@minix3.org>
Fri, 26 Apr 2013 09:54:33 +0000 (09:54 +0000)
committerBen Gras <ben@minix3.org>
Fri, 26 Apr 2013 13:57:08 +0000 (13:57 +0000)
libminixfs may now be informed of changes to the block usage on the
filesystem. if the net change becomes big enough, libminixfs may
resize the cache based on the new usage.

. update the 2 FSes to provide this information to libminixfs

Change-Id: I158815a11da801fd5572a8de89c9e6c039b82650

include/minix/libminixfs.h
lib/libminixfs/cache.c
servers/ext2/balloc.c
servers/mfs/proto.h
servers/mfs/stats.c
servers/mfs/super.c

index 0be011735eb1aeb18ed27d8843bc583df34be1cb..cece2c2f342bc94c29748a467c2ef4f3ecfd4ca7 100644 (file)
@@ -56,6 +56,8 @@ void lmfs_put_block(struct buf *bp, int block_type);
 void lmfs_rw_scattered(dev_t, struct buf **, int, int);
 void lmfs_setquiet(int q);
 int lmfs_do_bpeek(message *);
+void lmfs_cache_reevaluate(dev_t dev);
+void lmfs_blockschange(dev_t dev, int delta);
 
 /* calls that libminixfs does into fs */
 void fs_blockstats(u32_t *blocks, u32_t *free, u32_t *used);
index 579a02cfea82213519f825d2de18708b94ceed31..ad3c6469be9071cfba56fafc001bcacc9c4c9943 100644 (file)
@@ -29,6 +29,7 @@ static void rm_lru(struct buf *bp);
 static void read_block(struct buf *);
 static void flushall(dev_t dev);
 static void freeblock(struct buf *bp);
+static void cache_heuristic_check(int major);
 
 static int vmcache = 0; /* are we using vm's secondary cache? (initially not) */
 
@@ -60,13 +61,18 @@ u32_t fs_bufs_heuristic(int minbufs, u32_t btotal, u32_t bfree,
    * portion of the used FS, and at most a certain %age of remaining
    * memory
    */
-  if((vm_info_stats(&vsi) != OK)) {
+  if(vm_info_stats(&vsi) != OK) {
        bufs = 1024;
-       if(!quiet) printf("fslib: heuristic info fail: default to %d bufs\n", bufs);
+       if(!quiet)
+         printf("fslib: heuristic info fail: default to %d bufs\n", bufs);
        return bufs;
   }
 
-  kbytes_remain_mem = div64u(mul64u(vsi.vsi_free, vsi.vsi_pagesize), 1024);
+  /* remaining free memory is unused memory plus memory in used for cache,
+   * as the cache can be evicted
+   */
+  kbytes_remain_mem = (u64_t)(vsi.vsi_free + vsi.vsi_cached) *
+       vsi.vsi_pagesize / 1024;
 
   /* check fs usage. */
   kbytes_used_fs = div64u(mul64u(bused, blocksize), 1024);
@@ -89,6 +95,23 @@ u32_t fs_bufs_heuristic(int minbufs, u32_t btotal, u32_t bfree,
   return bufs;
 }
 
+void lmfs_blockschange(dev_t dev, int delta)
+{
+        /* Change the number of allocated blocks by 'delta.'
+         * Also accumulate the delta since the last cache re-evaluation.
+         * If it is outside a certain band, ask the cache library to
+         * re-evaluate the cache size.
+         */
+        static int bitdelta = 0;
+        bitdelta += delta;
+#define BANDKB (10*1024)       /* recheck cache every 10MB change */
+        if(bitdelta*fs_block_size/1024 > BANDKB ||
+          bitdelta*fs_block_size/1024 < -BANDKB) {
+                lmfs_cache_reevaluate(dev);
+                bitdelta = 0;
+        }
+}
+
 void
 lmfs_markdirty(struct buf *bp)
 {
@@ -455,6 +478,15 @@ int block_type;                    /* INODE_BLOCK, DIRECTORY_BLOCK, or whatever */
        }
   }
   bp->lmfs_needsetcache = 0;
+
+}
+
+void lmfs_cache_reevaluate(dev_t dev)
+{
+  if(bufs_in_use == 0 && dev != NO_DEV) {
+       /* if the cache isn't in use any more, we could resize it. */
+       cache_heuristic_check(major(dev));
+  }
 }
 
 /*===========================================================================*
@@ -734,22 +766,33 @@ static void cache_resize(unsigned int blocksize, unsigned int bufs)
   fs_block_size = blocksize;
 }
 
-/*===========================================================================*
- *                     lmfs_set_blocksize                                   *
- *===========================================================================*/
-void lmfs_set_blocksize(int new_block_size, int major)
+static void cache_heuristic_check(int major)
 {
-  int bufs;
+  int bufs, d;
   u32_t btotal, bfree, bused;
 
-  cache_resize(new_block_size, MINBUFS);
-
   fs_blockstats(&btotal, &bfree, &bused);
 
   bufs = fs_bufs_heuristic(10, btotal, bfree,
-        new_block_size, major);
+        fs_block_size, major);
+
+  /* set the cache to the new heuristic size if the new one
+   * is more than 10% off from the current one.
+   */
+  d = bufs-nr_bufs;
+  if(d < 0) d = -d;
+  if(d*100/nr_bufs > 10) {
+       cache_resize(fs_block_size, bufs);
+  }
+}
 
-  cache_resize(new_block_size, bufs);
+/*===========================================================================*
+ *                     lmfs_set_blocksize                                   *
+ *===========================================================================*/
+void lmfs_set_blocksize(int new_block_size, int major)
+{
+  cache_resize(new_block_size, MINBUFS);
+  cache_heuristic_check(major);
   
   /* Decide whether to use seconday cache or not.
    * Only do this if
index fac377f31553f2c4d30ee406aeadb027168f87c4..759220c242f86a459498770fd2af80fbca2c49ea 100644 (file)
@@ -232,6 +232,7 @@ struct inode *rip;          /* used for preallocation */
 
                        gd->free_blocks_count -= EXT2_PREALLOC_BLOCKS;
                        sp->s_free_blocks_count -= EXT2_PREALLOC_BLOCKS;
+                       lmfs_blockschange(sp->s_dev, -EXT2_PREALLOC_BLOCKS);
                        group_descriptors_dirty = 1;
                        return block;
                }
@@ -256,6 +257,7 @@ struct inode *rip;          /* used for preallocation */
 
        gd->free_blocks_count--;
        sp->s_free_blocks_count--;
+       lmfs_blockschange(sp->s_dev, -1);
        group_descriptors_dirty = 1;
 
        if (update_bsearch && block != -1 && block != NO_BLOCK) {
@@ -321,6 +323,7 @@ void free_block(struct super_block *sp, bit_t bit_returned)
 
   gd->free_blocks_count++;
   sp->s_free_blocks_count++;
+  lmfs_blockschange(sp->s_dev, 1);
 
   group_descriptors_dirty = 1;
 
index 38e4fc5d5e9755d15cba3cfc6974ca30e7c108fb..142c6f125720929d2655ee468734e179b1fbb7a7 100644 (file)
@@ -90,6 +90,7 @@ unsigned int get_block_size(dev_t dev);
 struct super_block *get_super(dev_t dev);
 int read_super(struct super_block *sp);
 int write_super(struct super_block *sp);
+u32_t get_used_blocks(struct super_block *sp);
 
 /* stats.c */
 bit_t count_free_bits(struct super_block *sp, int map);
index 55c75fd7dc69ab1271c905bf9b25fe69a32f7234..871576359312d88e0333f00dbb09fefd0f3a05a7 100644 (file)
@@ -95,17 +95,15 @@ int map;                    /* IMAP (inode map) or ZMAP (zone map) */
 void fs_blockstats(u32_t *blocks, u32_t *free, u32_t *used)
 {
   struct super_block *sp;
-  int scale;
 
   sp = get_super(fs_dev);
 
   assert(sp);
+  assert(!sp->s_log_zone_size);
 
-  scale = sp->s_log_zone_size;
-
-  *blocks = sp->s_zones << scale;
-  *free = count_free_bits(sp, ZMAP) << scale;
-  *used = *blocks - *free;
+  *blocks = sp->s_zones;
+  *used = get_used_blocks(sp);
+  *free = *blocks - *used;
 
   return;
 }
index 1268253340bd049f39425a68c1a026cd5ae7212b..63084ee8f91cf4fe387dc398e00eedcaacc8338f 100644 (file)
@@ -22,6 +22,7 @@
 #include "super.h"
 #include "const.h"
 
+static u32_t used_blocks = 0;
 
 /*===========================================================================*
  *                             alloc_bit                                    *
@@ -91,6 +92,10 @@ bit_t origin;                        /* number of bit to start searching at */
                *wptr = (bitchunk_t) conv4(sp->s_native, (int) k);
                MARKDIRTY(bp);
                put_block(bp, MAP_BLOCK);
+               if(map == ZMAP) {
+                       used_blocks++;
+                       lmfs_blockschange(sp->s_dev, 1);
+               }
                return(b);
        }
        put_block(bp, MAP_BLOCK);
@@ -144,8 +149,12 @@ bit_t bit_returned;                /* number of bit to insert into the map */
   MARKDIRTY(bp);
 
   put_block(bp, MAP_BLOCK);
-}
 
+  if(map == ZMAP) {
+       used_blocks--;
+       lmfs_blockschange(sp->s_dev, -1);
+  }
+}
 
 /*===========================================================================*
  *                             get_super                                    *
@@ -365,3 +374,14 @@ int write_super(struct super_block *sp)
   return rw_super(sp, 1);
 }
 
+static int blocks_known = 0;
+
+u32_t get_used_blocks(struct super_block *sp)
+{
+       if(!blocks_known)  {
+               /* how many blocks are in use? */
+               used_blocks = sp->s_zones - count_free_bits(sp, ZMAP);
+               blocks_known = 1;
+       }
+       return used_blocks;
+}