[BACK]Return to mkfs.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / usr.sbin / makefs / ffs

Annotation of src/usr.sbin/makefs/ffs/mkfs.c, Revision 1.30

1.30    ! dholland    1: /*     $NetBSD: mkfs.c,v 1.29 2013/06/23 02:06:06 dholland Exp $       */
1.1       lukem       2:
                      3: /*
1.14      fvdl        4:  * Copyright (c) 2002 Networks Associates Technology, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This software was developed for the FreeBSD Project by Marshall
                      8:  * Kirk McKusick and Network Associates Laboratories, the Security
                      9:  * Research Division of Network Associates, Inc. under DARPA/SPAWAR
                     10:  * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
                     11:  * research program
                     12:  *
1.1       lukem      13:  * Copyright (c) 1980, 1989, 1993
                     14:  *     The Regents of the University of California.  All rights reserved.
                     15:  *
                     16:  * Redistribution and use in source and binary forms, with or without
                     17:  * modification, are permitted provided that the following conditions
                     18:  * are met:
                     19:  * 1. Redistributions of source code must retain the above copyright
                     20:  *    notice, this list of conditions and the following disclaimer.
                     21:  * 2. Redistributions in binary form must reproduce the above copyright
                     22:  *    notice, this list of conditions and the following disclaimer in the
                     23:  *    documentation and/or other materials provided with the distribution.
1.16      agc        24:  * 3. Neither the name of the University nor the names of its contributors
1.1       lukem      25:  *    may be used to endorse or promote products derived from this software
                     26:  *    without specific prior written permission.
                     27:  *
                     28:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     29:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     30:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     31:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     32:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     33:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     34:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     35:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     36:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     37:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     38:  * SUCH DAMAGE.
                     39:  */
                     40:
1.19      jmc        41: #if HAVE_NBTOOL_CONFIG_H
                     42: #include "nbtool_config.h"
                     43: #endif
                     44:
1.1       lukem      45: #include <sys/cdefs.h>
1.14      fvdl       46: #ifndef lint
1.1       lukem      47: #if 0
                     48: static char sccsid[] = "@(#)mkfs.c     8.11 (Berkeley) 5/3/95";
                     49: #else
1.15      briggs     50: #ifdef __RCSID
1.30    ! dholland   51: __RCSID("$NetBSD: mkfs.c,v 1.29 2013/06/23 02:06:06 dholland Exp $");
1.15      briggs     52: #endif
1.1       lukem      53: #endif
                     54: #endif /* not lint */
                     55:
                     56: #include <sys/param.h>
                     57: #include <sys/time.h>
                     58: #include <sys/resource.h>
                     59:
                     60: #include <stdio.h>
                     61: #include <stdlib.h>
                     62: #include <string.h>
                     63: #include <unistd.h>
1.14      fvdl       64: #include <errno.h>
1.26      christos   65: #include <util.h>
1.1       lukem      66:
1.3       lukem      67: #include "makefs.h"
1.21      jmc        68: #include "ffs.h"
1.3       lukem      69:
1.6       lukem      70: #include <ufs/ufs/dinode.h>
1.4       lukem      71: #include <ufs/ufs/ufs_bswap.h>
                     72: #include <ufs/ffs/fs.h>
1.1       lukem      73:
1.5       lukem      74: #include "ffs/ufs_inode.h"
1.1       lukem      75: #include "ffs/ffs_extern.h"
                     76: #include "ffs/newfs_extern.h"
                     77:
                     78: static void initcg(int, time_t, const fsinfo_t *);
1.14      fvdl       79: static int ilog2(int);
1.1       lukem      80:
                     81: static int count_digits(int);
                     82:
                     83: /*
                     84:  * make file system for cylinder-group style file systems
                     85:  */
1.14      fvdl       86: #define        UMASK           0755
                     87: #define        POWEROF2(num)   (((num) & ((num) - 1)) == 0)
1.1       lukem      88:
                     89: union {
                     90:        struct fs fs;
1.14      fvdl       91:        char pad[SBLOCKSIZE];
1.1       lukem      92: } fsun;
                     93: #define        sblock  fsun.fs
1.14      fvdl       94: struct csum *fscs;
1.1       lukem      95:
                     96: union {
                     97:        struct cg cg;
1.20      lukem      98:        char pad[FFS_MAXBSIZE];
1.1       lukem      99: } cgun;
                    100: #define        acg     cgun.cg
                    101:
1.14      fvdl      102: char *iobuf;
                    103: int iobufsize;
1.1       lukem     104:
1.20      lukem     105: char writebuf[FFS_MAXBSIZE];
1.1       lukem     106:
1.14      fvdl      107: static int     Oflag;     /* format as an 4.3BSD file system */
                    108: static int64_t fssize;    /* file system size */
                    109: static int     sectorsize;        /* bytes/sector */
                    110: static int     fsize;     /* fragment size */
                    111: static int     bsize;     /* block size */
                    112: static int     maxbsize;   /* maximum clustering */
                    113: static int     maxblkspercg;
                    114: static int     minfree;           /* free space threshold */
                    115: static int     opt;               /* optimization preference (space or time) */
                    116: static int     density;           /* number of bytes per inode */
                    117: static int     maxcontig;         /* max contiguous blocks to allocate */
                    118: static int     maxbpg;    /* maximum blocks per file in a cyl group */
                    119: static int     bbsize;    /* boot block size */
                    120: static int     sbsize;    /* superblock size */
                    121: static int     avgfilesize;       /* expected average file size */
                    122: static int     avgfpdir;          /* expected number of files per directory */
