From f0cc0106146af66bf4971c74094faa5b0a0f78dc Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Fri, 26 Apr 2013 09:54:33 +0000 Subject: [PATCH] libminixfs, mfs, ext2: may re-evaluate cache size 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 | 2 ++ lib/libminixfs/cache.c | 69 +++++++++++++++++++++++++++++++------- servers/ext2/balloc.c | 3 ++ servers/mfs/proto.h | 1 + servers/mfs/stats.c | 10 +++--- servers/mfs/super.c | 22 +++++++++++- 6 files changed, 87 insertions(+), 20 deletions(-) diff --git a/include/minix/libminixfs.h b/include/minix/libminixfs.h index 0be011735..cece2c2f3 100644 --- a/include/minix/libminixfs.h +++ b/include/minix/libminixfs.h @@ -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); diff --git a/lib/libminixfs/cache.c b/lib/libminixfs/cache.c index 579a02cfe..ad3c6469b 100644 --- a/lib/libminixfs/cache.c +++ b/lib/libminixfs/cache.c @@ -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; } +static void cache_heuristic_check(int major) +{ + int bufs, d; + u32_t btotal, bfree, bused; + + fs_blockstats(&btotal, &bfree, &bused); + + bufs = fs_bufs_heuristic(10, btotal, bfree, + 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); + } +} + /*===========================================================================* * lmfs_set_blocksize * *===========================================================================*/ void lmfs_set_blocksize(int new_block_size, int major) { - int bufs; - 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); - - cache_resize(new_block_size, bufs); + cache_heuristic_check(major); /* Decide whether to use seconday cache or not. * Only do this if diff --git a/servers/ext2/balloc.c b/servers/ext2/balloc.c index fac377f31..759220c24 100644 --- a/servers/ext2/balloc.c +++ b/servers/ext2/balloc.c @@ -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; diff --git a/servers/mfs/proto.h b/servers/mfs/proto.h index 38e4fc5d5..142c6f125 100644 --- a/servers/mfs/proto.h +++ b/servers/mfs/proto.h @@ -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); diff --git a/servers/mfs/stats.c b/servers/mfs/stats.c index 55c75fd7d..871576359 100644 --- a/servers/mfs/stats.c +++ b/servers/mfs/stats.c @@ -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; } diff --git a/servers/mfs/super.c b/servers/mfs/super.c index 126825334..63084ee8f 100644 --- a/servers/mfs/super.c +++ b/servers/mfs/super.c @@ -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; +}