FreeBSD/sbin/growfs/growfs.c
/*
 * Here we actually start growing the file system. We basically read the
 * cylinder summary from the first cylinder group as we want to update
 * this on the fly during our various operations. First we handle the
 * changes in the former last cylinder group. Afterwards we create all new
 * cylinder groups.  Now we handle the cylinder group containing the
 * cylinder summary which might result in a relocation of the whole
 * structure.  In the end we write back the updated cylinder summary, the
 * new superblock, and slightly patched versions of the super block
 * copies.
 */
Here we actually start growing the file system. We basically read the
cylinder summary from the first cylinder group as we want to update
this on the fly during our various operations. First we handle the
changes in the former last cylinder group. Afterwards we create all new
cylinder groups.  Now we handle the cylinder group containing the
cylinder summary which might result in a relocation of the whole
structure.  In the end we write back the updated cylinder summary, the
new superblock, and slightly patched versions of the super block
copies.
Here we actually start growing the file system . We basically read the cylinder summary from the first cylinder group as we want to update this on the fly during our various operations . First we handle the changes in the former last cylinder group . Afterwards we create all new cylinder groups . Now we handle the cylinder group containing the cylinder summary which might result in a relocation of the whole structure . In the end we write back the updated cylinder summary the new superblock and slightly patched versions of the super block copies .
static void
growfs(int fsi, int fso, unsigned int Nflag)
{
	DBG_FUNC("growfs")
	time_t modtime;
	uint cylno;
	int i, j, width;
	char tmpbuf[100];
	DBG_ENTER;
	time(&modtime);
	fscs = (struct csum *)calloc((size_t)1, (size_t)sblock.fs_cssize);
	if (fscs == NULL)
		errx(1, "calloc failed");
	for (i = 0; i < osblock.fs_cssize; i += osblock.fs_bsize) {
		rdfs(fsbtodb(&osblock, osblock.fs_csaddr +
		    numfrags(&osblock, i)), (size_t)MIN(osblock.fs_cssize - i,
		    osblock.fs_bsize), (void *)(((char *)fscs) + i), fsi);
	}
#ifdef FS_DEBUG
	{
		struct csum *dbg_csp;
		u_int32_t dbg_csc;
		char dbg_line[80];
		dbg_csp = fscs;
		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++);
		}
	}
#endif 
	DBG_PRINT0("fscs read\n");
	updjcg(osblock.fs_ncg - 1, modtime, fsi, fso, Nflag);
#ifdef FS_DEBUG
#define B2MBFACTOR (1 / (1024.0 * 1024.0))
	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
#endif 
	printf("super-block backups (for fsck_ffs -b #) at:\n");
	i = 0;
	width = charsperline();
	for (cylno = osblock.fs_ncg; cylno < sblock.fs_ncg; cylno++) {
		initcg(cylno, modtime, fso, Nflag);
		j = sprintf(tmpbuf, " %jd%s",
		    (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cylno)),
		    cylno < (sblock.fs_ncg - 1) ? "," : "" );
		if (i + j >= width) {
			printf("\n");
			i = 0;
		}
		i += j;
		printf("%s", tmpbuf);
		fflush(stdout);
	}
	printf("\n");
	updcsloc(modtime, fsi, fso, Nflag);
	for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) {
		wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
		    (size_t)MIN(sblock.fs_cssize - i, sblock.fs_bsize),
		    (void *)(((char *)fscs) + i), fso, Nflag);
	}
	DBG_PRINT0("fscs written\n");
#ifdef FS_DEBUG
	{
		struct csum	*dbg_csp;
		u_int32_t	dbg_csc;
		char	dbg_line[80];
		dbg_csp = fscs;
		for (dbg_csc = 0; dbg_csc < sblock.fs_ncg; dbg_csc++) {
			snprintf(dbg_line, sizeof(dbg_line),
			    "%d. new csum in new location", dbg_csc);
			DBG_DUMP_CSUM(&sblock, dbg_line, dbg_csp++);
		}
	}
