Source-Changes-HG archive
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]
[src/trunk]: src/sys/lib/libsa Reduce memory footprint:
details: https://anonhg.NetBSD.org/src/rev/c19105bc1f79
branches: trunk
changeset: 550844:c19105bc1f79
user: dsl <dsl%NetBSD.org@localhost>
date: Fri Aug 22 21:33:52 2003 +0000
description:
Reduce memory footprint:
- use file buffer for all block reads
- only save a small amount of the indirect block list
Allows i386 bootxx_ufs code to load /boot from a filesystem with 32k blocks
while still fitting inside 64k of memory.
Code size reduced as well (by ~1k on i386).
It ought to be possible to use a buffer that is smaller than a filesystem
block. This might be needed in order to boot from filesystems with larger
block sizes.
diffstat:
sys/lib/libsa/ufs.c | 237 +++++++++++++++++++++------------------------------
1 files changed, 100 insertions(+), 137 deletions(-)
diffs (truncated from 445 to 300 lines):
diff -r 3a0691b3a2d5 -r c19105bc1f79 sys/lib/libsa/ufs.c
--- a/sys/lib/libsa/ufs.c Fri Aug 22 21:14:35 2003 +0000
+++ b/sys/lib/libsa/ufs.c Fri Aug 22 21:33:52 2003 +0000
@@ -1,4 +1,4 @@
-/* $NetBSD: ufs.c,v 1.39 2003/08/21 00:01:28 elric Exp $ */
+/* $NetBSD: ufs.c,v 1.40 2003/08/22 21:33:52 dsl Exp $ */
/*-
* Copyright (c) 1993
@@ -121,6 +121,13 @@
#define twiddle()
#endif
+#undef cgstart
+#if defined(LIBSA_FFSv2)
+#define cgstart(fc, c) cgstart_ufs2((fs), (c))
+#else
+#define cgstart(fc, c) cgstart_ufs1((fs), (c))
+#endif
+
#ifndef ufs_dinode
#define ufs_dinode ufs1_dinode
#endif
@@ -128,32 +135,39 @@
#define indp_t uint32_t
#endif
#ifndef FSBTODB
-#define FSBTODB(fs, daddr) fsbtodb(fs, daddr)
+#define FSBTODB(fs, indp) fsbtodb(fs, indp)
#endif
/*
+ * To avoid having a lot of filesystem-block sized buffers lurking (which
+ * could be 32k) we only keep a few entries of the indirect block map.
+ * With 8k blocks, 2^8 blocks is ~500k so we reread the indirect block
+ * ~13 times pulling in a 6M kernel.
+ * The cache size must be smaller than the smallest filesystem block,
+ * so LN2_IND_CACHE_SZ <= 9 (UFS2 and 4k blocks).
+ */
+#define LN2_IND_CACHE_SZ 6
+#define IND_CACHE_SZ (1 << LN2_IND_CACHE_SZ)
+#define IND_CACHE_MASK (IND_CACHE_SZ - 1)
+
+/*
* In-core open file.
*/
struct file {
off_t f_seekp; /* seek pointer */
struct fs *f_fs; /* pointer to super-block */
struct ufs_dinode f_di; /* copy of on-disk inode */
- daddr_t f_nindir[NIADDR];
- /* number of blocks mapped by
- indirect block at level i */
- int f_l2indir[NIADDR]; /* log2(f_nindir) */
- char *f_blk[NIADDR]; /* buffer for indirect block at
- level i */
- size_t f_blksize[NIADDR];
- /* size of buffer */
- daddr_t f_blkno[NIADDR];/* disk address of block in buffer */
+ uint f_nishift; /* for blocks in indirect block */
+ indp_t f_ind_cache_block;
+ indp_t f_ind_cache[IND_CACHE_SZ];
+
char *f_buf; /* buffer for data block */
size_t f_buf_size; /* size of data block */
daddr_t f_buf_blkno; /* block number of data block */
};
static int read_inode(ino_t, struct open_file *);
-static int block_map(struct open_file *, daddr_t, daddr_t *);
+static int block_map(struct open_file *, indp_t, indp_t *);
static int buf_read_file(struct open_file *, char **, size_t *);
static int search_directory(const char *, int, struct open_file *, ino_t *);
#ifdef LIBSA_FFSv1
@@ -228,30 +242,23 @@
/*
* Read inode and save it.
*/
- buf = alloc(fs->fs_bsize);
+ buf = fp->f_buf;
twiddle();
rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
- inode_sector, fs->fs_bsize,
- buf, &rsize);
+ inode_sector, fs->fs_bsize, buf, &rsize);
if (rc)
- goto out;
- if (rsize != fs->fs_bsize) {
- rc = EIO;
- goto out;
- }
+ return rc;
+ if (rsize != fs->fs_bsize)
+ return EIO;
#ifdef LIBSA_LFS
- rc = EINVAL;
cnt = INOPBx(fs);
- for (dip = (struct ufs_dinode *)buf + (cnt - 1); cnt--; --dip) {
- if (dip->di_inumber == inumber) {
- rc = 0;
- break;
- }
+ dip = (struct ufs_dinode *)buf + (cnt - 1);
+ for (; dip->di_inumber != inumber; --dip) {
+ /* kernel code panics, but boot blocks which panic are Bad. */
+ if (--cnt == 0)
+ return EINVAL;
}
- /* kernel code panics, but boot blocks which panic are Bad. */
- if (rc)
- goto out;
fp->f_di = *dip;
#else
fp->f_di = ((struct ufs_dinode *)buf)[ino_to_fsbo(fs, inumber)];
@@ -260,15 +267,8 @@
/*
* Clear out the old buffers
*/
- {
- int level;
-
- for (level = 0; level < NIADDR; level++)
- fp->f_blkno[level] = -1;
- fp->f_buf_blkno = -1;
- }
-out:
- free(buf, fs->fs_bsize);
+ fp->f_ind_cache_block = ~0;
+ fp->f_buf_blkno = -1;
return (rc);
}
@@ -277,15 +277,16 @@
* contains that block.
*/
static int
-block_map(struct open_file *f, daddr_t file_block, daddr_t *disk_block_p)
+block_map(struct open_file *f, indp_t file_block, indp_t *disk_block_p)
{
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
int level;
- int idx;
- daddr_t ind_block_num;
- indp_t *ind_p;
+ indp_t ind_cache;
+ indp_t ind_block_num;
+ size_t rsize;
int rc;
+ indp_t *buf = (void *)fp->f_buf;
/*
* Index structure of an inode:
@@ -318,54 +319,55 @@
file_block -= NDADDR;
- /*
- * nindir[0] = NINDIR
- * nindir[1] = NINDIR**2
- * nindir[2] = NINDIR**3
- * etc
- */
- for (level = 0; ; level++) {
- if (level == NIADDR)
+ ind_cache = file_block >> LN2_IND_CACHE_SZ;
+ if (ind_cache == fp->f_ind_cache_block) {
+ *disk_block_p = fp->f_ind_cache[file_block & IND_CACHE_MASK];
+ return 0;
+ }
+
+ for (level = 0;;) {
+ level += fp->f_nishift;
+ if (file_block < (indp_t)1 << level)
+ break;
+ if (level > NIADDR * fp->f_nishift)
/* Block number too high */
return (EFBIG);
- if (file_block < fp->f_nindir[level])
- break;
- file_block -= fp->f_nindir[level];
+ file_block -= (indp_t)1 << level;
}
- ind_block_num = fp->f_di.di_ib[level];
+ ind_block_num = fp->f_di.di_ib[level / fp->f_nishift - 1];
- for (; level >= 0; level--) {
+ for (;;) {
+ level -= fp->f_nishift;
if (ind_block_num == 0) {
*disk_block_p = 0; /* missing */
return (0);
}
- if (fp->f_blkno[level] != ind_block_num) {
- if (fp->f_blk[level] == NULL)
- fp->f_blk[level] = alloc(fs->fs_bsize);
- twiddle();
- rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
- FSBTODB(fp->f_fs, ind_block_num),
- fs->fs_bsize,
- fp->f_blk[level],
- &fp->f_blksize[level]);
- if (rc)
- return (rc);
- if (fp->f_blksize[level] != fs->fs_bsize)
- return (EIO);
- fp->f_blkno[level] = ind_block_num;
- }
+ twiddle();
+ /*
+ * If we were feeling brave, we could work out the number
+ * of the disk sector and read a single disk sector instead
+ * of a filesystem block.
+ * However we don't do this very often anyway...
+ */
+ rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
+ FSBTODB(fp->f_fs, ind_block_num), fs->fs_bsize,
+ buf, &rsize);
+ if (rc)
+ return (rc);
+ if (rsize != fs->fs_bsize)
+ return EIO;
+ ind_block_num = buf[file_block >> level];
+ if (level == 0)
+ break;
+ file_block &= (1 << level) - 1;
+ }
- if (level > 0) {
- idx = file_block >> fp->f_l2indir[level - 1];
- file_block &= fp->f_nindir[level - 1] - 1;
- } else
- idx = file_block;
-
- ind_p = (void *)fp->f_blk[level];
- ind_block_num = ind_p[idx];
- }
+ /* Save the part of the block that contains this sector */
+ memcpy(fp->f_ind_cache, &buf[file_block & ~IND_CACHE_MASK],
+ IND_CACHE_SZ * sizeof fp->f_ind_cache[0]);
+ fp->f_ind_cache_block = ind_cache;
*disk_block_p = ind_block_num;
@@ -373,8 +375,8 @@
}
/*
- * Read a portion of a file into an internal buffer. Return
- * the location in the buffer and the amount in the buffer.
+ * Read a portion of a file into an internal buffer.
+ * Return the location in the buffer and the amount in the buffer.
*/
static int
buf_read_file(struct open_file *f, char **buf_p, size_t *size_p)
@@ -382,8 +384,8 @@
struct file *fp = (struct file *)f->f_fsdata;
struct fs *fs = fp->f_fs;
long off;
- daddr_t file_block;
- daddr_t disk_block;
+ indp_t file_block;
+ indp_t disk_block;
size_t block_size;
int rc;
@@ -400,9 +402,6 @@
if (rc)
return (rc);
- if (fp->f_buf == NULL)
- fp->f_buf = alloc(fs->fs_bsize);
-
if (disk_block == 0) {
bzero(fp->f_buf, block_size);
fp->f_buf_size = block_size;
@@ -460,6 +459,8 @@
dp = (struct direct *)buf;
edp = (struct direct *)(buf + buf_size);
for (;dp < edp; dp = (void *)((char *)dp + dp->d_reclen)) {
+ if (dp->d_reclen <= 0)
+ break;
if (dp->d_ino == (ino_t)0)
continue;
#if BYTE_ORDER == LITTLE_ENDIAN
@@ -492,8 +493,7 @@
for (i = 0; sblock_try[i] != -1; i++) {
rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ,
- sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, (char *)fs,
- &buf_size);
+ sblock_try[i] / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size);
if (rc != 0 || buf_size != SBLOCKSIZE)
return rc;
if (fs->fs_magic == FS_UFS2_MAGIC) {
@@ -523,7 +523,7 @@
ino_t parent_inumber;
Home |
Main Index |
Thread Index |
Old Index