1.1       lukem     123:
                    124: struct fs *
                    125: ffs_mkfs(const char *fsys, const fsinfo_t *fsopts)
                    126: {
1.14      fvdl      127:        int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg;
                    128:        int32_t cylno, i, csfrags;
1.1       lukem     129:        long long sizepb;
                    130:        void *space;
                    131:        int size, blks;
                    132:        int nprintcols, printcolwidth;
1.21      jmc       133:        ffs_opt_t       *ffs_opts = fsopts->fs_specific;
1.1       lukem     134:
1.21      jmc       135:        Oflag =         ffs_opts->version;
1.14      fvdl      136:        fssize =        fsopts->size / fsopts->sectorsize;
                    137:        sectorsize =    fsopts->sectorsize;
1.21      jmc       138:        fsize =         ffs_opts->fsize;
                    139:        bsize =         ffs_opts->bsize;
                    140:        maxbsize =      ffs_opts->maxbsize;
                    141:        maxblkspercg =  ffs_opts->maxblkspercg;
                    142:        minfree =       ffs_opts->minfree;
                    143:        opt =           ffs_opts->optimization;
                    144:        density =       ffs_opts->density;
                    145:        maxcontig =     ffs_opts->maxcontig;
                    146:        maxbpg =        ffs_opts->maxbpg;
                    147:        avgfilesize =   ffs_opts->avgfilesize;
                    148:        avgfpdir =      ffs_opts->avgfpdir;
1.14      fvdl      149:        bbsize =        BBSIZE;
                    150:        sbsize =        SBLOCKSIZE;
1.22      christos  151:
                    152:        strlcpy((char *)sblock.fs_volname, ffs_opts->label,
                    153:            sizeof(sblock.fs_volname));
                    154:
1.14      fvdl      155:        if (Oflag == 0) {
                    156:                sblock.fs_old_inodefmt = FS_42INODEFMT;
1.1       lukem     157:                sblock.fs_maxsymlinklen = 0;
1.14      fvdl      158:                sblock.fs_old_flags = 0;
1.1       lukem     159:        } else {
1.14      fvdl      160:                sblock.fs_old_inodefmt = FS_44INODEFMT;
1.25      dholland  161:                sblock.fs_maxsymlinklen = (Oflag == 1 ? UFS1_MAXSYMLINKLEN :
                    162:                    UFS2_MAXSYMLINKLEN);
1.14      fvdl      163:                sblock.fs_old_flags = FS_FLAGS_UPDATED;
                    164:                sblock.fs_flags = 0;
1.1       lukem     165:        }
                    166:        /*
                    167:         * Validate the given file system size.
                    168:         * Verify that its last block can actually be accessed.
1.14      fvdl      169:         * Convert to file system fragment sized units.
1.1       lukem     170:         */
1.14      fvdl      171:        if (fssize <= 0) {
                    172:                printf("preposterous size %lld\n", (long long)fssize);
                    173:                exit(13);
                    174:        }
1.1       lukem     175:        ffs_wtfs(fssize - 1, sectorsize, (char *)&sblock, fsopts);
                    176:
                    177:        /*
                    178:         * collect and verify the filesystem density info
                    179:         */
                    180:        sblock.fs_avgfilesize = avgfilesize;
                    181:        sblock.fs_avgfpdir = avgfpdir;
                    182:        if (sblock.fs_avgfilesize <= 0)
                    183:                printf("illegal expected average file size %d\n",
                    184:                    sblock.fs_avgfilesize), exit(14);
                    185:        if (sblock.fs_avgfpdir <= 0)
                    186:                printf("illegal expected number of files per directory %d\n",
                    187:                    sblock.fs_avgfpdir), exit(15);
                    188:        /*
                    189:         * collect and verify the block and fragment sizes
                    190:         */
                    191:        sblock.fs_bsize = bsize;
                    192:        sblock.fs_fsize = fsize;
                    193:        if (!POWEROF2(sblock.fs_bsize)) {
                    194:                printf("block size must be a power of 2, not %d\n",
                    195:                    sblock.fs_bsize);
                    196:                exit(16);
                    197:        }
                    198:        if (!POWEROF2(sblock.fs_fsize)) {
                    199:                printf("fragment size must be a power of 2, not %d\n",
                    200:                    sblock.fs_fsize);
                    201:                exit(17);
                    202:        }
                    203:        if (sblock.fs_fsize < sectorsize) {
                    204:                printf("fragment size %d is too small, minimum is %d\n",
                    205:                    sblock.fs_fsize, sectorsize);
                    206:                exit(18);
                    207:        }
1.14      fvdl      208:        if (sblock.fs_bsize < MINBSIZE) {
                    209:                printf("block size %d is too small, minimum is %d\n",
                    210:                    sblock.fs_bsize, MINBSIZE);
                    211:                exit(19);
                    212:        }
1.20      lukem     213:        if (sblock.fs_bsize > FFS_MAXBSIZE) {
1.7       lukem     214:                printf("block size %d is too large, maximum is %d\n",
1.20      lukem     215:                    sblock.fs_bsize, FFS_MAXBSIZE);
1.7       lukem     216:                exit(19);
                    217:        }
1.1       lukem     218:        if (sblock.fs_bsize < sblock.fs_fsize) {
                    219:                printf("block size (%d) cannot be smaller than fragment size (%d)\n",
                    220:                    sblock.fs_bsize, sblock.fs_fsize);
                    221:                exit(20);
                    222:        }
1.14      fvdl      223:
                    224:        if (maxbsize < bsize || !POWEROF2(maxbsize)) {
                    225:                sblock.fs_maxbsize = sblock.fs_bsize;
                    226:                printf("Extent size set to %d\n", sblock.fs_maxbsize);
                    227:        } else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) {
                    228:                sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize;
                    229:                printf("Extent size reduced to %d\n", sblock.fs_maxbsize);
                    230:        } else {
                    231:                sblock.fs_maxbsize = maxbsize;
                    232:        }
                    233:        sblock.fs_maxcontig = maxcontig;
                    234:        if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) {
                    235:                sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize;
                    236:                printf("Maxcontig raised to %d\n", sblock.fs_maxbsize);
                    237:        }
                    238:
                    239:        if (sblock.fs_maxcontig > 1)
                    240:                sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG);
                    241:
