[BACK]Return to setup.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sbin / fsck_lfs

Annotation of src/sbin/fsck_lfs/setup.c, Revision 1.19

1.19    ! perseant    1: /* $NetBSD: setup.c,v 1.18 2004/09/15 03:24:09 minoura Exp $ */
1.1       perseant    2:
1.13      perseant    3: /*-
                      4:  * Copyright (c) 2003 The NetBSD Foundation, Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Konrad E. Schroder <perseant@hhhh.org>.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  * 3. All advertising materials mentioning features or use of this software
                     19:  *    must display the following acknowledgement:
                     20:  *     This product includes software developed by the NetBSD
                     21:  *     Foundation, Inc. and its contributors.
                     22:  * 4. Neither the name of The NetBSD Foundation nor the names of its
                     23:  *    contributors may be used to endorse or promote products derived
                     24:  *    from this software without specific prior written permission.
                     25:  *
                     26:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     27:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     28:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     29:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     30:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     31:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     32:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     33:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     34:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     35:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     36:  * POSSIBILITY OF SUCH DAMAGE.
                     37:  */
1.1       perseant   38: /*
                     39:  * Copyright (c) 1980, 1986, 1993
                     40:  *     The Regents of the University of California.  All rights reserved.
                     41:  *
                     42:  * Redistribution and use in source and binary forms, with or without
                     43:  * modification, are permitted provided that the following conditions
                     44:  * are met:
                     45:  * 1. Redistributions of source code must retain the above copyright
                     46:  *    notice, this list of conditions and the following disclaimer.
                     47:  * 2. Redistributions in binary form must reproduce the above copyright
                     48:  *    notice, this list of conditions and the following disclaimer in the
                     49:  *    documentation and/or other materials provided with the distribution.
1.17      agc        50:  * 3. Neither the name of the University nor the names of its contributors
1.1       perseant   51:  *    may be used to endorse or promote products derived from this software
                     52:  *    without specific prior written permission.
                     53:  *
                     54:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     55:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     56:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     57:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     58:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     59:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     60:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     61:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     62:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     63:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     64:  * SUCH DAMAGE.
                     65:  */
                     66:
                     67: /* #define DKTYPENAMES */
                     68: #define FSTYPENAMES
1.13      perseant   69: #include <sys/types.h>
1.1       perseant   70: #include <sys/param.h>
                     71: #include <sys/time.h>
1.13      perseant   72: #include <sys/buf.h>
                     73: #include <sys/mount.h>
                     74: #include <sys/queue.h>
1.1       perseant   75: #include <sys/stat.h>
                     76: #include <sys/ioctl.h>
                     77: #include <sys/disklabel.h>
                     78: #include <sys/file.h>
                     79:
1.13      perseant   80: #include <ufs/ufs/inode.h>
                     81: #include <ufs/ufs/ufsmount.h>
                     82: #define vnode uvnode
1.1       perseant   83: #include <ufs/lfs/lfs.h>
1.13      perseant   84: #undef vnode
1.1       perseant   85:
                     86: #include <ctype.h>
                     87: #include <err.h>
                     88: #include <errno.h>
                     89: #include <stdio.h>
                     90: #include <stdlib.h>
                     91: #include <string.h>
                     92:
1.13      perseant   93: #include "bufcache.h"
                     94: #include "vnode.h"
                     95: #include "lfs.h"
                     96:
1.1       perseant   97: #include "fsck.h"
                     98: #include "extern.h"
                     99: #include "fsutil.h"
                    100:
1.5       perseant  101: static struct disklabel *getdisklabel(const char *, int);
1.18      minoura   102: static uint64_t calcmaxfilesize(int);
1.1       perseant  103:
1.13      perseant  104: ufs_daddr_t *din_table;
                    105: SEGUSE *seg_table;
1.4       perseant  106:
1.1       perseant  107: #ifdef DKTYPENAMES
1.13      perseant  108: int useless(void);
1.1       perseant  109:
                    110: int
                    111: useless(void)
                    112: {
1.13      perseant  113:        char **foo = (char **) dktypenames;
                    114:        char **bar = (char **) fscknames;
1.1       perseant  115:
1.5       perseant  116:        return foo - bar;
1.1       perseant  117: }
                    118: #endif
                    119:
1.18      minoura   120: /*
                    121:  * calculate the maximum file size allowed with the specified block shift.
                    122:  */
                    123: static uint64_t
                    124: calcmaxfilesize(int bshift)
                    125: {
                    126:        uint64_t nptr; /* number of block pointers per block */
                    127:        uint64_t maxblock;
                    128:
                    129:        nptr = (1 << bshift) / sizeof(uint32_t);
                    130:        maxblock = NDADDR + nptr + nptr * nptr + nptr * nptr * nptr;
                    131:
                    132:        return maxblock << bshift;
                    133: }
                    134:
