From 4857d5d554cc88f82f6865da133ee3da16b5b5fb Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Thu, 8 Sep 2011 16:49:54 +0000 Subject: [PATCH] add -lminixfs with fs support routines . move cache size heuristic from mfs there so mfs and ext2 can share it . add vfs credentials retrieving function, with backwards compatability from previous struct format, to be used by both ext2 and mfs . fix for ext2 - STATICINIT was fed no. of bytes instead of no. of elements, overallocating memory by a megabyte or two for the superblock --- common/include/Makefile.inc | 2 +- common/include/minix/libminixfs.h | 16 ++++++++ common/include/minix/vfsif.h | 10 +++++ include/limits.h | 3 +- lib/Makefile | 2 +- lib/libminixfs/Makefile | 8 ++++ lib/libminixfs/cache.c | 59 ++++++++++++++++++++++++++++++ lib/libminixfs/fetch_credentials.c | 51 ++++++++++++++++++++++++++ lib/libminixfs/minixfs.h | 4 ++ servers/ext2/Makefile | 5 +-- servers/ext2/cache.c | 9 ++++- servers/ext2/main.c | 4 +- servers/ext2/mount.c | 7 +++- servers/ext2/path.c | 29 ++++++--------- servers/ext2/proto.h | 3 +- servers/ext2/super.c | 5 ++- servers/mfs/Makefile | 2 +- servers/mfs/cache.c | 47 ++---------------------- servers/mfs/path.c | 27 ++++++-------- 19 files changed, 202 insertions(+), 91 deletions(-) create mode 100644 common/include/minix/libminixfs.h create mode 100644 lib/libminixfs/Makefile create mode 100644 lib/libminixfs/cache.c create mode 100644 lib/libminixfs/fetch_credentials.c create mode 100644 lib/libminixfs/minixfs.h diff --git a/common/include/Makefile.inc b/common/include/Makefile.inc index 2736db87f..e06146a92 100644 --- a/common/include/Makefile.inc +++ b/common/include/Makefile.inc @@ -18,7 +18,7 @@ INCS+= minix/acpi.h minix/ansi.h minix/audio_fw.h minix/bitmap.h \ minix/sound.h minix/spin.h minix/sys_config.h minix/sysinfo.h \ minix/syslib.h minix/sysutil.h minix/timers.h minix/type.h \ minix/tty.h minix/u64.h minix/usb.h minix/usb_ch9.h minix/vm.h \ - minix/vfsif.h minix/vtreefs.h + minix/vfsif.h minix/vtreefs.h minix/libminixfs.h INCS+= net/gen/arp_io.h net/gen/dhcp.h net/gen/ether.h \ net/gen/eth_hdr.h net/gen/eth_io.h net/gen/icmp.h \ diff --git a/common/include/minix/libminixfs.h b/common/include/minix/libminixfs.h new file mode 100644 index 000000000..96d2b3e99 --- /dev/null +++ b/common/include/minix/libminixfs.h @@ -0,0 +1,16 @@ +/* Prototypes for -lminixfs. */ + +#ifndef _MINIX_FSLIB_H +#define _MINIX_FSLIB_H + +#include +#include +#include + +int fs_lookup_credentials(vfs_ucred_t *credentials, + uid_t *caller_uid, gid_t *caller_gid, cp_grant_id_t grant2, size_t cred_size); +u32_t fs_bufs_heuristic(int minbufs, u32_t btotal, u32_t bfree, + int blocksize, dev_t majordev); + +#endif /* _MINIX_FSLIB_H */ + diff --git a/common/include/minix/vfsif.h b/common/include/minix/vfsif.h index 6c40de2a0..2bde532a2 100644 --- a/common/include/minix/vfsif.h +++ b/common/include/minix/vfsif.h @@ -82,6 +82,16 @@ typedef struct { gid_t vu_sgroups[NGROUPS_MAX]; } vfs_ucred_t; +#define NGROUPS_MAX_OLD 8 +/* User credential structure before increasing + * uid_t and gid_t u8_t */ +typedef struct { + short vu_uid; + char vu_gid; + int vu_ngroups; + char vu_sgroups[NGROUPS_MAX_OLD]; +} vfs_ucred_old_t; + /* Request numbers */ #define REQ_GETNODE (VFS_BASE + 1) /* Should be removed */ #define REQ_PUTNODE (VFS_BASE + 2) diff --git a/include/limits.h b/include/limits.h index 792d3c1d8..23b1c3586 100644 --- a/include/limits.h +++ b/include/limits.h @@ -83,7 +83,6 @@ /* Some of these old names had better be defined when not POSIX. */ #define _NO_LIMIT 100 /* arbitrary number; limit not enforced */ -#define NGROUPS_MAX 8 /* max. number of supplemental groups */ #if _EM_WSIZE > 2 #define ARG_MAX 262144 /* # bytes of args + environ for exec() */ #else @@ -113,6 +112,8 @@ #define IOV_MAX INT_MAX /* maximum number of buffers for readv/writev */ #endif /* _POSIX_SOURCE */ +#define NGROUPS_MAX 8 /* max. number of supplemental groups */ + #define GID_MAX USHRT_MAX #define UID_MAX USHRT_MAX diff --git a/lib/Makefile b/lib/Makefile index 1009b1fa5..9cdb5f778 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -18,7 +18,7 @@ SUBDIR= csu ${LIBCOMPAT_DIR} ${LIBC_DIR} libdriver libnetdriver \ libedit ${LIBM_DIR} libsys libtimers libminixutil libbz2 libl libhgfs \ libz libfetch libarchive libvtreefs libaudiodriver libmthread \ libexec libdevman libusb ${LIBMINLIB_DIR} ${LIBASYN_DIR} \ - libddekit + libddekit libminixfs .if defined(NBSD_LIBC) && (${NBSD_LIBC} != "no") SUBDIR+= libelf libminc libcrypt libterminfo libcurses libvassert diff --git a/lib/libminixfs/Makefile b/lib/libminixfs/Makefile new file mode 100644 index 000000000..ade070374 --- /dev/null +++ b/lib/libminixfs/Makefile @@ -0,0 +1,8 @@ +# Makefile for libminixfs +.include + +LIB= minixfs + +SRCS= fetch_credentials.c cache.c + +.include diff --git a/lib/libminixfs/cache.c b/lib/libminixfs/cache.c new file mode 100644 index 000000000..bf43750c0 --- /dev/null +++ b/lib/libminixfs/cache.c @@ -0,0 +1,59 @@ + +#define _SYSTEM + +#include +#include +#include +#include +#include + +u32_t fs_bufs_heuristic(int minbufs, u32_t btotal, u32_t bfree, + int blocksize, dev_t majordev) +{ + struct vm_stats_info vsi; + int bufs; + u32_t kbytes_used_fs, kbytes_total_fs, kbcache, kb_fsmax; + u32_t kbytes_remain_mem, bused; + + bused = btotal-bfree; + + /* but we simply need minbufs no matter what, and we don't + * want more than that if we're a memory device + */ + if(majordev == MEMORY_MAJOR) { + return minbufs; + } + + /* 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("fslib: 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. */ + kbytes_used_fs = div64u(mul64u(bused, blocksize), 1024); + kbytes_total_fs = div64u(mul64u(btotal, blocksize), 1024); + + /* heuristic for a desired cache size based on FS usage; + * but never bigger than half of the total filesystem + */ + kb_fsmax = sqrt_approx(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 / blocksize; + + /* but we simply need MINBUFS no matter what */ + if(bufs < minbufs) + bufs = minbufs; + + return bufs; +} + diff --git a/lib/libminixfs/fetch_credentials.c b/lib/libminixfs/fetch_credentials.c new file mode 100644 index 000000000..26f62d2f9 --- /dev/null +++ b/lib/libminixfs/fetch_credentials.c @@ -0,0 +1,51 @@ + +#include +#include +#include + +#include "minixfs.h" + +int fs_lookup_credentials(vfs_ucred_t *credentials, + uid_t *caller_uid, gid_t *caller_gid, cp_grant_id_t grant2, size_t cred_size) +{ + vfs_ucred_old_t old_cred; + int r; + + memset(credentials, 0, sizeof(*credentials)); + + if(cred_size == sizeof(*credentials)) { + r = sys_safecopyfrom(VFS_PROC_NR, grant2, (vir_bytes) 0, + (vir_bytes) credentials, cred_size, D); + if (r != OK) { + printf("FS: cred copy (regular) failed.\n"); + return(r); + } + } else if(cred_size == sizeof(old_cred)) { + int g; + r = sys_safecopyfrom(VFS_PROC_NR, grant2, (vir_bytes) 0, + (vir_bytes) &old_cred, sizeof(old_cred), D); + if (r != OK) { + printf("FS: cred copy (fallback) failed.\n"); + return(r); + } + credentials->vu_ngroups = old_cred.vu_ngroups; + credentials->vu_uid = old_cred.vu_uid; + credentials->vu_gid = old_cred.vu_gid; + for(g = 0; g < NGROUPS_MAX_OLD; g++) { + assert(g < NGROUPS_MAX); + credentials->vu_sgroups[g] = old_cred.vu_sgroups[g]; + } + } else { + static int w = 0; + if(!w) { printf("FS: cred size incompatible with VFS.\n"); w = 1; } + return(EINVAL); /* Wrong size. */ + } + + assert(credentials->vu_ngroups <= NGROUPS_MAX); + + *caller_uid = credentials->vu_uid; + *caller_gid = credentials->vu_gid; + + return OK; +} + diff --git a/lib/libminixfs/minixfs.h b/lib/libminixfs/minixfs.h new file mode 100644 index 000000000..30d70b98a --- /dev/null +++ b/lib/libminixfs/minixfs.h @@ -0,0 +1,4 @@ +#define _SYSTEM + +#include /* common to all libraries */ +#include /* need task numbers + message types */ diff --git a/servers/ext2/Makefile b/servers/ext2/Makefile index 02e4aa8c4..35bd6892e 100644 --- a/servers/ext2/Makefile +++ b/servers/ext2/Makefile @@ -6,14 +6,11 @@ SRCS= balloc.c cache.c device.c link.c \ write.c ialloc.c inode.c main.c path.c \ super.c optset.c DPADD+= ${LIBSYS} -LDADD+= -lsys +LDADD+= -lminixfs -lsys MAN= BINDIR?= /sbin INSTALLFLAGS+= -S 128k -DEFAULT_NR_BUFS= 1024 -CPPFLAGS+= -DDEFAULT_NR_BUFS=${DEFAULT_NR_BUFS} - .include diff --git a/servers/ext2/cache.c b/servers/ext2/cache.c index e4a213b9d..2b0305d85 100644 --- a/servers/ext2/cache.c +++ b/servers/ext2/cache.c @@ -17,6 +17,7 @@ #include "fs.h" #include +#include #include #include #include "buf.h" @@ -489,10 +490,12 @@ PRIVATE void rm_lru( /*===========================================================================* * set_blocksize * *===========================================================================*/ -PUBLIC void set_blocksize(unsigned int blocksize) +PUBLIC void set_blocksize(unsigned int blocksize, u32_t blocks, + u32_t freeblocks, dev_t majordev) { struct buf *bp; struct inode *rip; + int new_nr_bufs; ASSERT(blocksize > 0); @@ -502,7 +505,9 @@ 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); + new_nr_bufs = fs_bufs_heuristic(10, blocks, freeblocks, blocksize, majordev); + + buf_pool(new_nr_bufs); fs_block_size = blocksize; } diff --git a/servers/ext2/main.c b/servers/ext2/main.c index eacb58d0c..07caa5a3f 100644 --- a/servers/ext2/main.c +++ b/servers/ext2/main.c @@ -157,7 +157,9 @@ PRIVATE int sef_cb_init_fresh(int type, sef_init_info_t *info) driver_endpoints[i].driver_e = NONE; SELF_E = getprocnr(); - buf_pool(DEFAULT_NR_BUFS); + + /* just a small number before we find out the block size at mount time */ + buf_pool(10); fs_block_size = _MIN_BLOCK_SIZE; return(OK); diff --git a/servers/ext2/mount.c b/servers/ext2/mount.c index e5802ab8a..a062e4e6b 100644 --- a/servers/ext2/mount.c +++ b/servers/ext2/mount.c @@ -70,7 +70,7 @@ PUBLIC int fs_readsuper() } /* Fill in the super block. */ - STATICINIT(superblock, sizeof(struct super_block)); + STATICINIT(superblock, 1); if (!superblock) panic("Can't allocate memory for superblock."); superblock->s_dev = fs_dev; /* read_super() needs to know which dev */ @@ -125,7 +125,10 @@ PUBLIC int fs_readsuper() } - set_blocksize(superblock->s_block_size); + set_blocksize(superblock->s_block_size, + superblock->s_blocks_count, + superblock->s_free_blocks_count, + major(fs_dev)); /* Get the root inode of the mounted file system. */ if ( (root_ip = get_inode(fs_dev, ROOT_INODE)) == NULL) { diff --git a/servers/ext2/path.c b/servers/ext2/path.c index 6b44433d9..ee054ac64 100644 --- a/servers/ext2/path.c +++ b/servers/ext2/path.c @@ -36,10 +36,10 @@ FORWARD _PROTOTYPE( int parse_path, (ino_t dir_ino, ino_t root_ino, *===========================================================================*/ PUBLIC int fs_lookup() { - cp_grant_id_t grant, grant2; + cp_grant_id_t grant; int r, r1, flags, symlinks; unsigned int len; - size_t offset = 0, path_size, cred_size; + size_t offset = 0, path_size; ino_t dir_ino, root_ino; struct inode *rip; @@ -62,21 +62,16 @@ PUBLIC int fs_lookup() /* Verify this is a null-terminated path. */ if(user_path[len - 1] != '\0') return(EINVAL); - if(flags & PATH_GET_UCRED) { /* Do we have to copy uid/gid credentials? */ - grant2 = (cp_grant_id_t) fs_m_in.REQ_GRANT2; - cred_size = (size_t) fs_m_in.REQ_UCRED_SIZE; - - if (cred_size > sizeof(credentials)) return(EINVAL); /* Too big. */ - r = sys_safecopyfrom(VFS_PROC_NR, grant2, (vir_bytes) 0, - (vir_bytes) &credentials, cred_size, D); - if (r != OK) return(r); - - caller_uid = (uid_t) credentials.vu_uid; - caller_gid = (gid_t) credentials.vu_gid; - } else { - memset(&credentials, 0, sizeof(credentials)); - caller_uid = fs_m_in.REQ_UID; - caller_gid = fs_m_in.REQ_GID; + memset(&credentials, 0, sizeof(credentials)); + if(!(flags & PATH_GET_UCRED)) { /* Do we have to copy uid/gid credentials? */ + caller_uid = (uid_t) fs_m_in.REQ_UID; + caller_gid = (gid_t) fs_m_in.REQ_GID; + } else { + if((r=fs_lookup_credentials(&credentials, + &caller_uid, &caller_gid, + (cp_grant_id_t) fs_m_in.REQ_GRANT2, + (size_t) fs_m_in.REQ_UCRED_SIZE)) != OK) + return r; } /* Lookup inode */ diff --git a/servers/ext2/proto.h b/servers/ext2/proto.h index eda3f6358..a76d0657e 100644 --- a/servers/ext2/proto.h +++ b/servers/ext2/proto.h @@ -21,7 +21,8 @@ _PROTOTYPE( void flushall, (dev_t dev) ); _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, (unsigned int blocksize, u32_t blocks, + u32_t freeblocks, dev_t major)); _PROTOTYPE( void rw_scattered, (dev_t dev, struct buf **bufq, int bufqsize, int rw_flag) ); diff --git a/servers/ext2/super.c b/servers/ext2/super.c index 628a1478c..45ab48d2f 100644 --- a/servers/ext2/super.c +++ b/servers/ext2/super.c @@ -85,14 +85,17 @@ register struct super_block *sp; /* pointer to a superblock */ super_block_offset = opt.block_with_super * 1024; } - STATICINIT(ondisk_superblock, sizeof(struct super_block)); + STATICINIT(ondisk_superblock, 1); if (!sp || !ondisk_superblock) panic("can't allocate memory for super_block buffers"); + printf("ext2: reading %d bytes into %d buffer\n", _MIN_BLOCK_SIZE, sizeof(*ondisk_superblock)); + r = block_dev_io(MFS_DEV_READ, dev, SELF_E, (char*) ondisk_superblock, cvu64(super_block_offset), _MIN_BLOCK_SIZE); + if (r != _MIN_BLOCK_SIZE) return(EINVAL); diff --git a/servers/mfs/Makefile b/servers/mfs/Makefile index 3730c4400..a937b97f3 100644 --- a/servers/mfs/Makefile +++ b/servers/mfs/Makefile @@ -6,7 +6,7 @@ SRCS= cache.c device.c link.c \ write.c inode.c main.c path.c super.c DPADD+= ${LIBM} ${LIBSYS} -LDADD+= -lsys +LDADD+= -lminixfs -lsys MAN= diff --git a/servers/mfs/cache.c b/servers/mfs/cache.c index 3a6898db7..96715f6c5 100644 --- a/servers/mfs/cache.c +++ b/servers/mfs/cache.c @@ -19,6 +19,7 @@ #include #include #include +#include #include #include "buf.h" #include "super.h" @@ -567,52 +568,12 @@ PRIVATE void cache_resize(unsigned int blocksize, unsigned int bufs) *===========================================================================*/ PRIVATE int bufs_heuristic(struct super_block *sp) { - struct vm_stats_info vsi; - int 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); + u32_t btotal, bfree, bused; - /* 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_approx(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; + return fs_bufs_heuristic(MINBUFS, btotal, bfree, + sp->s_block_size, major(sp->s_dev)); } /*===========================================================================* diff --git a/servers/mfs/path.c b/servers/mfs/path.c index 10732770d..4efffcad7 100644 --- a/servers/mfs/path.c +++ b/servers/mfs/path.c @@ -36,10 +36,10 @@ FORWARD _PROTOTYPE( int parse_path, (ino_t dir_ino, ino_t root_ino, *===========================================================================*/ PUBLIC int fs_lookup() { - cp_grant_id_t grant, grant2; + cp_grant_id_t grant; int r, r1, flags, symlinks; unsigned int len; - size_t offset = 0, path_size, cred_size; + size_t offset = 0, path_size; ino_t dir_ino, root_ino; struct inode *rip; @@ -62,21 +62,16 @@ PUBLIC int fs_lookup() /* Verify this is a null-terminated path. */ if(user_path[len - 1] != '\0') return(EINVAL); - if(flags & PATH_GET_UCRED) { /* Do we have to copy uid/gid credentials? */ - grant2 = (cp_grant_id_t) fs_m_in.REQ_GRANT2; - cred_size = (size_t) fs_m_in.REQ_UCRED_SIZE; - - if (cred_size > sizeof(credentials)) return(EINVAL); /* Too big. */ - r = sys_safecopyfrom(VFS_PROC_NR, grant2, (vir_bytes) 0, - (vir_bytes) &credentials, cred_size, D); - if (r != OK) return(r); - - caller_uid = credentials.vu_uid; - caller_gid = credentials.vu_gid; + memset(&credentials, 0, sizeof(credentials)); + if(!(flags & PATH_GET_UCRED)) { /* Do we have to copy uid/gid credentials? */ + caller_uid = (uid_t) fs_m_in.REQ_UID; + caller_gid = (gid_t) fs_m_in.REQ_GID; } else { - memset(&credentials, 0, sizeof(credentials)); - caller_uid = (uid_t) fs_m_in.REQ_UID; - caller_gid = (gid_t) fs_m_in.REQ_GID; + if((r=fs_lookup_credentials(&credentials, + &caller_uid, &caller_gid, + (cp_grant_id_t) fs_m_in.REQ_GRANT2, + (size_t) fs_m_in.REQ_UCRED_SIZE)) != OK) + return r; } /* Lookup inode */ -- 2.44.0