#endif 
	sblock.fs_time = modtime;
	wtfs(sblockloc, (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
	DBG_PRINT0("sblock written\n");
	DBG_DUMP_FS(&sblock, "new initial sblock");
	sblock.fs_fmod = 0;
	sblock.fs_clean = 1;
	sblock.fs_ronly = 0;
	sblock.fs_cgrotor = 0;
	sblock.fs_state = 0;
	memset((void *)&sblock.fs_fsmnt, 0, sizeof(sblock.fs_fsmnt));
	sblock.fs_flags &= FS_DOSOFTDEP;
	for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
		wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
		    (size_t)SBLOCKSIZE, (void *)&sblock, fso, Nflag);
	}
	DBG_PRINT0("sblock copies written\n");
	DBG_DUMP_FS(&sblock, "new other sblocks");
	DBG_LEAVE;
	return;
}
static void growfs ( int fsi , int fso , unsigned int Nflag ) { DBG_FUNC ( " " ) time_t modtime ; uint cylno ; int i , j , width ; char tmpbuf [ 100 ] ; DBG_ENTER ; time ( & modtime ) ; fscs = ( struct csum * ) calloc ( ( size_t ) 1 , ( size_t ) sblock . fs_cssize ) ; if ( fscs == NULL ) errx ( 1 , " " ) ; for ( i = 0 ; i < osblock . fs_cssize ; i += osblock . fs_bsize ) { rdfs ( fsbtodb ( & osblock , osblock . fs_csaddr + numfrags ( & osblock , i ) ) , ( size_t ) MIN ( osblock . fs_cssize - i , osblock . fs_bsize ) , ( void * ) ( ( ( char * ) fscs ) + i ) , fsi ) ; } #ifdef FS_DEBUG { struct csum * dbg_csp ; u_int32_t dbg_csc ; char dbg_line [ 80 ] ; dbg_csp = fscs ; for ( dbg_csc = 0 ; dbg_csc < osblock . fs_ncg ; dbg_csc ++ ) { snprintf ( dbg_line , sizeof ( dbg_line ) , " " , dbg_csc ) ; DBG_DUMP_CSUM ( & osblock , dbg_line , dbg_csp ++ ) ; } } #endif DBG_PRINT0 ( " \n " ) ; updjcg ( osblock . fs_ncg - 1 , modtime , fsi , fso , Nflag ) ; #ifdef FS_DEBUG #define B2MBFACTOR  (1 / (1024.0 * 1024.0)) printf ( " \n " , ( float ) sblock . fs_size * sblock . fs_fsize * B2MBFACTOR , ( intmax_t ) fsbtodb ( & sblock , sblock . fs_size ) , sblock . fs_bsize , sblock . fs_fsize ) ; printf ( " \t \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 ( " \t \n " ) ; #undef  B2MBFACTOR #endif printf ( " \n " ) ; i = 0 ; width = charsperline ( ) ; for ( cylno = osblock . fs_ncg ; cylno < sblock . fs_ncg ; cylno ++ ) { initcg ( cylno , modtime , fso , Nflag ) ; j = sprintf ( tmpbuf , " " , ( intmax_t ) fsbtodb ( & sblock , cgsblock ( & sblock , cylno ) ) , cylno < ( sblock . fs_ncg - 1 ) ? " " : " " ) ; if ( i + j >= width ) { printf ( " \n " ) ; i = 0 ; } i += j ; printf ( " " , tmpbuf ) ; fflush ( stdout ) ; } printf ( " \n " ) ; updcsloc ( modtime , fsi , fso , Nflag ) ; for ( i = 0 ; i < sblock . fs_cssize ; i += sblock . fs_bsize ) { wtfs ( fsbtodb ( & sblock , sblock . fs_csaddr + numfrags ( & sblock , i ) ) , ( size_t ) MIN ( sblock . fs_cssize - i , sblock . fs_bsize ) , ( void * ) ( ( ( char * ) fscs ) + i ) , fso , Nflag ) ; } DBG_PRINT0 ( " \n " ) ; #ifdef FS_DEBUG { struct csum * dbg_csp ; u_int32_t dbg_csc ; char dbg_line [ 80 ] ; dbg_csp = fscs ; for ( dbg_csc = 0 ; dbg_csc < sblock . fs_ncg ; dbg_csc ++ ) { snprintf ( dbg_line , sizeof ( dbg_line ) , " " , dbg_csc ) ; DBG_DUMP_CSUM ( & sblock , dbg_line , dbg_csp ++ ) ; } } #endif sblock . fs_time = modtime ; wtfs ( sblockloc , ( size_t ) SBLOCKSIZE , ( void * ) & sblock , fso , Nflag ) ; DBG_PRINT0 ( " \n " ) ; DBG_DUMP_FS ( & sblock , " " ) ; sblock . fs_fmod = 0 ; sblock . fs_clean = 1 ; sblock . fs_ronly = 0 ; sblock . fs_cgrotor = 0 ; sblock . fs_state = 0 ; memset ( ( void * ) & sblock . fs_fsmnt , 0 , sizeof ( sblock . fs_fsmnt ) ) ; sblock . fs_flags &= FS_DOSOFTDEP ; for ( cylno = 0 ; cylno < sblock . fs_ncg ; cylno ++ ) { wtfs ( fsbtodb ( & sblock , cgsblock ( & sblock , cylno ) ) , ( size_t ) SBLOCKSIZE , ( void * ) & sblock , fso , Nflag ) ; } DBG_PRINT0 ( " \n " ) ; DBG_DUMP_FS ( & sblock , " " ) ; DBG_LEAVE ; return ; }
Here we actually start growing the file system.
Here we actually start growing the file system .
/*
	 * Get the cylinder summary into the memory.
	 */ /* FS_DEBUG */ /*
	 * Do all needed changes in the former last cylinder group.
	 */ /*
	 * Dump out summary information about file system.
	 */ /* FS_DEBUG */ /*
	 * Now build the cylinders group blocks and
	 * then print out indices of cylinder groups.
	 */ /*
	 * Iterate for only the new cylinder groups.
	 */ /*
	 * Do all needed changes in the first cylinder group.
	 * allocate blocks in new location
	 */ /*
	 * Now write the cylinder summary back to disk.
	 */ /* FS_DEBUG */ /*
	 * Now write the new superblock back to disk.
	 */ /*
	 * Clean up the dynamic fields in our superblock copies.
	 */ /*
	 * XXX
	 * The following fields are currently distributed from the superblock
	 * to the copies:
	 *     fs_minfree
	 *     fs_rotdelay
	 *     fs_maxcontig
	 *     fs_maxbpg
	 *     fs_minfree,
	 *     fs_optim
	 *     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
	 * system were created initially with the new size. Therefor we still
	 * need to find an easy way of calculating that.
	 * Possibly we can try to read the first superblock copy and apply the
	 * "diffed" stats between the old and new superblock by still copying
	 * certain parameters onto that.
	 */ /*
	 * Write out the duplicate super blocks.
	 */