On Sat, 24 Apr 2010, Pawel Jakub Dawidek wrote:

Author: pjd
Date: Sat Apr 24 07:58:59 2010
New Revision: 207144
URL: http://svn.freebsd.org/changeset/base/207144

Log:
 suj.c seems to contain two versions of the code.
 Remove the one that doesn't compile.

Thanks pjd. I must've patched twice and not noticed. When I tried to just merge the changes from my projects branch it failed.

Jeff


Modified:
 head/sbin/fsck_ffs/suj.c

Modified: head/sbin/fsck_ffs/suj.c
==============================================================================
--- head/sbin/fsck_ffs/suj.c    Sat Apr 24 07:54:49 2010        (r207143)
+++ head/sbin/fsck_ffs/suj.c    Sat Apr 24 07:58:59 2010        (r207144)
@@ -2632,2068 +2632,3 @@ suj_check(const char *filesys)

        return (0);
}
-/*-
- * Copyright (c) 2009 Jeffrey W. Roberson <[email protected]>
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHORS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/param.h>
-#include <sys/disklabel.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-
-#include <ufs/ufs/ufsmount.h>
-#include <ufs/ufs/dinode.h>
-#include <ufs/ufs/dir.h>
-#include <ufs/ffs/fs.h>
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <libufs.h>
-#include <strings.h>
-#include <err.h>
-#include <assert.h>
-
-#include "fsck.h"
-
-static void    ino_decr(ino_t);
-
-#define        SUJ_HASHSIZE    128
-#define        SUJ_HASHMASK    (SUJ_HASHSIZE - 1)
-#define        SUJ_HASH(x)     ((x * 2654435761) & SUJ_HASHMASK)
-
-struct suj_seg {
-       TAILQ_ENTRY(suj_seg) ss_next;
-       struct jsegrec  ss_rec;
-       uint8_t         *ss_blk;
-};
-
-struct suj_rec {
-       TAILQ_ENTRY(suj_rec) sr_next;
-       union jrec      *sr_rec;
-};
-TAILQ_HEAD(srechd, suj_rec);
-
-struct suj_ino {
-       LIST_ENTRY(suj_ino)     si_next;
-       struct srechd           si_recs;
-       struct srechd           si_movs;
-       ino_t                   si_ino;
-       int                     si_nlinkadj;
-       int                     si_skipparent;
-       int                     si_linkadj;
-       int                     si_hasrecs;
-       int                     si_blkadj;
-};
-LIST_HEAD(inohd, suj_ino);
-
-struct suj_blk {
-       LIST_ENTRY(suj_blk)     sb_next;
-       struct srechd           sb_recs;
-       ufs2_daddr_t            sb_blk;
-};
-LIST_HEAD(blkhd, suj_blk);
-
-struct data_blk {
-       LIST_ENTRY(data_blk)    db_next;
-       uint8_t                 *db_buf;
-       ufs2_daddr_t            db_blk;
-       int                     db_size;
-};
-
-struct ino_blk {
-       LIST_ENTRY(ino_blk)     ib_next;
-       uint8_t                 *ib_buf;
-       int                     ib_dirty;
-       ufs2_daddr_t            ib_blk;
-};
-LIST_HEAD(iblkhd, ino_blk);
-
-struct suj_cg {
-       LIST_ENTRY(suj_cg)      sc_next;
-       struct blkhd            sc_blkhash[SUJ_HASHSIZE];
-       struct inohd            sc_inohash[SUJ_HASHSIZE];
-       struct iblkhd           sc_iblkhash[SUJ_HASHSIZE];
-       struct ino_blk          *sc_lastiblk;
-       uint8_t                 *sc_cgbuf;
-       struct cg               *sc_cgp;
-       int                     sc_dirty;
-       int                     sc_cgx;
-};
-
-LIST_HEAD(cghd, suj_cg) cghash[SUJ_HASHSIZE];
-LIST_HEAD(dblkhd, data_blk) dbhash[SUJ_HASHSIZE];
-
-TAILQ_HEAD(seghd, suj_seg) allsegs;
-uint64_t oldseq;
-static struct uufsd *disk = NULL;
-static struct fs *fs = NULL;
-
-/*
- * Summary statistics.
- */
-uint64_t freefrags;
-uint64_t freeblocks;
-uint64_t freeinos;
-uint64_t freedir;
-uint64_t jbytes;
-uint64_t jrecs;
-
-typedef void (*ino_visitor)(ino_t, ufs_lbn_t, ufs2_daddr_t, int);
-
-static void *
-errmalloc(size_t n)
-{
-       void *a;
-
-       a = malloc(n);
-       if (a == NULL)
-               errx(1, "malloc(%zu)", n);
-       return (a);
-}
-
-/*
- * Open the given provider, load superblock.
- */
-static void
-opendisk(const char *devnam)
-{
-       if (disk != NULL)
-               return;
-       disk = malloc(sizeof(*disk));
-       if (disk == NULL)
-               errx(1, "malloc(%zu)", sizeof(*disk));
-       if (ufs_disk_fillout(disk, devnam) == -1) {
-               err(1, "ufs_disk_fillout(%s) failed: %s", devnam,
-                   disk->d_error);
-       }
-       fs = &disk->d_fs;
-       /*
-        * Setup a few things so reply() can work.
-        */
-       bcopy(fs, &sblock, sizeof(sblock));
-       fsreadfd = disk->d_fd;
-       fswritefd = disk->d_fd;
-}
-
-/*
- * Mark file system as clean, write the super-block back, close the disk.
- */
-static void
-closedisk(const char *devnam)
-{
-       struct csum *cgsum;
-       int i;
-
-       /*
-        * Recompute the fs summary info from correct cs summaries.
-        */
-       bzero(&fs->fs_cstotal, sizeof(struct csum_total));
-       for (i = 0; i < fs->fs_ncg; i++) {
-               cgsum = &fs->fs_cs(fs, i);
-               fs->fs_cstotal.cs_nffree += cgsum->cs_nffree;
-               fs->fs_cstotal.cs_nbfree += cgsum->cs_nbfree;
-               fs->fs_cstotal.cs_nifree += cgsum->cs_nifree;
-               fs->fs_cstotal.cs_ndir += cgsum->cs_ndir;
-       }
-       /* XXX Don't set clean for now, we don't trust the journal. */
-       /* fs->fs_clean = 1; */
-       fs->fs_time = time(NULL);
-       fs->fs_mtime = time(NULL);
-       if (sbwrite(disk, 0) == -1)
-               err(1, "sbwrite(%s)", devnam);
-       if (ufs_disk_close(disk) == -1)
-               err(1, "ufs_disk_close(%s)", devnam);
-       free(disk);
-       disk = NULL;
-       fs = NULL;
-       fsreadfd = -1;
-       fswritefd = -1;
-}
-
-/*
- * Lookup a cg by number in the hash so we can keep track of which cgs
- * need stats rebuilt.
- */
-static struct suj_cg *
-cg_lookup(int cgx)
-{
-       struct cghd *hd;
-       struct suj_cg *sc;
-
-       if (cgx < 0 || cgx >= fs->fs_ncg) {
-               abort();
-               errx(1, "Bad cg number %d", cgx);
-       }
-       hd = &cghash[SUJ_HASH(cgx)];
-       LIST_FOREACH(sc, hd, sc_next)
-               if (sc->sc_cgx == cgx)
-                       return (sc);
-       sc = errmalloc(sizeof(*sc));
-       bzero(sc, sizeof(*sc));
-       sc->sc_cgbuf = errmalloc(fs->fs_bsize);
-       sc->sc_cgp = (struct cg *)sc->sc_cgbuf;
-       sc->sc_cgx = cgx;
-       LIST_INSERT_HEAD(hd, sc, sc_next);
-       if (bread(disk, fsbtodb(fs, cgtod(fs, sc->sc_cgx)), sc->sc_cgbuf,
-           fs->fs_bsize) == -1)
-               err(1, "Unable to read cylinder group %d", sc->sc_cgx);
-
-       return (sc);
-}
-
-/*
- * Lookup an inode number in the hash and allocate a suj_ino if it does
- * not exist.
- */
-static struct suj_ino *
-ino_lookup(ino_t ino, int creat)
-{
-       struct suj_ino *sino;
-       struct inohd *hd;
-       struct suj_cg *sc;
-
-       sc = cg_lookup(ino_to_cg(fs, ino));
-       hd = &sc->sc_inohash[SUJ_HASH(ino)];
-       LIST_FOREACH(sino, hd, si_next)
-               if (sino->si_ino == ino)
-                       return (sino);
-       if (creat == 0)
-               return (NULL);
-       sino = errmalloc(sizeof(*sino));
-       bzero(sino, sizeof(*sino));
-       sino->si_ino = ino;
-       sino->si_nlinkadj = 0;
-       TAILQ_INIT(&sino->si_recs);
-       TAILQ_INIT(&sino->si_movs);
-       LIST_INSERT_HEAD(hd, sino, si_next);
-
-       return (sino);
-}
-
-/*
- * Lookup a block number in the hash and allocate a suj_blk if it does
- * not exist.
- */
-static struct suj_blk *
-blk_lookup(ufs2_daddr_t blk, int creat)
-{
-       struct suj_blk *sblk;
-       struct suj_cg *sc;
-       struct blkhd *hd;
-
-       sc = cg_lookup(dtog(fs, blk));
-       hd = &sc->sc_blkhash[SUJ_HASH(blk)];
-       LIST_FOREACH(sblk, hd, sb_next)
-               if (sblk->sb_blk == blk)
-                       return (sblk);
-       if (creat == 0)
-               return (NULL);
-       sblk = errmalloc(sizeof(*sblk));
-       bzero(sblk, sizeof(*sblk));
-       sblk->sb_blk = blk;
-       TAILQ_INIT(&sblk->sb_recs);
-       LIST_INSERT_HEAD(hd, sblk, sb_next);
-
-       return (sblk);
-}
-
-static uint8_t *
-dblk_read(ufs2_daddr_t blk, int size)
-{
-       struct data_blk *dblk;
-       struct dblkhd *hd;
-
-       hd = &dbhash[SUJ_HASH(blk)];
-       LIST_FOREACH(dblk, hd, db_next)
-               if (dblk->db_blk == blk)
-                       goto found;
-       /*
-        * The inode block wasn't located, allocate a new one.
-        */
-       dblk = errmalloc(sizeof(*dblk));
-       bzero(dblk, sizeof(*dblk));
-       LIST_INSERT_HEAD(hd, dblk, db_next);
-       dblk->db_blk = blk;
-found:
-       /*
-        * I doubt size mismatches can happen in practice but it is trivial
-        * to handle.
-        */
-       if (size != dblk->db_size) {
-               if (dblk->db_buf)
-                       free(dblk->db_buf);
-               dblk->db_buf = errmalloc(size);
-               dblk->db_size = size;
-               if (bread(disk, fsbtodb(fs, blk), dblk->db_buf, size) == -1)
-                       err(1, "Failed to read data block %jd", blk);
-       }
-       return (dblk->db_buf);
-}
-
-static union dinode *
-ino_read(ino_t ino)
-{
-       struct ino_blk *iblk;
-       struct iblkhd *hd;
-       struct suj_cg *sc;
-       ufs2_daddr_t blk;
-       int off;
-
-       blk = ino_to_fsba(fs, ino);
-       sc = cg_lookup(ino_to_cg(fs, ino));
-       hd = &sc->sc_iblkhash[SUJ_HASH(blk)];
-       LIST_FOREACH(iblk, hd, ib_next)
-               if (iblk->ib_blk == blk)
-                       goto found;
-       /*
-        * The inode block wasn't located, allocate a new one.
-        */
-       iblk = errmalloc(sizeof(*iblk));
-       bzero(iblk, sizeof(*iblk));
-       iblk->ib_buf = errmalloc(fs->fs_bsize);
-       iblk->ib_blk = blk;
-       LIST_INSERT_HEAD(hd, iblk, ib_next);
-       if (bread(disk, fsbtodb(fs, blk), iblk->ib_buf, fs->fs_bsize) == -1)
-               err(1, "Failed to read inode block %jd", blk);
-found:
-       sc->sc_lastiblk = iblk;
-       off = ino_to_fsbo(fs, ino);
-       if (fs->fs_magic == FS_UFS1_MAGIC)
-               return (union dinode *)&((struct ufs1_dinode 
*)iblk->ib_buf)[off];
-       else
-               return (union dinode *)&((struct ufs2_dinode 
*)iblk->ib_buf)[off];
-}
-
-static void
-ino_dirty(ino_t ino)
-{
-       struct ino_blk *iblk;
-       struct iblkhd *hd;
-       struct suj_cg *sc;
-       ufs2_daddr_t blk;
-
-       blk = ino_to_fsba(fs, ino);
-       sc = cg_lookup(ino_to_cg(fs, ino));
-       iblk = sc->sc_lastiblk;
-       if (iblk && iblk->ib_blk == blk) {
-               iblk->ib_dirty = 1;
-               return;
-       }
-       hd = &sc->sc_iblkhash[SUJ_HASH(blk)];
-       LIST_FOREACH(iblk, hd, ib_next) {
-               if (iblk->ib_blk == blk) {
-                       iblk->ib_dirty = 1;
-                       return;
-               }
-       }
-       ino_read(ino);
-       ino_dirty(ino);
-}
-
-static void
-iblk_write(struct ino_blk *iblk)
-{
-
-       if (iblk->ib_dirty == 0)
-               return;
-       if (bwrite(disk, fsbtodb(fs, iblk->ib_blk), iblk->ib_buf,
-           fs->fs_bsize) == -1)
-               err(1, "Failed to write inode block %jd", iblk->ib_blk);
-}
-
-/*
- * Return 1 if the inode was free and 0 if it is allocated.
- */
-static int
-ino_isfree(ino_t ino)
-{
-       struct suj_cg *sc;
-       uint8_t *inosused;
-       struct cg *cgp;
-       int cg;
-
-       cg = ino_to_cg(fs, ino);
-       ino = ino % fs->fs_ipg;
-       sc = cg_lookup(cg);
-       cgp = sc->sc_cgp;
-       inosused = cg_inosused(cgp);
-       return isclr(inosused, ino);
-}
-
-static int
-blk_overlaps(struct jblkrec *brec, ufs2_daddr_t start, int frags)
-{
-       ufs2_daddr_t bstart;
-       ufs2_daddr_t bend;
-       ufs2_daddr_t end;
-
-       end = start + frags;
-       bstart = brec->jb_blkno + brec->jb_oldfrags;
-       bend = bstart + brec->jb_frags;
-       if (start < bend && end > bstart)
-               return (1);
-       return (0);
-}
-
-static int
-blk_equals(struct jblkrec *brec, ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t start,
-    int frags)
-{
-
-       if (brec->jb_ino != ino || brec->jb_lbn != lbn)
-               return (0);
-       if (brec->jb_blkno + brec->jb_oldfrags != start)
-               return (0);
-       if (brec->jb_frags != frags)
-               return (0);
-       return (1);
-}
-
-static void
-blk_setmask(struct jblkrec *brec, int *mask)
-{
-       int i;
-
-       for (i = brec->jb_oldfrags; i < brec->jb_oldfrags + brec->jb_frags; i++)
-               *mask |= 1 << i;
-}
-
-/*
- * Determine whether a given block has been reallocated to a new location.
- * Returns a mask of overlapping bits if any frags have been reused or
- * zero if the block has not been re-used and the contents can be trusted.
- *
- * This is used to ensure that an orphaned pointer due to truncate is safe
- * to be freed.  The mask value can be used to free partial blocks.
- */
-static int
-blk_isfree(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn, int frags)
-{
-       struct suj_blk *sblk;
-       struct suj_rec *srec;
-       struct jblkrec *brec;
-       int mask;
-       int off;
-
-       /*
-        * To be certain we're not freeing a reallocated block we lookup
-        * this block in the blk hash and see if there is an allocation
-        * journal record that overlaps with any fragments in the block
-        * we're concerned with.  If any fragments have ben reallocated
-        * the block has already been freed and re-used for another purpose.
-        */
-       mask = 0;
-       sblk = blk_lookup(blknum(fs, blk), 0);
-       if (sblk == NULL)
-               return (0);
-       off = blk - sblk->sb_blk;
-       TAILQ_FOREACH(srec, &sblk->sb_recs, sr_next) {
-               brec = (struct jblkrec *)srec->sr_rec;
-               /*
-                * If the block overlaps but does not match
-                * exactly it's a new allocation.  If it matches
-                * exactly this record refers to the current
-                * location.
-                */
-               if (blk_overlaps(brec, blk, frags) == 0)
-                       continue;
-               if (blk_equals(brec, ino, lbn, blk, frags) == 1)
-                       mask = 0;
-               else
-                       blk_setmask(brec, &mask);
-       }
-       if (debug)
-               printf("blk_isfree: blk %jd sblk %jd off %d mask 0x%X\n",
-                   blk, sblk->sb_blk, off, mask);
-       return (mask >> off);
-}
-
-/*
- * Determine whether it is safe to follow an indirect.  It is not safe
- * if any part of the indirect has been reallocated or the last journal
- * entry was an allocation.  Just allocated indirects may not have valid
- * pointers yet and all of their children will have their own records.
- *
- * Returns 1 if it's safe to follow the indirect and 0 otherwise.
- */
-static int
-blk_isindir(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t lbn)
-{
-       struct suj_blk *sblk;
-       struct jblkrec *brec;
-
-       sblk = blk_lookup(blk, 0);
-       if (sblk == NULL)
-               return (1);
-       if (TAILQ_EMPTY(&sblk->sb_recs))
-               return (1);
-       brec = (struct jblkrec *)TAILQ_LAST(&sblk->sb_recs, srechd)->sr_rec;
-       if (blk_equals(brec, ino, lbn, blk, fs->fs_frag))
-               if (brec->jb_op == JOP_FREEBLK)
-                       return (1);
-       return (0);
-}
-
-/*
- * Clear an inode from the cg bitmap.  If the inode was already clear return
- * 0 so the caller knows it does not have to check the inode contents.
- */
-static int
-ino_free(ino_t ino, int mode)
-{
-       struct suj_cg *sc;
-       uint8_t *inosused;
-       struct cg *cgp;
-       int cg;
-
-       cg = ino_to_cg(fs, ino);
-       ino = ino % fs->fs_ipg;
-       sc = cg_lookup(cg);
-       cgp = sc->sc_cgp;
-       inosused = cg_inosused(cgp);
-       /*
-        * The bitmap may never have made it to the disk so we have to
-        * conditionally clear.  We can avoid writing the cg in this case.
-        */
-       if (isclr(inosused, ino))
-               return (0);
-       freeinos++;
-       clrbit(inosused, ino);
-       if (ino < cgp->cg_irotor)
-               cgp->cg_irotor = ino;
-       cgp->cg_cs.cs_nifree++;
-       if ((mode & IFMT) == IFDIR) {
-               freedir++;
-               cgp->cg_cs.cs_ndir--;
-       }
-       sc->sc_dirty = 1;
-
-       return (1);
-}
-
-/*
- * Free 'frags' frags starting at filesystem block 'bno' skipping any frags
- * set in the mask.
- */
-static void
-blk_free(ufs2_daddr_t bno, int mask, int frags)
-{
-       ufs1_daddr_t fragno, cgbno;
-       struct suj_cg *sc;
-       struct cg *cgp;
-       int i, cg;
-       uint8_t *blksfree;
-
-       if (debug)
-               printf("Freeing %d frags at blk %jd\n", frags, bno);
-       cg = dtog(fs, bno);
-       sc = cg_lookup(cg);
-       cgp = sc->sc_cgp;
-       cgbno = dtogd(fs, bno);
-       blksfree = cg_blksfree(cgp);
-
-       /*
-        * If it's not allocated we only wrote the journal entry
-        * and never the bitmaps.  Here we unconditionally clear and
-        * resolve the cg summary later.
-        */
-       if (frags == fs->fs_frag && mask == 0) {
-               fragno = fragstoblks(fs, cgbno);
-               ffs_setblock(fs, blksfree, fragno);
-               freeblocks++;
-       } else {
-               /*
-                * deallocate the fragment
-                */
-               for (i = 0; i < frags; i++)
-                       if ((mask & (1 << i)) == 0 && isclr(blksfree, cgbno 
+i)) {
-                               freefrags++;
-                               setbit(blksfree, cgbno + i);
-                       }
-       }
-       sc->sc_dirty = 1;
-}
-
-/*
- * Fetch an indirect block to find the block at a given lbn.  The lbn
- * may be negative to fetch a specific indirect block pointer or positive
- * to fetch a specific block.
- */
-static ufs2_daddr_t
-indir_blkatoff(ufs2_daddr_t blk, ino_t ino, ufs_lbn_t cur, ufs_lbn_t lbn, int 
level)
-{
-       ufs2_daddr_t *bap2;
-       ufs2_daddr_t *bap1;
-       ufs_lbn_t lbnadd;
-       ufs_lbn_t base;
-       int i;
-
-       if (blk == 0)
-               return (0);
-       if (cur == lbn)
-               return (blk);
-       if (level == 0 && lbn < 0) {
-               abort();
-               errx(1, "Invalid lbn %jd", lbn);
-       }
-       bap2 = (void *)dblk_read(blk, fs->fs_bsize);
-       bap1 = (void *)bap2;
-       lbnadd = 1;
-       base = -(cur + level);
-       for (i = level; i > 0; i--)
-               lbnadd *= NINDIR(fs);
-       if (lbn > 0)
-               i = (lbn - base) / lbnadd;
-       else
-               i = (-lbn - base) / lbnadd;
-       if (i < 0 || i >= NINDIR(fs)) {
-               abort();
-               errx(1, "Invalid indirect index %d produced by lbn %jd",
-                   i, lbn);
-       }
-       if (level == 0)
-               cur = base + (i * lbnadd);
-       else
-               cur = -(base + (i * lbnadd)) - (level - 1);
-       if (fs->fs_magic == FS_UFS1_MAGIC)
-               blk = bap1[i];
-       else
-               blk = bap2[i];
-       if (cur == lbn)
-               return (blk);
-       if (level == 0) {
-               abort();
-               errx(1, "Invalid lbn %jd at level 0", lbn);
-       }
-       return indir_blkatoff(blk, ino, cur, lbn, level - 1);
-}
-
-/*
- * Finds the disk block address at the specified lbn within the inode
- * specified by ip.  This follows the whole tree and honors di_size and
- * di_extsize so it is a true test of reachability.  The lbn may be
- * negative if an extattr or indirect block is requested.
- */
-static ufs2_daddr_t
-ino_blkatoff(union dinode *ip, ino_t ino, ufs_lbn_t lbn, int *frags)
-{
-       ufs_lbn_t tmpval;
-       ufs_lbn_t cur;
-       ufs_lbn_t next;
-       int i;
-
-       /*
-        * Handle extattr blocks first.
-        */
-       if (lbn < 0 && lbn >= -NXADDR) {
-               lbn = -1 - lbn;
-               if (lbn > lblkno(fs, ip->dp2.di_extsize - 1))
-                       return (0);
-               *frags = numfrags(fs, sblksize(fs, ip->dp2.di_extsize, lbn));
-               return (ip->dp2.di_extb[lbn]);
-       }
-       /*
-        * And now direct and indirect.  Verify that the lbn does not
-        * exceed the size required to store the file by asking for
-        * the lbn of the last byte.  These blocks should be 0 anyway
-        * so this simply saves the traversal.
-        */
-       if (lbn > 0 && lbn > lblkno(fs, DIP(ip, di_size) - 1))
-               return (0);
-       if (lbn < 0 && -lbn > lblkno(fs, DIP(ip, di_size) - 1))
-               return (0);
-       if (lbn >= 0 && lbn < NDADDR) {
-               *frags = numfrags(fs, sblksize(fs, DIP(ip, di_size), lbn));
-               return (DIP(ip, di_db[lbn]));
-       }
-       *frags = fs->fs_frag;
-
-       for (i = 0, tmpval = NINDIR(fs), cur = NDADDR; i < NIADDR; i++,
-           tmpval *= NINDIR(fs), cur = next) {
-               next = cur + tmpval;
-               if (lbn == -cur)
-                       return (DIP(ip, di_ib[i]));
-               /*
-                * Determine whether the lbn in question is within this tree.
-                */
-               if (lbn < 0 && -lbn >= next)
-                       continue;
-               if (lbn > 0 && lbn >= next)
-                       continue;
-
-               return indir_blkatoff(DIP(ip, di_ib[i]), ino, -cur - i, lbn, i);
-       }
-       errx(1, "lbn %jd not in ino", lbn);
-}
-
-/*
- * Determine whether a block exists at a particular lbn in an inode.
- * Returns 1 if found, 0 if not.  lbn may be negative for indirects
- * or ext blocks.
- */
-static int
-blk_isat(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, int *frags)
-{
-       union dinode *ip;
-       ufs2_daddr_t nblk;
-
-       ip = ino_read(ino);
-
-       if (DIP(ip, di_nlink) == 0 || DIP(ip, di_mode) == 0)
-               return (0);
-       nblk = ino_blkatoff(ip, ino, lbn, frags);
-
-       return (nblk == blk);
-}
-
-/*
- * Determines whether a pointer to an inode exists within a directory
- * at a specified offset.  Returns the mode of the found entry.
- */
-static int
-ino_isat(ino_t parent, off_t diroff, ino_t child, int *mode, int *isdot)
-{
-       union dinode *dip;
-       struct direct *dp;
-       ufs2_daddr_t blk;
-       uint8_t *block;
-       ufs_lbn_t lbn;
-       int blksize;
-       int frags;
-       int dpoff;
-       int doff;
-
-       *isdot = 0;
-       dip = ino_read(parent);
-       *mode = DIP(dip, di_mode);
-       if ((*mode & IFMT) != IFDIR) {
-               if (debug) {
-                       /* This can happen if the parent inode was reallocated. 
*/
-                       if (*mode != 0)
-                               printf("Directory %d has bad mode %o\n",
-                                   parent, *mode);
-                       else
-                               printf("Directory %d zero inode\n", parent);
-               }
-               return (0);
-       }
-       lbn = lblkno(fs, diroff);
-       doff = blkoff(fs, diroff);
-       blksize = sblksize(fs, DIP(dip, di_size), lbn);
-       if (diroff + DIRECTSIZ(1) > DIP(dip, di_size) || doff >= blksize) {
-               if (debug)
-                       printf("ino %d absent from %d due to offset %jd"
-                           " exceeding size %jd\n",
-                           child, parent, diroff, DIP(dip, di_size));
-               return (0);
-       }
-       blk = ino_blkatoff(dip, parent, lbn, &frags);
-       if (blk <= 0) {
-               if (debug)
-                       printf("Sparse directory %d", parent);
-               return (0);
-       }
-       block = dblk_read(blk, blksize);
-       /*
-        * Walk through the records from the start of the block to be
-        * certain we hit a valid record and not some junk in the middle
-        * of a file name.  Stop when we reach or pass the expected offset.
-        */
-       dpoff = 0;
-       do {
-               dp = (struct direct *)&block[dpoff];
-               if (dpoff == doff)
-                       break;
-               if (dp->d_reclen == 0)
-                       break;
-               dpoff += dp->d_reclen;
-       } while (dpoff <= doff);
-       if (dpoff > fs->fs_bsize)
-               errx(1, "Corrupt directory block in dir inode %d", parent);
-       /* Not found. */
-       if (dpoff != doff) {
-               if (debug)
-                       printf("ino %d not found in %d, lbn %jd, dpoff %d\n",
-                           child, parent, lbn, dpoff);
-               return (0);
-       }
-       /*
-        * We found the item in question.  Record the mode and whether it's
-        * a . or .. link for the caller.
-        */
-       if (dp->d_ino == child) {
-               if (child == parent)
-                       *isdot = 1;
-               else if (dp->d_namlen == 2 &&
-                   dp->d_name[0] == '.' && dp->d_name[1] == '.')
-                       *isdot = 1;
-               *mode = DTTOIF(dp->d_type);
-               return (1);
-       }
-       if (debug)
-               printf("ino %d doesn't match dirent ino %d in parent %d\n",
-                   child, dp->d_ino, parent);
-       return (0);
-}
-
-#define        VISIT_INDIR     0x0001
-#define        VISIT_EXT       0x0002
-
-/*
- * Read an indirect level which may or may not be linked into an inode.
- */
-static void
-indir_visit(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, uint64_t *frags,
-    ino_visitor visitor, int flags)
-{
-       ufs2_daddr_t *bap2;
-       ufs1_daddr_t *bap1;
-       ufs_lbn_t lbnadd;
-       ufs2_daddr_t nblk;
-       ufs_lbn_t nlbn;
-       int level;
-       int i;
-
-       /*
-        * Don't visit indirect blocks with contents we can't trust.  This
-        * should only happen when indir_visit() is called to complete a
-        * truncate that never finished and not when a pointer is found via
-        * an inode.
-        */
-       if (blk == 0)
-               return;
-       if (blk_isindir(blk, ino, lbn) == 0) {
-               if (debug)
-                       printf("blk %jd ino %d lbn %jd is not indir.\n",
-                           blk, ino, lbn);
-               goto out;
-       }
-       level = lbn_level(lbn);
-       if (level == -1) {
-               abort();
-               errx(1, "Invalid level for lbn %jd", lbn);
-       }
-       lbnadd = 1;
-       for (i = level; i > 0; i--)
-               lbnadd *= NINDIR(fs);
-       bap1 = (void *)dblk_read(blk, fs->fs_bsize);
-       bap2 = (void *)bap1;
-       for (i = 0; i < NINDIR(fs); i++) {
-               if (fs->fs_magic == FS_UFS1_MAGIC)
-                       nblk = *bap1++;
-               else
-                       nblk = *bap2++;
-               if (nblk == 0)
-                       continue;
-               if (level == 0) {
-                       nlbn = -lbn + i * lbnadd;
-                       (*frags) += fs->fs_frag;
-                       visitor(ino, nlbn, nblk, fs->fs_frag);
-               } else {
-                       nlbn = (lbn + 1) - (i * lbnadd);
-                       indir_visit(ino, nlbn, nblk, frags, visitor, flags);
-               }
-       }
-out:
-       if (flags & VISIT_INDIR) {
-               (*frags) += fs->fs_frag;
-               visitor(ino, lbn, blk, fs->fs_frag);
-       }
-}
-
-/*
- * Visit each block in an inode as specified by 'flags' and call a
- * callback function.  The callback may inspect or free blocks.  The
- * count of frags found according to the size in the file is returned.
- * This is not valid for sparse files but may be used to determine
- * the correct di_blocks for a file.
- */
-static uint64_t
-ino_visit(union dinode *ip, ino_t ino, ino_visitor visitor, int flags)
-{
-       ufs_lbn_t tmpval;
-       ufs_lbn_t lbn;
-       uint64_t size;
-       uint64_t fragcnt;
-       int mode;
-       int frags;
-       int i;
-
-       size = DIP(ip, di_size);
-       mode = DIP(ip, di_mode) & IFMT;
-       fragcnt = 0;
-       if ((flags & VISIT_EXT) &&
-           fs->fs_magic == FS_UFS2_MAGIC && ip->dp2.di_extsize) {
-               for (i = 0; i < NXADDR; i++) {
-                       if (ip->dp2.di_extb[i] == 0)
-                               continue;
-                       frags = sblksize(fs, ip->dp2.di_extsize, i);
-                       frags = numfrags(fs, frags);
-                       fragcnt += frags;
-                       visitor(ino, -1 - i, ip->dp2.di_extb[i], frags);
-               }
-       }
-       /* Skip datablocks for short links and devices. */
-       if (mode == IFBLK || mode == IFCHR ||
-           (mode == IFLNK && size < fs->fs_maxsymlinklen))
-               return (fragcnt);
-       for (i = 0; i < NDADDR; i++) {
-               if (DIP(ip, di_db[i]) == 0)
-                       continue;
-               frags = sblksize(fs, size, i);
-               frags = numfrags(fs, frags);
-               fragcnt += frags;
-               visitor(ino, i, DIP(ip, di_db[i]), frags);
-       }
-       for (i = 0, tmpval = NINDIR(fs), lbn = NDADDR; i < NIADDR; i++,
-           tmpval *= NINDIR(fs), lbn += tmpval) {
-               if (DIP(ip, di_ib[i]) == 0)
-                       continue;
-               indir_visit(ino, -lbn - i, DIP(ip, di_ib[i]), &fragcnt, visitor,
-                   flags);
-       }
-       return (fragcnt);
-}
-
-/*
- * Null visitor function used when we just want to count blocks.
- */
-static void
-null_visit(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, int frags)
-{
-}
-
-/*
- * Recalculate di_blocks when we discover that a block allocation or
- * free was not successfully completed.  The kernel does not roll this back
- * because it would be too expensive to compute which indirects were
- * reachable at the time the inode was written.
- */
-static void
-ino_adjblks(ino_t ino)
-{
-       struct suj_ino *sino;
-       union dinode *ip;
-       uint64_t blocks;
-       uint64_t frags;
-
-       sino = ino_lookup(ino, 1);
-       if (sino->si_blkadj)
-               return;
-       sino->si_blkadj = 1;
-       ip = ino_read(ino);
-       /* No need to adjust zero'd inodes. */
-       if (DIP(ip, di_mode) == 0)
-               return;
-       frags = ino_visit(ip, ino, null_visit, VISIT_INDIR | VISIT_EXT);
-       blocks = fsbtodb(fs, frags);
-       if (blocks == DIP(ip, di_blocks))
-               return;
-       if (debug)
-               printf("ino %d adjusting block count from %jd to %jd\n",
-                   ino, DIP(ip, di_blocks), blocks);
-       DIP_SET(ip, di_blocks, blocks);
-       ino_dirty(ino);
-}
-
-static void
-blk_free_visit(ino_t ino, ufs_lbn_t lbn, ufs2_daddr_t blk, int frags)
-{
-       int mask;

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***

_______________________________________________
[email protected] mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "[email protected]"

Reply via email to