diff options
author | Todd C. Miller <millert@cvs.openbsd.org> | 2007-07-07 08:22:56 +0000 |
---|---|---|
committer | Todd C. Miller <millert@cvs.openbsd.org> | 2007-07-07 08:22:56 +0000 |
commit | df0498ed6550de222d8ec106d789391e0c6ebfd6 (patch) | |
tree | c0569c6d26ad051cf50350357e83f3b8ec330f19 /sbin/growfs | |
parent | e1e1baa8d343bdc409d1f12d26aac117909ac749 (diff) |
Pull in ffs2 support and other updates from FreeBSD. OK deraadt@
Diffstat (limited to 'sbin/growfs')
-rw-r--r-- | sbin/growfs/debug.c | 497 | ||||
-rw-r--r-- | sbin/growfs/debug.h | 27 | ||||
-rw-r--r-- | sbin/growfs/growfs.8 | 10 | ||||
-rw-r--r-- | sbin/growfs/growfs.c | 1209 |
4 files changed, 967 insertions, 776 deletions
diff --git a/sbin/growfs/debug.c b/sbin/growfs/debug.c index b9109daf770..bcacdc2b9b4 100644 --- a/sbin/growfs/debug.c +++ b/sbin/growfs/debug.c @@ -1,4 +1,4 @@ -/* $OpenBSD: debug.c,v 1.6 2007/06/01 19:26:06 deraadt Exp $ */ +/* $OpenBSD: debug.c,v 1.7 2007/07/07 08:22:55 millert Exp $ */ /* * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz * Copyright (c) 1980, 1989, 1993 The Regents of the University of California. @@ -37,13 +37,13 @@ * SUCH DAMAGE. * * $TSHeader: src/sbin/growfs/debug.c,v 1.3 2000/12/12 19:31:00 tomsoft Exp $ - * $FreeBSD: src/sbin/growfs/debug.c,v 1.7 2002/09/25 04:06:36 mike Exp $ + * $FreeBSD: src/sbin/growfs/debug.c,v 1.10 2006/10/31 22:02:24 pjd Exp $ * */ #ifndef lint static const char rcsid[] = - "$OpenBSD: debug.c,v 1.6 2007/06/01 19:26:06 deraadt Exp $"; + "$OpenBSD: debug.c,v 1.7 2007/07/07 08:22:55 millert Exp $"; #endif /* not lint */ /* ********************************************************** INCLUDES ***** */ @@ -51,6 +51,8 @@ static const char rcsid[] = #include <limits.h> #include <stdio.h> +#include <string.h> + #include <ufs/ufs/dinode.h> #include <ufs/ffs/fs.h> @@ -59,8 +61,8 @@ static const char rcsid[] = #ifdef FS_DEBUG /* *********************************************************** GLOBALS ***** */ -static FILE *dbg_log=NULL; -static unsigned int indent=0; +static FILE *dbg_log; +static unsigned int indent; /* * prototypes not done here, as they come with debug.h @@ -75,9 +77,9 @@ dbg_open(const char *fn) { if (strcmp(fn, "-") == 0) - dbg_log=fopen("/dev/stdout", "a"); + dbg_log = stdout; else - dbg_log=fopen(fn, "a"); + dbg_log = fopen(fn, "a"); return; } @@ -90,9 +92,10 @@ void dbg_close(void) { - if(dbg_log) { - fclose(dbg_log); - dbg_log=NULL; + if (dbg_log) { + if (dbg_log != stdout) + fclose(dbg_log); + dbg_log = NULL; } return; @@ -107,17 +110,16 @@ 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; i<sb->fs_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"); @@ -139,176 +141,221 @@ dbg_dump_fs(struct fs *sb, const char *comment) 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", + fprintf(dbg_log, "sblkno int32_t 0x%08x\n", sb->fs_sblkno); - fprintf(dbg_log, "cblkno int32_t 0x%08x\n", + fprintf(dbg_log, "cblkno int32_t 0x%08x\n", sb->fs_cblkno); - fprintf(dbg_log, "iblkno int32_t 0x%08x\n", + fprintf(dbg_log, "iblkno int32_t 0x%08x\n", sb->fs_iblkno); - fprintf(dbg_log, "dblkno int32_t 0x%08x\n", + fprintf(dbg_log, "dblkno int32_t 0x%08x\n", sb->fs_dblkno); - fprintf(dbg_log, "cgoffset int32_t 0x%08x\n", + fprintf(dbg_log, "cgoffset int32_t 0x%08x\n", sb->fs_cgoffset); - fprintf(dbg_log, "cgmask int32_t 0x%08x\n", + fprintf(dbg_log, "cgmask int32_t 0x%08x\n", sb->fs_cgmask); - fprintf(dbg_log, "time time_t %10u\n", - (unsigned int)sb->fs_ffs1_time); - fprintf(dbg_log, "size int32_t 0x%08x\n", + fprintf(dbg_log, "time int32_t %10d\n", + sb->fs_ffs1_time); + fprintf(dbg_log, "size int32_t 0x%08x\n", sb->fs_ffs1_size); - fprintf(dbg_log, "dsize int32_t 0x%08x\n", + fprintf(dbg_log, "dsize int32_t 0x%08x\n", sb->fs_ffs1_dsize); - fprintf(dbg_log, "ncg int32_t 0x%08x\n", + fprintf(dbg_log, "ncg int32_t 0x%08x\n", sb->fs_ncg); - fprintf(dbg_log, "bsize int32_t 0x%08x\n", + fprintf(dbg_log, "bsize int32_t 0x%08x\n", sb->fs_bsize); - fprintf(dbg_log, "fsize int32_t 0x%08x\n", + fprintf(dbg_log, "fsize int32_t 0x%08x\n", sb->fs_fsize); - fprintf(dbg_log, "frag int32_t 0x%08x\n", + fprintf(dbg_log, "frag int32_t 0x%08x\n", sb->fs_frag); - fprintf(dbg_log, "minfree int32_t 0x%08x\n", + fprintf(dbg_log, "minfree int32_t 0x%08x\n", sb->fs_minfree); - fprintf(dbg_log, "rotdelay int32_t 0x%08x\n", + fprintf(dbg_log, "rotdelay int32_t 0x%08x\n", sb->fs_rotdelay); - fprintf(dbg_log, "rps int32_t 0x%08x\n", + fprintf(dbg_log, "rps int32_t 0x%08x\n", sb->fs_rps); - fprintf(dbg_log, "bmask int32_t 0x%08x\n", + fprintf(dbg_log, "bmask int32_t 0x%08x\n", sb->fs_bmask); - fprintf(dbg_log, "fmask int32_t 0x%08x\n", + fprintf(dbg_log, "fmask int32_t 0x%08x\n", sb->fs_fmask); - fprintf(dbg_log, "bshift int32_t 0x%08x\n", + fprintf(dbg_log, "bshift int32_t 0x%08x\n", sb->fs_bshift); - fprintf(dbg_log, "fshift int32_t 0x%08x\n", + fprintf(dbg_log, "fshift int32_t 0x%08x\n", sb->fs_fshift); - fprintf(dbg_log, "maxcontig int32_t 0x%08x\n", + fprintf(dbg_log, "maxcontig int32_t 0x%08x\n", sb->fs_maxcontig); - fprintf(dbg_log, "maxbpg int32_t 0x%08x\n", + fprintf(dbg_log, "maxbpg int32_t 0x%08x\n", sb->fs_maxbpg); - fprintf(dbg_log, "fragshift int32_t 0x%08x\n", + fprintf(dbg_log, "fragshift int32_t 0x%08x\n", sb->fs_fragshift); - fprintf(dbg_log, "fsbtodb int32_t 0x%08x\n", + fprintf(dbg_log, "fsbtodb int32_t 0x%08x\n", sb->fs_fsbtodb); - fprintf(dbg_log, "sbsize int32_t 0x%08x\n", + fprintf(dbg_log, "sbsize int32_t 0x%08x\n", sb->fs_sbsize); - fprintf(dbg_log, "csmask int32_t 0x%08x\n", + fprintf(dbg_log, "csmask int32_t 0x%08x\n", sb->fs_csmask); - fprintf(dbg_log, "csshift int32_t 0x%08x\n", + fprintf(dbg_log, "csshift int32_t 0x%08x\n", sb->fs_csshift); - fprintf(dbg_log, "nindir int32_t 0x%08x\n", + fprintf(dbg_log, "nindir int32_t 0x%08x\n", sb->fs_nindir); - fprintf(dbg_log, "inopb int32_t 0x%08x\n", + fprintf(dbg_log, "inopb int32_t 0x%08x\n", sb->fs_inopb); - fprintf(dbg_log, "nspf int32_t 0x%08x\n", + fprintf(dbg_log, "nspf int32_t 0x%08x\n", sb->fs_nspf); - fprintf(dbg_log, "optim int32_t 0x%08x\n", + fprintf(dbg_log, "optim int32_t 0x%08x\n", sb->fs_optim); - fprintf(dbg_log, "npsect int32_t 0x%08x\n", + fprintf(dbg_log, "npsect int32_t 0x%08x\n", sb->fs_npsect); - fprintf(dbg_log, "interleave int32_t 0x%08x\n", + fprintf(dbg_log, "interleave int32_t 0x%08x\n", sb->fs_interleave); - fprintf(dbg_log, "trackskew int32_t 0x%08x\n", + fprintf(dbg_log, "trackskew int32_t 0x%08x\n", sb->fs_trackskew); - fprintf(dbg_log, "id int32_t[2] %08x %08x\n", + fprintf(dbg_log, "id int32_t[2] 0x%08x 0x%08x\n", sb->fs_id[0], sb->fs_id[1]); - fprintf(dbg_log, "csaddr int32_t 0x%08x\n", + fprintf(dbg_log, "ffs1_csaddr int32_t 0x%08x\n", sb->fs_ffs1_csaddr); - fprintf(dbg_log, "cssize int32_t 0x%08x\n", + fprintf(dbg_log, "cssize int32_t 0x%08x\n", sb->fs_cssize); - fprintf(dbg_log, "cgsize int32_t 0x%08x\n", + fprintf(dbg_log, "cgsize int32_t 0x%08x\n", sb->fs_cgsize); - fprintf(dbg_log, "ntrak int32_t 0x%08x\n", + fprintf(dbg_log, "ntrak int32_t 0x%08x\n", sb->fs_ntrak); - fprintf(dbg_log, "nsect int32_t 0x%08x\n", + fprintf(dbg_log, "nsect int32_t 0x%08x\n", sb->fs_nsect); - fprintf(dbg_log, "spc int32_t 0x%08x\n", + fprintf(dbg_log, "spc int32_t 0x%08x\n", sb->fs_spc); - fprintf(dbg_log, "ncyl int32_t 0x%08x\n", + fprintf(dbg_log, "ncyl int32_t 0x%08x\n", sb->fs_ncyl); - fprintf(dbg_log, "cpg int32_t 0x%08x\n", + fprintf(dbg_log, "cpg int32_t 0x%08x\n", sb->fs_cpg); - fprintf(dbg_log, "ipg int32_t 0x%08x\n", + fprintf(dbg_log, "ipg int32_t 0x%08x\n", sb->fs_ipg); - fprintf(dbg_log, "fpg int32_t 0x%08x\n", + fprintf(dbg_log, "fpg int32_t 0x%08x\n", sb->fs_fpg); dbg_dump_csum("internal cstotal", &sb->fs_ffs1_cstotal); - fprintf(dbg_log, "fmod int8_t 0x%02x\n", + fprintf(dbg_log, "fmod int8_t 0x%02x\n", sb->fs_fmod); - fprintf(dbg_log, "clean int8_t 0x%02x\n", + fprintf(dbg_log, "clean int8_t 0x%02x\n", sb->fs_clean); - fprintf(dbg_log, "ronly int8_t 0x%02x\n", + fprintf(dbg_log, "ronly int8_t 0x%02x\n", sb->fs_ronly); - fprintf(dbg_log, "flags int8_t 0x%02x\n", + fprintf(dbg_log, "ffs1_flags int8_t 0x%02x\n", sb->fs_ffs1_flags); - fprintf(dbg_log, "fsmnt u_char[MAXMNTLEN] \"%s\"\n", + fprintf(dbg_log, "fsmnt u_char[MAXMNTLEN] \"%s\"\n", sb->fs_fsmnt); - - fprintf(dbg_log, "cgrotor int32_t 0x%08x\n", + 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, "cpc int32_t 0x%08x\n", + fprintf(dbg_log, "cpc int32_t 0x%08x\n", sb->fs_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); +#ifdef notyet + fprintf(dbg_log, "unrefs int64_t 0x%08llx\n", + sb->fs_unrefs); +#endif + 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 int64_t %10lld\n", + (long long)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 int64_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; j<FSMAXSNAP; j++) { - fprintf(dbg_log, "snapinum int32_t[%2d] 0x%08x\n", + for (j = 0; j < FSMAXSNAP; j++) { + fprintf(dbg_log, "snapinum int32_t[%2d] 0x%08x\n", j, sb->fs_snapinum[j]); - if(!sb->fs_snapinum[j]) { /* list is dense */ + if (!sb->fs_snapinum[j]) { /* list is dense */ break; } } #endif /* FSMAXSNAP */ - fprintf(dbg_log, "contigsumsize int32_t 0x%08x\n", + fprintf(dbg_log, "avgfilesize int32_t 0x%08x\n", + sb->fs_avgfilesize); + fprintf(dbg_log, "avgfpdir int32_t 0x%08x\n", + sb->fs_avgfpdir); +#ifdef notyet + fprintf(dbg_log, "save_cgsize int32_t 0x%08x\n", + sb->fs_save_cgsize); +#endif + 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", + fprintf(dbg_log, "maxsymlinklen int32_t 0x%08x\n", sb->fs_maxsymlinklen); - fprintf(dbg_log, "inodefmt int32_t 0x%08x\n", + fprintf(dbg_log, "inodefmt int32_t 0x%08x\n", sb->fs_inodefmt); - fprintf(dbg_log, "maxfilesize u_int64_t 0x%08x%08x\n", + 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", + 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", + 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", + fprintf(dbg_log, "state int32_t 0x%08x\n", sb->fs_state); - fprintf(dbg_log, "postblformat int32_t 0x%08x\n", + fprintf(dbg_log, "postblformat int32_t 0x%08x\n", sb->fs_postblformat); - fprintf(dbg_log, "nrpos int32_t 0x%08x\n", + fprintf(dbg_log, "nrpos int32_t 0x%08x\n", sb->fs_nrpos); - fprintf(dbg_log, "postbloff int32_t 0x%08x\n", + fprintf(dbg_log, "postbloff int32_t 0x%08x\n", sb->fs_postbloff); - fprintf(dbg_log, "rotbloff int32_t 0x%08x\n", + fprintf(dbg_log, "rotbloff int32_t 0x%08x\n", sb->fs_rotbloff); - fprintf(dbg_log, "magic int32_t 0x%08x\n", + fprintf(dbg_log, "magic int32_t 0x%08x\n", sb->fs_magic); indent--; @@ -326,17 +373,15 @@ 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, "time time_t %10u\n", (unsigned int) - cgr->cg_time); + fprintf(dbg_log, "time int32_t 0x%08x\n", cgr->cg_time); fprintf(dbg_log, "cgx int32_t 0x%08x\n", cgr->cg_cgx); fprintf(dbg_log, "ncyl int16_t 0x%04x\n", cgr->cg_ncyl); fprintf(dbg_log, "niblk int16_t 0x%04x\n", cgr->cg_niblk); @@ -345,7 +390,7 @@ dbg_dump_cg(const char *comment, struct cg *cgr) 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; j<MAXFRAG; j++) { + for (j = 0; j < MAXFRAG; j++) { fprintf(dbg_log, "frsum int32_t[%d] 0x%08x\n", j, cgr->cg_frsum[j]); } @@ -357,10 +402,17 @@ dbg_dump_cg(const char *comment, struct cg *cgr) cgr->cg_nextfreeoff); fprintf(dbg_log, "clustersumoff int32_t 0x%08x\n", cgr->cg_clustersumoff); - fprintf(dbg_log, "clusterof int32_t 0x%08x\n", + 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, "ffs2_niblk int32_t 0x%08x\n", cgr->cg_ffs2_niblk); + fprintf(dbg_log, "initediblk int32_t 0x%08x\n", cgr->cg_initediblk); +#ifdef notyet + fprintf(dbg_log, "unrefs int32_t 0x%08x\n", cgr->cg_unrefs); +#endif + fprintf(dbg_log, "ffs2_time int64_t %10u\n", /* XXX */ + (unsigned int)cgr->cg_initediblk); indent--; fprintf(dbg_log, "===== END CYLINDER GROUP =====\n"); @@ -376,9 +428,8 @@ 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); @@ -395,6 +446,44 @@ dbg_dump_csum(const char *comment, struct csum *cs) return; } +/* ************************************************ dbg_dump_csum_total ***** */ +/* + * Dump a cylinder summary. + */ +void +dbg_dump_csum_total(const char *comment, struct csum_total *cs) +{ + + 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]); +#ifdef notyet + fprintf(dbg_log, "numclusters int64_t 0x%08x%08x\n", + ((unsigned int *)&(cs->cs_numclusters))[1], + ((unsigned int *)&(cs->cs_numclusters))[0]); +#endif + + indent--; + fprintf(dbg_log, "===== END CYLINDER SUMMARY TOTAL =====\n"); + + return; +} /* **************************************************** dbg_dump_inmap ***** */ /* * Dump the inode allocation map in one cylinder group. @@ -402,33 +491,32 @@ dbg_dump_csum(const char *comment, struct csum *cs) void dbg_dump_inmap(struct fs *sb, const char *comment, struct cg *cgr) { - int j,k,l,e; + 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; j<e; j+=32) { - fprintf(dbg_log, "%08x: ", j); - for(k=0; k<32; k+=8) { - if(j+k+8<e) { + cp = (unsigned char *)cg_inosused(cgr); + e = sb->fs_ipg / 8; + for (j = 0; j < e; j += 32) { + fprintf(dbg_log, "0x%08x: ", j); + for (k = 0; k < 32; k += 8) { + if (j + k + 8 < e) { fprintf(dbg_log, "%02x%02x%02x%02x%02x%02x%02x%02x ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } else { - for(l=0; (l<8)&&(j+k+l<e); l++) { + for (l = 0; (l < 8) && (j + k + l < e); l++) { fprintf(dbg_log, "%02x", cp[l]); } } - cp+=8; + cp += 8; } fprintf(dbg_log, "\n"); } @@ -447,33 +535,35 @@ dbg_dump_inmap(struct fs *sb, const char *comment, struct cg *cgr) void dbg_dump_frmap(struct fs *sb, const char *comment, struct cg *cgr) { - int j,k,l,e; + int j, k, l, e; unsigned char *cp; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START FRAGMENT ALLOCATION MAP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment); indent++; - cp=(unsigned char *)cg_blksfree(cgr); - e=howmany((sb->fs_cpg * sb->fs_spc / NSPF(sb)), CHAR_BIT); - for(j=0; j<e; j+=32) { - fprintf(dbg_log, "%08x: ", j); - for(k=0; k<32; k+=8) { - if(j+k+8<e) { + cp = (unsigned char *)cg_blksfree(cgr); + if (sb->fs_nspf) + e = howmany((sb->fs_cpg * sb->fs_spc / sb->fs_nspf), CHAR_BIT); + else + e = 0; + for (j = 0; j < e; j += 32) { + fprintf(dbg_log, "0x%08x: ", j); + for (k = 0; k < 32; k += 8) { + if (j + k + 8 < e) { fprintf(dbg_log, "%02x%02x%02x%02x%02x%02x%02x%02x ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } else { - for(l=0; (l<8)&&(j+k+l<e); l++) { + for (l = 0; (l < 8) && (j + k + l < e); l++) { fprintf(dbg_log, "%02x", cp[l]); } } - cp+=8; + cp += 8; } fprintf(dbg_log, "\n"); } @@ -491,33 +581,34 @@ dbg_dump_frmap(struct fs *sb, const char *comment, struct cg *cgr) void dbg_dump_clmap(struct fs *sb, const char *comment, struct cg *cgr) { - int j,k,l,e; + int j, k, l, e; unsigned char *cp; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START CLUSTER ALLOCATION MAP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment); indent++; - cp=(unsigned char *)cg_clustersfree(cgr); - e=howmany(sb->fs_cpg * sb->fs_spc / NSPB(sb), CHAR_BIT); - for(j=0; j<e; j+=32) { - fprintf(dbg_log, "%08x: ", j); - for(k=0; k<32; k+=8) { - if(j+k+8<e) { + cp = (unsigned char *)cg_clustersfree(cgr); + if (sb->fs_nspf) + e = howmany(sb->fs_cpg * sb->fs_spc / (sb->fs_nspf << sb->fs_fragshift), CHAR_BIT); + else + e = 0; + for (j = 0; j < e; j += 32) { + fprintf(dbg_log, "0x%08x: ", j); + for (k = 0; k < 32; k += 8) { + if (j + k + 8 < e) { fprintf(dbg_log, "%02x%02x%02x%02x%02x%02x%02x%02x ", cp[0], cp[1], cp[2], cp[3], cp[4], cp[5], cp[6], cp[7]); } else { - for(l=0; (l<8)&&(j+k+l<e); l++) { + for (l = 0; (l < 8) && (j + k + l < e); l++) fprintf(dbg_log, "%02x", cp[l]); - } } - cp+=8; + cp += 8; } fprintf(dbg_log, "\n"); } @@ -538,16 +629,15 @@ dbg_dump_clsum(struct fs *sb, const char *comment, struct cg *cgr) int j; int *ip; - if(!dbg_log) { + if (!dbg_log) return; - } fprintf(dbg_log, "===== START CLUSTER SUMMARY =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)cgr, comment); indent++; - ip=(int *)cg_clustersum(cgr); - for(j=0; j<=sb->fs_contigsumsize; j++) { + ip = (int *)cg_clustersum(cgr); + for (j = 0; j <= sb->fs_contigsumsize; j++) { fprintf(dbg_log, "%02d: %8d\n", j, *ip++); } @@ -557,6 +647,14 @@ dbg_dump_clsum(struct fs *sb, const char *comment, struct cg *cgr) 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. @@ -564,24 +662,23 @@ dbg_dump_clsum(struct fs *sb, const char *comment, struct cg *cgr) void dbg_dump_sptbl(struct fs *sb, const char *comment, struct cg *cgr) { - int j,k; + 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; j<sb->fs_cpg; j++) { + ip = (int *)cg_blktot(cgr); + for (j = 0; j < sb->fs_cpg; j++) { fprintf(dbg_log, "%2d: %5d = ", j, *ip++); - for(k=0; k<sb->fs_nrpos; k++) { + for (k = 0; k < sb->fs_nrpos; k++) { fprintf(dbg_log, "%4d", cg_blks(sb, cgr, j)[k]); - if(k<sb->fs_nrpos-1) { + if (k < sb->fs_nrpos - 1) { fprintf(dbg_log, " + "); } } @@ -593,10 +690,11 @@ dbg_dump_sptbl(struct fs *sb, const char *comment, struct cg *cgr) return; } +#endif /* ****************************************************** dbg_dump_ino ***** */ /* - * Dump an inode structure. + * Dump an UFS1 inode structure. */ void dbg_dump_ino(struct fs *sb, const char *comment, struct ufs1_dinode *ino) @@ -604,11 +702,10 @@ dbg_dump_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 INODE DUMP =====\n"); + fprintf(dbg_log, "===== START UFS1 INODE DUMP =====\n"); fprintf(dbg_log, "# %d@%lx: %s\n", indent, (unsigned long)ino, comment); indent++; @@ -620,33 +717,32 @@ dbg_dump_ino(struct fs *sb, const char *comment, struct ufs1_dinode *ino) 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, "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 int32_t[%x] 0x%08x\n", ictr, ino->di_db[ictr]); } remaining_blocks-=NDADDR; - if(remaining_blocks>0) { + if (remaining_blocks > 0) { fprintf(dbg_log, "ib int32_t[0] 0x%08x\n", ino->di_ib[0]); } - remaining_blocks-=howmany(sb->fs_bsize, sizeof(int32_t)); - if(remaining_blocks>0) { + remaining_blocks -= howmany(sb->fs_bsize, sizeof(int32_t)); + if (remaining_blocks > 0) { fprintf(dbg_log, "ib int32_t[1] 0x%08x\n", ino->di_ib[1]); } #define SQUARE(a) ((a)*(a)) - remaining_blocks-=SQUARE(howmany(sb->fs_bsize, sizeof(ufs_daddr_t))); + remaining_blocks -= SQUARE(howmany(sb->fs_bsize, sizeof(int32_t))); #undef SQUARE - if(remaining_blocks>0) { + if (remaining_blocks > 0) { fprintf(dbg_log, "ib int32_t[2] 0x%08x\n", ino->di_ib[2]); } @@ -658,7 +754,79 @@ dbg_dump_ino(struct fs *sb, const char *comment, struct ufs1_dinode *ino) fprintf(dbg_log, "gid u_int32_t 0x%08x\n", ino->di_gid); indent--; - fprintf(dbg_log, "===== END INODE DUMP =====\n"); + 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) + 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]); + 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++) { + fprintf(dbg_log, "db daddr64_t[%x] 0x%16jx\n", ictr, + ino->di_db[ictr]); + } + remaining_blocks -= NDADDR; + if (remaining_blocks > 0) { + fprintf(dbg_log, "ib daddr64_t[0] 0x%16jx\n", + ino->di_ib[0]); + } + remaining_blocks -= howmany(sb->fs_bsize, sizeof(daddr64_t)); + if (remaining_blocks > 0) { + fprintf(dbg_log, "ib daddr64_t[1] 0x%16jx\n", + ino->di_ib[1]); + } +#define SQUARE(a) ((a)*(a)) + remaining_blocks -= SQUARE(howmany(sb->fs_bsize, sizeof(daddr64_t))); +#undef SQUARE + if (remaining_blocks > 0) { + fprintf(dbg_log, "ib daddr64_t[2] 0x%16jx\n", + ino->di_ib[2]); + } + + indent--; + fprintf(dbg_log, "===== END UFS2 INODE DUMP =====\n"); return; } @@ -671,24 +839,26 @@ dbg_dump_ino(struct fs *sb, const char *comment, struct ufs1_dinode *ino) void dbg_dump_iblk(struct fs *sb, const char *comment, char *block, size_t length) { - unsigned int *mem; - int i, j; + 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++; - mem=(unsigned int *)block; - for (i=0; (size_t)i<MIN(howmany(sb->fs_bsize, sizeof(ufs_daddr_t)), - length); i+=8) { + if (sb->fs_magic == FS_UFS1_MAGIC) + size = sizeof(int32_t); + else + size = sizeof(int64_t); + + 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)<length) { + for (j = 0; j < 8; j++) { + if ((size_t)(i + j) < length) { fprintf(dbg_log, "%08X ", *mem++); } } @@ -702,4 +872,3 @@ dbg_dump_iblk(struct fs *sb, const char *comment, char *block, size_t length) } #endif /* FS_DEBUG */ - diff --git a/sbin/growfs/debug.h b/sbin/growfs/debug.h index d788f905b52..f6556b79c22 100644 --- a/sbin/growfs/debug.h +++ b/sbin/growfs/debug.h @@ -1,12 +1,12 @@ -/* $OpenBSD: debug.h,v 1.3 2003/08/25 23:28:15 tedu Exp $ */ +/* $OpenBSD: debug.h,v 1.4 2007/07/07 08:22:55 millert Exp $ */ /* * 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: @@ -23,7 +23,7 @@ * 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 @@ -37,24 +37,21 @@ * SUCH DAMAGE. * * $TSHeader: src/sbin/growfs/debug.h,v 1.2 2000/11/16 18:43:50 tom Exp $ - * $FreeBSD: src/sbin/growfs/debug.h,v 1.1 2000/12/09 15:27:35 tomsoft Exp $ + * $FreeBSD: src/sbin/growfs/debug.h,v 1.3 2004/07/06 17:48:34 stefanf Exp $ * */ #ifdef FS_DEBUG -/* ********************************************************** INCLUDES ***** */ -#include <sys/param.h> - -#include <ufs/ufs/dinode.h> - void dbg_open(const char *); void dbg_close(void); void dbg_dump_hex(struct fs *, const char *, unsigned char *); void dbg_dump_fs(struct fs *, const char *); void dbg_dump_cg(const char *, struct cg *); void dbg_dump_csum(const char *, struct csum *); -void dbg_dump_ino(struct fs *, const char *, struct ufs1_dinode *); +void dbg_dump_csum_total(const char *, struct csum_total *); +void dbg_dump_ufs1_ino(struct fs *, const char *, struct ufs1_dinode *); +void dbg_dump_ufs2_ino(struct fs *, const char *, struct ufs2_dinode *); void dbg_dump_iblk(struct fs *, const char *, char *, size_t); void dbg_dump_inmap(struct fs *, const char *, struct cg *); void dbg_dump_frmap(struct fs *, const char *, struct cg *); @@ -68,19 +65,23 @@ void dbg_dump_sptbl(struct fs *, const char *, struct cg *); #define DBG_DUMP_FS(F,C) dbg_dump_fs((F),(C)) #define DBG_DUMP_CG(F,C,M) dbg_dump_cg((C),(M)) #define DBG_DUMP_CSUM(F,C,M) dbg_dump_csum((C),(M)) -#define DBG_DUMP_INO(F,C,M) dbg_dump_ino((F),(C),(M)) +#define DBG_DUMP_INO(F,C,M) (F)->fs_magic == FS_UFS1_MAGIC \ + ? dbg_dump_ufs1_ino((F),(C),(struct ufs1_dinode *)(M)) \ + : dbg_dump_ufs2_ino((F),(C),(struct ufs2_dinode *)(M)) #define DBG_DUMP_IBLK(F,C,M,L) dbg_dump_iblk((F),(C),(M),(L)) #define DBG_DUMP_INMAP(F,C,M) dbg_dump_inmap((F),(C),(M)) #define DBG_DUMP_FRMAP(F,C,M) dbg_dump_frmap((F),(C),(M)) #define DBG_DUMP_CLMAP(F,C,M) dbg_dump_clmap((F),(C),(M)) #define DBG_DUMP_CLSUM(F,C,M) dbg_dump_clsum((F),(C),(M)) +#ifdef NOT_CURRENTLY #define DBG_DUMP_SPTBL(F,C,M) dbg_dump_sptbl((F),(C),(M)) +#endif #define DL_TRC 0x01 #define DL_INFO 0x02 extern int _dbg_lvl_; -#define DBG_FUNC(N) char __FKT__[] = (N); +#define DBG_FUNC(N) char __FKT__[] = {N}; #define DBG_ENTER if(_dbg_lvl_ & DL_TRC) { \ fprintf(stderr, "~>%s: %s\n", __FILE__, __FKT__ ); \ } diff --git a/sbin/growfs/growfs.8 b/sbin/growfs/growfs.8 index 3b78f88ede3..0fab66ef780 100644 --- a/sbin/growfs/growfs.8 +++ b/sbin/growfs/growfs.8 @@ -1,4 +1,4 @@ -.\" $OpenBSD: growfs.8,v 1.8 2007/05/31 19:19:44 jmc Exp $ +.\" $OpenBSD: growfs.8,v 1.9 2007/07/07 08:22:55 millert Exp $ .\" Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz .\" Copyright (c) 1980, 1989, 1993 The Regents of the University of California. .\" All rights reserved. @@ -36,9 +36,9 @@ .\" SUCH DAMAGE. .\" .\" $TSHeader: src/sbin/growfs/growfs.8,v 1.3 2000/12/12 19:31:00 tomsoft Exp $ -.\" $FreeBSD: src/sbin/growfs/growfs.8,v 1.18 2002/12/12 17:25:55 ru Exp $ +.\" $FreeBSD: src/sbin/growfs/growfs.8,v 1.24 2005/01/18 10:09:34 ru Exp $ .\" -.Dd $Mdocdate: May 31 2007 $ +.Dd $Mdocdate: July 7 2007 $ .Dt GROWFS 8 .Os .Sh NAME @@ -66,8 +66,8 @@ utility extends the size of the file system on the specified special file. Currently .Nm can only enlarge unmounted file systems. -Do not try enlarging a mounted file system \- your system may panic and you will -not be able to use the file system any longer. +Do not try enlarging a mounted file system \- your system may panic and +you will not be able to use the file system any longer. Most of the .Xr newfs 8 options cannot be changed by diff --git a/sbin/growfs/growfs.c b/sbin/growfs/growfs.c index 5baaf04b04a..bb827808e98 100644 --- a/sbin/growfs/growfs.c +++ b/sbin/growfs/growfs.c @@ -1,4 +1,4 @@ -/* $OpenBSD: growfs.c,v 1.20 2007/06/01 19:26:06 deraadt Exp $ */ +/* $OpenBSD: growfs.c,v 1.21 2007/07/07 08:22:55 millert Exp $ */ /* * Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz * Copyright (c) 1980, 1989, 1993 The Regents of the University of California. @@ -37,6 +37,7 @@ * SUCH DAMAGE. * * $TSHeader: src/sbin/growfs/growfs.c,v 1.5 2000/12/12 19:31:00 tomsoft Exp $ + * $FreeBSD: src/sbin/growfs/growfs.c,v 1.25 2006/07/17 20:48:36 stefanf Exp $ * */ @@ -45,8 +46,6 @@ static const char copyright[] = "@(#) Copyright (c) 2000 Christoph Herrmann, Thomas-Henning von Kamptz\n\ Copyright (c) 1980, 1989, 1993 The Regents of the University of California.\n\ All rights reserved.\n"; - -static const char rcsid[] = "$OpenBSD: growfs.c,v 1.20 2007/06/01 19:26:06 deraadt Exp $"; #endif /* not lint */ /* ********************************************************** INCLUDES ***** */ @@ -60,8 +59,11 @@ static const char rcsid[] = "$OpenBSD: growfs.c,v 1.20 2007/06/01 19:26:06 deraa #include <ctype.h> #include <err.h> #include <fcntl.h> +#include <limits.h> #include <stdlib.h> +#include <stdint.h> #include <string.h> +#include <time.h> #include <unistd.h> #include <util.h> @@ -70,20 +72,29 @@ static const char rcsid[] = "$OpenBSD: growfs.c,v 1.20 2007/06/01 19:26:06 deraa #include "debug.h" +#define rounddown(x, y) (((x)/(y))*(y)) +#define roundup(x, y) ((((x)+((y)-1))/(y))*(y)) + /* *************************************************** GLOBALS & TYPES ***** */ #ifdef FS_DEBUG int _dbg_lvl_ = (DL_INFO); /* DL_TRC */ #endif /* FS_DEBUG */ -int quiet = 0; /* quiet flag */ +static int quiet; /* quiet flag */ static union { struct fs fs; - char pad[SBSIZE]; + 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 daddr64_t sblockloc; + static union { struct cg cg; char pad[MAXBSIZE]; @@ -92,24 +103,25 @@ static union { #define aocg cgun2.cg /* an old cylinder group */ static char ablk[MAXBSIZE]; /* a block */ -static char i1blk[MAXBSIZE]; /* some indirect blocks */ -static char i2blk[MAXBSIZE]; -static char i3blk[MAXBSIZE]; - - /* where to write back updated blocks */ -static daddr_t in_src, i1_src, i2_src, i3_src; - - /* what object contains the reference */ -enum pointer_source { - GFS_PS_INODE, - GFS_PS_IND_BLK_LVL1, - GFS_PS_IND_BLK_LVL2, - GFS_PS_IND_BLK_LVL3 -}; -static struct csum *fscs; /* cylinder summary */ +static struct csum *fscs; /* cylinder summary */ -static struct ufs1_dinode zino[MAXBSIZE / sizeof(struct ufs1_dinode)]; /* some inodes */ +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 daddr64_t inoblk; /* inode block address */ +static char inobuf[MAXBSIZE]; /* inode block */ +ino_t maxino; /* last valid inode */ /* * An array of elements of type struct gfs_bpp describes all blocks to @@ -117,8 +129,8 @@ static struct ufs1_dinode zino[MAXBSIZE / sizeof(struct ufs1_dinode)]; /* some i * summary for all cylinder groups located in the first cylinder group. */ struct gfs_bpp { - daddr_t old; /* old block number */ - daddr_t new; /* new block number */ + daddr64_t old; /* old block number */ + daddr64_t new; /* new block number */ #define GFS_FL_FIRST 1 #define GFS_FL_LAST 2 unsigned int flags; /* special handling required */ @@ -126,10 +138,10 @@ struct gfs_bpp { }; /* ******************************************************** PROTOTYPES ***** */ -static void growfs(char *, int, int, unsigned int); -static void rdfs(daddr_t, size_t, void *, int); -static void wtfs(daddr_t, size_t, void *, int, unsigned int); -static daddr_t alloc(void); +static void growfs(int, int, unsigned int); +static void rdfs(daddr64_t, size_t, void *, int); +static void wtfs(daddr64_t, size_t, void *, int, unsigned int); +static daddr64_t alloc(void); static int charsperline(void); static void usage(void); static int isblock(struct fs *, unsigned char *, int); @@ -140,12 +152,15 @@ 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 struct ufs1_dinode *ginode(ino_t, int, int); -static void frag_adjust(daddr_t, int); -static void cond_bl_upd(int32_t *, struct gfs_bpp *, - enum pointer_source, int, unsigned int); +static union dinode *ginode(ino_t, int, int); +static void frag_adjust(daddr64_t, int); +static int cond_bl_upd(daddr64_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(daddr64_t, daddr64_t, daddr64_t, daddr64_t, + struct gfs_bpp *, int, int, unsigned int); +static void ffs1_sb_update(struct fs *, daddr64_t); /* ************************************************************ growfs ***** */ /* @@ -160,7 +175,7 @@ static void updrefs(int, ino_t, struct gfs_bpp *, int, int, unsigned int); * copies. */ static void -growfs(char *fsys, int fsi, int fso, unsigned int Nflag) +growfs(int fsi, int fso, unsigned int Nflag) { DBG_FUNC("growfs") int i; @@ -180,9 +195,9 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) if (fscs == NULL) errx(1, "calloc failed"); for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) { - rdfs(fsbtodb(&osblock, osblock.fs_ffs1_csaddr + + rdfs(fsbtodb(&osblock, osblock.fs_csaddr + numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i, - osblock.fs_bsize), (((char *)fscs) + i), fsi); + osblock.fs_bsize), (void *)(((char *)fscs)+i), fsi); } #ifdef FS_DEBUG @@ -195,9 +210,7 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) for (dbg_csc = 0; dbg_csc < osblock.fs_ncg; dbg_csc++) { snprintf(dbg_line, sizeof(dbg_line), "%d. old csum in old location", dbg_csc); - DBG_DUMP_CSUM(&osblock, - dbg_line, - dbg_csp++); + DBG_DUMP_CSUM(&osblock, dbg_line, dbg_csp++); } } #endif /* FS_DEBUG */ @@ -211,15 +224,16 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) /* * Dump out summary information about filesystem. */ - printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", - fsys, sblock.fs_ffs1_size * NSPF(&sblock), sblock.fs_ncyl, - "cylinders", sblock.fs_ntrak, sblock.fs_nsect); #define B2MBFACTOR (1 / (1024.0 * 1024.0)) - printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)\n", - (float)sblock.fs_ffs1_size * sblock.fs_fsize * B2MBFACTOR, - sblock.fs_ncg, sblock.fs_cpg, - (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, - sblock.fs_ipg); + printf("growfs: %.1fMB (%jd sectors) block size %d, fragment size %d\n", + (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, + (intmax_t)fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize, + sblock.fs_fsize); + printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n", + sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, + sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg); + if (sblock.fs_flags & FS_DOSOFTDEP) + printf("\twith soft updates\n"); #undef B2MBFACTOR /* @@ -227,7 +241,7 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) * then print out indices of cylinder groups. */ if (!quiet) - printf("superblock backups (for fsck -b #) at:\n"); + printf("super-block backups (for fsck -b #) at:\n"); i = 0; width = charsperline(); @@ -238,11 +252,11 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) initcg(cylno, utime, fso, Nflag); if (quiet) continue; - j = snprintf(tmpbuf, sizeof tmpbuf, " %d%s", - (int)fsbtodb(&sblock, cgsblock(&sblock, cylno)), + j = snprintf(tmpbuf, sizeof(tmpbuf), " %d%s", + fsbtodb(&sblock, cgsblock(&sblock, cylno)), cylno < (sblock.fs_ncg - 1) ? "," : ""); - if (j >= sizeof tmpbuf) - j = sizeof tmpbuf - 1; + if (j >= sizeof(tmpbuf)) + j = sizeof(tmpbuf) - 1; if (j == -1 || i + j >= width) { printf("\n"); i = 0; @@ -264,9 +278,9 @@ growfs(char *fsys, int fsi, int fso, unsigned int 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_ffs1_csaddr + numfrags(&sblock, i)), + wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), (size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize), - (((char *)fscs) + i), fso, Nflag); + (void *)(((char *)fscs) + i), fso, Nflag); } DBG_PRINT0("fscs written\n"); @@ -285,15 +299,25 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) } #endif /* FS_DEBUG */ - /* Force update on next mount */ - sblock.fs_ffs1_flags &= ~FS_FLAGS_UPDATED; - /* * Now write the new superblock back to disk. */ - sblock.fs_ffs1_time = utime; - wtfs((daddr_t)(SBOFF / DEV_BSIZE), (size_t)SBSIZE, &sblock, - fso, Nflag); + sblock.fs_time = utime; + if (sblock.fs_magic == FS_UFS1_MAGIC) { + sblock.fs_ffs1_time = (int32_t)sblock.fs_time; + sblock.fs_ffs1_size = (int32_t)sblock.fs_size; + sblock.fs_ffs1_dsize = (int32_t)sblock.fs_dsize; + sblock.fs_ffs1_csaddr = (int32_t)sblock.fs_csaddr; + sblock.fs_ffs1_cstotal.cs_ndir = + (int32_t)sblock.fs_cstotal.cs_ndir; + sblock.fs_ffs1_cstotal.cs_nbfree = + (int32_t)sblock.fs_cstotal.cs_nbfree; + sblock.fs_ffs1_cstotal.cs_nifree = + (int32_t)sblock.fs_cstotal.cs_nifree; + sblock.fs_ffs1_cstotal.cs_nffree = + (int32_t)sblock.fs_cstotal.cs_nffree; + } + wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag); DBG_PRINT0("sblock written\n"); DBG_DUMP_FS(&sblock, "new initial sblock"); @@ -305,8 +329,10 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) sblock.fs_ronly = 0; sblock.fs_cgrotor = 0; sblock.fs_state = 0; - memset(&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt)); - sblock.fs_ffs1_flags &= FS_DOSOFTDEP; + memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt)); + sblock.fs_flags &= FS_DOSOFTDEP; + if (sblock.fs_magic == FS_UFS1_MAGIC) + sblock.fs_ffs1_flags &= FS_DOSOFTDEP; /* * XXX @@ -318,7 +344,7 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) * fs_maxbpg * fs_minfree, * fs_optim - * fs_ffs1_flags regarding SOFTUPDATES + * fs_flags regarding SOFTPDATES * * We probably should rather change the summary for the cylinder group * statistics here to the value of what would be in there, if the file @@ -334,7 +360,7 @@ growfs(char *fsys, int fsi, int fso, unsigned int Nflag) */ for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), - (size_t)SBSIZE, &sblock, fso, Nflag); + (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag); } DBG_PRINT0("sblock copies written\n"); DBG_DUMP_FS(&sblock, "new other sblocks"); @@ -353,88 +379,106 @@ static void initcg(int cylno, time_t utime, int fso, unsigned int Nflag) { DBG_FUNC("initcg") - daddr_t cbase, d, dlower, dupper, dmax, blkno; - int i; + static char *iobuf; + daddr64_t d, dlower, dupper, blkno, start; + daddr64_t i, cbase, dmax; + struct ufs1_dinode *dp1; + struct ufs2_dinode *dp2; struct csum *cs; - int j; + ino_t j; + size_t iobufsize; - DBG_ENTER; + if (sblock.fs_bsize < SBLOCKSIZE) + iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize; + else + iobufsize = 4 * sblock.fs_bsize; + + if (iobuf == NULL && (iobuf = malloc(iobufsize)) == NULL) + errx(37, "panic: cannot allocate I/O buffer"); + bzero(iobuf, iobufsize); /* * Determine block bounds for cylinder group. + * Allow space for super block summary information in first + * cylinder group. */ cbase = cgbase(&sblock, cylno); dmax = cbase + sblock.fs_fpg; - if (dmax > sblock.fs_ffs1_size) - dmax = sblock.fs_ffs1_size; + if (dmax > 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, (size_t)sblock.fs_cgsize); - acg.cg_time = utime; + cs = &fscs[cylno]; + memset(&acg, 0, sblock.fs_cgsize); + acg.cg_ffs2_time = utime; acg.cg_magic = CG_MAGIC; acg.cg_cgx = cylno; - if (cylno == sblock.fs_ncg - 1) - acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; - else - acg.cg_ncyl = sblock.fs_cpg; - acg.cg_niblk = sblock.fs_ipg; + acg.cg_ffs2_niblk = sblock.fs_ipg; + acg.cg_initediblk = MIN(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; - acg.cg_btotoff = sizeof(struct cg); - acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t); - acg.cg_iusedoff = acg.cg_boff + - sblock.fs_cpg * sblock.fs_nrpos * sizeof(u_int16_t); - acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); - if (sblock.fs_contigsumsize <= 0) { - acg.cg_nextfreeoff = acg.cg_freeoff + - howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY); + start = sizeof(struct cg); + if (sblock.fs_magic == FS_UFS2_MAGIC) { + acg.cg_iusedoff = start; } else { - acg.cg_clustersumoff = acg.cg_freeoff + howmany - (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - - sizeof(u_int32_t); + if (cylno == sblock.fs_ncg - 1) + acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; + else + acg.cg_ncyl = sblock.fs_cpg; + acg.cg_time = (int32_t)acg.cg_ffs2_time; + acg.cg_ffs2_time = 0; + acg.cg_niblk = (int16_t)acg.cg_ffs2_niblk; + acg.cg_ffs2_niblk = 0; + acg.cg_initediblk = 0; + acg.cg_btotoff = start; + acg.cg_boff = acg.cg_btotoff + + sblock.fs_cpg * sizeof(int32_t); + acg.cg_iusedoff = acg.cg_boff + + sblock.fs_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_clustersumoff, sizeof(u_int32_t)); + 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 - (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); + acg.cg_nextfreeoff = acg.cg_clusteroff + + howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT); } - if (acg.cg_nextfreeoff-(int)(&acg.cg_firstfield) > sblock.fs_cgsize) { + if (acg.cg_nextfreeoff > sblock.fs_cgsize) { /* - * XXX This should never happen as we would have had that panic + * This should never happen as we would have had that panic * already on filesystem creation */ errx(37, "panic: cylinder group too big"); } acg.cg_cs.cs_nifree += sblock.fs_ipg; - if (cylno == 0) - for (i = 0; (size_t)i < ROOTINO; i++) { + if (cylno == 0) { + for (i = 0; i < ROOTINO; i++) { setbit(cg_inosused(&acg), i); acg.cg_cs.cs_nifree--; } - for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) { - for (j = 0; (unsigned)j < sblock.fs_bsize / sizeof(struct ufs1_dinode); j++) - zino[j].di_gen = arc4random(); - wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), - (size_t)sblock.fs_bsize, zino, fso, Nflag); } - 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); + 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++; } - acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]++; + sblock.fs_dsize += dlower; } - sblock.fs_ffs1_dsize += dlower; - sblock.fs_ffs1_dsize += acg.cg_ndblk - dupper; + 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++) { @@ -442,21 +486,17 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag) acg.cg_cs.cs_nffree++; } } - for (d = dupper; d + sblock.fs_frag <= dmax - cbase;) { + for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk; + d += sblock.fs_frag) { blkno = d / sblock.fs_frag; setblock(&sblock, cg_blksfree(&acg), blkno); - if (sblock.fs_contigsumsize > 0) { + if (sblock.fs_contigsumsize > 0) setbit(cg_clustersfree(&acg), blkno); - } acg.cg_cs.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]++; - d += sblock.fs_frag; - } - if (d < dmax - cbase) { - acg.cg_frsum[dmax - cbase - d]++; - for (; d < dmax - cbase; d++) { + } + 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++; } @@ -477,7 +517,7 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag) sump[run]++; run = 0; } - if ((i & (NBBY - 1)) != (NBBY - 1)) + if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1) bit <<= 1; else { map = *mapp++; @@ -485,19 +525,53 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag) } } if (run != 0) { - if (run > sblock.fs_contigsumsize) { + if (run > sblock.fs_contigsumsize) run = sblock.fs_contigsumsize; - } sump[run]++; } } - sblock.fs_ffs1_cstotal.cs_ndir += acg.cg_cs.cs_ndir; - sblock.fs_ffs1_cstotal.cs_nffree += acg.cg_cs.cs_nffree; - sblock.fs_ffs1_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; - sblock.fs_ffs1_cstotal.cs_nifree += acg.cg_cs.cs_nifree; + 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; - wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), - (size_t)sblock.fs_bsize, &acg, fso, Nflag); + + /* + * Write out the duplicate superblock, the cylinder group map + * and two blocks worth of inodes in a single write. + */ + bcopy(&sblock, iobuf, SBLOCKSIZE); + start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE; + bcopy(&acg, &iobuf[start], sblock.fs_cgsize); + start += sblock.fs_bsize; + dp1 = (struct ufs1_dinode *)&iobuf[start]; + dp2 = (struct ufs2_dinode *)&iobuf[start]; + for (i = MIN(sblock.fs_ipg, 2 * INOPB(&sblock)); i != 0; i--) { + if (sblock.fs_magic == FS_UFS1_MAGIC) { + dp1->di_gen = arc4random(); + dp1++; + } else { + dp2->di_gen = arc4random(); + dp2++; + } + } + wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, + iobuf, fso, Nflag); + + /* Initialize inodes for FFS1. */ + if (sblock.fs_magic == FS_UFS1_MAGIC) { + for (i = 2 * sblock.fs_frag; i < sblock.fs_ipg / INOPF(&sblock); + i += sblock.fs_frag) { + dp1 = (struct ufs1_dinode *)&iobuf[start]; + for (j = 0; j < INOPB(&sblock); j++) { + dp1->di_gen = arc4random(); + dp1++; + } + wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), + (size_t)sblock.fs_bsize, &iobuf[start], fso, Nflag); + } + } + DBG_DUMP_CG(&sblock, "new cg", &acg); DBG_LEAVE; @@ -508,10 +582,10 @@ initcg(int cylno, time_t utime, int fso, unsigned int Nflag) * 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 an rather complex operation. + * statistic, which seems to be otherwise a rather complex operation. */ static void -frag_adjust(daddr_t frag, int sign) +frag_adjust(daddr64_t frag, int sign) { DBG_FUNC("frag_adjust") int fragsize; @@ -524,21 +598,22 @@ frag_adjust(daddr_t frag, int sign) * Here frag only needs to point to any fragment in the block we want * to examine. */ -#define rounddown(x, y) (((x)/(y))*(y)) for (f = rounddown(frag, sblock.fs_frag); - f < roundup(frag + 1, sblock.fs_frag); f++) { + f < roundup(frag + 1, sblock.fs_frag); + f++) { /* * Count contiguous free fragments. */ - if (isset(cg_blksfree(&acg), f)) + if (isset(cg_blksfree(&acg), f)) { fragsize++; - else { + } else { if (fragsize && fragsize < sblock.fs_frag) { /* * We found something in between. */ - acg.cg_frsum[fragsize]+=sign; - DBG_PRINT2("frag_adjust [%d]+=%d\n", fragsize, sign); + acg.cg_frsum[fragsize] += sign; + DBG_PRINT2("frag_adjust [%d]+=%d\n", fragsize, + sign); } fragsize = 0; } @@ -547,7 +622,7 @@ frag_adjust(daddr_t frag, int sign) /* * We found something. */ - acg.cg_frsum[fragsize]+=sign; + acg.cg_frsum[fragsize] += sign; DBG_PRINT2("frag_adjust [%d]+=%d\n", fragsize, sign); } DBG_PRINT2("frag_adjust [[%d]]+=%d\n", fragsize, sign); @@ -558,75 +633,60 @@ frag_adjust(daddr_t frag, int sign) /* ******************************************************* cond_bl_upd ***** */ /* * Here we conditionally update a pointer to a fragment. We check for all - * relocated blocks if any of it's fragments is referenced by the current + * relocated blocks if any of its fragments is referenced by the current * field, and update the pointer to the respective fragment in our new * block. If we find a reference we write back the block immediately, * as there is no easy way for our general block reading engine to figure * out if a write back operation is needed. */ -static void -cond_bl_upd(int32_t *block, struct gfs_bpp *field, - enum pointer_source source, int fso, unsigned int Nflag) +static int +cond_bl_upd(daddr64_t *block, struct gfs_bpp *field, int fsi, int fso, + unsigned int Nflag) { DBG_FUNC("cond_bl_upd") struct gfs_bpp *f; - char *src; - daddr_t dst = 0; + daddr64_t src, dst; + int fragnum; + void *ibuf; DBG_ENTER; - f = field; - while (f->old) { /* for all old blocks */ - if (*block/sblock.fs_frag == f->old) { - /* - * The fragment is part of the block, so update. - */ - *block = (f->new * sblock.fs_frag + (*block % sblock.fs_frag)); - f->found++; - DBG_PRINT3("scg (%d->%d)[%d] reference updated\n", - f->old, f->new, *block % sblock.fs_frag); - - /* Write the block back to disk immediately */ - switch (source) { - case GFS_PS_INODE: - src = ablk; - dst = in_src; - break; - case GFS_PS_IND_BLK_LVL1: - src = i1blk; - dst = i1_src; - break; - case GFS_PS_IND_BLK_LVL2: - src = i2blk; - dst = i2_src; - break; - case GFS_PS_IND_BLK_LVL3: - src = i3blk; - dst = i3_src; - break; - default: /* error */ - src = NULL; - break; - } - if (src) { - /* - * XXX If src is not of type inode we have to - * implement copy on write here in case - * of active snapshots. - */ - wtfs(dst, (size_t)sblock.fs_bsize, src, - fso, Nflag); - } + for (f = field; f->old != 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); - /* - * The same block can't be found again in this loop. - */ - break; - } - f++; + /* + * Copy the block back immediately. + * + * XXX If src is 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 ***** */ @@ -645,7 +705,7 @@ static void updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) { DBG_FUNC("updjcg") - daddr_t cbase, dmax, dupper; + daddr64_t cbase, dmax, dupper; struct csum *cs; int i, k; int j = 0; @@ -657,27 +717,28 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) * a copy. */ rdfs(fsbtodb(&osblock, cgtod(&osblock, cylno)), - (size_t)osblock.fs_cgsize, &aocg, fsi); + (size_t)osblock.fs_cgsize, (void *)&aocg, fsi); DBG_PRINT0("jcg read\n"); DBG_DUMP_CG(&sblock, "old joining cg", &aocg); memcpy(&cgun1, &cgun2, sizeof(cgun2)); /* - * If the cylinder group had already it's new final size almost + * 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_ffs1_size) { - acg.cg_ncyl = sblock.fs_cpg; + if (cgbase(&osblock, cylno+1) == osblock.fs_size) { + if (sblock.fs_magic == FS_UFS1_MAGIC) + acg.cg_ncyl = sblock.fs_cpg; wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), - (size_t)sblock.fs_cgsize, &acg, fso, Nflag); + (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); DBG_PRINT0("jcg written\n"); DBG_DUMP_CG(&sblock, "new joining cg", &acg); + DBG_LEAVE; return; } @@ -687,10 +748,10 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) */ cbase = cgbase(&sblock, cylno); dmax = cbase + sblock.fs_fpg; - if (dmax > sblock.fs_ffs1_size) - dmax = sblock.fs_ffs1_size; + 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); /* @@ -703,18 +764,24 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) * needed, update the free space in the superblock. */ acg.cg_time = utime; - if (cylno == sblock.fs_ncg - 1) { - /* - * This is still the last cylinder group. - */ - acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; - } else { - acg.cg_ncyl = sblock.fs_cpg; + if (sblock.fs_magic == FS_UFS1_MAGIC) { + if (cylno == sblock.fs_ncg - 1) { + /* + * This is still the last cylinder group. + */ + acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; + } else { + acg.cg_ncyl = sblock.fs_cpg; + } } - DBG_PRINT4("jcg dbg: %d %u %d %u\n", cylno, sblock.fs_ncg, acg.cg_ncyl, - sblock.fs_cpg); + 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_ncyl, sblock.fs_cpg); +#endif + DBG_PRINT0("\n"); acg.cg_ndblk = dmax - cbase; - sblock.fs_ffs1_dsize += acg.cg_ndblk - aocg.cg_ndblk; + sblock.fs_dsize += acg.cg_ndblk-aocg.cg_ndblk; if (sblock.fs_contigsumsize > 0) acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; @@ -730,15 +797,15 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) * Handle the first new block here if it was partially available * before. */ - if (osblock.fs_ffs1_size % sblock.fs_frag) { - if (roundup(osblock.fs_ffs1_size, sblock.fs_frag)<=sblock.fs_ffs1_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_ffs1_size - cbase, sblock.fs_frag)-1; - i >= osblock.fs_ffs1_size - cbase; i--) { + 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++; @@ -750,21 +817,18 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) * filesystem. */ if (isblock(&sblock, cg_blksfree(&acg), - ((osblock.fs_ffs1_size - cgbase(&sblock, cylno))/ + ((osblock.fs_size - cgbase(&sblock, cylno))/ sblock.fs_frag))) { /* - * The block is now completely available + * The block is now completely available. */ DBG_PRINT0("block was\n"); - acg.cg_frsum[osblock.fs_ffs1_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_ffs1_size - cbase, + k = rounddown(osblock.fs_size-cbase, sblock.fs_frag); - cg_blktot(&acg)[cbtocylno(&sblock, k)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, k)) - [cbtorpos(&sblock, k)]++; - updclst((osblock.fs_ffs1_size - cbase)/sblock.fs_frag); + updclst((osblock.fs_size-cbase)/sblock.fs_frag); } else { /* * Lets rejoin a possible partially growed @@ -772,7 +836,7 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) */ k = 0; while (isset(cg_blksfree(&acg), i) && - (i >= rounddown(osblock.fs_ffs1_size - cbase, + (i >= rounddown(osblock.fs_size - cbase, sblock.fs_frag))) { i--; k++; @@ -786,8 +850,8 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) * We only grow by some fragments within this last * block. */ - for (i = sblock.fs_ffs1_size - cbase - 1; - i >= osblock.fs_ffs1_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++; @@ -797,7 +861,7 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) */ k = 0; while (isset(cg_blksfree(&acg), i) && - (i >= rounddown(osblock.fs_ffs1_size - cbase, + (i >= rounddown(osblock.fs_size - cbase, sblock.fs_frag))) { i--; k++; @@ -811,16 +875,13 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) /* * Handle all new complete blocks here. */ - for (i = roundup(osblock.fs_ffs1_size - cbase, sblock.fs_frag); - i + sblock.fs_frag<=dmax-cbase; /* XXX <= or only < ? */ + 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++; - cg_blktot(&acg)[cbtocylno(&sblock, i)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, i)) - [cbtorpos(&sblock, i)]++; } /* @@ -836,14 +897,14 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) } } - sblock.fs_ffs1_cstotal.cs_nffree += + sblock.fs_cstotal.cs_nffree += (acg.cg_cs.cs_nffree - aocg.cg_cs.cs_nffree); - sblock.fs_ffs1_cstotal.cs_nbfree += + sblock.fs_cstotal.cs_nbfree += (acg.cg_cs.cs_nbfree - aocg.cg_cs.cs_nbfree); /* * The following statistics are not changed here: - * sblock.fs_ffs1_cstotal.cs_ndir - * sblock.fs_ffs1_cstotal.cs_nifree + * 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. */ @@ -853,11 +914,9 @@ updjcg(int cylno, time_t utime, int fsi, int fso, unsigned int Nflag) * Write the updated "joining" cylinder group back to disk. */ wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), (size_t)sblock.fs_cgsize, - &acg, fso, Nflag); + (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; } @@ -886,7 +945,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) struct csum *cs; int ocscg, ncscg; int blocks; - daddr_t cbase, dupper, odupper, d, f, g; + daddr64_t cbase, dupper, odupper, d, f, g; int ind; int cylno, inc; struct gfs_bpp *bp; @@ -904,7 +963,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) DBG_LEAVE; return; } - ocscg = dtog(&osblock, osblock.fs_ffs1_csaddr); + 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); @@ -916,11 +975,9 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * block from disk. */ rdfs(fsbtodb(&osblock, cgtod(&osblock, ocscg)), - (size_t)osblock.fs_cgsize, &aocg, fsi); + (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(&cgun1, &cgun2, sizeof(cgun2)); @@ -936,8 +993,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * also up to 8*3 blocks for indirect blocks for all possible * references. */ - if (/* ((int)sblock.fs_ffs1_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 @@ -958,14 +1014,14 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * 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_ffs1_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 @@ -986,7 +1042,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) */ d--; - DBG_PRINT1("d=%d\n", d); + DBG_PRINT1("d=%jd\n", (intmax_t)d); if ((d + 1) % sblock.fs_frag) { /* * The end of the cylinder summary is not a complete @@ -995,11 +1051,10 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) DBG_TRC; frag_adjust(d % sblock.fs_fpg, -1); for (; (d + 1) % sblock.fs_frag; d--) { - DBG_PRINT1("d=%d\n", - d); + DBG_PRINT1("d=%jd\n", (intmax_t)d); setbit(cg_blksfree(&acg), d % sblock.fs_fpg); acg.cg_cs.cs_nffree++; - sblock.fs_ffs1_cstotal.cs_nffree++; + sblock.fs_cstotal.cs_nffree++; } /* * Point "d" to the last fragment of the last @@ -1009,24 +1064,20 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) frag_adjust(d % sblock.fs_fpg, 1); if (isblock(&sblock, cg_blksfree(&acg), - (d % sblock.fs_fpg)/sblock.fs_frag)) { - DBG_PRINT1("d=%d\n", - d); - acg.cg_cs.cs_nffree-=sblock.fs_frag; + (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_nbfree++; - sblock.fs_ffs1_cstotal.cs_nffree-=sblock.fs_frag; - sblock.fs_ffs1_cstotal.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, - d % sblock.fs_fpg)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, - d % sblock.fs_fpg))[cbtorpos(&sblock, - d % sblock.fs_fpg)]++; + sblock.fs_cstotal.cs_nffree -= sblock.fs_frag; + sblock.fs_cstotal.cs_nbfree++; if (sblock.fs_contigsumsize > 0) { setbit(cg_clustersfree(&acg), - (d % sblock.fs_fpg)/sblock.fs_frag); + (d % sblock.fs_fpg) / sblock.fs_frag); if (lcs < sblock.fs_contigsumsize) { - if (lcs) - cg_clustersum(&acg)[lcs]--; + if (lcs) { + cg_clustersum(&acg) + [lcs]--; + } lcs++; cg_clustersum(&acg)[lcs]++; } @@ -1039,30 +1090,25 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) d--; } - DBG_PRINT1("d=%d\n", - d); - for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_ffs1_csaddr; + DBG_PRINT1("d=%jd\n", (intmax_t)d); + for (d = rounddown(d, sblock.fs_frag); d >= osblock.fs_csaddr; d -= sblock.fs_frag) { DBG_TRC; - DBG_PRINT1("d=%d\n", - d); + DBG_PRINT1("d=%d\n", 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_ffs1_cstotal.cs_nbfree++; - cg_blktot(&acg)[cbtocylno(&sblock, d % sblock.fs_fpg)]++; - cg_blks(&sblock, &acg, cbtocylno(&sblock, - d % sblock.fs_fpg))[cbtorpos(&sblock, - d % sblock.fs_fpg)]++; + sblock.fs_cstotal.cs_nbfree++; 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) { cg_clustersum(&acg)[lcs]--; + } lcs++; cg_clustersum(&acg)[lcs]++; } @@ -1075,7 +1121,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * summary back to disk. */ wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), - (size_t)sblock.fs_cgsize, &acg, fso, Nflag); + (size_t)sblock.fs_cgsize, (void *)&acg, fso, Nflag); DBG_PRINT0("oscg written\n"); DBG_DUMP_CG(&sblock, "old summary cg", &acg); @@ -1083,8 +1129,8 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * Find the beginning of the new cylinder group containing the * cylinder summary. */ - sblock.fs_ffs1_csaddr = cgdmin(&sblock, osblock.fs_ncg); - ncscg = dtog(&sblock, sblock.fs_ffs1_csaddr); + sblock.fs_csaddr = cgdmin(&sblock, osblock.fs_ncg); + ncscg = dtog(&sblock, sblock.fs_csaddr); cs = fscs + ncscg; @@ -1106,9 +1152,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) rdfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)), (size_t)sblock.fs_cgsize, &aocg, fsi); DBG_PRINT0("nscg read\n"); - DBG_DUMP_CG(&sblock, - "new summary cg", - &aocg); + DBG_DUMP_CG(&sblock, "new summary cg", &aocg); memcpy(&cgun1, &cgun2, sizeof(cgun2)); @@ -1116,20 +1160,16 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * Allocate all complete blocks used by the new cylinder * summary. */ - for (d = sblock.fs_ffs1_csaddr; d + sblock.fs_frag <= - sblock.fs_ffs1_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); acg.cg_cs.cs_nbfree--; - sblock.fs_ffs1_cstotal.cs_nbfree--; - cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, - d%sblock.fs_fpg))[cbtorpos(&sblock, - d%sblock.fs_fpg)]--; + sblock.fs_cstotal.cs_nbfree--; if (sblock.fs_contigsumsize > 0) { clrbit(cg_clustersfree(&acg), - (d%sblock.fs_fpg)/sblock.fs_frag); + (d % sblock.fs_fpg) / sblock.fs_frag); } } @@ -1137,33 +1177,29 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * Allocate all fragments used by the cylinder summary in the * last block. */ - if (d < sblock.fs_ffs1_csaddr+(sblock.fs_cssize/sblock.fs_fsize)) { - for (; d - sblock.fs_ffs1_csaddr< + if (d < sblock.fs_csaddr + (sblock.fs_cssize / sblock.fs_fsize)) { + for (; d - sblock.fs_csaddr < sblock.fs_cssize/sblock.fs_fsize; d++) { clrbit(cg_blksfree(&acg), d%sblock.fs_fpg); acg.cg_cs.cs_nffree--; - sblock.fs_ffs1_cstotal.cs_nffree--; + sblock.fs_cstotal.cs_nffree--; } acg.cg_cs.cs_nbfree--; - acg.cg_cs.cs_nffree+=sblock.fs_frag; - sblock.fs_ffs1_cstotal.cs_nbfree--; - sblock.fs_ffs1_cstotal.cs_nffree+=sblock.fs_frag; - cg_blktot(&acg)[cbtocylno(&sblock, d%sblock.fs_fpg)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, - d%sblock.fs_fpg))[cbtorpos(&sblock, - d%sblock.fs_fpg)]--; + acg.cg_cs.cs_nffree += sblock.fs_frag; + sblock.fs_cstotal.cs_nbfree--; + 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 than the maximum cluster size. This is + * 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 @@ -1180,11 +1216,9 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * back to disk. */ wtfs(fsbtodb(&sblock, cgtod(&sblock, ncscg)), - (size_t)sblock.fs_cgsize, &acg, fso, Nflag); + (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; @@ -1197,21 +1231,21 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) DBG_TRC; cbase = cgbase(&osblock, ocscg); /* old and new are equal */ - dupper = sblock.fs_ffs1_csaddr - cbase + + dupper = sblock.fs_csaddr - cbase + howmany(sblock.fs_cssize, sblock.fs_fsize); - odupper = osblock.fs_ffs1_csaddr - cbase + + odupper = osblock.fs_csaddr - cbase + howmany(osblock.fs_cssize, osblock.fs_fsize); - sblock.fs_ffs1_dsize -= dupper - odupper; + sblock.fs_dsize -= dupper-odupper; /* * Allocate the space for the array of blocks to be relocated. */ - bp= malloc(((dupper - odupper)/sblock.fs_frag + 2) * + bp = (struct gfs_bpp *)malloc(((dupper-odupper) / sblock.fs_frag + 2) * sizeof(struct gfs_bpp)); if (bp == NULL) errx(1, "malloc failed"); - memset(bp, 0, ((dupper - odupper) / sblock.fs_frag + 2) * + memset((char *)bp, 0, ((dupper-odupper) / sblock.fs_frag + 2) * sizeof(struct gfs_bpp)); /* @@ -1225,7 +1259,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) ind = 0; frag_adjust(odupper, -1); for (d = odupper; ((d < dupper) && (d % sblock.fs_frag)); d++) { - DBG_PRINT1("scg first frag check loop d=%d\n", d); + DBG_PRINT1("scg first frag check loop d=%jd\n", (intmax_t)d); if (isclr(cg_blksfree(&acg), d)) { if (!ind) { bp[ind].old = d / sblock.fs_frag; @@ -1237,7 +1271,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) } else { clrbit(cg_blksfree(&acg), d); acg.cg_cs.cs_nffree--; - sblock.fs_ffs1_cstotal.cs_nffree--; + sblock.fs_cstotal.cs_nffree--; } /* * No cluster handling is needed here, as there was at least @@ -1252,26 +1286,22 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) /* * Handle all needed complete blocks here. */ - for (; d + sblock.fs_frag<=dupper; d+=sblock.fs_frag) { - DBG_PRINT1("scg block check loop d=%d\n", - d); - if (!isblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag)) { + 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 < d + sblock.fs_frag; f++) { if (isset(cg_blksfree(&aocg), f)) { acg.cg_cs.cs_nffree--; - sblock.fs_ffs1_cstotal.cs_nffree--; + sblock.fs_cstotal.cs_nffree--; } } - clrblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag); + clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag); bp[ind].old = d / sblock.fs_frag; ind++; } else { - clrblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag); + clrblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag); acg.cg_cs.cs_nbfree--; - sblock.fs_ffs1_cstotal.cs_nbfree--; - cg_blktot(&acg)[cbtocylno(&sblock, d)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]--; + sblock.fs_cstotal.cs_nbfree--; if (sblock.fs_contigsumsize > 0) { clrbit(cg_clustersfree(&acg), d / sblock.fs_frag); for (lcs = 0, l = (d / sblock.fs_frag) + 1; @@ -1299,14 +1329,11 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) if (d < dupper) { frag_adjust(dupper - 1, -1); - if (isblock(&sblock, cg_blksfree(&acg), d/sblock.fs_frag)) { + if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) { acg.cg_cs.cs_nbfree--; - sblock.fs_ffs1_cstotal.cs_nbfree--; + sblock.fs_cstotal.cs_nbfree--; acg.cg_cs.cs_nffree+=sblock.fs_frag; - sblock.fs_ffs1_cstotal.cs_nffree+=sblock.fs_frag; - cg_blktot(&acg)[cbtocylno(&sblock, d)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) - [cbtorpos(&sblock, d)]--; + sblock.fs_cstotal.cs_nffree+=sblock.fs_frag; if (sblock.fs_contigsumsize > 0) { clrbit(cg_clustersfree(&acg), d / sblock.fs_frag); for (lcs = 0, l = (d / sblock.fs_frag) + 1; @@ -1324,14 +1351,15 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) } for (; d < dupper; d++) { - DBG_PRINT1("scg second frag check loop d=%d\n", d); + DBG_PRINT1("scg second frag check loop d=%jd\n", + (intmax_t)d); if (isclr(cg_blksfree(&acg), d)) { bp[ind].old = d / sblock.fs_frag; bp[ind].flags |= GFS_FL_LAST; } else { clrbit(cg_blksfree(&acg), d); acg.cg_cs.cs_nffree--; - sblock.fs_ffs1_cstotal.cs_nffree--; + sblock.fs_cstotal.cs_nffree--; } } if (bp[ind].flags & GFS_FL_LAST) /* we have to advance here */ @@ -1369,7 +1397,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) if (isset(cg_blksfree(&aocg), f)) { setbit(cg_blksfree(&acg), g); acg.cg_cs.cs_nffree++; - sblock.fs_ffs1_cstotal.cs_nffree++; + sblock.fs_cstotal.cs_nffree++; } } @@ -1384,14 +1412,14 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) if (bp[i].flags & GFS_FL_FIRST) { for (f = bp[i].old * sblock.fs_frag, g = bp[i].new * sblock.fs_frag; - f < odupper; f++, g++) { + f < odupper; + f++, g++) { setbit(cg_blksfree(&acg), g); acg.cg_cs.cs_nffree++; - sblock.fs_ffs1_cstotal.cs_nffree++; + sblock.fs_cstotal.cs_nffree++; } if (!(bp[i].flags & GFS_FL_LAST)) - frag_adjust(bp[i].new * sblock.fs_frag,1); - + frag_adjust(bp[i].new * sblock.fs_frag, 1); } /* @@ -1402,11 +1430,12 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) frag_adjust(bp[i].new * sblock.fs_frag, 1); frag_adjust(bp[i].old * sblock.fs_frag, -1); for (f = dupper; - f < roundup(dupper, sblock.fs_frag); f++) { + f < roundup(dupper, sblock.fs_frag); + f++) { if (isclr(cg_blksfree(&acg), f)) { setbit(cg_blksfree(&acg), f); acg.cg_cs.cs_nffree++; - sblock.fs_ffs1_cstotal.cs_nffree++; + sblock.fs_cstotal.cs_nffree++; } } frag_adjust(bp[i].old * sblock.fs_frag, 1); @@ -1426,14 +1455,14 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * in the case we have any active snapshots. */ rdfs(fsbtodb(&sblock, bp[i].old * sblock.fs_frag), - (size_t)sblock.fs_bsize, &ablk, fsi); + (size_t)sblock.fs_bsize, (void *)&ablk, fsi); wtfs(fsbtodb(&sblock, bp[i].new * sblock.fs_frag), - (size_t)sblock.fs_bsize, &ablk, fso, Nflag); + (size_t)sblock.fs_bsize, (void *)&ablk, fso, Nflag); DBG_DUMP_HEX(&sblock, "copied full block", (unsigned char *)&ablk); - DBG_PRINT2("scg (%d->%d) block relocated\n", - bp[i].old, bp[i].new); + DBG_PRINT2("scg (%jd->%jd) block relocated\n", + (intmax_t)bp[i].old, (intmax_t)bp[i].new); } /* @@ -1444,7 +1473,7 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) */ 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--) { + for (inc = osblock.fs_ipg - 1; inc > 0; inc--) { updrefs(cylno, (ino_t)inc, bp, fsi, fso, Nflag); } } @@ -1454,20 +1483,20 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * references found make sense. */ for (i = 0; i < ind; i++) { - if (!bp[i].found || (bp[i].found>sblock.fs_frag)) { - warnx("error: %d refs found for block %d.", - bp[i].found, bp[i].old); + 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_ffs1_cstotal.cs_ndir - * sblock.fs_ffs1_cstotal.cs_nifree + * sblock.fs_cstotal.cs_ndir + * sblock.fs_cstotal.cs_nifree * The following statistics were already updated on the fly: - * sblock.fs_ffs1_cstotal.cs_nffree - * sblock.fs_ffs1_cstotal.cs_nbfree + * 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. */ @@ -1478,11 +1507,9 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * Write summary cylinder group back to disk. */ wtfs(fsbtodb(&sblock, cgtod(&sblock, ocscg)), (size_t)sblock.fs_cgsize, - &acg, fso, Nflag); + (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; } @@ -1492,19 +1519,21 @@ updcsloc(time_t utime, int fsi, int fso, unsigned int Nflag) * Here we read some block(s) from disk. */ static void -rdfs(daddr_t bno, size_t size, void *bf, int fsi) +rdfs(daddr64_t bno, size_t size, void *bf, int fsi) { DBG_FUNC("rdfs") ssize_t n; - DBG_ENTER; - if (lseek(fsi, (off_t)bno * DEV_BSIZE, SEEK_SET) < 0) { - err(33, "rdfs: seek error: %ld", (long)bno); + if (bno < 0) { + err(32, "rdfs: attempting to read negative block number"); + } + 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) { - err(34, "rdfs: read error: %ld", (long)bno); + err(34, "rdfs: read error: %jd", (intmax_t)bno); } DBG_LEAVE; @@ -1515,7 +1544,7 @@ rdfs(daddr_t bno, size_t size, void *bf, int fsi) * Here we write some block(s) to disk. */ static void -wtfs(daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) +wtfs(daddr64_t bno, size_t size, void *bf, int fso, unsigned int Nflag) { DBG_FUNC("wtfs") ssize_t n; @@ -1526,11 +1555,13 @@ wtfs(daddr_t bno, size_t size, void *bf, int fso, unsigned int 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; } @@ -1541,11 +1572,11 @@ wtfs(daddr_t bno, size_t size, void *bf, int fso, unsigned int Nflag) * that acg contains the current cylinder group. As we may take a block from * somewhere in the filesystem we have to handle cluster summary here. */ -static daddr_t +static daddr64_t alloc(void) { DBG_FUNC("alloc") - daddr_t d, blkno; + daddr64_t d, blkno; int lcs1, lcs2; int l; int csmin, csmax; @@ -1573,18 +1604,17 @@ alloc(void) 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_ffs1_size) { - dmax = sblock.fs_ffs1_size; + if (dmax > sblock.fs_size) { + dmax = sblock.fs_size; } dmax -= cgbase(&sblock, acg.cg_cgx); /* retransform into cg */ - csmin = sblock.fs_ffs1_csaddr - cgbase(&sblock, acg.cg_cgx); + 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_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) { + if (d >= csmin && d <= csmax) { continue; } if (isblock(&sblock, cg_blksfree(&acg), fragstoblks(&sblock, @@ -1603,7 +1633,7 @@ alloc(void) break; } } - if (blkno==-1) { + if (blkno == -1) { warnx("internal error: couldn't find promised block in cg"); DBG_LEAVE; return (0); @@ -1627,7 +1657,7 @@ alloc(void) * * Lets start with the blocks before our allocated block ... */ - for (lcs1 = 0, l = blkno - 1; lcs1<sblock.fs_contigsumsize; + for (lcs1 = 0, l = blkno - 1; lcs1 < sblock.fs_contigsumsize; l--, lcs1++) { if (isclr(cg_clustersfree(&acg), l)) break; @@ -1636,7 +1666,7 @@ alloc(void) * ... and continue with the blocks right after our allocated * block. */ - for (lcs2 = 0, l = blkno + 1; lcs2<sblock.fs_contigsumsize; + for (lcs2 = 0, l = blkno + 1; lcs2 < sblock.fs_contigsumsize; l++, lcs2++) { if (isclr(cg_clustersfree(&acg), l)) break; @@ -1645,7 +1675,7 @@ alloc(void) /* * Now update all counters. */ - cg_clustersum(&acg)[MIN(lcs1+lcs2 + 1, sblock.fs_contigsumsize)]--; + cg_clustersum(&acg)[MIN(lcs1 + lcs2 + 1, sblock.fs_contigsumsize)]--; if (lcs1) cg_clustersum(&acg)[lcs1]++; if (lcs2) @@ -1655,9 +1685,7 @@ alloc(void) * Update all statistics based on blocks. */ acg.cg_cs.cs_nbfree--; - sblock.fs_ffs1_cstotal.cs_nbfree--; - cg_blktot(&acg)[cbtocylno(&sblock, d)]--; - cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; + sblock.fs_cstotal.cs_nbfree--; DBG_LEAVE; return (d); @@ -1776,32 +1804,45 @@ setblock(struct fs *fs, unsigned char *cp, int h) * not read the same block again and again if we iterate linearly over all * inodes. */ -static struct ufs1_dinode * +static union dinode * ginode(ino_t inumber, int fsi, int cg) { DBG_FUNC("ginode") - int32_t iblk; static ino_t startinum = 0; /* first inode in cached block */ - struct ufs1_dinode *pi; DBG_ENTER; - pi = (struct ufs1_dinode *)ablk; + /* + * 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 (startinum == 0 || inumber < startinum || - inumber >= startinum + INOPB(&sblock)) { - /* - * The block needed is not cached, so we have to read it from - * disk now. - */ - iblk = ino_to_fsba(&sblock, inumber); - in_src = fsbtodb(&sblock, iblk); - rdfs(in_src, (size_t)sblock.fs_bsize, &ablk, fsi); + 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; - return (&(pi[inumber % INOPB(&sblock)])); + 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 ***** */ @@ -1862,7 +1903,7 @@ int main(int argc, char **argv) { DBG_FUNC("main") - char *device, *rdev; + char *device; int ch; unsigned int size = 0; unsigned int Nflag = 0; @@ -1870,7 +1911,7 @@ main(int argc, char **argv) struct stat st; struct disklabel *lp; struct partition *pp; - int fsi, fso; + int i,fsi,fso; char reply[5]; #ifdef FSMAXSNAP int j; @@ -1878,7 +1919,7 @@ main(int argc, char **argv) DBG_ENTER; - while ((ch = getopt(argc, argv, "Nqs:y")) != -1) { + while ((ch = getopt(argc, argv, "Nqs:vy")) != -1) { switch (ch) { case 'N': Nflag = 1; @@ -1888,9 +1929,10 @@ main(int argc, char **argv) break; case 's': size = (size_t)atol(optarg); - if (size < 1) { + if (size < 1) usage(); - } + break; + case 'v': /* for compatibility to newfs */ break; case 'y': ExpertFlag = 1; @@ -1904,27 +1946,25 @@ main(int argc, char **argv) argc -= optind; argv += optind; - if (argc != 1) { + if (argc != 1) usage(); - } - device = *argv; /* * Rather than guessing, use opendev() to get the device * name, which we open for reading. */ - if ((fsi = opendev(device, O_RDONLY, 0, &rdev)) < 0) - err(1, "%s", rdev); + if ((fsi = opendev(*argv, O_RDONLY, 0, &device)) < 0) + err(1, "%s", *argv); /* - * Try to access our device for writing ... + * Try to access our devices for writing ... */ if (Nflag) { fso = -1; } else { - fso = open(rdev, O_WRONLY); + fso = open(device, O_WRONLY); if (fso < 0) - err(1, "%s", rdev); + err(1, "%s", device); } /* @@ -1932,7 +1972,7 @@ main(int argc, char **argv) * figure out the partition number. */ if (fstat(fsi, &st) != 0) - err(1, "%s: fstat()", rdev); + err(1, "%s: fstat()", device); /* * Try to read a label from the disk. Then get the partition from the @@ -1944,23 +1984,36 @@ main(int argc, char **argv) pp = &lp->d_partitions[DISKPART(st.st_rdev)]; else errx(1, "%s: invalid partition number %u", - rdev, DISKPART(st.st_rdev)); + device, DISKPART(st.st_rdev)); /* - * Check if that partition looks suited for growing a filesystem. + * Check if that partition is suitable for growing a file system. */ if (pp->p_size < 1) errx(1, "partition is unavailable"); if (pp->p_fstype != FS_BSDFFS) - errx(1, "partition not 4.2BSD"); + errx(1, "can only grow ffs partitions"); /* * Read the current superblock, and take a backup. */ - rdfs((daddr_t)(SBOFF / DEV_BSIZE), (size_t)SBSIZE, &osblock, fsi); - if (osblock.fs_magic != FS_MAGIC) + 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_bsize <= MAXBSIZE && + osblock.fs_bsize >= (int32_t) sizeof(struct fs)) + break; + } + if (sblock_try[i] == -1) errx(1, "superblock not recognized"); + if (sblock.fs_magic == FS_UFS1_MAGIC && + (sblock.fs_ffs1_flags & FS_FLAGS_UPDATED) == 0) + ffs1_sb_update(&sblock, sblock_try[i]); memcpy(&fsun1, &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"); @@ -1969,21 +2022,21 @@ main(int argc, char **argv) * Determine size to grow to. Default to the full size specified in * the disk label. */ - sblock.fs_ffs1_size = dbtofsb(&osblock, pp->p_size); + sblock.fs_size = dbtofsb(&osblock, pp->p_size); if (size != 0) { if (size > pp->p_size) { - errx(1, "There is not enough space (%d < %d)", + errx(1, "there is not enough space (%d < %d)", pp->p_size, size); } - sblock.fs_ffs1_size = dbtofsb(&osblock, size); + sblock.fs_size = dbtofsb(&osblock, size); } /* * Are we really growing ? */ - if (osblock.fs_ffs1_size >= sblock.fs_ffs1_size) { - errx(1, "we are not growing (%d->%d)", osblock.fs_ffs1_size, - sblock.fs_ffs1_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); } @@ -1998,14 +2051,14 @@ main(int argc, char **argv) " please remove all snapshots before " "using growfs"); } - if (!sblock.fs_snapinum[j]) /* list is dense */ + if (!sblock.fs_snapinum[j]) /* list is dense */ break; } } #endif if (ExpertFlag == 0 && Nflag == 0) { - printf("We strongly recommend you make a backup " + printf("We strongly recommend you to make a backup " "before growing the Filesystem\n\n" " Did you backup your data (Yes/No) ? "); fgets(reply, (int)sizeof(reply), stdin); @@ -2016,60 +2069,53 @@ main(int argc, char **argv) } if (!quiet) - printf("new file system size is: %d frags\n", sblock.fs_ffs1_size); + printf("new file systemsize is: %jd frags\n", + (intmax_t)sblock.fs_size); /* * Try to access our new last block in the filesystem. Even if we * later on realize we have to abort our operation, on that block * there should be no data, so we can't destroy something yet. */ - wtfs((daddr_t)pp->p_size - 1, (size_t)DEV_BSIZE, &sblock, fso, - Nflag); + wtfs((daddr64_t)pp->p_size-1, (size_t)DEV_BSIZE, (void *)&sblock, + fso, Nflag); /* * Now calculate new superblock values and check for reasonable * bound for new filesystem size: - * fs_ffs1_size: is derived from label or user input - * fs_ffs1_dsize: should get updated in the routines creating or + * fs_size: is derived from label or user input + * fs_dsize: should get updated in the routines creating or * updating the cylinder groups on the fly - * fs_ffs1_cstotal: should get updated in the routines creating or + * fs_cstotal: should get updated in the routines creating or * updating the cylinder groups */ /* - * Update the number of cylinders in the filesystem. + * Update the number of cylinders and cylinder groups in the file system. */ - sblock.fs_ncyl = sblock.fs_ffs1_size * NSPF(&sblock) / sblock.fs_spc; - if (sblock.fs_ffs1_size * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) + if (sblock.fs_magic == FS_UFS1_MAGIC) { + sblock.fs_ncyl = sblock.fs_size * NSPF(&sblock) / sblock.fs_spc; + if (sblock.fs_size * NSPF(&sblock) > + sblock.fs_ncyl * sblock.fs_spc) sblock.fs_ncyl++; + } + sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg); + maxino = sblock.fs_ncg * sblock.fs_ipg; - /* - * Update the number of cylinder groups in the filesystem. - */ - sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; - if (sblock.fs_ncyl % sblock.fs_cpg) - sblock.fs_ncg++; - - if ((sblock.fs_ffs1_size - (sblock.fs_ncg - 1) * sblock.fs_fpg) < - sblock.fs_fpg && cgdmin(&sblock, (sblock.fs_ncg - 1))- - cgbase(&sblock, (sblock.fs_ncg - 1)) > (sblock.fs_ffs1_size - - (sblock.fs_ncg - 1) * sblock.fs_fpg)) { + 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 1 /* this is a bit more safe */ - sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg; -#else - sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; -#endif - sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; + if (sblock.fs_magic == FS_UFS1_MAGIC) + sblock.fs_ncyl = sblock.fs_ncg * sblock.fs_cpg; if (!quiet) - printf("Warning: %d sector(s) cannot be allocated.\n", - (sblock.fs_ffs1_size-(sblock.fs_ncg)*sblock.fs_fpg) * - NSPF(&sblock)); - sblock.fs_ffs1_size = sblock.fs_ncyl * sblock.fs_spc / NSPF(&sblock); + 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; } /* @@ -2079,23 +2125,22 @@ main(int argc, char **argv) sblock.fs_cssize = fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); - if (osblock.fs_ffs1_size >= sblock.fs_ffs1_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(rdev, fsi, fso, Nflag); + growfs(fsi, fso, Nflag); /* * Update the disk label. */ pp->p_fragblock = DISKLABELV1_FFS_FRAGBLOCK(sblock.fs_fsize, sblock.fs_frag); - pp->p_cpg = sblock.fs_cpg; + pp->p_cpg = sblock.fs_fpg; return_disklabel(fso, lp, Nflag); DBG_PRINT0("label rewritten\n"); @@ -2107,7 +2152,7 @@ main(int argc, char **argv) DBG_CLOSE; DBG_LEAVE; - return (0); + return 0; } /* ************************************************** return_disklabel ***** */ @@ -2137,7 +2182,6 @@ return_disklabel(int fd, struct disklabel *lp, unsigned int Nflag) */ while (ptr < (u_short *)&lp->d_partitions[lp->d_npartitions]) sum ^= *ptr++; - lp->d_checksum = sum; if (ioctl(fd, DIOCWDINFO, (char *)lp) < 0) @@ -2146,6 +2190,7 @@ return_disklabel(int fd, struct disklabel *lp, unsigned int Nflag) free(lp); DBG_LEAVE; + return ; } /* ***************************************************** get_disklabel ***** */ @@ -2160,11 +2205,11 @@ get_disklabel(int fd) DBG_ENTER; - lab = malloc(sizeof(struct disklabel)); + lab = (struct disklabel *)malloc(sizeof(struct disklabel)); if (!lab) errx(1, "malloc failed"); - if (ioctl(fd, DIOCGDINFO, (char *)lab) < 0) - errx(1, "DIOCGDINFO failed"); + if (ioctl(fd, DIOCGDINFO, (char *)lab) != 0) + err(1, "DIOCGDINFO"); DBG_LEAVE; return (lab); @@ -2182,7 +2227,7 @@ usage(void) DBG_ENTER; - fprintf(stderr, "usage: growfs [-Nqy] [-s size] special\n"); + fprintf(stderr, "usage: growfs [-Ny] [-s size] special\n"); DBG_LEAVE; exit(1); @@ -2191,7 +2236,7 @@ usage(void) /* *********************************************************** updclst ***** */ /* * This updates most parameters and the bitmap related to cluster. We have to - * assume, that sblock, osblock, acg are set up. + * assume that sblock, osblock, acg are set up. */ static void updclst(int block) @@ -2201,8 +2246,9 @@ updclst(int block) DBG_ENTER; - if (sblock.fs_contigsumsize < 1) /* no clustering */ + if (sblock.fs_contigsumsize < 1) /* no clustering */ return; + /* * update cluster allocation map */ @@ -2241,160 +2287,135 @@ updrefs(int cg, ino_t in, struct gfs_bpp *bp, int fsi, int fso, unsigned int Nflag) { DBG_FUNC("updrefs") - unsigned int ictr, ind2ctr, ind3ctr; - int32_t *iptr, *ind2ptr, *ind3ptr; - struct ufs1_dinode *ino; - int remaining_blocks; + daddr64_t len, lbn, numblks; + daddr64_t iptr, blksperindir; + union dinode *ino; + int i, mode, inodeupdated; DBG_ENTER; - /* - * XXX We should skip unused inodes even from beeing read from disk - * here by using the bitmap. - */ ino = ginode(in, fsi, cg); - if (!((ino->di_mode & IFMT) == IFDIR || (ino->di_mode & IFMT) == IFREG || - (ino->di_mode & IFMT) == IFLNK)) { + if (ino == NULL) { + DBG_LEAVE; + return; + } + mode = DIP(ino, di_mode) & IFMT; + if (mode != IFDIR && mode != IFREG && mode != IFLNK) { DBG_LEAVE; return; /* only check DIR, FILE, LINK */ } - if (((ino->di_mode & IFMT) == IFLNK) && - (ino->di_size < MAXSYMLINKLEN_UFS1)) { + if (mode == IFLNK && + DIP(ino, di_size) < (u_int64_t) sblock.fs_maxsymlinklen) { DBG_LEAVE; return; /* skip short symlinks */ } - if (!ino->di_size) { + numblks = howmany(DIP(ino, di_size), sblock.fs_bsize); + if (numblks == 0) { DBG_LEAVE; return; /* skip empty file */ } - if (!ino->di_blocks) { + if (DIP(ino, di_blocks) == 0) { DBG_LEAVE; return; /* skip empty swiss cheesy file or old fastlink */ } DBG_PRINT2("scg checking inode (%d in %d)\n", in, cg); /* - * Start checking all direct blocks. + * Check all the blocks. */ - remaining_blocks = howmany(ino->di_size, sblock.fs_bsize); - for (ictr = 0; ictr < MIN(NDADDR, (unsigned int)remaining_blocks); - ictr++) { - iptr = &(ino->di_db[ictr]); - if (*iptr) - cond_bl_upd(iptr, bp, GFS_PS_INODE, fso, Nflag); + inodeupdated = 0; + len = numblks < NDADDR ? numblks : NDADDR; + for (i = 0; i < len; i++) { + iptr = DIP(ino, di_db[i]); + if (iptr == 0) + continue; + if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) { + DIP_SET(ino, di_db[i], iptr); + inodeupdated++; + } } DBG_PRINT0("~~scg direct blocks checked\n"); - remaining_blocks -= NDADDR; - if (remaining_blocks < 0) { - DBG_LEAVE; - return; - } - if (ino->di_ib[0]) { - /* - * Start checking first indirect block - */ - cond_bl_upd(&(ino->di_ib[0]), bp, GFS_PS_INODE, fso, Nflag); - i1_src = fsbtodb(&sblock, ino->di_ib[0]); - rdfs(i1_src, (size_t)sblock.fs_bsize, &i1blk, fsi); - for (ictr = 0; ictr < MIN(howmany(sblock.fs_bsize, - sizeof(int32_t)), (unsigned int)remaining_blocks); - ictr++) { - iptr = &((int32_t *)&i1blk)[ictr]; - if (*iptr) { - cond_bl_upd(iptr, bp, GFS_PS_IND_BLK_LVL1, - fso, Nflag); - } + blksperindir = 1; + len = numblks - NDADDR; + lbn = NDADDR; + for (i = 0; len > 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); } - DBG_PRINT0("scg indirect_1 blocks checked\n"); + if (inodeupdated) + wtfs(inoblk, sblock.fs_bsize, inobuf, fso, Nflag); - remaining_blocks -= howmany(sblock.fs_bsize, sizeof(int32_t)); - if (remaining_blocks<0) { - DBG_LEAVE; - return; - } - if (ino->di_ib[1]) { - /* - * Start checking second indirect block - */ - cond_bl_upd(&(ino->di_ib[1]), bp, GFS_PS_INODE, fso, Nflag); - i2_src = fsbtodb(&sblock, ino->di_ib[1]); - rdfs(i2_src, (size_t)sblock.fs_bsize, &i2blk, fsi); - for (ind2ctr = 0; ind2ctr < howmany(sblock.fs_bsize, - sizeof(int32_t)); ind2ctr++) { - ind2ptr = &((int32_t *)&i2blk)[ind2ctr]; - if (!*ind2ptr) - continue; - cond_bl_upd(ind2ptr, bp, GFS_PS_IND_BLK_LVL2, fso, - Nflag); - i1_src = fsbtodb(&sblock, *ind2ptr); - rdfs(i1_src, (size_t)sblock.fs_bsize, &i1blk, - fsi); - for (ictr = 0; ictr < MIN(howmany((unsigned int) - sblock.fs_bsize, sizeof(int32_t)), - (unsigned int)remaining_blocks); ictr++) { - iptr = &((int32_t *)&i1blk)[ictr]; - if (*iptr) { - cond_bl_upd(iptr, bp, - GFS_PS_IND_BLK_LVL1, fso, Nflag); - } - } - } - } - DBG_PRINT0("scg indirect_2 blocks checked\n"); + DBG_LEAVE; +} -#define SQUARE(a) ((a)*(a)) - remaining_blocks -= SQUARE(howmany(sblock.fs_bsize, sizeof(int32_t))); -#undef SQUARE - if (remaining_blocks < 0) { - DBG_LEAVE; - return; - } +/* + * Recursively check all the indirect blocks. + */ +static void +indirchk(daddr64_t blksperindir, daddr64_t lbn, daddr64_t blkno, + daddr64_t lastlbn, struct gfs_bpp *bp, int fsi, int fso, unsigned int Nflag) +{ + DBG_FUNC("indirchk") + void *ibuf; + int i, last; + daddr64_t iptr; - if (ino->di_ib[2]) { - /* - * Start checking third indirect block - */ - cond_bl_upd(&(ino->di_ib[2]), bp, GFS_PS_INODE, fso, Nflag); - i3_src = fsbtodb(&sblock, ino->di_ib[2]); - rdfs(i3_src, (size_t)sblock.fs_bsize, &i3blk, fsi); - for (ind3ctr = 0; ind3ctr < howmany(sblock.fs_bsize, - sizeof(int32_t)); ind3ctr++) { - ind3ptr = &((int32_t *)&i3blk)[ind3ctr]; - if (!*ind3ptr) - continue; - cond_bl_upd(ind3ptr, bp, GFS_PS_IND_BLK_LVL3, fso, - Nflag); - i2_src = fsbtodb(&sblock, *ind3ptr); - rdfs(i2_src, (size_t)sblock.fs_bsize, &i2blk, - fsi); - for (ind2ctr = 0; ind2ctr < howmany(sblock.fs_bsize, - sizeof(int32_t)); ind2ctr++) { - ind2ptr = &((int32_t *)&i2blk)[ind2ctr]; - if (!*ind2ptr) - continue; - cond_bl_upd(ind2ptr, bp, GFS_PS_IND_BLK_LVL2, - fso, Nflag); - i1_src = fsbtodb(&sblock, *ind2ptr); - rdfs(i1_src, (size_t)sblock.fs_bsize, - &i1blk, fsi); - for (ictr = 0; ictr < MIN(howmany(sblock.fs_bsize, - sizeof(int32_t)), - (unsigned int)remaining_blocks); ictr++) { - iptr = &((int32_t *)&i1blk)[ictr]; - if (*iptr) { - cond_bl_upd(iptr, bp, - GFS_PS_IND_BLK_LVL1, fso, - Nflag); - } - } - } + 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 = ((int32_t *)ibuf)[i]; + else + iptr = ((daddr64_t *)ibuf)[i]; + if (iptr == 0) + continue; + if (cond_bl_upd(&iptr, bp, fsi, fso, Nflag)) { + if (sblock.fs_magic == FS_UFS1_MAGIC) + ((int32_t *)ibuf)[i] = iptr; + else + ((daddr64_t *)ibuf)[i] = iptr; } + if (blksperindir == 1) + continue; + indirchk(blksperindir / NINDIR(&sblock), lbn + blksperindir * i, + iptr, lastlbn, bp, fsi, fso, Nflag); } - - DBG_PRINT0("scg indirect_3 blocks checked\n"); + free(ibuf); DBG_LEAVE; } +static void +ffs1_sb_update(struct fs *fs, daddr64_t sbloc) +{ + fs->fs_flags = fs->fs_ffs1_flags; + fs->fs_sblockloc = sbloc; + fs->fs_maxbsize = fs->fs_bsize; + fs->fs_time = fs->fs_ffs1_time; + fs->fs_size = fs->fs_ffs1_size; + fs->fs_dsize = fs->fs_ffs1_dsize; + fs->fs_csaddr = fs->fs_ffs1_csaddr; + fs->fs_cstotal.cs_ndir = fs->fs_ffs1_cstotal.cs_ndir; + fs->fs_cstotal.cs_nbfree = fs->fs_ffs1_cstotal.cs_nbfree; + fs->fs_cstotal.cs_nifree = fs->fs_ffs1_cstotal.cs_nifree; + fs->fs_cstotal.cs_nffree = fs->fs_ffs1_cstotal.cs_nffree; + fs->fs_ffs1_flags |= FS_FLAGS_UPDATED; +} |