1.1       lukem     242:        sblock.fs_bmask = ~(sblock.fs_bsize - 1);
                    243:        sblock.fs_fmask = ~(sblock.fs_fsize - 1);
                    244:        sblock.fs_qbmask = ~sblock.fs_bmask;
                    245:        sblock.fs_qfmask = ~sblock.fs_fmask;
                    246:        for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
                    247:                sblock.fs_bshift++;
                    248:        for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
                    249:                sblock.fs_fshift++;
1.30    ! dholland  250:        sblock.fs_frag = ffs_numfrags(&sblock, sblock.fs_bsize);
1.1       lukem     251:        for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
                    252:                sblock.fs_fragshift++;
                    253:        if (sblock.fs_frag > MAXFRAG) {
                    254:                printf("fragment size %d is too small, "
                    255:                        "minimum with block size %d is %d\n",
                    256:                    sblock.fs_fsize, sblock.fs_bsize,
                    257:                    sblock.fs_bsize / MAXFRAG);
                    258:                exit(21);
                    259:        }
1.14      fvdl      260:        sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize);
1.29      dholland  261:        sblock.fs_size = fssize = FFS_DBTOFSB(&sblock, fssize);
1.14      fvdl      262:
                    263:        if (Oflag <= 1) {
                    264:                sblock.fs_magic = FS_UFS1_MAGIC;
                    265:                sblock.fs_sblockloc = SBLOCK_UFS1;
                    266:                sblock.fs_nindir = sblock.fs_bsize / sizeof(int32_t);
                    267:                sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode);
1.25      dholland  268:                sblock.fs_maxsymlinklen = ((UFS_NDADDR + UFS_NIADDR) *
1.14      fvdl      269:                    sizeof (int32_t));
                    270:                sblock.fs_old_inodefmt = FS_44INODEFMT;
                    271:                sblock.fs_old_cgoffset = 0;
                    272:                sblock.fs_old_cgmask = 0xffffffff;
                    273:                sblock.fs_old_size = sblock.fs_size;
                    274:                sblock.fs_old_rotdelay = 0;
                    275:                sblock.fs_old_rps = 60;
                    276:                sblock.fs_old_nspf = sblock.fs_fsize / sectorsize;
                    277:                sblock.fs_old_cpg = 1;
                    278:                sblock.fs_old_interleave = 1;
                    279:                sblock.fs_old_trackskew = 0;
                    280:                sblock.fs_old_cpc = 0;
                    281:                sblock.fs_old_postblformat = 1;
                    282:                sblock.fs_old_nrpos = 1;
                    283:        } else {
                    284:                sblock.fs_magic = FS_UFS2_MAGIC;
                    285: #if 0 /* XXX makefs is used for small filesystems. */
                    286:                sblock.fs_sblockloc = SBLOCK_UFS2;
                    287: #else
                    288:                sblock.fs_sblockloc = SBLOCK_UFS1;
                    289: #endif
                    290:                sblock.fs_nindir = sblock.fs_bsize / sizeof(int64_t);
                    291:                sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode);
1.25      dholland  292:                sblock.fs_maxsymlinklen = ((UFS_NDADDR + UFS_NIADDR) *
1.14      fvdl      293:                    sizeof (int64_t));
                    294:        }
                    295:
1.1       lukem     296:        sblock.fs_sblkno =
1.14      fvdl      297:            roundup(howmany(sblock.fs_sblockloc + SBLOCKSIZE, sblock.fs_fsize),
                    298:                sblock.fs_frag);
1.1       lukem     299:        sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno +
1.14      fvdl      300:            roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag));
1.1       lukem     301:        sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
1.25      dholland  302:        sblock.fs_maxfilesize = sblock.fs_bsize * UFS_NDADDR - 1;
                    303:        for (sizepb = sblock.fs_bsize, i = 0; i < UFS_NIADDR; i++) {
1.28      dholland  304:                sizepb *= FFS_NINDIR(&sblock);
1.1       lukem     305:                sblock.fs_maxfilesize += sizepb;
                    306:        }
