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