diff --git a/sbin/growfs/debug.c b/sbin/growfs/debug.c index 5072fc176ca8..7b57ec764492 100644 --- a/sbin/growfs/debug.c +++ b/sbin/growfs/debug.c @@ -1,877 +1,845 @@ /* * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz * Copyright (c) 1980, 1989, 1993 The Regents of the University of California. * All rights reserved. * * This code is derived from software contributed to Berkeley by * Christoph Herrmann and Thomas-Henning von Kamptz, Munich and Frankfurt. * * 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. * 3. All advertising materials mentioning features or use of this software * must display the following acknowledgment: * This product includes software developed by the University of * California, Berkeley and its contributors, as well as Christoph * Herrmann and Thomas-Henning von Kamptz. * 4. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. * * $TSHeader: src/sbin/growfs/debug.c,v 1.3 2000/12/12 19:31:00 tomsoft Exp $ * */ #ifndef lint static const char rcsid[] = "$FreeBSD$"; #endif /* not lint */ -/* ********************************************************** INCLUDES ***** */ #include #include #include #include #include #include #include "debug.h" #ifdef FS_DEBUG -/* *********************************************************** GLOBALS ***** */ -static FILE *dbg_log=NULL; -static unsigned int indent=0; +static FILE *dbg_log = NULL; +static unsigned int indent = 0; /* * prototypes not done here, as they come with debug.h */ -/* ********************************************************** dbg_open ***** */ /* * Open the filehandle where all debug output has to go. */ void dbg_open(const char *fn) { if (strcmp(fn, "-") == 0) - dbg_log=fopen("/dev/stdout", "a"); + dbg_log = fopen("/dev/stdout", "a"); else - dbg_log=fopen(fn, "a"); + dbg_log = fopen(fn, "a"); return; } -/* ********************************************************* dbg_close ***** */ /* * Close the filehandle where all debug output went to. */ void dbg_close(void) { - if(dbg_log) { + if (dbg_log) { fclose(dbg_log); - dbg_log=NULL; + dbg_log = NULL; } return; } -/* ****************************************************** dbg_dump_hex ***** */ /* * Dump out a full file system block in hex. */ void dbg_dump_hex(struct fs *sb, const char *comment, unsigned char *mem) { int i, j, k; - if(!dbg_log) { + if (!dbg_log) return; - } + fprintf(dbg_log, "===== START HEXDUMP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)mem, comment); indent++; - for (i=0; ifs_bsize; i+=24) { - for (j=0; j<3; j++) { - for (k=0; k<8; k++) { + for (i = 0; i < sb->fs_bsize; i += 24) { + for (j = 0; j < 3; j++) { + for (k = 0; k < 8; k++) fprintf(dbg_log, "%02x ", *mem++); - } fprintf(dbg_log, " "); } fprintf(dbg_log, "\n"); } indent--; fprintf(dbg_log, "===== END HEXDUMP =====\n"); return; } -/* ******************************************************* dbg_dump_fs ***** */ /* * Dump the superblock. */ void dbg_dump_fs(struct fs *sb, const char *comment) { #ifdef FSMAXSNAP - int j; + int j; #endif /* FSMAXSNAP */ - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START SUPERBLOCK =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)sb, comment); indent++; fprintf(dbg_log, "sblkno int32_t 0x%08x\n", sb->fs_sblkno); fprintf(dbg_log, "cblkno int32_t 0x%08x\n", sb->fs_cblkno); fprintf(dbg_log, "iblkno int32_t 0x%08x\n", sb->fs_iblkno); fprintf(dbg_log, "dblkno int32_t 0x%08x\n", sb->fs_dblkno); fprintf(dbg_log, "old_cgoffset int32_t 0x%08x\n", sb->fs_old_cgoffset); fprintf(dbg_log, "old_cgmask int32_t 0x%08x\n", sb->fs_old_cgmask); fprintf(dbg_log, "old_time int32_t %10u\n", (unsigned int)sb->fs_old_time); fprintf(dbg_log, "old_size int32_t 0x%08x\n", sb->fs_old_size); fprintf(dbg_log, "old_dsize int32_t 0x%08x\n", sb->fs_old_dsize); fprintf(dbg_log, "ncg int32_t 0x%08x\n", sb->fs_ncg); fprintf(dbg_log, "bsize int32_t 0x%08x\n", sb->fs_bsize); fprintf(dbg_log, "fsize int32_t 0x%08x\n", sb->fs_fsize); fprintf(dbg_log, "frag int32_t 0x%08x\n", sb->fs_frag); fprintf(dbg_log, "minfree int32_t 0x%08x\n", sb->fs_minfree); fprintf(dbg_log, "old_rotdelay int32_t 0x%08x\n", sb->fs_old_rotdelay); fprintf(dbg_log, "old_rps int32_t 0x%08x\n", sb->fs_old_rps); fprintf(dbg_log, "bmask int32_t 0x%08x\n", sb->fs_bmask); fprintf(dbg_log, "fmask int32_t 0x%08x\n", sb->fs_fmask); fprintf(dbg_log, "bshift int32_t 0x%08x\n", sb->fs_bshift); fprintf(dbg_log, "fshift int32_t 0x%08x\n", sb->fs_fshift); fprintf(dbg_log, "maxcontig int32_t 0x%08x\n", sb->fs_maxcontig); fprintf(dbg_log, "maxbpg int32_t 0x%08x\n", sb->fs_maxbpg); fprintf(dbg_log, "fragshift int32_t 0x%08x\n", sb->fs_fragshift); fprintf(dbg_log, "fsbtodb int32_t 0x%08x\n", sb->fs_fsbtodb); fprintf(dbg_log, "sbsize int32_t 0x%08x\n", sb->fs_sbsize); fprintf(dbg_log, "spare1 int32_t[2] 0x%08x 0x%08x\n", sb->fs_spare1[0], sb->fs_spare1[1]); fprintf(dbg_log, "nindir int32_t 0x%08x\n", sb->fs_nindir); fprintf(dbg_log, "inopb int32_t 0x%08x\n", sb->fs_inopb); fprintf(dbg_log, "old_nspf int32_t 0x%08x\n", sb->fs_old_nspf); fprintf(dbg_log, "optim int32_t 0x%08x\n", sb->fs_optim); fprintf(dbg_log, "old_npsect int32_t 0x%08x\n", sb->fs_old_npsect); fprintf(dbg_log, "old_interleave int32_t 0x%08x\n", sb->fs_old_interleave); fprintf(dbg_log, "old_trackskew int32_t 0x%08x\n", sb->fs_old_trackskew); fprintf(dbg_log, "id int32_t[2] 0x%08x 0x%08x\n", sb->fs_id[0], sb->fs_id[1]); fprintf(dbg_log, "old_csaddr int32_t 0x%08x\n", sb->fs_old_csaddr); fprintf(dbg_log, "cssize int32_t 0x%08x\n", sb->fs_cssize); fprintf(dbg_log, "cgsize int32_t 0x%08x\n", sb->fs_cgsize); fprintf(dbg_log, "spare2 int32_t 0x%08x\n", sb->fs_spare2); fprintf(dbg_log, "old_nsect int32_t 0x%08x\n", sb->fs_old_nsect); fprintf(dbg_log, "old_spc int32_t 0x%08x\n", sb->fs_old_spc); fprintf(dbg_log, "old_ncyl int32_t 0x%08x\n", sb->fs_old_ncyl); fprintf(dbg_log, "old_cpg int32_t 0x%08x\n", sb->fs_old_cpg); fprintf(dbg_log, "ipg int32_t 0x%08x\n", sb->fs_ipg); fprintf(dbg_log, "fpg int32_t 0x%08x\n", sb->fs_fpg); dbg_dump_csum("internal old_cstotal", &sb->fs_old_cstotal); fprintf(dbg_log, "fmod int8_t 0x%02x\n", sb->fs_fmod); fprintf(dbg_log, "clean int8_t 0x%02x\n", sb->fs_clean); fprintf(dbg_log, "ronly int8_t 0x%02x\n", sb->fs_ronly); fprintf(dbg_log, "old_flags int8_t 0x%02x\n", sb->fs_old_flags); fprintf(dbg_log, "fsmnt u_char[MAXMNTLEN] \"%s\"\n", sb->fs_fsmnt); fprintf(dbg_log, "volname u_char[MAXVOLLEN] \"%s\"\n", sb->fs_volname); fprintf(dbg_log, "swuid u_int64_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_swuid))[1], ((unsigned int *)&(sb->fs_swuid))[0]); fprintf(dbg_log, "pad int32_t 0x%08x\n", sb->fs_pad); fprintf(dbg_log, "cgrotor int32_t 0x%08x\n", sb->fs_cgrotor); /* * struct csum[MAXCSBUFS] - is only maintained in memory */ /* fprintf(dbg_log, " int32_t\n", sb->*fs_maxcluster);*/ fprintf(dbg_log, "old_cpc int32_t 0x%08x\n", sb->fs_old_cpc); /* * int16_t fs_opostbl[16][8] - is dumped when used in dbg_dump_sptbl */ fprintf(dbg_log, "maxbsize int32_t 0x%08x\n", sb->fs_maxbsize); fprintf(dbg_log, "unrefs int64_t 0x%08jx\n", sb->fs_unrefs); fprintf(dbg_log, "sblockloc int64_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_sblockloc))[1], ((unsigned int *)&(sb->fs_sblockloc))[0]); dbg_dump_csum_total("internal cstotal", &sb->fs_cstotal); fprintf(dbg_log, "time ufs_time_t %10u\n", (unsigned int)sb->fs_time); fprintf(dbg_log, "size int64_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_size))[1], ((unsigned int *)&(sb->fs_size))[0]); fprintf(dbg_log, "dsize int64_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_dsize))[1], ((unsigned int *)&(sb->fs_dsize))[0]); fprintf(dbg_log, "csaddr ufs2_daddr_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_csaddr))[1], ((unsigned int *)&(sb->fs_csaddr))[0]); fprintf(dbg_log, "pendingblocks int64_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_pendingblocks))[1], ((unsigned int *)&(sb->fs_pendingblocks))[0]); fprintf(dbg_log, "pendinginodes int32_t 0x%08x\n", sb->fs_pendinginodes); #ifdef FSMAXSNAP - for(j=0; jfs_snapinum[j]); - if(!sb->fs_snapinum[j]) { /* list is dense */ + if (!sb->fs_snapinum[j]) { /* list is dense */ break; } } #endif /* FSMAXSNAP */ fprintf(dbg_log, "avgfilesize int32_t 0x%08x\n", sb->fs_avgfilesize); fprintf(dbg_log, "avgfpdir int32_t 0x%08x\n", sb->fs_avgfpdir); fprintf(dbg_log, "save_cgsize int32_t 0x%08x\n", sb->fs_save_cgsize); fprintf(dbg_log, "flags int32_t 0x%08x\n", sb->fs_flags); fprintf(dbg_log, "contigsumsize int32_t 0x%08x\n", sb->fs_contigsumsize); fprintf(dbg_log, "maxsymlinklen int32_t 0x%08x\n", sb->fs_maxsymlinklen); fprintf(dbg_log, "old_inodefmt int32_t 0x%08x\n", sb->fs_old_inodefmt); fprintf(dbg_log, "maxfilesize u_int64_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_maxfilesize))[1], ((unsigned int *)&(sb->fs_maxfilesize))[0]); fprintf(dbg_log, "qbmask int64_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_qbmask))[1], ((unsigned int *)&(sb->fs_qbmask))[0]); fprintf(dbg_log, "qfmask int64_t 0x%08x%08x\n", ((unsigned int *)&(sb->fs_qfmask))[1], ((unsigned int *)&(sb->fs_qfmask))[0]); fprintf(dbg_log, "state int32_t 0x%08x\n", sb->fs_state); fprintf(dbg_log, "old_postblformat int32_t 0x%08x\n", sb->fs_old_postblformat); fprintf(dbg_log, "old_nrpos int32_t 0x%08x\n", sb->fs_old_nrpos); fprintf(dbg_log, "spare5 int32_t[2] 0x%08x 0x%08x\n", sb->fs_spare5[0], sb->fs_spare5[1]); fprintf(dbg_log, "magic int32_t 0x%08x\n", sb->fs_magic); indent--; fprintf(dbg_log, "===== END SUPERBLOCK =====\n"); return; } -/* ******************************************************* dbg_dump_cg ***** */ /* * Dump a cylinder group. */ void dbg_dump_cg(const char *comment, struct cg *cgr) { int j; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START CYLINDER GROUP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment); indent++; fprintf(dbg_log, "magic int32_t 0x%08x\n", cgr->cg_magic); fprintf(dbg_log, "old_time int32_t 0x%08x\n", cgr->cg_old_time); fprintf(dbg_log, "cgx int32_t 0x%08x\n", cgr->cg_cgx); fprintf(dbg_log, "old_ncyl int16_t 0x%04x\n", cgr->cg_old_ncyl); fprintf(dbg_log, "old_niblk int16_t 0x%04x\n", cgr->cg_old_niblk); fprintf(dbg_log, "ndblk int32_t 0x%08x\n", cgr->cg_ndblk); dbg_dump_csum("internal cs", &cgr->cg_cs); fprintf(dbg_log, "rotor int32_t 0x%08x\n", cgr->cg_rotor); fprintf(dbg_log, "frotor int32_t 0x%08x\n", cgr->cg_frotor); fprintf(dbg_log, "irotor int32_t 0x%08x\n", cgr->cg_irotor); - for(j=0; jcg_frsum[j]); } fprintf(dbg_log, "old_btotoff int32_t 0x%08x\n", cgr->cg_old_btotoff); fprintf(dbg_log, "old_boff int32_t 0x%08x\n", cgr->cg_old_boff); fprintf(dbg_log, "iusedoff int32_t 0x%08x\n", cgr->cg_iusedoff); fprintf(dbg_log, "freeoff int32_t 0x%08x\n", cgr->cg_freeoff); fprintf(dbg_log, "nextfreeoff int32_t 0x%08x\n", cgr->cg_nextfreeoff); fprintf(dbg_log, "clustersumoff int32_t 0x%08x\n", cgr->cg_clustersumoff); fprintf(dbg_log, "clusteroff int32_t 0x%08x\n", cgr->cg_clusteroff); fprintf(dbg_log, "nclusterblks int32_t 0x%08x\n", cgr->cg_nclusterblks); fprintf(dbg_log, "niblk int32_t 0x%08x\n", cgr->cg_niblk); fprintf(dbg_log, "initediblk int32_t 0x%08x\n", cgr->cg_initediblk); fprintf(dbg_log, "unrefs int32_t 0x%08x\n", cgr->cg_unrefs); fprintf(dbg_log, "time ufs_time_t %10u\n", (unsigned int)cgr->cg_initediblk); indent--; fprintf(dbg_log, "===== END CYLINDER GROUP =====\n"); return; } -/* ***************************************************** dbg_dump_csum ***** */ /* * Dump a cylinder summary. */ void dbg_dump_csum(const char *comment, struct csum *cs) { - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START CYLINDER SUMMARY =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cs, comment); indent++; fprintf(dbg_log, "ndir int32_t 0x%08x\n", cs->cs_ndir); fprintf(dbg_log, "nbfree int32_t 0x%08x\n", cs->cs_nbfree); fprintf(dbg_log, "nifree int32_t 0x%08x\n", cs->cs_nifree); fprintf(dbg_log, "nffree int32_t 0x%08x\n", cs->cs_nffree); indent--; fprintf(dbg_log, "===== END CYLINDER SUMMARY =====\n"); return; } -/* ************************************************ dbg_dump_csum_total ***** */ /* * Dump a cylinder summary. */ void dbg_dump_csum_total(const char *comment, struct csum_total *cs) { - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START CYLINDER SUMMARY TOTAL =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cs, comment); indent++; fprintf(dbg_log, "ndir int64_t 0x%08x%08x\n", ((unsigned int *)&(cs->cs_ndir))[1], ((unsigned int *)&(cs->cs_ndir))[0]); fprintf(dbg_log, "nbfree int64_t 0x%08x%08x\n", ((unsigned int *)&(cs->cs_nbfree))[1], ((unsigned int *)&(cs->cs_nbfree))[0]); fprintf(dbg_log, "nifree int64_t 0x%08x%08x\n", ((unsigned int *)&(cs->cs_nifree))[1], ((unsigned int *)&(cs->cs_nifree))[0]); fprintf(dbg_log, "nffree int64_t 0x%08x%08x\n", ((unsigned int *)&(cs->cs_nffree))[1], ((unsigned int *)&(cs->cs_nffree))[0]); fprintf(dbg_log, "numclusters int64_t 0x%08x%08x\n", ((unsigned int *)&(cs->cs_numclusters))[1], ((unsigned int *)&(cs->cs_numclusters))[0]); indent--; fprintf(dbg_log, "===== END CYLINDER SUMMARY TOTAL =====\n"); return; } -/* **************************************************** dbg_dump_inmap ***** */ /* * Dump the inode allocation map in one cylinder group. */ void dbg_dump_inmap(struct fs *sb, const char *comment, struct cg *cgr) { int j,k,l,e; unsigned char *cp; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START INODE ALLOCATION MAP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment); indent++; - cp=(unsigned char *)cg_inosused(cgr); - e=sb->fs_ipg/8; - for(j=0; jfs_ipg / 8; + for (j = 0; j < e; j += 32) { fprintf(dbg_log, "%08x: ", j); - for(k=0; k<32; k+=8) { - if(j+k+8fs_old_nspf) - e=howmany((sb->fs_old_cpg * sb->fs_old_spc / sb->fs_old_nspf), CHAR_BIT); + e = howmany((sb->fs_old_cpg * sb->fs_old_spc / sb->fs_old_nspf), CHAR_BIT); else e = 0; - for(j=0; jfs_old_nspf) - e=howmany(sb->fs_old_cpg * sb->fs_old_spc / (sb->fs_old_nspf << sb->fs_fragshift), CHAR_BIT); + e = howmany(sb->fs_old_cpg * sb->fs_old_spc / (sb->fs_old_nspf << sb->fs_fragshift), CHAR_BIT); else e = 0; - for(j=0; jfs_contigsumsize; j++) { + ip = (int *)cg_clustersum(cgr); + for (j = 0; j <= sb->fs_contigsumsize; j++) { fprintf(dbg_log, "%02d: %8d\n", j, *ip++); } indent--; fprintf(dbg_log, "===== END CLUSTER SUMMARY =====\n"); return; } #ifdef NOT_CURRENTLY /* * This code dates from before the UFS2 integration, and doesn't compile * post-UFS2 due to the use of cg_blks(). I'm not sure how best to update * this for UFS2, where the rotational bits of UFS no longer apply, so * will leave it disabled for now; it should probably be re-enabled * specifically for UFS1. */ -/* **************************************************** dbg_dump_sptbl ***** */ /* * Dump the block summary, and the rotational layout table. */ void dbg_dump_sptbl(struct fs *sb, const char *comment, struct cg *cgr) { int j,k; int *ip; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START BLOCK SUMMARY AND POSITION TABLE =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment); indent++; - ip=(int *)cg_blktot(cgr); - for(j=0; jfs_old_cpg; j++) { + ip = (int *)cg_blktot(cgr); + for (j = 0; j < sb->fs_old_cpg; j++) { fprintf(dbg_log, "%2d: %5d = ", j, *ip++); - for(k=0; kfs_old_nrpos; k++) { + for (k = 0; k < sb->fs_old_nrpos; k++) { fprintf(dbg_log, "%4d", cg_blks(sb, cgr, j)[k]); - if(kfs_old_nrpos-1) { + if (k < sb->fs_old_nrpos - 1) fprintf(dbg_log, " + "); - } } fprintf(dbg_log, "\n"); } indent--; fprintf(dbg_log, "===== END BLOCK SUMMARY AND POSITION TABLE =====\n"); return; } #endif -/* ************************************************** dbg_dump_ufs1_ino ***** */ /* * Dump a UFS1 inode structure. */ void dbg_dump_ufs1_ino(struct fs *sb, const char *comment, struct ufs1_dinode *ino) { int ictr; int remaining_blocks; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START UFS1 INODE DUMP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)ino, comment); indent++; fprintf(dbg_log, "mode u_int16_t 0%o\n", ino->di_mode); fprintf(dbg_log, "nlink int16_t 0x%04x\n", ino->di_nlink); fprintf(dbg_log, "size u_int64_t 0x%08x%08x\n", ((unsigned int *)&(ino->di_size))[1], ((unsigned int *)&(ino->di_size))[0]); fprintf(dbg_log, "atime int32_t 0x%08x\n", ino->di_atime); fprintf(dbg_log, "atimensec int32_t 0x%08x\n", ino->di_atimensec); fprintf(dbg_log, "mtime int32_t 0x%08x\n", ino->di_mtime); fprintf(dbg_log, "mtimensec int32_t 0x%08x\n", ino->di_mtimensec); fprintf(dbg_log, "ctime int32_t 0x%08x\n", ino->di_ctime); fprintf(dbg_log, "ctimensec int32_t 0x%08x\n", ino->di_ctimensec); - remaining_blocks=howmany(ino->di_size, sb->fs_bsize); /* XXX ts - +1? */ - for(ictr=0; ictr < MIN(NDADDR, remaining_blocks); ictr++) { + remaining_blocks = howmany(ino->di_size, sb->fs_bsize); /* XXX ts - +1? */ + for (ictr = 0; ictr < MIN(NDADDR, remaining_blocks); ictr++) { fprintf(dbg_log, "db ufs_daddr_t[%x] 0x%08x\n", ictr, ino->di_db[ictr]); } - remaining_blocks-=NDADDR; - if(remaining_blocks>0) { + remaining_blocks -= NDADDR; + if (remaining_blocks > 0) { fprintf(dbg_log, "ib ufs_daddr_t[0] 0x%08x\n", ino->di_ib[0]); } - remaining_blocks-=howmany(sb->fs_bsize, sizeof(ufs1_daddr_t)); - if(remaining_blocks>0) { + remaining_blocks -= howmany(sb->fs_bsize, sizeof(ufs1_daddr_t)); + if (remaining_blocks > 0) { fprintf(dbg_log, "ib ufs_daddr_t[1] 0x%08x\n", ino->di_ib[1]); } -#define SQUARE(a) ((a)*(a)) - remaining_blocks-=SQUARE(howmany(sb->fs_bsize, sizeof(ufs1_daddr_t))); +#define SQUARE(a) ((a) * (a)) + remaining_blocks -= SQUARE(howmany(sb->fs_bsize, sizeof(ufs1_daddr_t))); #undef SQUARE - if(remaining_blocks>0) { + if (remaining_blocks > 0) { fprintf(dbg_log, "ib ufs_daddr_t[2] 0x%08x\n", ino->di_ib[2]); } fprintf(dbg_log, "flags u_int32_t 0x%08x\n", ino->di_flags); fprintf(dbg_log, "blocks int32_t 0x%08x\n", ino->di_blocks); fprintf(dbg_log, "gen int32_t 0x%08x\n", ino->di_gen); fprintf(dbg_log, "uid u_int32_t 0x%08x\n", ino->di_uid); fprintf(dbg_log, "gid u_int32_t 0x%08x\n", ino->di_gid); indent--; fprintf(dbg_log, "===== END UFS1 INODE DUMP =====\n"); return; } -/* ************************************************** dbg_dump_ufs2_ino ***** */ /* * Dump a UFS2 inode structure. */ void dbg_dump_ufs2_ino(struct fs *sb, const char *comment, struct ufs2_dinode *ino) { int ictr; int remaining_blocks; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START UFS2 INODE DUMP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)ino, comment); indent++; fprintf(dbg_log, "mode u_int16_t 0%o\n", ino->di_mode); fprintf(dbg_log, "nlink int16_t 0x%04x\n", ino->di_nlink); fprintf(dbg_log, "uid u_int32_t 0x%08x\n", ino->di_uid); fprintf(dbg_log, "gid u_int32_t 0x%08x\n", ino->di_gid); fprintf(dbg_log, "blksize u_int32_t 0x%08x\n", ino->di_blksize); fprintf(dbg_log, "size u_int64_t 0x%08x%08x\n", ((unsigned int *)&(ino->di_size))[1], ((unsigned int *)&(ino->di_size))[0]); fprintf(dbg_log, "blocks u_int64_t 0x%08x%08x\n", - ((unsigned int *)&(ino->di_blocks))[1], - ((unsigned int *)&(ino->di_blocks))[0]); + ((unsigned int *)&(ino->di_blocks))[1], + ((unsigned int *)&(ino->di_blocks))[0]); fprintf(dbg_log, "atime ufs_time_t %10jd\n", ino->di_atime); fprintf(dbg_log, "mtime ufs_time_t %10jd\n", ino->di_mtime); fprintf(dbg_log, "ctime ufs_time_t %10jd\n", ino->di_ctime); fprintf(dbg_log, "birthtime ufs_time_t %10jd\n", ino->di_birthtime); fprintf(dbg_log, "mtimensec int32_t 0x%08x\n", ino->di_mtimensec); fprintf(dbg_log, "atimensec int32_t 0x%08x\n", ino->di_atimensec); fprintf(dbg_log, "ctimensec int32_t 0x%08x\n", ino->di_ctimensec); fprintf(dbg_log, "birthnsec int32_t 0x%08x\n", ino->di_birthnsec); fprintf(dbg_log, "gen int32_t 0x%08x\n", ino->di_gen); fprintf(dbg_log, "kernflags u_int32_t 0x%08x\n", ino->di_kernflags); fprintf(dbg_log, "flags u_int32_t 0x%08x\n", ino->di_flags); fprintf(dbg_log, "extsize int32_t 0x%08x\n", ino->di_extsize); /* XXX: What do we do with di_extb[NXADDR]? */ - remaining_blocks=howmany(ino->di_size, sb->fs_bsize); /* XXX ts - +1? */ - for(ictr=0; ictr < MIN(NDADDR, remaining_blocks); ictr++) { + remaining_blocks = howmany(ino->di_size, sb->fs_bsize); /* XXX ts - +1? */ + for (ictr = 0; ictr < MIN(NDADDR, remaining_blocks); ictr++) { fprintf(dbg_log, "db ufs2_daddr_t[%x] 0x%16jx\n", ictr, ino->di_db[ictr]); } - remaining_blocks-=NDADDR; - if(remaining_blocks>0) { + remaining_blocks -= NDADDR; + if (remaining_blocks > 0) { fprintf(dbg_log, "ib ufs2_daddr_t[0] 0x%16jx\n", ino->di_ib[0]); } - remaining_blocks-=howmany(sb->fs_bsize, sizeof(ufs2_daddr_t)); - if(remaining_blocks>0) { + remaining_blocks -= howmany(sb->fs_bsize, sizeof(ufs2_daddr_t)); + if (remaining_blocks > 0) { fprintf(dbg_log, "ib ufs2_daddr_t[1] 0x%16jx\n", ino->di_ib[1]); } -#define SQUARE(a) ((a)*(a)) - remaining_blocks-=SQUARE(howmany(sb->fs_bsize, sizeof(ufs2_daddr_t))); +#define SQUARE(a) ((a) * (a)) + remaining_blocks -= SQUARE(howmany(sb->fs_bsize, sizeof(ufs2_daddr_t))); #undef SQUARE - if(remaining_blocks>0) { + if (remaining_blocks > 0) { fprintf(dbg_log, "ib ufs2_daddr_t[2] 0x%16jx\n", ino->di_ib[2]); } indent--; fprintf(dbg_log, "===== END UFS2 INODE DUMP =====\n"); return; } -/* ***************************************************** dbg_dump_iblk ***** */ /* * Dump an indirect block. The iteration to dump a full file has to be * written around. */ void dbg_dump_iblk(struct fs *sb, const char *comment, char *block, size_t length) { unsigned int *mem, i, j, size; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START INDIRECT BLOCK DUMP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)block, comment); indent++; if (sb->fs_magic == FS_UFS1_MAGIC) size = sizeof(ufs1_daddr_t); else size = sizeof(ufs2_daddr_t); - mem=(unsigned int *)block; - for (i=0; (size_t)ifs_bsize, size), - length); i+=8) { + mem = (unsigned int *)block; + for (i = 0; (size_t)i < MIN(howmany(sb->fs_bsize, size), length); + i += 8) { fprintf(dbg_log, "%04x: ", i); - for (j=0; j<8; j++) { - if((size_t)(i+j) __FBSDID("$FreeBSD$"); -/* ********************************************************** INCLUDES ***** */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "debug.h" -/* *************************************************** GLOBALS & TYPES ***** */ #ifdef FS_DEBUG int _dbg_lvl_ = (DL_INFO); /* DL_TRC */ #endif /* FS_DEBUG */ static union { struct fs fs; char pad[SBLOCKSIZE]; } fsun1, fsun2; #define sblock fsun1.fs /* the new superblock */ #define osblock fsun2.fs /* the old superblock */ /* * Possible superblock locations ordered from most to least likely. */ static int sblock_try[] = SBLOCKSEARCH; static ufs2_daddr_t sblockloc; static union { struct cg cg; char pad[MAXBSIZE]; } cgun1, cgun2; #define acg cgun1.cg /* a cylinder cgroup (new) */ #define aocg cgun2.cg /* an old cylinder group */ static char ablk[MAXBSIZE]; /* a block */ static struct csum *fscs; /* cylinder summary */ union dinode { struct ufs1_dinode dp1; struct ufs2_dinode dp2; }; #define DIP(dp, field) \ ((sblock.fs_magic == FS_UFS1_MAGIC) ? \ (uint32_t)(dp)->dp1.field : (dp)->dp2.field) #define DIP_SET(dp, field, val) do { \ if (sblock.fs_magic == FS_UFS1_MAGIC) \ (dp)->dp1.field = (val); \ else \ (dp)->dp2.field = (val); \ } while (0) static ufs2_daddr_t inoblk; /* inode block address */ static char inobuf[MAXBSIZE]; /* inode block */ static ino_t maxino; /* last valid inode */ -static int unlabeled; /* unlabeled partition, e.g. vinum volume etc. */ +static int unlabeled; /* unlabeled partition, e.g. vinum volume */ /* * An array of elements of type struct gfs_bpp describes all blocks to * be relocated in order to free the space needed for the cylinder group * summary for all cylinder groups located in the first cylinder group. */ struct gfs_bpp { ufs2_daddr_t old; /* old block number */ ufs2_daddr_t new; /* new block number */ #define GFS_FL_FIRST 1 #define GFS_FL_LAST 2 unsigned int flags; /* special handling required */ - int found; /* how many references were updated */ + int found; /* how many references were updated */ }; -/* ******************************************************** PROTOTYPES ***** */ static void growfs(int, int, unsigned int); static void rdfs(ufs2_daddr_t, size_t, void *, int); static void wtfs(ufs2_daddr_t, size_t, void *, int, unsigned int); static ufs2_daddr_t alloc(void); static int charsperline(void); static void usage(void); static int isblock(struct fs *, unsigned char *, int); static void clrblock(struct fs *, unsigned char *, int); static void setblock(struct fs *, unsigned char *, int); static void initcg(int, time_t, int, unsigned int); static void updjcg(int, time_t, int, int, unsigned int); static void updcsloc(time_t, int, int, unsigned int); static struct disklabel *get_disklabel(int); static void return_disklabel(int, struct disklabel *, unsigned int); static union dinode *ginode(ino_t, int, int); static void frag_adjust(ufs2_daddr_t, int); static int cond_bl_upd(ufs2_daddr_t *, struct gfs_bpp *, int, int, unsigned int); static void updclst(int); static void updrefs(int, ino_t, struct gfs_bpp *, int, int, unsigned int); static void indirchk(ufs_lbn_t, ufs_lbn_t, ufs2_daddr_t, ufs_lbn_t, struct gfs_bpp *, int, int, unsigned int); static void get_dev_size(int, int *); -/* ************************************************************ growfs ***** */ /* * Here we actually start growing the file system. We basically read the * cylinder summary from the first cylinder group as we want to update * this on the fly during our various operations. First we handle the * changes in the former last cylinder group. Afterwards we create all new * cylinder groups. Now we handle the cylinder group containing the * cylinder summary which might result in a relocation of the whole * structure. In the end we write back the updated cylinder summary, the * new superblock, and slightly patched versions of the super block * copies. */ static void growfs(int fsi, int fso, unsigned int Nflag) { DBG_FUNC("growfs") - time_t modtime; - uint cylno; - int i, j, width; - char tmpbuf[100]; + time_t modtime; + uint cylno; + int i, j, width; + char tmpbuf[100]; #ifdef FSIRAND - static int randinit=0; + static int randinit=0; DBG_ENTER; if (!randinit) { randinit = 1; srandomdev(); } #else /* not FSIRAND */ DBG_ENTER; #endif /* FSIRAND */ time(&modtime); /* * Get the cylinder summary into the memory. */ fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize); - if(fscs == NULL) { + if (fscs == NULL) errx(1, "calloc failed"); - } for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) { rdfs(fsbtodb(&osblock, osblock.fs_csaddr + numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i, - osblock.fs_bsize), (void *)(((char *)fscs)+i), fsi); + osblock.fs_bsize), (void *)(((char *)fscs) + i), fsi); } #ifdef FS_DEBUG -{ - struct csum *dbg_csp; - int dbg_csc; - char dbg_line[80]; - - dbg_csp=fscs; - for(dbg_csc=0; dbg_csc= width) { printf("\n"); i = 0; } i += j; printf("%s", tmpbuf); fflush(stdout); } printf("\n"); /* * Do all needed changes in the first cylinder group. * allocate blocks in new location */ updcsloc(modtime, fsi, fso, Nflag); /* * Now write the cylinder summary back to disk. */ for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) { wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), (size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize), (void *)(((char *)fscs) + i), fso, Nflag); } DBG_PRINT0("fscs written\n"); #ifdef FS_DEBUG -{ - struct csum *dbg_csp; - int dbg_csc; - char dbg_line[80]; - - dbg_csp=fscs; - for(dbg_csc=0; dbg_csc sblock.fs_size) dmax = sblock.fs_size; dlower = cgsblock(&sblock, cylno) - cbase; dupper = cgdmin(&sblock, cylno) - cbase; if (cylno == 0) /* XXX fscs may be relocated */ dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); cs = &fscs[cylno]; memset(&acg, 0, sblock.fs_cgsize); acg.cg_time = modtime; acg.cg_magic = CG_MAGIC; acg.cg_cgx = cylno; acg.cg_niblk = sblock.fs_ipg; acg.cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ? sblock.fs_ipg : 2 * INOPB(&sblock); acg.cg_ndblk = dmax - cbase; if (sblock.fs_contigsumsize > 0) acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); if (sblock.fs_magic == FS_UFS2_MAGIC) { acg.cg_iusedoff = start; } else { acg.cg_old_ncyl = sblock.fs_old_cpg; acg.cg_old_time = acg.cg_time; acg.cg_time = 0; acg.cg_old_niblk = acg.cg_niblk; acg.cg_niblk = 0; acg.cg_initediblk = 0; acg.cg_old_btotoff = start; acg.cg_old_boff = acg.cg_old_btotoff + sblock.fs_old_cpg * sizeof(int32_t); acg.cg_iusedoff = acg.cg_old_boff + sblock.fs_old_cpg * sizeof(u_int16_t); } acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT); acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT); if (sblock.fs_contigsumsize > 0) { acg.cg_clustersumoff = roundup(acg.cg_nextfreeoff, sizeof(u_int32_t)); acg.cg_clustersumoff -= sizeof(u_int32_t); acg.cg_clusteroff = acg.cg_clustersumoff + (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); acg.cg_nextfreeoff = acg.cg_clusteroff + howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); } if (acg.cg_nextfreeoff > (unsigned)sblock.fs_cgsize) { /* * This should never happen as we would have had that panic * already on file system creation */ errx(37, "panic: cylinder group too big"); } acg.cg_cs.cs_nifree += sblock.fs_ipg; if (cylno == 0) for (i = 0; i < ROOTINO; i++) { setbit(cg_inosused(&acg), i); acg.cg_cs.cs_nifree--; } /* * For the old file system, we have to initialize all the inodes. */ if (sblock.fs_magic == FS_UFS1_MAGIC) { bzero(iobuf, sblock.fs_bsize); for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); - i += sblock.fs_frag) { + i += sblock.fs_frag) { #ifdef FSIRAND dp1 = (struct ufs1_dinode *)(void *)iobuf; for (j = 0; j < INOPB(&sblock); j++) { dp1->di_gen = random(); dp1++; } #endif wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), sblock.fs_bsize, iobuf, fso, Nflag); } } if (cylno > 0) { /* * In cylno 0, beginning space is reserved * for boot and super blocks. */ for (d = 0; d < dlower; d += sblock.fs_frag) { blkno = d / sblock.fs_frag; setblock(&sblock, cg_blksfree(&acg), blkno); if (sblock.fs_contigsumsize > 0) setbit(cg_clustersfree(&acg), blkno); acg.cg_cs.cs_nbfree++; } sblock.fs_dsize += dlower; } sblock.fs_dsize += acg.cg_ndblk - dupper; if ((i = dupper % sblock.fs_frag)) { acg.cg_frsum[sblock.fs_frag - i]++; for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { setbit(cg_blksfree(&acg), dupper); acg.cg_cs.cs_nffree++; } } for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk; - d += sblock.fs_frag) { + d += sblock.fs_frag) { blkno = d / sblock.fs_frag; setblock(&sblock, cg_blksfree(&acg), blkno); if (sblock.fs_contigsumsize > 0) setbit(cg_clustersfree(&acg), blkno); acg.cg_cs.cs_nbfree++; } if (d < acg.cg_ndblk) { acg.cg_frsum[acg.cg_ndblk - d]++; for (; d < acg.cg_ndblk; d++) { setbit(cg_blksfree(&acg), d); acg.cg_cs.cs_nffree++; } } if (sblock.fs_contigsumsize > 0) { int32_t *sump = cg_clustersum(&acg); u_char *mapp = cg_clustersfree(&acg); int map = *mapp++; int bit = 1; int run = 0; for (i = 0; i < acg.cg_nclusterblks; i++) { if ((map & bit) != 0) run++; else if (run != 0) { if (run > sblock.fs_contigsumsize) run = sblock.fs_contigsumsize; sump[run]++; run = 0; } if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1) bit <<= 1; else { map = *mapp++; bit = 1; } } if (run != 0) { if (run > sblock.fs_contigsumsize) run = sblock.fs_contigsumsize; sump[run]++; } } sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; *cs = acg.cg_cs; memcpy(iobuf, &acg, sblock.fs_cgsize); memset(iobuf + sblock.fs_cgsize, '\0', sblock.fs_bsize * 3 - sblock.fs_cgsize); wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), sblock.fs_bsize * 3, iobuf, fso, Nflag); DBG_DUMP_CG(&sblock, "new cg", &acg); DBG_LEAVE; return; } -/* ******************************************************* frag_adjust ***** */ /* * Here we add or subtract (sign +1/-1) the available fragments in a given * block to or from the fragment statistics. By subtracting before and adding * after an operation on the free frag map we can easy update the fragment * statistic, which seems to be otherwise a rather complex operation. */ static void frag_adjust(ufs2_daddr_t frag, int sign) { DBG_FUNC("frag_adjust") int fragsize; int f; DBG_ENTER; fragsize=0; /* * Here frag only needs to point to any fragment in the block we want * to examine. */ - for(f=rounddown(frag, sblock.fs_frag); - fold != 0; f++) { src = *block; if (fragstoblks(&sblock, src) != f->old) continue; /* * The fragment is part of the block, so update. */ dst = blkstofrags(&sblock, f->new); fragnum = fragnum(&sblock, src); *block = dst + fragnum; f->found++; DBG_PRINT3("scg (%jd->%jd)[%d] reference updated\n", - (intmax_t)f->old, - (intmax_t)f->new, - fragnum); + (intmax_t)f->old, (intmax_t)f->new, fragnum); /* * Copy the block back immediately. * * XXX If src is from an indirect block we have * to implement copy on write here in case of * active snapshots. */ ibuf = malloc(sblock.fs_bsize); if (!ibuf) errx(1, "malloc failed"); src -= fragnum; rdfs(fsbtodb(&sblock, src), (size_t)sblock.fs_bsize, ibuf, fsi); wtfs(dst, (size_t)sblock.fs_bsize, ibuf, fso, Nflag); free(ibuf); /* * The same block can't be found again in this loop. */ return (1); } DBG_LEAVE; return (0); } -/* ************************************************************ updjcg ***** */ /* * Here we do all needed work for the former last cylinder group. It has to be * changed in any case, even if the file system ended exactly on the end of * this group, as there is some slightly inconsistent handling of the number * of cylinders in the cylinder group. We start again by reading the cylinder * group from disk. If the last block was not fully available, we first handle * the missing fragments, then we handle all new full blocks in that file * system and finally we handle the new last fragmented block in the file * system. We again have to handle the fragment statistics rotational layout * tables and cluster summary during all those operations. */ static void updjcg(int cylno, time_t modtime, int fsi, int fso, unsigned int Nflag) { DBG_FUNC("updjcg") - ufs2_daddr_t cbase, dmax, dupper; - struct csum *cs; - int i,k; - int j=0; + ufs2_daddr_t cbase, dmax, dupper; + struct csum *cs; + int i, k; + int j = 0; DBG_ENTER; /* * Read the former last (joining) cylinder group from disk, and make * a copy. */ rdfs(fsbtodb(&osblock, cgtod(&osblock, cylno)), (size_t)osblock.fs_cgsize, (void *)&aocg, fsi); DBG_PRINT0("jcg read\n"); - DBG_DUMP_CG(&sblock, - "old joining cg", - &aocg); + DBG_DUMP_CG(&sblock, "old joining cg", &aocg); memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); /* * If the cylinder group had already its new final size almost * nothing is to be done ... except: * For some reason the value of cg_ncyl in the last cylinder group has * to be zero instead of fs_cpg. As this is now no longer the last * cylinder group we have to change that value now to fs_cpg. */ - if(cgbase(&osblock, cylno+1) == osblock.fs_size) { + if (cgbase(&osblock, cylno + 1) == osblock.fs_size) { if (sblock.fs_magic == FS_UFS1_MAGIC) acg.cg_old_ncyl=sblock.fs_old_cpg; wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); DBG_PRINT0("jcg written\n"); - DBG_DUMP_CG(&sblock, - "new joining cg", - &acg); + DBG_DUMP_CG(&sblock, "new joining cg", &acg); DBG_LEAVE; return; } /* * Set up some variables needed later. */ cbase = cgbase(&sblock, cylno); dmax = cbase + sblock.fs_fpg; if (dmax > sblock.fs_size) dmax = sblock.fs_size; dupper = cgdmin(&sblock, cylno) - cbase; - if (cylno == 0) { /* XXX fscs may be relocated */ + if (cylno == 0) /* XXX fscs may be relocated */ dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); - } /* * Set pointer to the cylinder summary for our cylinder group. */ cs = fscs + cylno; /* * Touch the cylinder group, update all fields in the cylinder group as * needed, update the free space in the superblock. */ acg.cg_time = modtime; if ((unsigned)cylno == sblock.fs_ncg - 1) { /* * This is still the last cylinder group. */ if (sblock.fs_magic == FS_UFS1_MAGIC) acg.cg_old_ncyl = sblock.fs_old_ncyl % sblock.fs_old_cpg; } else { acg.cg_old_ncyl = sblock.fs_old_cpg; } - DBG_PRINT2("jcg dbg: %d %u", - cylno, - sblock.fs_ncg); + DBG_PRINT2("jcg dbg: %d %u", cylno, sblock.fs_ncg); #ifdef FS_DEBUG if (sblock.fs_magic == FS_UFS1_MAGIC) - DBG_PRINT2("%d %u", - acg.cg_old_ncyl, - sblock.fs_old_cpg); + DBG_PRINT2("%d %u", acg.cg_old_ncyl, sblock.fs_old_cpg); #endif DBG_PRINT0("\n"); acg.cg_ndblk = dmax - cbase; - sblock.fs_dsize += acg.cg_ndblk-aocg.cg_ndblk; - if (sblock.fs_contigsumsize > 0) { + sblock.fs_dsize += acg.cg_ndblk - aocg.cg_ndblk; + if (sblock.fs_contigsumsize > 0) acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; - } /* * Now we have to update the free fragment bitmap for our new free * space. There again we have to handle the fragmentation and also * the rotational layout tables and the cluster summary. This is * also done per fragment for the first new block if the old file * system end was not on a block boundary, per fragment for the new * last block if the new file system end is not on a block boundary, * and per block for all space in between. * * Handle the first new block here if it was partially available * before. */ - if(osblock.fs_size % sblock.fs_frag) { - if(roundup(osblock.fs_size, sblock.fs_frag)<=sblock.fs_size) { + if (osblock.fs_size % sblock.fs_frag) { + if (roundup(osblock.fs_size, sblock.fs_frag) <= + sblock.fs_size) { /* * The new space is enough to fill at least this * block */ - j=0; - for(i=roundup(osblock.fs_size-cbase, sblock.fs_frag)-1; - i>=osblock.fs_size-cbase; + j = 0; + for (i = roundup(osblock.fs_size - cbase, + sblock.fs_frag) - 1; i >= osblock.fs_size - cbase; i--) { setbit(cg_blksfree(&acg), i); acg.cg_cs.cs_nffree++; j++; } /* * Check if the fragment just created could join an * already existing fragment at the former end of the * file system. */ - if(isblock(&sblock, cg_blksfree(&acg), - ((osblock.fs_size - cgbase(&sblock, cylno))/ - sblock.fs_frag))) { + if (isblock(&sblock, cg_blksfree(&acg), + ((osblock.fs_size - cgbase(&sblock, cylno)) / + sblock.fs_frag))) { /* * The block is now completely available. */ DBG_PRINT0("block was\n"); - acg.cg_frsum[osblock.fs_size%sblock.fs_frag]--; + acg.cg_frsum[osblock.fs_size % sblock.fs_frag]--; acg.cg_cs.cs_nbfree++; - acg.cg_cs.cs_nffree-=sblock.fs_frag; - k=rounddown(osblock.fs_size-cbase, + acg.cg_cs.cs_nffree -= sblock.fs_frag; + k = rounddown(osblock.fs_size - cbase, + sblock.fs_frag); + updclst((osblock.fs_size - cbase) / sblock.fs_frag); - updclst((osblock.fs_size-cbase)/sblock.fs_frag); } else { /* * Lets rejoin a possible partially growed * fragment. */ - k=0; - while(isset(cg_blksfree(&acg), i) && - (i>=rounddown(osblock.fs_size-cbase, + k = 0; + while (isset(cg_blksfree(&acg), i) && + (i >= rounddown(osblock.fs_size - cbase, sblock.fs_frag))) { i--; k++; } - if(k) { + if (k) acg.cg_frsum[k]--; - } - acg.cg_frsum[k+j]++; + acg.cg_frsum[k + j]++; } } else { /* * We only grow by some fragments within this last * block. */ - for(i=sblock.fs_size-cbase-1; - i>=osblock.fs_size-cbase; - i--) { + for (i = sblock.fs_size - cbase - 1; + i >= osblock.fs_size - cbase; i--) { setbit(cg_blksfree(&acg), i); acg.cg_cs.cs_nffree++; j++; } /* * Lets rejoin a possible partially growed fragment. */ - k=0; - while(isset(cg_blksfree(&acg), i) && - (i>=rounddown(osblock.fs_size-cbase, + k = 0; + while (isset(cg_blksfree(&acg), i) && + (i >= rounddown(osblock.fs_size - cbase, sblock.fs_frag))) { i--; k++; } - if(k) { + if (k) acg.cg_frsum[k]--; - } - acg.cg_frsum[k+j]++; + acg.cg_frsum[k + j]++; } } /* * Handle all new complete blocks here. */ - for(i=roundup(osblock.fs_size-cbase, sblock.fs_frag); - i+sblock.fs_frag<=dmax-cbase; /* XXX <= or only < ? */ - i+=sblock.fs_frag) { + for (i = roundup(osblock.fs_size - cbase, sblock.fs_frag); + i + sblock.fs_frag <= dmax - cbase; /* XXX <= or only < ? */ + i += sblock.fs_frag) { j = i / sblock.fs_frag; setblock(&sblock, cg_blksfree(&acg), j); updclst(j); acg.cg_cs.cs_nbfree++; } /* * Handle the last new block if there are stll some new fragments left. * Here we don't have to bother about the cluster summary or the even * the rotational layout table. */ if (i < (dmax - cbase)) { acg.cg_frsum[dmax - cbase - i]++; for (; i < dmax - cbase; i++) { setbit(cg_blksfree(&acg), i); acg.cg_cs.cs_nffree++; } } sblock.fs_cstotal.cs_nffree += (acg.cg_cs.cs_nffree - aocg.cg_cs.cs_nffree); sblock.fs_cstotal.cs_nbfree += (acg.cg_cs.cs_nbfree - aocg.cg_cs.cs_nbfree); /* * The following statistics are not changed here: * sblock.fs_cstotal.cs_ndir * sblock.fs_cstotal.cs_nifree * As the statistics for this cylinder group are ready, copy it to * the summary information array. */ *cs = acg.cg_cs; /* * Write the updated "joining" cylinder group back to disk. */ wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); DBG_PRINT0("jcg written\n"); - DBG_DUMP_CG(&sblock, - "new joining cg", - &acg); + DBG_DUMP_CG(&sblock, "new joining cg", &acg); DBG_LEAVE; return; } -/* ********************************************************** updcsloc ***** */ /* * Here we update the location of the cylinder summary. We have two possible * ways of growing the cylinder summary. * (1) We can try to grow the summary in the current location, and relocate * possibly used blocks within the current cylinder group. * (2) Alternatively we can relocate the whole cylinder summary to the first * new completely empty cylinder group. Once the cylinder summary is no * longer in the beginning of the first cylinder group you should never * use a version of fsck which is not aware of the possibility to have * this structure in a non standard place. * Option (1) is considered to be less intrusive to the structure of the file- * system. So we try to stick to that whenever possible. If there is not enough * space in the cylinder group containing the cylinder summary we have to use * method (2). In case of active snapshots in the file system we probably can * completely avoid implementing copy on write if we stick to method (2) only. */ static void updcsloc(time_t modtime, int fsi, int fso, unsigned int Nflag) { DBG_FUNC("updcsloc") - struct csum *cs; - int ocscg, ncscg; - int blocks; - ufs2_daddr_t cbase, dupper, odupper, d, f, g; - int ind, inc; - uint cylno; - struct gfs_bpp *bp; - int i, l; - int lcs=0; - int block; + struct csum *cs; + int ocscg, ncscg; + int blocks; + ufs2_daddr_t cbase, dupper, odupper, d, f, g; + int ind, inc; + uint cylno; + struct gfs_bpp *bp; + int i, l; + int lcs = 0; + int block; DBG_ENTER; - if(howmany(sblock.fs_cssize, sblock.fs_fsize) == + if (howmany(sblock.fs_cssize, sblock.fs_fsize) == howmany(osblock.fs_cssize, osblock.fs_fsize)) { /* * No new fragment needed. */ DBG_LEAVE; return; } - ocscg=dtog(&osblock, osblock.fs_csaddr); - cs=fscs+ocscg; - blocks = 1+howmany(sblock.fs_cssize, sblock.fs_bsize)- + ocscg = dtog(&osblock, osblock.fs_csaddr); + cs = fscs + ocscg; + blocks = 1 + howmany(sblock.fs_cssize, sblock.fs_bsize) - howmany(osblock.fs_cssize, osblock.fs_bsize); /* * Read original cylinder group from disk, and make a copy. * XXX If Nflag is set in some very rare cases we now miss * some changes done in updjcg by reading the unmodified * block from disk. */ rdfs(fsbtodb(&osblock, cgtod(&osblock, ocscg)), (size_t)osblock.fs_cgsize, (void *)&aocg, fsi); DBG_PRINT0("oscg read\n"); - DBG_DUMP_CG(&sblock, - "old summary cg", - &aocg); + DBG_DUMP_CG(&sblock, "old summary cg", &aocg); memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); /* * Touch the cylinder group, set up local variables needed later * and update the superblock. */ acg.cg_time = modtime; /* * XXX In the case of having active snapshots we may need much more * blocks for the copy on write. We need each block twice, and * also up to 8*3 blocks for indirect blocks for all possible * references. */ - if(/*((int)sblock.fs_time&0x3)>0||*/ cs->cs_nbfree < blocks) { + if (/*((int)sblock.fs_time&0x3)>0||*/ cs->cs_nbfree < blocks) { /* * There is not enough space in the old cylinder group to * relocate all blocks as needed, so we relocate the whole * cylinder group summary to a new group. We try to use the * first complete new cylinder group just created. Within the * cylinder group we align the area immediately after the * cylinder group information location in order to be as * close as possible to the original implementation of ffs. * * First we have to make sure we'll find enough space in the * new cylinder group. If not, then we currently give up. * We start with freeing everything which was used by the * fragments of the old cylinder summary in the current group. * Now we write back the group meta data, read in the needed * meta data from the new cylinder group, and start allocating * within that group. Here we can assume, the group to be * completely empty. Which makes the handling of fragments and * clusters a lot easier. */ DBG_TRC; - if(sblock.fs_ncg-osblock.fs_ncg < 2) { + if (sblock.fs_ncg - osblock.fs_ncg < 2) errx(2, "panic: not enough space"); - } /* * Point "d" to the first fragment not used by the cylinder * summary. */ - d=osblock.fs_csaddr+(osblock.fs_cssize/osblock.fs_fsize); + d = osblock.fs_csaddr + (osblock.fs_cssize / osblock.fs_fsize); /* * Set up last cluster size ("lcs") already here. Calculate * the size for the trailing cluster just behind where "d" * points to. */ - if(sblock.fs_contigsumsize > 0) { - for(block=howmany(d%sblock.fs_fpg, sblock.fs_frag), - lcs=0; lcs 0) { + for (block = howmany(d % sblock.fs_fpg, sblock.fs_frag), + lcs = 0; lcs < sblock.fs_contigsumsize; block++, lcs++) { - if(isclr(cg_clustersfree(&acg), block)){ + if (isclr(cg_clustersfree(&acg), block)) break; - } } } /* * Point "d" to the last frag used by the cylinder summary. */ d--; - DBG_PRINT1("d=%jd\n", - (intmax_t)d); - if((d+1)%sblock.fs_frag) { + DBG_PRINT1("d=%jd\n", (intmax_t)d); + if ((d + 1) % sblock.fs_frag) { /* * The end of the cylinder summary is not a complete * block. */ DBG_TRC; - frag_adjust(d%sblock.fs_fpg, -1); - for(; (d+1)%sblock.fs_frag; d--) { - DBG_PRINT1("d=%jd\n", - (intmax_t)d); - setbit(cg_blksfree(&acg), d%sblock.fs_fpg); + frag_adjust(d % sblock.fs_fpg, -1); + for (; (d + 1) % sblock.fs_frag; d--) { + DBG_PRINT1("d=%jd\n", (intmax_t)d); + setbit(cg_blksfree(&acg), d % sblock.fs_fpg); acg.cg_cs.cs_nffree++; sblock.fs_cstotal.cs_nffree++; } /* * Point "d" to the last fragment of the last * (incomplete) block of the cylinder summary. */ d++; frag_adjust(d%sblock.fs_fpg, 1); - if(isblock(&sblock, cg_blksfree(&acg), - (d%sblock.fs_fpg)/sblock.fs_frag)) { + if (isblock(&sblock, cg_blksfree(&acg), + (d % sblock.fs_fpg) / sblock.fs_frag)) { DBG_PRINT1("d=%jd\n", (intmax_t)d); - acg.cg_cs.cs_nffree-=sblock.fs_frag; + acg.cg_cs.cs_nffree -= sblock.fs_frag; acg.cg_cs.cs_nbfree++; - sblock.fs_cstotal.cs_nffree-=sblock.fs_frag; + sblock.fs_cstotal.cs_nffree -= sblock.fs_frag; sblock.fs_cstotal.cs_nbfree++; - if(sblock.fs_contigsumsize > 0) { + if (sblock.fs_contigsumsize > 0) { setbit(cg_clustersfree(&acg), - (d%sblock.fs_fpg)/sblock.fs_frag); - if(lcs < sblock.fs_contigsumsize) { - if(lcs) { - cg_clustersum(&acg) - [lcs]--; - } + (d % sblock.fs_fpg) / + sblock.fs_frag); + if (lcs < sblock.fs_contigsumsize) { + if (lcs) + cg_clustersum(&acg)[lcs]--; lcs++; cg_clustersum(&acg)[lcs]++; } } } /* * Point "d" to the first fragment of the block before * the last incomplete block. */ d--; } DBG_PRINT1("d=%jd\n", (intmax_t)d); - for(d=rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr; - d-=sblock.fs_frag) { + for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr; + d -= sblock.fs_frag) { DBG_TRC; DBG_PRINT1("d=%jd\n", (intmax_t)d); setblock(&sblock, cg_blksfree(&acg), - (d%sblock.fs_fpg)/sblock.fs_frag); + (d % sblock.fs_fpg) / sblock.fs_frag); acg.cg_cs.cs_nbfree++; sblock.fs_cstotal.cs_nbfree++; - if(sblock.fs_contigsumsize > 0) { + if (sblock.fs_contigsumsize > 0) { setbit(cg_clustersfree(&acg), - (d%sblock.fs_fpg)/sblock.fs_frag); + (d % sblock.fs_fpg) / sblock.fs_frag); /* * The last cluster size is already set up. */ - if(lcs < sblock.fs_contigsumsize) { - if(lcs) { + if (lcs < sblock.fs_contigsumsize) { + if (lcs) cg_clustersum(&acg)[lcs]--; - } lcs++; cg_clustersum(&acg)[lcs]++; } } } *cs = acg.cg_cs; /* * Now write the former cylinder group containing the cylinder * summary back to disk. */ wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); DBG_PRINT0("oscg written\n"); - DBG_DUMP_CG(&sblock, - "old summary cg", - &acg); + DBG_DUMP_CG(&sblock, "old summary cg", &acg); /* * Find the beginning of the new cylinder group containing the * cylinder summary. */ - sblock.fs_csaddr=cgdmin(&sblock, osblock.fs_ncg); - ncscg=dtog(&sblock, sblock.fs_csaddr); - cs=fscs+ncscg; - + sblock.fs_csaddr = cgdmin(&sblock, osblock.fs_ncg); + ncscg = dtog(&sblock, sblock.fs_csaddr); + cs = fscs + ncscg; /* * If Nflag is specified, we would now read random data instead * of an empty cg structure from disk. So we can't simulate that * part for now. */ - if(Nflag) { + if (Nflag) { DBG_PRINT0("nscg update skipped\n"); DBG_LEAVE; return; } /* * Read the future cylinder group containing the cylinder * summary from disk, and make a copy. */ rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)), (size_t)sblock.fs_cgsize, (void *)&aocg, fsi); DBG_PRINT0("nscg read\n"); - DBG_DUMP_CG(&sblock, - "new summary cg", - &aocg); + DBG_DUMP_CG(&sblock, "new summary cg", &aocg); memcpy((void *)&cgun1, (void *)&cgun2, sizeof(cgun2)); /* * Allocate all complete blocks used by the new cylinder * summary. */ - for(d=sblock.fs_csaddr; d+sblock.fs_frag <= - sblock.fs_csaddr+(sblock.fs_cssize/sblock.fs_fsize); - d+=sblock.fs_frag) { + for (d = sblock.fs_csaddr; d + sblock.fs_frag <= + sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize); + d += sblock.fs_frag) { clrblock(&sblock, cg_blksfree(&acg), - (d%sblock.fs_fpg)/sblock.fs_frag); + (d % sblock.fs_fpg) / sblock.fs_frag); acg.cg_cs.cs_nbfree--; sblock.fs_cstotal.cs_nbfree--; - if(sblock.fs_contigsumsize > 0) { + if (sblock.fs_contigsumsize > 0) { clrbit(cg_clustersfree(&acg), - (d%sblock.fs_fpg)/sblock.fs_frag); + (d % sblock.fs_fpg) / sblock.fs_frag); } } /* * Allocate all fragments used by the cylinder summary in the * last block. */ - if(d 0) { + sblock.fs_cstotal.cs_nffree += sblock.fs_frag; + if (sblock.fs_contigsumsize > 0) clrbit(cg_clustersfree(&acg), - (d%sblock.fs_fpg)/sblock.fs_frag); - } + (d % sblock.fs_fpg) / sblock.fs_frag); - frag_adjust(d%sblock.fs_fpg, +1); + frag_adjust(d % sblock.fs_fpg, 1); } /* * XXX Handle the cluster statistics here in the case this * cylinder group is now almost full, and the remaining * space is less then the maximum cluster size. This is * probably not needed, as you would hardly find a file * system which has only MAXCSBUFS+FS_MAXCONTIG of free * space right behind the cylinder group information in * any new cylinder group. */ /* * Update our statistics in the cylinder summary. */ *cs = acg.cg_cs; /* * Write the new cylinder group containing the cylinder summary * back to disk. */ wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)), (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); DBG_PRINT0("nscg written\n"); - DBG_DUMP_CG(&sblock, - "new summary cg", - &acg); + DBG_DUMP_CG(&sblock, "new summary cg", &acg); DBG_LEAVE; return; } /* * We have got enough of space in the current cylinder group, so we * can relocate just a few blocks, and let the summary information * grow in place where it is right now. */ DBG_TRC; cbase = cgbase(&osblock, ocscg); /* old and new are equal */ dupper = sblock.fs_csaddr - cbase + howmany(sblock.fs_cssize, sblock.fs_fsize); odupper = osblock.fs_csaddr - cbase + howmany(osblock.fs_cssize, osblock.fs_fsize); - sblock.fs_dsize -= dupper-odupper; + sblock.fs_dsize -= dupper - odupper; /* * Allocate the space for the array of blocks to be relocated. */ - bp=(struct gfs_bpp *)malloc(((dupper-odupper)/sblock.fs_frag+2)* - sizeof(struct gfs_bpp)); - if(bp == NULL) { + bp = (struct gfs_bpp *)malloc(((dupper - odupper) / + sblock.fs_frag + 2) * sizeof(struct gfs_bpp)); + if (bp == NULL) errx(1, "malloc failed"); - } - memset((char *)bp, 0, ((dupper-odupper)/sblock.fs_frag+2)* + memset((char *)bp, 0, ((dupper - odupper) / sblock.fs_frag + 2) * sizeof(struct gfs_bpp)); /* * Lock all new frags needed for the cylinder group summary. This is * done per fragment in the first and last block of the new required * area, and per block for all other blocks. * * Handle the first new block here (but only if some fragments where * already used for the cylinder summary). */ - ind=0; + ind = 0; frag_adjust(odupper, -1); - for(d=odupper; ((d= dupper) { - bp[ind].flags|=GFS_FL_LAST; - } + bp[ind].old = d / sblock.fs_frag; + bp[ind].flags |= GFS_FL_FIRST; + if (roundup(d, sblock.fs_frag) >= dupper) + bp[ind].flags |= GFS_FL_LAST; ind++; } } else { clrbit(cg_blksfree(&acg), d); acg.cg_cs.cs_nffree--; sblock.fs_cstotal.cs_nffree--; } /* * No cluster handling is needed here, as there was at least * one fragment in use by the cylinder summary in the old * file system. * No block-free counter handling here as this block was not * a free block. */ } frag_adjust(odupper, 1); /* * Handle all needed complete blocks here. */ - for(; d+sblock.fs_frag<=dupper; d+=sblock.fs_frag) { - DBG_PRINT1("scg block check loop d=%jd\n", - (intmax_t)d); - if(!isblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag)) { - for(f=d; f 0) { - clrbit(cg_clustersfree(&acg), d/sblock.fs_frag); - for(lcs=0, l=(d/sblock.fs_frag)+1; - lcs 0) { + clrbit(cg_clustersfree(&acg), d / sblock.fs_frag); + for (lcs = 0, l = (d / sblock.fs_frag) + 1; + lcs < sblock.fs_contigsumsize; l++, lcs++ ) { + if (isclr(cg_clustersfree(&acg), l)) break; - } } - if(lcs < sblock.fs_contigsumsize) { - cg_clustersum(&acg)[lcs+1]--; - if(lcs) { + if (lcs < sblock.fs_contigsumsize) { + cg_clustersum(&acg)[lcs + 1]--; + if (lcs) cg_clustersum(&acg)[lcs]++; - } } } } /* * No fragment counter handling is needed here, as this finally * doesn't change after the relocation. */ } /* * Handle all fragments needed in the last new affected block. */ - if(d 0) { - clrbit(cg_clustersfree(&acg), d/sblock.fs_frag); - for(lcs=0, l=(d/sblock.fs_frag)+1; - lcs 0) { + clrbit(cg_clustersfree(&acg), d / sblock.fs_frag); + for (lcs = 0, l =(d / sblock.fs_frag) + 1; + lcs < sblock.fs_contigsumsize; l++, lcs++ ) { + if (isclr(cg_clustersfree(&acg),l)) break; - } } - if(lcs < sblock.fs_contigsumsize) { - cg_clustersum(&acg)[lcs+1]--; - if(lcs) { + if (lcs < sblock.fs_contigsumsize) { + cg_clustersum(&acg)[lcs + 1]--; + if (lcs) cg_clustersum(&acg)[lcs]++; - } } } } - for(; d%jd) block relocated\n", - (intmax_t)bp[i].old, - (intmax_t)bp[i].new); + (intmax_t)bp[i].old, (intmax_t)bp[i].new); } /* * Now we have to update all references to any fragment which * belongs to any block relocated. We iterate now over all * cylinder groups, within those over all non zero length * inodes. */ - for(cylno=0; cylno0 ; inc--) { + for (cylno = 0; cylno < osblock.fs_ncg; cylno++) { + DBG_PRINT1("scg doing cg (%d)\n", cylno); + for (inc = osblock.fs_ipg - 1 ; inc > 0 ; inc--) updrefs(cylno, (ino_t)inc, bp, fsi, fso, Nflag); - } } /* * All inodes are checked, now make sure the number of * references found make sense. */ - for(i=0; isblock.fs_frag)) { + for (i = 0; i < ind; i++) { + if (!bp[i].found || (bp[i].found > sblock.fs_frag)) { warnx("error: %jd refs found for block %jd.", (intmax_t)bp[i].found, (intmax_t)bp[i].old); } - } } /* * The following statistics are not changed here: * sblock.fs_cstotal.cs_ndir * sblock.fs_cstotal.cs_nifree * The following statistics were already updated on the fly: * sblock.fs_cstotal.cs_nffree * sblock.fs_cstotal.cs_nbfree * As the statistics for this cylinder group are ready, copy it to * the summary information array. */ *cs = acg.cg_cs; /* * Write summary cylinder group back to disk. */ wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); DBG_PRINT0("scg written\n"); - DBG_DUMP_CG(&sblock, - "new summary cg", - &acg); + DBG_DUMP_CG(&sblock, "new summary cg", &acg); DBG_LEAVE; return; } -/* ************************************************************** rdfs ***** */ /* * Here we read some block(s) from disk. */ static void rdfs(ufs2_daddr_t bno, size_t size, void *bf, int fsi) { DBG_FUNC("rdfs") ssize_t n; DBG_ENTER; - if (bno < 0) { + if (bno < 0) err(32, "rdfs: attempting to read negative block number"); - } - if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) { + if (lseek(fsi, (off_t)bno * DEV_BSIZE, 0) < 0) err(33, "rdfs: seek error: %jd", (intmax_t)bno); - } n = read(fsi, bf, size); - if (n != (ssize_t)size) { + if (n != (ssize_t)size) err(34, "rdfs: read error: %jd", (intmax_t)bno); - } DBG_LEAVE; return; } -/* ************************************************************** wtfs ***** */ /* * Here we write some block(s) to disk. */ static void wtfs(ufs2_daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) { DBG_FUNC("wtfs") ssize_t n; DBG_ENTER; if (Nflag) { DBG_LEAVE; return; } - if (lseek(fso, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0) { + if (lseek(fso, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0) err(35, "wtfs: seek error: %ld", (long)bno); - } n = write(fso, bf, size); - if (n != (ssize_t)size) { + if (n != (ssize_t)size) err(36, "wtfs: write error: %ld", (long)bno); - } DBG_LEAVE; return; } -/* ************************************************************* alloc ***** */ /* * Here we allocate a free block in the current cylinder group. It is assumed, * that acg contains the current cylinder group. As we may take a block from * somewhere in the file system we have to handle cluster summary here. */ static ufs2_daddr_t alloc(void) { DBG_FUNC("alloc") - ufs2_daddr_t d, blkno; - int lcs1, lcs2; - int l; - int csmin, csmax; - int dlower, dupper, dmax; + ufs2_daddr_t d, blkno; + int lcs1, lcs2; + int l; + int csmin, csmax; + int dlower, dupper, dmax; DBG_ENTER; if (acg.cg_magic != CG_MAGIC) { warnx("acg: bad magic number"); DBG_LEAVE; return (0); } if (acg.cg_cs.cs_nbfree == 0) { warnx("error: cylinder group ran out of space"); DBG_LEAVE; return (0); } /* * We start seeking for free blocks only from the space available after * the end of the new grown cylinder summary. Otherwise we allocate a * block here which we have to relocate a couple of seconds later again * again, and we are not prepared to to this anyway. */ - blkno=-1; - dlower=cgsblock(&sblock, acg.cg_cgx)-cgbase(&sblock, acg.cg_cgx); - dupper=cgdmin(&sblock, acg.cg_cgx)-cgbase(&sblock, acg.cg_cgx); - dmax=cgbase(&sblock, acg.cg_cgx)+sblock.fs_fpg; - if (dmax > sblock.fs_size) { + blkno =- 1; + dlower = cgsblock(&sblock, acg.cg_cgx) - cgbase(&sblock, acg.cg_cgx); + dupper = cgdmin(&sblock, acg.cg_cgx) - cgbase(&sblock, acg.cg_cgx); + dmax = cgbase(&sblock, acg.cg_cgx) + sblock.fs_fpg; + if (dmax > sblock.fs_size) dmax = sblock.fs_size; - } - dmax-=cgbase(&sblock, acg.cg_cgx); /* retransform into cg */ - csmin=sblock.fs_csaddr-cgbase(&sblock, acg.cg_cgx); - csmax=csmin+howmany(sblock.fs_cssize, sblock.fs_fsize); - DBG_PRINT3("seek range: dl=%d, du=%d, dm=%d\n", - dlower, - dupper, - dmax); - DBG_PRINT2("range cont: csmin=%d, csmax=%d\n", - csmin, - csmax); - - for(d=0; (d=csmin && d<=csmax) { + dmax -= cgbase(&sblock, acg.cg_cgx); /* retransform into cg */ + csmin = sblock.fs_csaddr - cgbase(&sblock, acg.cg_cgx); + csmax = csmin + howmany(sblock.fs_cssize, sblock.fs_fsize); + DBG_PRINT3("seek range: dl=%d, du=%d, dm=%d\n", dlower, dupper, dmax); + DBG_PRINT2("range cont: csmin=%d, csmax=%d\n", csmin, csmax); + + for (d = 0; (d < dlower && blkno == -1); d += sblock.fs_frag) { + if (d >= csmin && d <= csmax) continue; - } - if(isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock, - d))) { + if (isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock, d))) { blkno = fragstoblks(&sblock, d);/* Yeah found a block */ break; } } - for(d=dupper; (d=csmin && d<=csmax) { + for (d = dupper; (d < dmax && blkno == -1); d += sblock.fs_frag) { + if (d >= csmin && d <= csmax) { continue; } - if(isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock, - d))) { + if (isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock, d))) { blkno = fragstoblks(&sblock, d);/* Yeah found a block */ break; } } - if(blkno==-1) { + if (blkno == -1) { warnx("internal error: couldn't find promised block in cg"); DBG_LEAVE; return (0); } /* * This is needed if the block was found already in the first loop. */ - d=blkstofrags(&sblock, blkno); + d = blkstofrags(&sblock, blkno); clrblock(&sblock, cg_blksfree(&acg), blkno); if (sblock.fs_contigsumsize > 0) { /* * Handle the cluster allocation bitmap. */ clrbit(cg_clustersfree(&acg), blkno); /* * We possibly have split a cluster here, so we have to do * recalculate the sizes of the remaining cluster halves now, * and use them for updating the cluster summary information. * * Lets start with the blocks before our allocated block ... */ - for(lcs1=0, l=blkno-1; lcs1fs_frag) { case 8: DBG_LEAVE; return (cp[h] == 0xff); case 4: mask = 0x0f << ((h & 0x1) << 2); DBG_LEAVE; return ((cp[h >> 1] & mask) == mask); case 2: mask = 0x03 << ((h & 0x3) << 1); DBG_LEAVE; return ((cp[h >> 2] & mask) == mask); case 1: mask = 0x01 << (h & 0x7); DBG_LEAVE; return ((cp[h >> 3] & mask) == mask); default: fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); DBG_LEAVE; return (0); } } -/* ********************************************************** clrblock ***** */ /* * Here we allocate a complete block in the block map. For more details again * please see the source of newfs(8), as this function is taken over almost * unchanged. */ static void clrblock(struct fs *fs, unsigned char *cp, int h) { DBG_FUNC("clrblock") DBG_ENTER; switch ((fs)->fs_frag) { case 8: cp[h] = 0; break; case 4: cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); break; case 2: cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); break; case 1: cp[h >> 3] &= ~(0x01 << (h & 0x7)); break; default: warnx("clrblock bad fs_frag %d", fs->fs_frag); break; } DBG_LEAVE; return; } -/* ********************************************************** setblock ***** */ /* * Here we free a complete block in the free block map. For more details again * please see the source of newfs(8), as this function is taken over almost * unchanged. */ static void setblock(struct fs *fs, unsigned char *cp, int h) { DBG_FUNC("setblock") DBG_ENTER; switch (fs->fs_frag) { case 8: cp[h] = 0xff; break; case 4: cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); break; case 2: cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); break; case 1: cp[h >> 3] |= (0x01 << (h & 0x7)); break; default: warnx("setblock bad fs_frag %d", fs->fs_frag); break; } DBG_LEAVE; return; } -/* ************************************************************ ginode ***** */ /* * This function provides access to an individual inode. We find out in which * block the requested inode is located, read it from disk if needed, and * return the pointer into that block. We maintain a cache of one block to * not read the same block again and again if we iterate linearly over all * inodes. */ static union dinode * ginode(ino_t inumber, int fsi, int cg) { DBG_FUNC("ginode") - static ino_t startinum = 0; /* first inode in cached block */ + static ino_t startinum = 0; /* first inode in cached block */ DBG_ENTER; /* * The inumber passed in is relative to the cg, so use it here to see * if the inode has been allocated yet. */ if (isclr(cg_inosused(&aocg), inumber)) { DBG_LEAVE; return NULL; } /* * Now make the inumber relative to the entire inode space so it can * be sanity checked. */ inumber += (cg * sblock.fs_ipg); if (inumber < ROOTINO) { DBG_LEAVE; return NULL; } if (inumber > maxino) errx(8, "bad inode number %d to ginode", inumber); if (startinum == 0 || inumber < startinum || inumber >= startinum + INOPB(&sblock)) { inoblk = fsbtodb(&sblock, ino_to_fsba(&sblock, inumber)); rdfs(inoblk, (size_t)sblock.fs_bsize, inobuf, fsi); startinum = (inumber / INOPB(&sblock)) * INOPB(&sblock); } DBG_LEAVE; if (sblock.fs_magic == FS_UFS1_MAGIC) return (union dinode *)((uintptr_t)inobuf + (inumber % INOPB(&sblock)) * sizeof(struct ufs1_dinode)); return (union dinode *)((uintptr_t)inobuf + (inumber % INOPB(&sblock)) * sizeof(struct ufs2_dinode)); } -/* ****************************************************** charsperline ***** */ /* * Figure out how many lines our current terminal has. For more details again * please see the source of newfs(8), as this function is taken over almost * unchanged. */ static int charsperline(void) { DBG_FUNC("charsperline") - int columns; - char *cp; - struct winsize ws; + int columns; + char *cp; + struct winsize ws; DBG_ENTER; columns = 0; - if (ioctl(0, TIOCGWINSZ, &ws) != -1) { + if (ioctl(0, TIOCGWINSZ, &ws) != -1) columns = ws.ws_col; - } - if (columns == 0 && (cp = getenv("COLUMNS"))) { + if (columns == 0 && (cp = getenv("COLUMNS"))) columns = atoi(cp); - } - if (columns == 0) { + if (columns == 0) columns = 80; /* last resort */ - } DBG_LEAVE; return columns; } -/* ****************************************************** get_dev_size ***** */ /* * Get the size of the partition if we can't figure it out from the disklabel, * e.g. from vinum volumes. */ static void get_dev_size(int fd, int *size) { - int sectorsize; - off_t mediasize; + int sectorsize; + off_t mediasize; - if (ioctl(fd, DIOCGSECTORSIZE, §orsize) == -1) - err(1,"DIOCGSECTORSIZE"); - if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) - err(1,"DIOCGMEDIASIZE"); + if (ioctl(fd, DIOCGSECTORSIZE, §orsize) == -1) + err(1,"DIOCGSECTORSIZE"); + if (ioctl(fd, DIOCGMEDIASIZE, &mediasize) == -1) + err(1,"DIOCGMEDIASIZE"); - if (sectorsize <= 0) - errx(1, "bogus sectorsize: %d", sectorsize); + if (sectorsize <= 0) + errx(1, "bogus sectorsize: %d", sectorsize); - *size = mediasize / sectorsize; + *size = mediasize / sectorsize; } -/* ************************************************************** main ***** */ /* - * growfs(8) is a utility which allows to increase the size of an existing + * growfs(8) is a utility which allows to increase the size of an existing * ufs file system. Currently this can only be done on unmounted file system. * It recognizes some command line options to specify the new desired size, * and it does some basic checkings. The old file system size is determined * and after some more checks like we can really access the new last block * on the disk etc. we calculate the new parameters for the superblock. After * having done this we just call growfs() which will do the work. Before * we finish the only thing left is to update the disklabel. * We still have to provide support for snapshots. Therefore we first have to * understand what data structures are always replicated in the snapshot on * creation, for all other blocks we touch during our procedure, we have to * keep the old blocks unchanged somewhere available for the snapshots. If we * are lucky, then we only have to handle our blocks to be relocated in that * way. * Also we have to consider in what order we actually update the critical * data structures of the file system to make sure, that in case of a disaster * fsck(8) is still able to restore any lost data. * The foreseen last step then will be to provide for growing even mounted * file systems. There we have to extend the mount() system call to provide * userland access to the file system locking facility. */ int main(int argc, char **argv) { DBG_FUNC("main") - char *device, *special, *cp; - int ch; - unsigned int size=0; - size_t len; - unsigned int Nflag=0; - int ExpertFlag=0; - struct stat st; - struct disklabel *lp; - struct partition *pp; - int i,fsi,fso; - u_int32_t p_size; - char reply[5]; + char *device, *special, *cp; + int ch; + unsigned int size = 0; + size_t len; + unsigned int Nflag = 0; + int ExpertFlag = 0; + struct stat st; + struct disklabel *lp; + struct partition *pp; + int i, fsi, fso; + u_int32_t p_size; + char reply[5]; #ifdef FSMAXSNAP - int j; + int j; #endif /* FSMAXSNAP */ DBG_ENTER; - while((ch=getopt(argc, argv, "Ns:vy")) != -1) { + while ((ch = getopt(argc, argv, "Ns:vy")) != -1) { switch(ch) { case 'N': - Nflag=1; + Nflag = 1; break; case 's': - size=(size_t)atol(optarg); - if(size<1) { + size = (size_t)atol(optarg); + if (size < 1) usage(); - } break; case 'v': /* for compatibility to newfs */ break; case 'y': - ExpertFlag=1; + ExpertFlag = 1; break; case '?': /* FALLTHROUGH */ default: usage(); } } argc -= optind; argv += optind; - if(argc != 1) { + if (argc != 1) usage(); - } - device=*argv; + + device = *argv; /* * Now try to guess the (raw)device name. */ if (0 == strrchr(device, '/')) { /* * No path prefix was given, so try in that order: * /dev/r%s * /dev/%s * /dev/vinum/r%s * /dev/vinum/%s. * * FreeBSD now doesn't distinguish between raw and block * devices any longer, but it should still work this way. */ - len=strlen(device)+strlen(_PATH_DEV)+2+strlen("vinum/"); - special=(char *)malloc(len); - if(special == NULL) { + len = strlen(device) + strlen(_PATH_DEV) + 2 + strlen("vinum/"); + special = (char *)malloc(len); + if (special == NULL) errx(1, "malloc failed"); - } snprintf(special, len, "%sr%s", _PATH_DEV, device); if (stat(special, &st) == -1) { snprintf(special, len, "%s%s", _PATH_DEV, device); if (stat(special, &st) == -1) { snprintf(special, len, "%svinum/r%s", _PATH_DEV, device); if (stat(special, &st) == -1) { /* For now this is the 'last resort' */ snprintf(special, len, "%svinum/%s", _PATH_DEV, device); } } } device = special; } /* * Try to access our devices for writing ... */ if (Nflag) { fso = -1; } else { fso = open(device, O_WRONLY); - if (fso < 0) { + if (fso < 0) err(1, "%s", device); - } } /* * ... and reading. */ fsi = open(device, O_RDONLY); - if (fsi < 0) { + if (fsi < 0) err(1, "%s", device); - } /* * Try to read a label and guess the slice if not specified. This * code should guess the right thing and avoid to bother the user * with the task of specifying the option -v on vinum volumes. */ - cp=device+strlen(device)-1; + cp = device + strlen(device) - 1; lp = get_disklabel(fsi); pp = NULL; - if (lp != NULL) { - if (isdigit(*cp)) { - pp = &lp->d_partitions[2]; - } else if (*cp>='a' && *cp<='h') { - pp = &lp->d_partitions[*cp - 'a']; - } else { - errx(1, "unknown device"); - } - p_size = pp->p_size; - } else { - get_dev_size(fsi, &p_size); - } + if (lp != NULL) { + if (isdigit(*cp)) + pp = &lp->d_partitions[2]; + else if (*cp>='a' && *cp<='h') + pp = &lp->d_partitions[*cp - 'a']; + else + errx(1, "unknown device"); + p_size = pp->p_size; + } else { + get_dev_size(fsi, &p_size); + } /* * Check if that partition is suitable for growing a file system. */ - if (p_size < 1) { + if (p_size < 1) errx(1, "partition is unavailable"); - } /* * Read the current superblock, and take a backup. */ for (i = 0; sblock_try[i] != -1; i++) { sblockloc = sblock_try[i] / DEV_BSIZE; rdfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&(osblock), fsi); if ((osblock.fs_magic == FS_UFS1_MAGIC || - (osblock.fs_magic == FS_UFS2_MAGIC && - osblock.fs_sblockloc == sblock_try[i])) && + (osblock.fs_magic == FS_UFS2_MAGIC && + osblock.fs_sblockloc == sblock_try[i])) && osblock.fs_bsize <= MAXBSIZE && osblock.fs_bsize >= (int32_t) sizeof(struct fs)) break; } - if (sblock_try[i] == -1) { + if (sblock_try[i] == -1) errx(1, "superblock not recognized"); - } memcpy((void *)&fsun1, (void *)&fsun2, sizeof(fsun2)); maxino = sblock.fs_ncg * sblock.fs_ipg; DBG_OPEN("/tmp/growfs.debug"); /* already here we need a superblock */ - DBG_DUMP_FS(&sblock, - "old sblock"); + DBG_DUMP_FS(&sblock, "old sblock"); /* * Determine size to grow to. Default to the full size specified in * the disk label. */ sblock.fs_size = dbtofsb(&osblock, p_size); if (size != 0) { - if (size > p_size){ + if (size > p_size) errx(1, "there is not enough space (%d < %d)", p_size, size); - } sblock.fs_size = dbtofsb(&osblock, size); } /* * Are we really growing ? */ - if(osblock.fs_size >= sblock.fs_size) { + if (osblock.fs_size >= sblock.fs_size) { errx(1, "we are not growing (%jd->%jd)", (intmax_t)osblock.fs_size, (intmax_t)sblock.fs_size); } #ifdef FSMAXSNAP /* * Check if we find an active snapshot. */ - if(ExpertFlag == 0) { - for(j=0; j sblock.fs_old_ncyl * sblock.fs_old_spc) sblock.fs_old_ncyl++; } sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg); maxino = sblock.fs_ncg * sblock.fs_ipg; if (sblock.fs_size % sblock.fs_fpg != 0 && sblock.fs_size % sblock.fs_fpg < cgdmin(&sblock, sblock.fs_ncg)) { /* * The space in the new last cylinder group is too small, * so revert back. */ sblock.fs_ncg--; if (sblock.fs_magic == FS_UFS1_MAGIC) sblock.fs_old_ncyl = sblock.fs_ncg * sblock.fs_old_cpg; printf("Warning: %jd sector(s) cannot be allocated.\n", (intmax_t)fsbtodb(&sblock, sblock.fs_size % sblock.fs_fpg)); sblock.fs_size = sblock.fs_ncg * sblock.fs_fpg; maxino -= sblock.fs_ipg; } /* * Update the space for the cylinder group summary information in the * respective cylinder group data area. */ sblock.fs_cssize = fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); - if(osblock.fs_size >= sblock.fs_size) { + if (osblock.fs_size >= sblock.fs_size) errx(1, "not enough new space"); - } DBG_PRINT0("sblock calculated\n"); /* * Ok, everything prepared, so now let's do the tricks. */ growfs(fsi, fso, Nflag); /* * Update the disk label. */ - if (!unlabeled) { - pp->p_fsize = sblock.fs_fsize; - pp->p_frag = sblock.fs_frag; - pp->p_cpg = sblock.fs_fpg; + if (!unlabeled) { + pp->p_fsize = sblock.fs_fsize; + pp->p_frag = sblock.fs_frag; + pp->p_cpg = sblock.fs_fpg; - return_disklabel(fso, lp, Nflag); - DBG_PRINT0("label rewritten\n"); - } + return_disklabel(fso, lp, Nflag); + DBG_PRINT0("label rewritten\n"); + } close(fsi); - if(fso>-1) close(fso); + if (fso > -1) + close(fso); DBG_CLOSE; DBG_LEAVE; return 0; } -/* ************************************************** return_disklabel ***** */ /* * Write the updated disklabel back to disk. */ static void return_disklabel(int fd, struct disklabel *lp, unsigned int Nflag) { DBG_FUNC("return_disklabel") u_short sum; u_short *ptr; DBG_ENTER; - if(!lp) { + if (!lp) { DBG_LEAVE; return; } - if(!Nflag) { - lp->d_checksum=0; + if (!Nflag) { + lp->d_checksum = 0; sum = 0; - ptr=(u_short *)lp; + ptr = (u_short *)lp; /* * recalculate checksum */ - while(ptr < (u_short *)&lp->d_partitions[lp->d_npartitions]) { + while (ptr < (u_short *)&lp->d_partitions[lp->d_npartitions]) sum ^= *ptr++; - } lp->d_checksum=sum; - if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) { + if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) errx(1, "DIOCWDINFO failed"); - } } free(lp); DBG_LEAVE; return ; } -/* ***************************************************** get_disklabel ***** */ /* * Read the disklabel from disk. */ static struct disklabel * get_disklabel(int fd) { DBG_FUNC("get_disklabel") - static struct disklabel *lab; + static struct disklabel *lab; DBG_ENTER; - lab=(struct disklabel *)malloc(sizeof(struct disklabel)); + lab = (struct disklabel *)malloc(sizeof(struct disklabel)); if (!lab) errx(1, "malloc failed"); - if (!ioctl(fd, DIOCGDINFO, (char *)lab)) - return (lab); + if (!ioctl(fd, DIOCGDINFO, (char *)lab)) + return (lab); - unlabeled++; + unlabeled++; DBG_LEAVE; return (NULL); } -/* ************************************************************* usage ***** */ /* * Dump a line of usage. */ static void usage(void) { DBG_FUNC("usage") DBG_ENTER; fprintf(stderr, "usage: growfs [-Ny] [-s size] special\n"); DBG_LEAVE; exit(1); } -/* *********************************************************** updclst ***** */ /* * This updates most parameters and the bitmap related to cluster. We have to * assume that sblock, osblock, acg are set up. */ static void updclst(int block) { DBG_FUNC("updclst") - static int lcs=0; + static int lcs = 0; DBG_ENTER; - if(sblock.fs_contigsumsize < 1) { /* no clustering */ + if (sblock.fs_contigsumsize < 1) /* no clustering */ return; - } /* * update cluster allocation map */ setbit(cg_clustersfree(&acg), block); /* * update cluster summary table */ - if(!lcs) { + if (!lcs) { /* * calculate size for the trailing cluster */ - for(block--; lcs 0 && i < NIADDR; i++) { iptr = DIP(ino, di_ib[i]); if (iptr == 0) continue; if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) { DIP_SET(ino, di_ib[i], iptr); inodeupdated++; } indirchk(blksperindir, lbn, iptr, numblks, bp, fsi, fso, Nflag); blksperindir *= NINDIR(&sblock); lbn += blksperindir; len -= blksperindir; DBG_PRINT1("scg indirect_%d blocks checked\n", i + 1); } if (inodeupdated) wtfs(inoblk, sblock.fs_bsize, inobuf, fso, Nflag); DBG_LEAVE; return; } /* * Recursively check all the indirect blocks. */ static void indirchk(ufs_lbn_t blksperindir, ufs_lbn_t lbn, ufs2_daddr_t blkno, ufs_lbn_t lastlbn, struct gfs_bpp *bp, int fsi, int fso, unsigned int Nflag) { DBG_FUNC("indirchk") void *ibuf; int i, last; ufs2_daddr_t iptr; DBG_ENTER; /* read in the indirect block. */ ibuf = malloc(sblock.fs_bsize); if (!ibuf) errx(1, "malloc failed"); rdfs(fsbtodb(&sblock, blkno), (size_t)sblock.fs_bsize, ibuf, fsi); last = howmany(lastlbn - lbn, blksperindir) < NINDIR(&sblock) ? howmany(lastlbn - lbn, blksperindir) : NINDIR(&sblock); for (i = 0; i < last; i++) { if (sblock.fs_magic == FS_UFS1_MAGIC) iptr = ((ufs1_daddr_t *)ibuf)[i]; else iptr = ((ufs2_daddr_t *)ibuf)[i]; if (iptr == 0) continue; if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) { if (sblock.fs_magic == FS_UFS1_MAGIC) ((ufs1_daddr_t *)ibuf)[i] = iptr; else ((ufs2_daddr_t *)ibuf)[i] = iptr; } if (blksperindir == 1) continue; indirchk(blksperindir / NINDIR(&sblock), lbn + blksperindir * i, iptr, lastlbn, bp, fsi, fso, Nflag); } free(ibuf); DBG_LEAVE; return; }