1.14      fvdl      307:
1.1       lukem     308:        /*
1.14      fvdl      309:         * Calculate the number of blocks to put into each cylinder group.
                    310:         *
                    311:         * This algorithm selects the number of blocks per cylinder
                    312:         * group. The first goal is to have at least enough data blocks
                    313:         * in each cylinder group to meet the density requirement. Once
                    314:         * this goal is achieved we try to expand to have at least
                    315:         * 1 cylinder group. Once this goal is achieved, we pack as
                    316:         * many blocks into each cylinder group map as will fit.
                    317:         *
                    318:         * We start by calculating the smallest number of blocks that we
                    319:         * can put into each cylinder group. If this is too big, we reduce
                    320:         * the density until it fits.
                    321:         */
                    322:        origdensity = density;
                    323:        for (;;) {
1.30    ! dholland  324:                fragsperinode = MAX(ffs_numfrags(&sblock, density), 1);
1.28      dholland  325:                minfpg = fragsperinode * FFS_INOPB(&sblock);
1.14      fvdl      326:                if (minfpg > sblock.fs_size)
                    327:                        minfpg = sblock.fs_size;
1.28      dholland  328:                sblock.fs_ipg = FFS_INOPB(&sblock);
1.14      fvdl      329:                sblock.fs_fpg = roundup(sblock.fs_iblkno +
1.28      dholland  330:                    sblock.fs_ipg / FFS_INOPF(&sblock), sblock.fs_frag);
1.14      fvdl      331:                if (sblock.fs_fpg < minfpg)
                    332:                        sblock.fs_fpg = minfpg;
                    333:                sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
1.28      dholland  334:                    FFS_INOPB(&sblock));
1.14      fvdl      335:                sblock.fs_fpg = roundup(sblock.fs_iblkno +
1.28      dholland  336:                    sblock.fs_ipg / FFS_INOPF(&sblock), sblock.fs_frag);
1.14      fvdl      337:                if (sblock.fs_fpg < minfpg)
                    338:                        sblock.fs_fpg = minfpg;
                    339:                sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
1.28      dholland  340:                    FFS_INOPB(&sblock));
1.14      fvdl      341:                if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
                    342:                        break;
                    343:                density -= sblock.fs_fsize;
1.1       lukem     344:        }
1.14      fvdl      345:        if (density != origdensity)
                    346:                printf("density reduced from %d to %d\n", origdensity, density);
                    347:
                    348:        if (maxblkspercg <= 0 || maxblkspercg >= fssize)
                    349:                maxblkspercg = fssize - 1;
1.1       lukem     350:        /*
1.14      fvdl      351:         * Start packing more blocks into the cylinder group until
                    352:         * it cannot grow any larger, the number of cylinder groups
                    353:         * drops below 1, or we reach the size requested.
                    354:         */
                    355:        for ( ; sblock.fs_fpg < maxblkspercg; sblock.fs_fpg += sblock.fs_frag) {
                    356:                sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
1.28      dholland  357:                    FFS_INOPB(&sblock));
1.14      fvdl      358:                if (sblock.fs_size / sblock.fs_fpg < 1)
1.1       lukem     359:                        break;
1.14      fvdl      360:                if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
                    361:                        continue;
                    362:                if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
1.1       lukem     363:                        break;
1.14      fvdl      364:                sblock.fs_fpg -= sblock.fs_frag;
                    365:                sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
1.28      dholland  366:                    FFS_INOPB(&sblock));
1.14      fvdl      367:                break;
                    368:        }
                    369:        /*
                    370:         * Check to be sure that the last cylinder group has enough blocks
                    371:         * to be viable. If it is too small, reduce the number of blocks
                    372:         * per cylinder group which will have the effect of moving more
                    373:         * blocks into the last cylinder group.
                    374:         */
                    375:        optimalfpg = sblock.fs_fpg;
                    376:        for (;;) {
                    377:                sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
                    378:                lastminfpg = roundup(sblock.fs_iblkno +
1.28      dholland  379:                    sblock.fs_ipg / FFS_INOPF(&sblock), sblock.fs_frag);
1.14      fvdl      380:                if (sblock.fs_size < lastminfpg) {
                    381:                        printf("Filesystem size %lld < minimum size of %d\n",
                    382:                            (long long)sblock.fs_size, lastminfpg);
                    383:                        exit(28);
1.1       lukem     384:                }
1.14      fvdl      385:                if (sblock.fs_size % sblock.fs_fpg >= lastminfpg ||
                    386:                    sblock.fs_size % sblock.fs_fpg == 0)
                    387:                        break;
                    388:                sblock.fs_fpg -= sblock.fs_frag;
                    389:                sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
1.28      dholland  390:                    FFS_INOPB(&sblock));
1.14      fvdl      391:        }
                    392:        if (optimalfpg != sblock.fs_fpg)
                    393:                printf("Reduced frags per cylinder group from %d to %d %s\n",
                    394:                   optimalfpg, sblock.fs_fpg, "to enlarge last cyl group");
1.30    ! dholland  395:        sblock.fs_cgsize = ffs_fragroundup(&sblock, CGSIZE(&sblock));
1.28      dholland  396:        sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / FFS_INOPF(&sblock);
1.14      fvdl      397:        if (Oflag <= 1) {
                    398:                sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf;
                    399:                sblock.fs_old_nsect = sblock.fs_old_spc;
                    400:                sblock.fs_old_npsect = sblock.fs_old_spc;
                    401:                sblock.fs_old_ncyl = sblock.fs_ncg;
1.1       lukem     402:        }
1.14      fvdl      403:
1.1       lukem     404:        /*
                    405:         * fill in remaining fields of the super block
                    406:         */
                    407:        sblock.fs_csaddr = cgdmin(&sblock, 0);
                    408:        sblock.fs_cssize =
1.30    ! dholland  409:            ffs_fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
1.1       lukem     410:
                    411:        /*
                    412:         * Setup memory for temporary in-core cylgroup summaries.
                    413:         * Cribbed from ffs_mountfs().
                    414:         */
                    415:        size = sblock.fs_cssize;
                    416:        blks = howmany(size, sblock.fs_fsize);
                    417:        if (sblock.fs_contigsumsize > 0)
                    418:                size += sblock.fs_ncg * sizeof(int32_t);
