auto-tune mfs cache size based on FS usage and remaining system memory
This commit is contained in:
parent
b6f25271a9
commit
c90cdadcfb
6 changed files with 106 additions and 11 deletions
|
@ -1100,7 +1100,7 @@
|
|||
/* Basic vm calls allowed to every process. */
|
||||
#define VM_BASIC_CALLS \
|
||||
VM_MMAP, VM_MUNMAP, VM_MUNMAP_TEXT, VM_MAP_PHYS, VM_UNMAP_PHYS, \
|
||||
VM_FORGETBLOCKS, VM_FORGETBLOCK, VM_YIELDBLOCKGETBLOCK
|
||||
VM_FORGETBLOCKS, VM_FORGETBLOCK, VM_YIELDBLOCKGETBLOCK, VM_INFO
|
||||
|
||||
/*===========================================================================*
|
||||
* Messages for IPC server *
|
||||
|
|
|
@ -16,8 +16,10 @@
|
|||
|
||||
#include "fs.h"
|
||||
#include <minix/u64.h>
|
||||
#include <sys/param.h>
|
||||
#include <stdlib.h>
|
||||
#include <assert.h>
|
||||
#include <math.h>
|
||||
#include "buf.h"
|
||||
#include "super.h"
|
||||
#include "inode.h"
|
||||
|
@ -538,14 +540,17 @@ struct buf *bp;
|
|||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* set_blocksize *
|
||||
* cache_resize *
|
||||
*===========================================================================*/
|
||||
PUBLIC void set_blocksize(unsigned int blocksize)
|
||||
PRIVATE void cache_resize(unsigned int blocksize, unsigned int bufs)
|
||||
{
|
||||
struct buf *bp;
|
||||
struct inode *rip;
|
||||
int scale, r;
|
||||
|
||||
ASSERT(blocksize > 0);
|
||||
#define MINBUFS 10
|
||||
assert(blocksize > 0);
|
||||
assert(bufs >= MINBUFS);
|
||||
|
||||
for (bp = &buf[0]; bp < &buf[nr_bufs]; bp++)
|
||||
if(bp->b_count != 0) panic("change blocksize with buffer in use");
|
||||
|
@ -553,10 +558,76 @@ PUBLIC void set_blocksize(unsigned int blocksize)
|
|||
for (rip = &inode[0]; rip < &inode[NR_INODES]; rip++)
|
||||
if (rip->i_count > 0) panic("change blocksize with inode in use");
|
||||
|
||||
buf_pool(nr_bufs);
|
||||
buf_pool(bufs);
|
||||
|
||||
fs_block_size = blocksize;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* bufs_heuristic *
|
||||
*===========================================================================*/
|
||||
PRIVATE int bufs_heuristic(struct super_block *sp)
|
||||
{
|
||||
struct vm_stats_info vsi;
|
||||
int r, bufs;
|
||||
u32_t btotal, bfree, bused, kbytes_used_fs,
|
||||
kbytes_total_fs, kbcache, kb_fsmax;
|
||||
u32_t kbytes_remain_mem;
|
||||
|
||||
/* but we simply need MINBUFS no matter what, and we don't
|
||||
* want more than that if we're a memory device
|
||||
*/
|
||||
if(major(sp->s_dev) == MEMORY_MAJOR) {
|
||||
bufs = MINBUFS;
|
||||
return bufs;
|
||||
}
|
||||
|
||||
/* set a reasonable cache size; cache at most a certain
|
||||
* portion of the used FS, and at most a certain %age of remaining
|
||||
* memory
|
||||
*/
|
||||
if((vm_info_stats(&vsi) != OK)) {
|
||||
bufs = 1024;
|
||||
printf("mfs: heuristic info fail: default to %d bufs\n", bufs);
|
||||
return bufs;
|
||||
}
|
||||
|
||||
kbytes_remain_mem = div64u(mul64u(vsi.vsi_free, vsi.vsi_pagesize), 1024);
|
||||
|
||||
/* check fs usage. */
|
||||
blockstats(&btotal, &bfree, &bused);
|
||||
kbytes_used_fs = div64u(mul64u(bused, sp->s_block_size), 1024);
|
||||
kbytes_total_fs = div64u(mul64u(btotal, sp->s_block_size), 1024);
|
||||
|
||||
/* heuristic for a desired cache size based on FS usage;
|
||||
* but never bigger than half of the total filesystem
|
||||
*/
|
||||
kb_fsmax = sqrt(kbytes_used_fs)*40;
|
||||
kb_fsmax = MIN(kb_fsmax, kbytes_total_fs/2);
|
||||
|
||||
/* heuristic for a maximum usage - 10% of remaining memory */
|
||||
kbcache = MIN(kbytes_remain_mem/10, kb_fsmax);
|
||||
bufs = kbcache * 1024 / sp->s_block_size;
|
||||
|
||||
/* but we simply need MINBUFS no matter what */
|
||||
if(bufs < MINBUFS)
|
||||
bufs = MINBUFS;
|
||||
|
||||
return bufs;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* set_blocksize *
|
||||
*===========================================================================*/
|
||||
PUBLIC void set_blocksize(struct super_block *sp)
|
||||
{
|
||||
int bufs;
|
||||
|
||||
cache_resize(sp->s_block_size, MINBUFS);
|
||||
bufs = bufs_heuristic(sp);
|
||||
cache_resize(sp->s_block_size, bufs);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* buf_pool *
|
||||
*===========================================================================*/
|
||||
|
@ -565,7 +636,7 @@ PUBLIC void buf_pool(int new_nr_bufs)
|
|||
/* Initialize the buffer pool. */
|
||||
register struct buf *bp;
|
||||
|
||||
assert(new_nr_bufs > 0);
|
||||
assert(new_nr_bufs >= MINBUFS);
|
||||
|
||||
if(nr_bufs > 0) {
|
||||
assert(buf);
|
||||
|
|
|
@ -68,7 +68,7 @@ PUBLIC int fs_readsuper()
|
|||
return(r);
|
||||
}
|
||||
|
||||
set_blocksize(superblock.s_block_size);
|
||||
set_blocksize(&superblock);
|
||||
|
||||
/* Get the root inode of the mounted file system. */
|
||||
if( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL) {
|
||||
|
|
|
@ -18,7 +18,7 @@ _PROTOTYPE( void free_zone, (dev_t dev, zone_t numb) );
|
|||
_PROTOTYPE( struct buf *get_block, (dev_t dev, block_t block,int only_search));
|
||||
_PROTOTYPE( void invalidate, (dev_t device) );
|
||||
_PROTOTYPE( void put_block, (struct buf *bp, int block_type) );
|
||||
_PROTOTYPE( void set_blocksize, (unsigned int blocksize) );
|
||||
_PROTOTYPE( void set_blocksize, (struct super_block *) );
|
||||
_PROTOTYPE( void rw_scattered, (dev_t dev,
|
||||
struct buf **bufq, int bufqsize, int rw_flag) );
|
||||
|
||||
|
@ -103,6 +103,7 @@ _PROTOTYPE( int read_super, (struct super_block *sp) );
|
|||
|
||||
/* stats.c */
|
||||
_PROTOTYPE( bit_t count_free_bits, (struct super_block *sp, int map));
|
||||
_PROTOTYPE( void blockstats, (u32_t *total, u32_t *free, u32_t *avail));
|
||||
|
||||
/* time.c */
|
||||
_PROTOTYPE( int fs_utime, (void) );
|
||||
|
|
|
@ -81,16 +81,17 @@ PUBLIC int fs_statvfs()
|
|||
struct statvfs st;
|
||||
struct super_block *sp;
|
||||
int r, scale;
|
||||
u32_t used;
|
||||
|
||||
sp = get_super(fs_dev);
|
||||
|
||||
scale = sp->s_log_zone_size;
|
||||
|
||||
blockstats(&st.f_blocks, &st.f_bfree, &used);
|
||||
st.f_bavail = st.f_bfree;
|
||||
|
||||
st.f_bsize = sp->s_block_size << scale;
|
||||
st.f_frsize = sp->s_block_size;
|
||||
st.f_blocks = sp->s_zones << scale;
|
||||
st.f_bfree = count_free_bits(sp, ZMAP) << scale;
|
||||
st.f_bavail = st.f_bfree;
|
||||
st.f_files = sp->s_ninodes;
|
||||
st.f_ffree = count_free_bits(sp, IMAP);
|
||||
st.f_favail = st.f_ffree;
|
||||
|
|
|
@ -85,3 +85,25 @@ int map; /* IMAP (inode map) or ZMAP (zone map) */
|
|||
} while (--bcount > 0);
|
||||
return free_bits; /* no bit could be allocated */
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* blockstats *
|
||||
*===========================================================================*/
|
||||
PUBLIC void blockstats(u32_t *blocks, u32_t *free, u32_t *used)
|
||||
{
|
||||
struct super_block *sp;
|
||||
int scale;
|
||||
|
||||
sp = get_super(fs_dev);
|
||||
|
||||
assert(sp);
|
||||
|
||||
scale = sp->s_log_zone_size;
|
||||
|
||||
*blocks = sp->s_zones << scale;
|
||||
*free = count_free_bits(sp, ZMAP) << scale;
|
||||
*used = *blocks - *free;
|
||||
|
||||
return;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue