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
This commit is contained in:
Ben Gras 2013-04-26 09:54:33 +00:00
parent 988c7e39c0
commit f0cc010614
6 changed files with 87 additions and 20 deletions

View 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);

View 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;
}
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

View 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;

View 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);

View 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;
}

View 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;
}