1.26      christos  419:        space = ecalloc(1, size);
1.1       lukem     420:        sblock.fs_csp = space;
                    421:        space = (char *)space + sblock.fs_cssize;
                    422:        if (sblock.fs_contigsumsize > 0) {
                    423:                int32_t *lp;
                    424:
                    425:                sblock.fs_maxcluster = lp = space;
                    426:                for (i = 0; i < sblock.fs_ncg; i++)
1.14      fvdl      427:                *lp++ = sblock.fs_contigsumsize;
1.1       lukem     428:        }
                    429:
1.30    ! dholland  430:        sblock.fs_sbsize = ffs_fragroundup(&sblock, sizeof(struct fs));
1.14      fvdl      431:        if (sblock.fs_sbsize > SBLOCKSIZE)
                    432:                sblock.fs_sbsize = SBLOCKSIZE;
1.1       lukem     433:        sblock.fs_minfree = minfree;
                    434:        sblock.fs_maxcontig = maxcontig;
                    435:        sblock.fs_maxbpg = maxbpg;
                    436:        sblock.fs_optim = opt;
                    437:        sblock.fs_cgrotor = 0;
1.14      fvdl      438:        sblock.fs_pendingblocks = 0;
                    439:        sblock.fs_pendinginodes = 0;
1.1       lukem     440:        sblock.fs_cstotal.cs_ndir = 0;
                    441:        sblock.fs_cstotal.cs_nbfree = 0;
                    442:        sblock.fs_cstotal.cs_nifree = 0;
                    443:        sblock.fs_cstotal.cs_nffree = 0;
                    444:        sblock.fs_fmod = 0;
1.14      fvdl      445:        sblock.fs_ronly = 0;
                    446:        sblock.fs_state = 0;
1.1       lukem     447:        sblock.fs_clean = FS_ISCLEAN;
                    448:        sblock.fs_ronly = 0;
1.14      fvdl      449:        sblock.fs_id[0] = start_time.tv_sec;
1.18      fvdl      450:        sblock.fs_id[1] = random();
1.14      fvdl      451:        sblock.fs_fsmnt[0] = '\0';
                    452:        csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize);
                    453:        sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno -
                    454:            sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno);
                    455:        sblock.fs_cstotal.cs_nbfree =
                    456:            fragstoblks(&sblock, sblock.fs_dsize) -
                    457:            howmany(csfrags, sblock.fs_frag);
                    458:        sblock.fs_cstotal.cs_nffree =
                    459:            fragnum(&sblock, sblock.fs_size) +
                    460:            (fragnum(&sblock, csfrags) > 0 ?
                    461:            sblock.fs_frag - fragnum(&sblock, csfrags) : 0);
1.25      dholland  462:        sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - UFS_ROOTINO;
1.14      fvdl      463:        sblock.fs_cstotal.cs_ndir = 0;
                    464:        sblock.fs_dsize -= csfrags;
                    465:        sblock.fs_time = start_time.tv_sec;
                    466:        if (Oflag <= 1) {
                    467:                sblock.fs_old_time = start_time.tv_sec;
                    468:                sblock.fs_old_dsize = sblock.fs_dsize;
                    469:                sblock.fs_old_csaddr = sblock.fs_csaddr;
                    470:                sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
                    471:                sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
                    472:                sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
                    473:                sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
                    474:        }
1.1       lukem     475:        /*
                    476:         * Dump out summary information about file system.
                    477:         */