1.1       perseant  135: int
1.5       perseant  136: setup(const char *dev)
1.1       perseant  137: {
1.13      perseant  138:        long bmapsize;
1.1       perseant  139:        struct disklabel *lp;
1.13      perseant  140:        struct stat statb;
                    141:        int doskipclean;
                    142:        u_int64_t maxfilesize;
                    143:        int open_flags;
                    144:        struct uvnode *ivp;
                    145:        struct ubuf *bp;
                    146:        int i;
                    147:        SEGUSE *sup;
1.1       perseant  148:
                    149:        havesb = 0;
                    150:        doskipclean = skipclean;
                    151:        if (stat(dev, &statb) < 0) {
                    152:                printf("Can't stat %s: %s\n", dev, strerror(errno));
                    153:                return (0);
                    154:        }
                    155:        if (!S_ISCHR(statb.st_mode)) {
                    156:                pfatal("%s is not a character device", dev);
                    157:                if (reply("CONTINUE") == 0)
                    158:                        return (0);
                    159:        }
1.13      perseant  160:        if (nflag)
                    161:                open_flags = O_RDONLY;
                    162:        else
                    163:                open_flags = O_RDWR;
                    164:
                    165:        if ((fsreadfd = open(dev, open_flags)) < 0) {
1.1       perseant  166:                printf("Can't open %s: %s\n", dev, strerror(errno));
                    167:                return (0);
                    168:        }
                    169:        if (preen == 0)
                    170:                printf("** %s", dev);
1.13      perseant  171:        if (nflag) {
1.1       perseant  172:                if (preen)
                    173:                        pfatal("NO WRITE ACCESS");
                    174:                printf(" (NO WRITE)");
                    175:        }
                    176:        if (preen == 0)
                    177:                printf("\n");
                    178:        fsmodified = 0;
                    179:        lfdir = 0;
1.13      perseant  180:
                    181:        bufinit();
1.19    ! perseant  182:        fs = lfs_init(fsreadfd, bflag, idaddr, 0, debug);
1.13      perseant  183:        if (fs == NULL) {
                    184:                if (preen)
                    185:                        printf("%s: ", cdevname());
                    186:                pfatal("BAD SUPER BLOCK\n");
                    187:        }
1.5       perseant  188:        if ((lp = getdisklabel((char *) NULL, fsreadfd)) != NULL)
1.1       perseant  189:                dev_bsize = secsize = lp->d_secsize;
                    190:        else
                    191:                dev_bsize = secsize = DEV_BSIZE;
                    192:
1.13      perseant  193:        if (fs->lfs_pflags & LFS_PF_CLEAN) {
                    194:                if (doskipclean) {
                    195:                        pwarn("%sile system is clean; not checking\n",
                    196:                                preen ? "f" : "** F");
                    197:                        return (-1);
1.1       perseant  198:                }
1.13      perseant  199:                if (!preen)
                    200:                        pwarn("** File system is already clean\n");
                    201:        }
1.9       perseant  202:
1.5       perseant  203:        if (debug) {
1.15      perseant  204:                printf("idaddr    = 0x%lx\n", idaddr ? (unsigned long)idaddr :
                    205:                        (unsigned long)fs->lfs_idaddr);
1.5       perseant  206:                printf("dev_bsize = %lu\n", dev_bsize);
1.13      perseant  207:                printf("lfs_bsize = %lu\n", (unsigned long) fs->lfs_bsize);
                    208:                printf("lfs_fsize = %lu\n", (unsigned long) fs->lfs_fsize);
                    209:                printf("lfs_frag  = %lu\n", (unsigned long) fs->lfs_frag);
                    210:                printf("lfs_inopb = %lu\n", (unsigned long) fs->lfs_inopb);
                    211:        }
                    212:        if (fs->lfs_version == 1)
                    213:                maxfsblock = fs->lfs_size * (fs->lfs_bsize / dev_bsize);
                    214:        else
                    215:                maxfsblock = fs->lfs_size;
1.18      minoura   216:        maxfilesize = calcmaxfilesize(fs->lfs_bshift);
1.13      perseant  217:        if ((fs->lfs_minfree < 0 || fs->lfs_minfree > 99)) {
1.1       perseant  218:                pfatal("IMPOSSIBLE MINFREE=%d IN SUPERBLOCK",
1.13      perseant  219:                    fs->lfs_minfree);
1.1       perseant  220:                if (reply("SET TO DEFAULT") == 1) {
1.13      perseant  221:                        fs->lfs_minfree = 10;
1.1       perseant  222:                        sbdirty();
                    223:                }
                    224:        }
1.13      perseant  225:        if (fs->lfs_bmask != fs->lfs_bsize - 1) {
1.1       perseant  226:                pwarn("INCORRECT BMASK=%x IN SUPERBLOCK (should be %x)",
1.13      perseant  227:                    (unsigned int) fs->lfs_bmask,
                    228:                    (unsigned int) fs->lfs_bsize - 1);
                    229:                fs->lfs_bmask = fs->lfs_bsize - 1;
1.1       perseant  230:                if (preen)
                    231:                        printf(" (FIXED)\n");
                    232:                if (preen || reply("FIX") == 1) {
                    233:                        sbdirty();
                    234:                }
                    235:        }
1.13      perseant  236:        if (fs->lfs_ffmask != fs->lfs_fsize - 1) {
                    237:                pwarn("INCORRECT FFMASK=%" PRId64 " IN SUPERBLOCK",
                    238:                    fs->lfs_ffmask);
                    239:                fs->lfs_ffmask = fs->lfs_fsize - 1;
1.1       perseant  240:                if (preen)
                    241:                        printf(" (FIXED)\n");
                    242:                if (preen || reply("FIX") == 1) {
                    243:                        sbdirty();
                    244:                }
                    245:        }
1.13      perseant  246:        if (fs->lfs_fbmask != (1 << fs->lfs_fbshift) - 1) {
                    247:                pwarn("INCORRECT FFMASK=%" PRId64 " IN SUPERBLOCK",
                    248:                    fs->lfs_ffmask);
                    249:                fs->lfs_fbmask = (1 << fs->lfs_fbshift) - 1;
                    250:                if (preen)
                    251:                        printf(" (FIXED)\n");
                    252:                if (preen || reply("FIX") == 1) {
                    253:                        sbdirty();
                    254:                }
                    255:        }
                    256:        if (fs->lfs_maxfilesize != maxfilesize) {
1.8       lukem     257:                pwarn(
                    258:                    "INCORRECT MAXFILESIZE=%llu IN SUPERBLOCK (should be %llu)",
1.13      perseant  259:                    (unsigned long long) fs->lfs_maxfilesize,
                    260:                    (unsigned long long) maxfilesize);
                    261:                fs->lfs_maxfilesize = maxfilesize;
1.5       perseant  262:                if (preen)
                    263:                        printf(" (FIXED)\n");
                    264:                if (preen || reply("FIX") == 1) {
                    265:                        sbdirty();
1.1       perseant  266:                }
1.5       perseant  267:        }
1.16      fvdl      268:        if (fs->lfs_maxsymlinklen != MAXSYMLINKLEN_UFS1) {
1.5       perseant  269:                pwarn("INCORRECT MAXSYMLINKLEN=%d IN SUPERBLOCK",
1.13      perseant  270:                    fs->lfs_maxsymlinklen);
1.16      fvdl      271:                fs->lfs_maxsymlinklen = MAXSYMLINKLEN_UFS1;
1.5       perseant  272:                if (preen)
                    273:                        printf(" (FIXED)\n");
                    274:                if (preen || reply("FIX") == 1) {
                    275:                        sbdirty();
1.1       perseant  276:                }
1.5       perseant  277:        }
1.13      perseant  278:
                    279:        /*
                    280:         * Read in the Ifile; we'll be using it a lot.
                    281:         * XXX If the Ifile is corrupted we are in bad shape.  We need to
                    282:         * XXX run through the segment headers of the entire disk to
                    283:         * XXX reconstruct the inode table, then pretend all segments are
                    284:         * XXX dirty while we do the rest.
                    285:         */
                    286:        ivp = fs->lfs_ivnode;
1.16      fvdl      287:        maxino = ((VTOI(ivp)->i_ffs1_size - (fs->lfs_cleansz + fs->lfs_segtabsz)
1.13      perseant  288:                * fs->lfs_bsize) / fs->lfs_bsize) * fs->lfs_ifpb;
                    289:        if (debug)
                    290:                printf("maxino    = %d\n", maxino);
1.16      fvdl      291:        for (i = 0; i < VTOI(ivp)->i_ffs1_size; i += fs->lfs_bsize) {
1.13      perseant  292:                bread(ivp, i >> fs->lfs_bshift, fs->lfs_bsize, NOCRED, &bp);
                    293:                /* XXX check B_ERROR */
                    294:                brelse(bp);
                    295:        }
                    296:
1.1       perseant  297:        /*
                    298:         * allocate and initialize the necessary maps
                    299:         */
1.13      perseant  300:        din_table = (ufs_daddr_t *) malloc(maxino * sizeof(*din_table));
                    301:        memset(din_table, 0, maxino * sizeof(*din_table));
                    302:        seg_table = (SEGUSE *) malloc(fs->lfs_nseg * sizeof(SEGUSE));
                    303:        memset(seg_table, 0, fs->lfs_nseg * sizeof(SEGUSE));
                    304:        /* Get segment flags */
                    305:        for (i = 0; i < fs->lfs_nseg; i++) {
                    306:                LFS_SEGENTRY(sup, fs, i, bp);
                    307:                seg_table[i].su_flags = sup->su_flags & ~SEGUSE_ACTIVE;
1.14      perseant  308:                if (preen)
                    309:                        seg_table[i].su_nbytes = sup->su_nbytes;
1.13      perseant  310:                brelse(bp);
                    311:        }
                    312:
                    313:        /* Initialize Ifile entry */
                    314:        din_table[fs->lfs_ifile] = fs->lfs_idaddr;
1.16      fvdl      315:        seg_table[dtosn(fs, fs->lfs_idaddr)].su_nbytes += DINODE1_SIZE;
1.13      perseant  316:
1.1       perseant  317: #ifndef VERBOSE_BLOCKMAP
                    318:        bmapsize = roundup(howmany(maxfsblock, NBBY), sizeof(int16_t));
1.13      perseant  319:        blockmap = calloc((unsigned) bmapsize, sizeof(char));
1.1       perseant  320: #else
1.5       perseant  321:        bmapsize = maxfsblock * sizeof(ino_t);
1.13      perseant  322:        blockmap = (ino_t *) calloc(maxfsblock, sizeof(ino_t));
1.1       perseant  323: #endif
                    324:        if (blockmap == NULL) {
                    325:                printf("cannot alloc %u bytes for blockmap\n",
1.13      perseant  326:                    (unsigned) bmapsize);
1.1       perseant  327:                goto badsblabel;
                    328:        }
1.13      perseant  329:        statemap = calloc((unsigned) maxino, sizeof(char));
1.1       perseant  330:        if (statemap == NULL) {
                    331:                printf("cannot alloc %u bytes for statemap\n",
1.13      perseant  332:                    (unsigned) maxino);
1.1       perseant  333:                goto badsblabel;
                    334:        }
1.13      perseant  335:        typemap = calloc((unsigned) maxino, sizeof(char));
1.1       perseant  336:        if (typemap == NULL) {
                    337:                printf("cannot alloc %u bytes for typemap\n",
1.13      perseant  338:                    (unsigned) maxino);
1.1       perseant  339:                goto badsblabel;
                    340:        }
1.13      perseant  341:        lncntp = (int16_t *) calloc((unsigned) maxino, sizeof(int16_t));
1.1       perseant  342:        if (lncntp == NULL) {
1.5       perseant  343:                printf("cannot alloc %lu bytes for lncntp\n",
1.13      perseant  344:                    (unsigned long) maxino * sizeof(int16_t));
1.1       perseant  345:                goto badsblabel;
                    346:        }
1.14      perseant  347:
                    348:        if (preen) {
                    349:                n_files = fs->lfs_nfiles;
                    350:                n_blks  = fs->lfs_dsize - fs->lfs_bfree;
                    351:                numdirs = maxino;
                    352:                inplast = 0;
                    353:                listmax = numdirs + 10;
                    354:                inpsort = (struct inoinfo **) calloc((unsigned) listmax,
                    355:                        sizeof(struct inoinfo *));
                    356:                inphead = (struct inoinfo **) calloc((unsigned) numdirs,
                    357:                        sizeof(struct inoinfo *));
                    358:                if (inpsort == NULL || inphead == NULL) {
                    359:                        printf("cannot alloc %lu bytes for inphead\n",
                    360:                                (unsigned long) numdirs * sizeof(struct inoinfo *));
                    361:                        exit(1);
                    362:                }
                    363:        }
                    364:
1.1       perseant  365:        return (1);
                    366:
                    367: badsblabel:
                    368:        ckfini(0);
                    369:        return (0);
                    370: }
                    371:
                    372: static struct disklabel *
1.5       perseant  373: getdisklabel(const char *s, int fd)
1.1       perseant  374: {
                    375:        static struct disklabel lab;
                    376:
1.5       perseant  377:        if (ioctl(fd, DIOCGDINFO, (char *) &lab) < 0) {
1.1       perseant  378:                if (s == NULL)
1.5       perseant  379:                        return ((struct disklabel *) NULL);
1.1       perseant  380:                pwarn("ioctl (GCINFO): %s\n", strerror(errno));
1.4       perseant  381:                return NULL;
1.1       perseant  382:        }
                    383:        return (&lab);
                    384: }

CVSweb <webmaster@jp.NetBSD.org>