1.14      fvdl      478: #define        B2MBFACTOR (1 / (1024.0 * 1024.0))
                    479:        printf("%s: %.1fMB (%lld sectors) block size %d, "
                    480:               "fragment size %d\n",
                    481:            fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
1.29      dholland  482:            (long long)FFS_FSBTODB(&sblock, sblock.fs_size),
1.14      fvdl      483:            sblock.fs_bsize, sblock.fs_fsize);
                    484:        printf("\tusing %d cylinder groups of %.2fMB, %d blks, "
                    485:               "%d inodes.\n",
                    486:            sblock.fs_ncg,
                    487:            (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
                    488:            sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
1.1       lukem     489: #undef B2MBFACTOR
                    490:        /*
                    491:         * Now determine how wide each column will be, and calculate how
                    492:         * many columns will fit in a 76 char line. 76 is the width of the
                    493:         * subwindows in sysinst.
                    494:         */
                    495:        printcolwidth = count_digits(
1.29      dholland  496:                        FFS_FSBTODB(&sblock, cgsblock(&sblock, sblock.fs_ncg -1)));
1.1       lukem     497:        nprintcols = 76 / (printcolwidth + 2);
1.14      fvdl      498:
                    499:        /*
                    500:         * allocate space for superblock, cylinder group map, and
                    501:         * two sets of inode blocks.
                    502:         */
                    503:        if (sblock.fs_bsize < SBLOCKSIZE)
                    504:                iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize;
                    505:        else
                    506:                iobufsize = 4 * sblock.fs_bsize;
1.26      christos  507:        iobuf = ecalloc(1, iobufsize);
1.1       lukem     508:        /*
1.14      fvdl      509:         * Make a copy of the superblock into the buffer that we will be
                    510:         * writing out in each cylinder group.
1.1       lukem     511:         */
1.14      fvdl      512:        memcpy(writebuf, &sblock, sbsize);
                    513:        if (fsopts->needswap)
                    514:                ffs_sb_swap(&sblock, (struct fs*)writebuf);
                    515:        memcpy(iobuf, writebuf, SBLOCKSIZE);
                    516:
                    517:        printf("super-block backups (for fsck -b #) at:");
1.1       lukem     518:        for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
                    519:                initcg(cylno, start_time.tv_sec, fsopts);
                    520:                if (cylno % nprintcols == 0)
                    521:                        printf("\n");
1.12      fvdl      522:                printf(" %*lld,", printcolwidth,
1.29      dholland  523:                        (long long)FFS_FSBTODB(&sblock, cgsblock(&sblock, cylno)));
1.1       lukem     524:                fflush(stdout);
                    525:        }
                    526:        printf("\n");
                    527:
                    528:        /*
                    529:         * Now construct the initial file system,
                    530:         * then write out the super-block.
                    531:         */
                    532:        sblock.fs_time = start_time.tv_sec;
1.14      fvdl      533:        if (Oflag <= 1) {
                    534:                sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
                    535:                sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
                    536:                sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
                    537:                sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
                    538:        }
1.1       lukem     539:        if (fsopts->needswap)
                    540:                sblock.fs_flags |= FS_SWAPPED;
                    541:        ffs_write_superblock(&sblock, fsopts);
                    542:        return (&sblock);
                    543: }
                    544:
                    545: /*
                    546:  * Write out the superblock and its duplicates,
                    547:  * and the cylinder group summaries
                    548:  */
                    549: void
                    550: ffs_write_superblock(struct fs *fs, const fsinfo_t *fsopts)
                    551: {
1.14      fvdl      552:        int cylno, size, blks, i, saveflag;
                    553:        void *space;
                    554:        char *wrbuf;
1.1       lukem     555:
                    556:        saveflag = fs->fs_flags & FS_INTERNAL;
                    557:        fs->fs_flags &= ~FS_INTERNAL;
                    558:
1.14      fvdl      559:         memcpy(writebuf, &sblock, sbsize);
1.1       lukem     560:        if (fsopts->needswap)
                    561:                ffs_sb_swap(fs, (struct fs*)writebuf);
1.14      fvdl      562:        ffs_wtfs(fs->fs_sblockloc / sectorsize, sbsize, writebuf, fsopts);
1.1       lukem     563:
1.14      fvdl      564:        /* Write out the duplicate super blocks */
                    565:        for (cylno = 0; cylno < fs->fs_ncg; cylno++)
1.29      dholland  566:                ffs_wtfs(FFS_FSBTODB(fs, cgsblock(fs, cylno)),
1.1       lukem     567:                    sbsize, writebuf, fsopts);
                    568:
1.14      fvdl      569:        /* Write out the cylinder group summaries */
1.1       lukem     570:        size = fs->fs_cssize;
                    571:        blks = howmany(size, fs->fs_fsize);
                    572:        space = (void *)fs->fs_csp;
1.26      christos  573:        wrbuf = emalloc(size);
1.1       lukem     574:        for (i = 0; i < blks; i+= fs->fs_frag) {
                    575:                size = fs->fs_bsize;
                    576:                if (i + fs->fs_frag > blks)
                    577:                        size = (blks - i) * fs->fs_fsize;
                    578:                if (fsopts->needswap)
                    579:                        ffs_csum_swap((struct csum *)space,
                    580:                            (struct csum *)wrbuf, size);
                    581:                else
                    582:                        memcpy(wrbuf, space, (u_int)size);
1.29      dholland  583:                ffs_wtfs(FFS_FSBTODB(fs, fs->fs_csaddr + i), size, wrbuf, fsopts);
1.1       lukem     584:                space = (char *)space + size;
                    585:        }
                    586:        free(wrbuf);
                    587:        fs->fs_flags |= saveflag;
                    588: }
                    589:
                    590: /*
                    591:  * Initialize a cylinder group.
                    592:  */
                    593: static void
                    594: initcg(int cylno, time_t utime, const fsinfo_t *fsopts)
                    595: {
1.14      fvdl      596:        daddr_t cbase, dmax;
1.23      christos  597:        int i, j, d, dlower, dupper, blkno;
1.14      fvdl      598:        struct ufs1_dinode *dp1;
                    599:        struct ufs2_dinode *dp2;
                    600:        int start;
1.1       lukem     601:
                    602:        /*
                    603:         * Determine block bounds for cylinder group.
                    604:         * Allow space for super block summary information in first
                    605:         * cylinder group.
                    606:         */
                    607:        cbase = cgbase(&sblock, cylno);
                    608:        dmax = cbase + sblock.fs_fpg;
                    609:        if (dmax > sblock.fs_size)
                    610:                dmax = sblock.fs_size;
                    611:        dlower = cgsblock(&sblock, cylno) - cbase;
                    612:        dupper = cgdmin(&sblock, cylno) - cbase;
                    613:        if (cylno == 0)
                    614:                dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
                    615:        memset(&acg, 0, sblock.fs_cgsize);
                    616:        acg.cg_time = utime;
                    617:        acg.cg_magic = CG_MAGIC;
                    618:        acg.cg_cgx = cylno;
                    619:        acg.cg_niblk = sblock.fs_ipg;
1.28      dholland  620:        acg.cg_initediblk = sblock.fs_ipg < 2 * FFS_INOPB(&sblock) ?
                    621:            sblock.fs_ipg : 2 * FFS_INOPB(&sblock);
1.1       lukem     622:        acg.cg_ndblk = dmax - cbase;
                    623:        if (sblock.fs_contigsumsize > 0)
1.14      fvdl      624:                acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift;
                    625:        start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
                    626:        if (Oflag == 2) {
                    627:                acg.cg_iusedoff = start;
                    628:        } else {
                    629:                if (cylno == sblock.fs_ncg - 1)
                    630:                        acg.cg_old_ncyl = howmany(acg.cg_ndblk,
                    631:                            sblock.fs_fpg / sblock.fs_old_cpg);
                    632:                else
                    633:                        acg.cg_old_ncyl = sblock.fs_old_cpg;
                    634:                acg.cg_old_time = acg.cg_time;
                    635:                acg.cg_time = 0;
                    636:                acg.cg_old_niblk = acg.cg_niblk;
                    637:                acg.cg_niblk = 0;
                    638:                acg.cg_initediblk = 0;
                    639:                acg.cg_old_btotoff = start;
                    640:                acg.cg_old_boff = acg.cg_old_btotoff +
                    641:                    sblock.fs_old_cpg * sizeof(int32_t);
                    642:                acg.cg_iusedoff = acg.cg_old_boff +
                    643:                    sblock.fs_old_cpg * sizeof(u_int16_t);
                    644:        }
                    645:        acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
1.1       lukem     646:        if (sblock.fs_contigsumsize <= 0) {
                    647:                acg.cg_nextfreeoff = acg.cg_freeoff +
1.14      fvdl      648:                   howmany(sblock.fs_fpg, CHAR_BIT);
1.1       lukem     649:        } else {
1.14      fvdl      650:                acg.cg_clustersumoff = acg.cg_freeoff +
                    651:                    howmany(sblock.fs_fpg, CHAR_BIT) - sizeof(int32_t);
1.1       lukem     652:                acg.cg_clustersumoff =
                    653:                    roundup(acg.cg_clustersumoff, sizeof(int32_t));
                    654:                acg.cg_clusteroff = acg.cg_clustersumoff +
                    655:                    (sblock.fs_contigsumsize + 1) * sizeof(int32_t);
1.14      fvdl      656:                acg.cg_nextfreeoff = acg.cg_clusteroff +
                    657:                    howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
1.1       lukem     658:        }
                    659:        if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
                    660:                printf("Panic: cylinder group too big\n");
                    661:                exit(37);
                    662:        }
                    663:        acg.cg_cs.cs_nifree += sblock.fs_ipg;
1.24      dholland  664:        if (cylno == 0) {
                    665:                size_t r;
                    666:
1.25      dholland  667:                for (r = 0; r < UFS_ROOTINO; r++) {
1.23      christos  668:                        setbit(cg_inosused(&acg, 0), r);
1.1       lukem     669:                        acg.cg_cs.cs_nifree--;
                    670:                }
1.24      dholland  671:        }
1.1       lukem     672:        if (cylno > 0) {
                    673:                /*
                    674:                 * In cylno 0, beginning space is reserved
                    675:                 * for boot and super blocks.
                    676:                 */
1.14      fvdl      677:                for (d = 0, blkno = 0; d < dlower;) {
1.1       lukem     678:                        ffs_setblock(&sblock, cg_blksfree(&acg, 0), blkno);
                    679:                        if (sblock.fs_contigsumsize > 0)
                    680:                                setbit(cg_clustersfree(&acg, 0), blkno);
                    681:                        acg.cg_cs.cs_nbfree++;
1.14      fvdl      682:                        d += sblock.fs_frag;
                    683:                        blkno++;
1.1       lukem     684:                }
                    685:        }
1.14      fvdl      686:        if ((i = (dupper & (sblock.fs_frag - 1))) != 0) {
1.1       lukem     687:                acg.cg_frsum[sblock.fs_frag - i]++;
                    688:                for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
                    689:                        setbit(cg_blksfree(&acg, 0), dupper);
                    690:                        acg.cg_cs.cs_nffree++;
                    691:                }
                    692:        }
1.14      fvdl      693:        for (d = dupper, blkno = dupper >> sblock.fs_fragshift;
                    694:             d + sblock.fs_frag <= acg.cg_ndblk; ) {
1.1       lukem     695:                ffs_setblock(&sblock, cg_blksfree(&acg, 0), blkno);
                    696:                if (sblock.fs_contigsumsize > 0)
                    697:                        setbit(cg_clustersfree(&acg, 0), blkno);
                    698:                acg.cg_cs.cs_nbfree++;
                    699:                d += sblock.fs_frag;
1.14      fvdl      700:                blkno++;
1.1       lukem     701:        }
1.14      fvdl      702:        if (d < acg.cg_ndblk) {
                    703:                acg.cg_frsum[acg.cg_ndblk - d]++;
                    704:                for (; d < acg.cg_ndblk; d++) {
1.1       lukem     705:                        setbit(cg_blksfree(&acg, 0), d);
                    706:                        acg.cg_cs.cs_nffree++;
                    707:                }
                    708:        }
                    709:        if (sblock.fs_contigsumsize > 0) {
                    710:                int32_t *sump = cg_clustersum(&acg, 0);
                    711:                u_char *mapp = cg_clustersfree(&acg, 0);
                    712:                int map = *mapp++;
                    713:                int bit = 1;
                    714:                int run = 0;
                    715:
                    716:                for (i = 0; i < acg.cg_nclusterblks; i++) {
                    717:                        if ((map & bit) != 0) {
                    718:                                run++;
                    719:                        } else if (run != 0) {
                    720:                                if (run > sblock.fs_contigsumsize)
                    721:                                        run = sblock.fs_contigsumsize;
                    722:                                sump[run]++;
                    723:                                run = 0;
                    724:                        }
1.14      fvdl      725:                        if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) {
1.1       lukem     726:                                bit <<= 1;
                    727:                        } else {
                    728:                                map = *mapp++;
                    729:                                bit = 1;
                    730:                        }
                    731:                }
                    732:                if (run != 0) {
                    733:                        if (run > sblock.fs_contigsumsize)
                    734:                                run = sblock.fs_contigsumsize;
                    735:                        sump[run]++;
                    736:                }
                    737:        }
                    738:        sblock.fs_cs(&sblock, cylno) = acg.cg_cs;
1.14      fvdl      739:        /*
                    740:         * Write out the duplicate super block, the cylinder group map
                    741:         * and two blocks worth of inodes in a single write.
                    742:         */
                    743:        start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE;
                    744:        memcpy(&iobuf[start], &acg, sblock.fs_cgsize);
1.1       lukem     745:        if (fsopts->needswap)
1.14      fvdl      746:                ffs_cg_swap(&acg, (struct cg*)&iobuf[start], &sblock);
                    747:        start += sblock.fs_bsize;
                    748:        dp1 = (struct ufs1_dinode *)(&iobuf[start]);
                    749:        dp2 = (struct ufs2_dinode *)(&iobuf[start]);
                    750:        for (i = 0; i < acg.cg_initediblk; i++) {
                    751:                if (sblock.fs_magic == FS_UFS1_MAGIC) {
                    752:                        /* No need to swap, it'll stay random */
1.18      fvdl      753:                        dp1->di_gen = random();
1.14      fvdl      754:                        dp1++;
                    755:                } else {
1.18      fvdl      756:                        dp2->di_gen = random();
1.14      fvdl      757:                        dp2++;
                    758:                }
                    759:        }
1.29      dholland  760:        ffs_wtfs(FFS_FSBTODB(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf,
1.14      fvdl      761:            fsopts);
                    762:        /*
                    763:         * For the old file system, we have to initialize all the inodes.
                    764:         */
                    765:        if (Oflag <= 1) {
                    766:                for (i = 2 * sblock.fs_frag;
1.28      dholland  767:                     i < sblock.fs_ipg / FFS_INOPF(&sblock);
1.14      fvdl      768:                     i += sblock.fs_frag) {
                    769:                        dp1 = (struct ufs1_dinode *)(&iobuf[start]);
1.28      dholland  770:                        for (j = 0; j < FFS_INOPB(&sblock); j++) {
1.18      fvdl      771:                                dp1->di_gen = random();
1.14      fvdl      772:                                dp1++;
                    773:                        }
1.29      dholland  774:                        ffs_wtfs(FFS_FSBTODB(&sblock, cgimin(&sblock, cylno) + i),
1.14      fvdl      775:                            sblock.fs_bsize, &iobuf[start], fsopts);
1.1       lukem     776:                }
                    777:        }
                    778: }
                    779:
                    780: /*
                    781:  * read a block from the file system
                    782:  */
                    783: void
                    784: ffs_rdfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
                    785: {
                    786:        int n;
                    787:        off_t offset;
                    788:
1.27      christos  789:        offset = bno * fsopts->sectorsize + fsopts->offset;
1.1       lukem     790:        if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
1.27      christos  791:                err(1, "%s: seek error for sector %lld", __func__,
                    792:                    (long long)bno);
1.1       lukem     793:        n = read(fsopts->fd, bf, size);
1.14      fvdl      794:        if (n == -1) {
1.27      christos  795:                err(1, "%s: read error bno %lld size %d", __func__,
                    796:                    (long long)bno, size);
1.14      fvdl      797:        }
1.1       lukem     798:        else if (n != size)
1.27      christos  799:                errx(1, "%s: short read error for sector %lld", __func__,
                    800:                    (long long)bno);
1.1       lukem     801: }
                    802:
                    803: /*
                    804:  * write a block to the file system
                    805:  */
                    806: void
                    807: ffs_wtfs(daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
                    808: {
                    809:        int n;
                    810:        off_t offset;
                    811:
1.27      christos  812:        offset = bno * fsopts->sectorsize + fsopts->offset;
                    813:        if (lseek(fsopts->fd, offset, SEEK_SET) == -1)
                    814:                err(1, "%s: seek error for sector %lld", __func__,
                    815:                    (long long)bno);
1.1       lukem     816:        n = write(fsopts->fd, bf, size);
                    817:        if (n == -1)
1.27      christos  818:                err(1, "%s: write error for sector %lld", __func__,
                    819:                    (long long)bno);
1.1       lukem     820:        else if (n != size)
1.27      christos  821:                errx(1, "%s: short write error for sector %lld", __func__,
                    822:                    (long long)bno);
1.1       lukem     823: }
                    824:
                    825:
                    826: /* Determine how many digits are needed to print a given integer */
                    827: static int
                    828: count_digits(int num)
                    829: {
                    830:        int ndig;
                    831:
                    832:        for(ndig = 1; num > 9; num /=10, ndig++);
                    833:
                    834:        return (ndig);
1.14      fvdl      835: }
                    836:
                    837: static int
                    838: ilog2(int val)
                    839: {
                    840:        u_int n;
                    841:
                    842:        for (n = 0; n < sizeof(n) * CHAR_BIT; n++)
                    843:                if (1 << n == val)
                    844:                        return (n);
1.27      christos  845:        errx(1, "%s: %d is not a power of 2", __func__, val);
1.1       lukem     846: }

CVSweb <webmaster@jp.NetBSD.org>