xref: /dflybsd-src/usr.sbin/makefs/ffs/mkfs.c (revision d0a13d2ff133469dfc81f38950a52add4ff904e7)
15978408cSSascha Wildner /*	$NetBSD: mkfs.c,v 1.22 2011/10/09 22:30:13 christos Exp $	*/
25978408cSSascha Wildner 
35978408cSSascha Wildner /*-
45978408cSSascha Wildner  * SPDX-License-Identifier: BSD-3-Clause
55978408cSSascha Wildner  *
65978408cSSascha Wildner  * Copyright (c) 2002 Networks Associates Technology, Inc.
75978408cSSascha Wildner  * All rights reserved.
85978408cSSascha Wildner  *
95978408cSSascha Wildner  * This software was developed for the FreeBSD Project by Marshall
105978408cSSascha Wildner  * Kirk McKusick and Network Associates Laboratories, the Security
115978408cSSascha Wildner  * Research Division of Network Associates, Inc. under DARPA/SPAWAR
125978408cSSascha Wildner  * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
135978408cSSascha Wildner  * research program
145978408cSSascha Wildner  *
155978408cSSascha Wildner  * Copyright (c) 1980, 1989, 1993
165978408cSSascha Wildner  *	The Regents of the University of California.  All rights reserved.
175978408cSSascha Wildner  *
185978408cSSascha Wildner  * Redistribution and use in source and binary forms, with or without
195978408cSSascha Wildner  * modification, are permitted provided that the following conditions
205978408cSSascha Wildner  * are met:
215978408cSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
225978408cSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
235978408cSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
245978408cSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
255978408cSSascha Wildner  *    documentation and/or other materials provided with the distribution.
265978408cSSascha Wildner  * 3. Neither the name of the University nor the names of its contributors
275978408cSSascha Wildner  *    may be used to endorse or promote products derived from this software
285978408cSSascha Wildner  *    without specific prior written permission.
295978408cSSascha Wildner  *
305978408cSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
315978408cSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
325978408cSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
335978408cSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
345978408cSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
355978408cSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
365978408cSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
375978408cSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
385978408cSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
395978408cSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
405978408cSSascha Wildner  * SUCH DAMAGE.
41811c2036SSascha Wildner  *
42811c2036SSascha Wildner  * $FreeBSD: head/usr.sbin/makefs/ffs/mkfs.c 326025 2017-11-20 19:49:47Z pfg $
435978408cSSascha Wildner  */
445978408cSSascha Wildner 
455978408cSSascha Wildner #include <sys/param.h>
465978408cSSascha Wildner #include <sys/time.h>
475978408cSSascha Wildner #include <sys/resource.h>
485978408cSSascha Wildner 
495978408cSSascha Wildner #include <stdio.h>
505978408cSSascha Wildner #include <stdlib.h>
515978408cSSascha Wildner #include <string.h>
525978408cSSascha Wildner #include <unistd.h>
535978408cSSascha Wildner #include <errno.h>
545978408cSSascha Wildner #include <util.h>
555978408cSSascha Wildner 
565978408cSSascha Wildner #include "makefs.h"
575978408cSSascha Wildner #include "ffs.h"
585978408cSSascha Wildner 
59346b9dadSzrj #include <vfs/ufs/dinode.h>
60346b9dadSzrj #include <vfs/ufs/fs.h>
615978408cSSascha Wildner 
625978408cSSascha Wildner #include "ffs/ufs_bswap.h"
635978408cSSascha Wildner #include "ffs/ufs_inode.h"
645978408cSSascha Wildner #include "ffs/ffs_extern.h"
655978408cSSascha Wildner #include "ffs/newfs_extern.h"
665978408cSSascha Wildner 
675978408cSSascha Wildner #ifndef BBSIZE
685978408cSSascha Wildner #define	BBSIZE	8192			/* size of boot area, with label */
695978408cSSascha Wildner #endif
705978408cSSascha Wildner 
715978408cSSascha Wildner static void initcg(uint32_t, time_t, const fsinfo_t *);
725978408cSSascha Wildner static int ilog2(int);
735978408cSSascha Wildner 
745978408cSSascha Wildner static int count_digits(int);
755978408cSSascha Wildner 
765978408cSSascha Wildner /*
775978408cSSascha Wildner  * make file system for cylinder-group style file systems
785978408cSSascha Wildner  */
795978408cSSascha Wildner #define	UMASK		0755
805978408cSSascha Wildner 
815978408cSSascha Wildner static union {
825978408cSSascha Wildner 	struct fs fs;
835978408cSSascha Wildner 	char pad[SBLOCKSIZE];
845978408cSSascha Wildner } fsun;
855978408cSSascha Wildner #define	sblock	fsun.fs
865978408cSSascha Wildner 
875978408cSSascha Wildner static union {
885978408cSSascha Wildner 	struct cg cg;
895978408cSSascha Wildner 	char pad[FFS_MAXBSIZE];
905978408cSSascha Wildner } cgun;
915978408cSSascha Wildner #define	acg	cgun.cg
925978408cSSascha Wildner 
935978408cSSascha Wildner static char *iobuf;
945978408cSSascha Wildner static int iobufsize;
955978408cSSascha Wildner 
965978408cSSascha Wildner static char writebuf[FFS_MAXBSIZE];
975978408cSSascha Wildner 
985978408cSSascha Wildner static int     Oflag;	   /* format as an 4.3BSD file system */
995978408cSSascha Wildner static int64_t fssize;	   /* file system size */
1005978408cSSascha Wildner static int     sectorsize;	   /* bytes/sector */
1015978408cSSascha Wildner static int     fsize;	   /* fragment size */
1025978408cSSascha Wildner static int     bsize;	   /* block size */
103811c2036SSascha Wildner #ifndef __DragonFly__
1045978408cSSascha Wildner static int     maxbsize;   /* maximum clustering */
105811c2036SSascha Wildner #endif
1065978408cSSascha Wildner static int     maxblkspercg;
1075978408cSSascha Wildner static int     minfree;	   /* free space threshold */
1085978408cSSascha Wildner static int     opt;		   /* optimization preference (space or time) */
1095978408cSSascha Wildner static int     density;	   /* number of bytes per inode */
1105978408cSSascha Wildner static int     maxcontig;	   /* max contiguous blocks to allocate */
1115978408cSSascha Wildner static int     maxbpg;	   /* maximum blocks per file in a cyl group */
1125978408cSSascha Wildner static int     bbsize;	   /* boot block size */
1135978408cSSascha Wildner static int     sbsize;	   /* superblock size */
1145978408cSSascha Wildner static int     avgfilesize;	   /* expected average file size */
1155978408cSSascha Wildner static int     avgfpdir;	   /* expected number of files per directory */
1165978408cSSascha Wildner 
1175978408cSSascha Wildner struct fs *
ffs_mkfs(const char * fsys,const fsinfo_t * fsopts,time_t tstamp)1185978408cSSascha Wildner ffs_mkfs(const char *fsys, const fsinfo_t *fsopts, time_t tstamp)
1195978408cSSascha Wildner {
1207660903bSTomohiro Kusumi 	int fragsperinode, optimalfpg, origdensity, mindensity;
1217660903bSTomohiro Kusumi 	int minfpg, lastminfpg;
1225978408cSSascha Wildner 	int32_t csfrags;
1235978408cSSascha Wildner 	uint32_t i, cylno;
1245978408cSSascha Wildner 	long long sizepb;
1257660903bSTomohiro Kusumi 	ino_t maxinum;
1267660903bSTomohiro Kusumi 	int minfragsperinode;   /* minimum ratio of frags to inodes */
1275978408cSSascha Wildner 	void *space;
1285978408cSSascha Wildner 	int size;
1295978408cSSascha Wildner 	int nprintcols, printcolwidth;
1305978408cSSascha Wildner 	ffs_opt_t	*ffs_opts = fsopts->fs_specific;
1315978408cSSascha Wildner 
1325978408cSSascha Wildner 	Oflag =		ffs_opts->version;
1335978408cSSascha Wildner 	fssize =        fsopts->size / fsopts->sectorsize;
1345978408cSSascha Wildner 	sectorsize =    fsopts->sectorsize;
1355978408cSSascha Wildner 	fsize =         ffs_opts->fsize;
1365978408cSSascha Wildner 	bsize =         ffs_opts->bsize;
137811c2036SSascha Wildner #ifndef __DragonFly__
1385978408cSSascha Wildner 	maxbsize =      ffs_opts->maxbsize;
139811c2036SSascha Wildner #endif
1405978408cSSascha Wildner 	maxblkspercg =  ffs_opts->maxblkspercg;
1415978408cSSascha Wildner 	minfree =       ffs_opts->minfree;
1425978408cSSascha Wildner 	opt =           ffs_opts->optimization;
1435978408cSSascha Wildner 	density =       ffs_opts->density;
1445978408cSSascha Wildner 	maxcontig =     ffs_opts->maxcontig;
1455978408cSSascha Wildner 	maxbpg =        ffs_opts->maxbpg;
1465978408cSSascha Wildner 	avgfilesize =   ffs_opts->avgfilesize;
1475978408cSSascha Wildner 	avgfpdir =      ffs_opts->avgfpdir;
1485978408cSSascha Wildner 	bbsize =        BBSIZE;
1495978408cSSascha Wildner 	sbsize =        SBLOCKSIZE;
1505978408cSSascha Wildner 
151c3ba2018STomohiro Kusumi 	strlcpy((char *)sblock.fs_volname, ffs_opts->label,
152c3ba2018STomohiro Kusumi 	    sizeof(sblock.fs_volname));
1535978408cSSascha Wildner 
154811c2036SSascha Wildner #ifndef __DragonFly__ /* XXX dead code */
1555978408cSSascha Wildner 	if (Oflag == 0) {
1565978408cSSascha Wildner 		sblock.fs_old_inodefmt = FS_42INODEFMT;
1575978408cSSascha Wildner 		sblock.fs_maxsymlinklen = 0;
1585978408cSSascha Wildner 		sblock.fs_old_flags = 0;
159811c2036SSascha Wildner 	} else
160811c2036SSascha Wildner #endif
161811c2036SSascha Wildner 	{
1625978408cSSascha Wildner 		sblock.fs_old_inodefmt = FS_44INODEFMT;
163811c2036SSascha Wildner #ifndef __DragonFly__ /* XXX UFS2 */
1645978408cSSascha Wildner 		sblock.fs_maxsymlinklen = (Oflag == 1 ? UFS1_MAXSYMLINKLEN :
1655978408cSSascha Wildner 		    UFS2_MAXSYMLINKLEN);
166811c2036SSascha Wildner #else
167811c2036SSascha Wildner 		sblock.fs_maxsymlinklen = UFS1_MAXSYMLINKLEN;
168811c2036SSascha Wildner #endif
169811c2036SSascha Wildner #ifndef __DragonFly__
1705978408cSSascha Wildner 		sblock.fs_old_flags = FS_FLAGS_UPDATED;
171811c2036SSascha Wildner #endif
1725978408cSSascha Wildner 		sblock.fs_flags = 0;
1735978408cSSascha Wildner 	}
1745978408cSSascha Wildner 	/*
1755978408cSSascha Wildner 	 * Validate the given file system size.
1765978408cSSascha Wildner 	 * Verify that its last block can actually be accessed.
1775978408cSSascha Wildner 	 * Convert to file system fragment sized units.
1785978408cSSascha Wildner 	 */
1795978408cSSascha Wildner 	if (fssize <= 0) {
1805978408cSSascha Wildner 		printf("preposterous size %lld\n", (long long)fssize);
1815978408cSSascha Wildner 		exit(13);
1825978408cSSascha Wildner 	}
1835978408cSSascha Wildner 	ffs_wtfs(fssize - 1, sectorsize, (char *)&sblock, fsopts);
1845978408cSSascha Wildner 
1855978408cSSascha Wildner 	/*
1865978408cSSascha Wildner 	 * collect and verify the filesystem density info
1875978408cSSascha Wildner 	 */
1885978408cSSascha Wildner 	sblock.fs_avgfilesize = avgfilesize;
1895978408cSSascha Wildner 	sblock.fs_avgfpdir = avgfpdir;
1905978408cSSascha Wildner 	if (sblock.fs_avgfilesize <= 0)
1915978408cSSascha Wildner 		printf("illegal expected average file size %d\n",
1925978408cSSascha Wildner 		    sblock.fs_avgfilesize), exit(14);
1935978408cSSascha Wildner 	if (sblock.fs_avgfpdir <= 0)
1945978408cSSascha Wildner 		printf("illegal expected number of files per directory %d\n",
1955978408cSSascha Wildner 		    sblock.fs_avgfpdir), exit(15);
1965978408cSSascha Wildner 	/*
1975978408cSSascha Wildner 	 * collect and verify the block and fragment sizes
1985978408cSSascha Wildner 	 */
1995978408cSSascha Wildner 	sblock.fs_bsize = bsize;
2005978408cSSascha Wildner 	sblock.fs_fsize = fsize;
201161c3d83SSascha Wildner 	if (!powerof2(sblock.fs_bsize)) {
2025978408cSSascha Wildner 		printf("block size must be a power of 2, not %d\n",
2035978408cSSascha Wildner 		    sblock.fs_bsize);
2045978408cSSascha Wildner 		exit(16);
2055978408cSSascha Wildner 	}
206161c3d83SSascha Wildner 	if (!powerof2(sblock.fs_fsize)) {
2075978408cSSascha Wildner 		printf("fragment size must be a power of 2, not %d\n",
2085978408cSSascha Wildner 		    sblock.fs_fsize);
2095978408cSSascha Wildner 		exit(17);
2105978408cSSascha Wildner 	}
2115978408cSSascha Wildner 	if (sblock.fs_fsize < sectorsize) {
2125978408cSSascha Wildner 		printf("fragment size %d is too small, minimum is %d\n",
2135978408cSSascha Wildner 		    sblock.fs_fsize, sectorsize);
2145978408cSSascha Wildner 		exit(18);
2155978408cSSascha Wildner 	}
2165978408cSSascha Wildner 	if (sblock.fs_bsize < MINBSIZE) {
2175978408cSSascha Wildner 		printf("block size %d is too small, minimum is %d\n",
2185978408cSSascha Wildner 		    sblock.fs_bsize, MINBSIZE);
2195978408cSSascha Wildner 		exit(19);
2205978408cSSascha Wildner 	}
2215978408cSSascha Wildner 	if (sblock.fs_bsize > FFS_MAXBSIZE) {
2225978408cSSascha Wildner 		printf("block size %d is too large, maximum is %d\n",
2235978408cSSascha Wildner 		    sblock.fs_bsize, FFS_MAXBSIZE);
2245978408cSSascha Wildner 		exit(19);
2255978408cSSascha Wildner 	}
2265978408cSSascha Wildner 	if (sblock.fs_bsize < sblock.fs_fsize) {
2275978408cSSascha Wildner 		printf("block size (%d) cannot be smaller than fragment size (%d)\n",
2285978408cSSascha Wildner 		    sblock.fs_bsize, sblock.fs_fsize);
2295978408cSSascha Wildner 		exit(20);
2305978408cSSascha Wildner 	}
2315978408cSSascha Wildner 
232811c2036SSascha Wildner #ifndef __DragonFly__
233161c3d83SSascha Wildner 	if (maxbsize < bsize || !powerof2(maxbsize)) {
2345978408cSSascha Wildner 		sblock.fs_maxbsize = sblock.fs_bsize;
2355978408cSSascha Wildner 		printf("Extent size set to %d\n", sblock.fs_maxbsize);
2365978408cSSascha Wildner 	} else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) {
2375978408cSSascha Wildner 		sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize;
2385978408cSSascha Wildner 		printf("Extent size reduced to %d\n", sblock.fs_maxbsize);
2395978408cSSascha Wildner 	} else {
2405978408cSSascha Wildner 		sblock.fs_maxbsize = maxbsize;
2415978408cSSascha Wildner 	}
242811c2036SSascha Wildner #endif
2435978408cSSascha Wildner 	sblock.fs_maxcontig = maxcontig;
244811c2036SSascha Wildner #ifndef __DragonFly__
2455978408cSSascha Wildner 	if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) {
2465978408cSSascha Wildner 		sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize;
2475978408cSSascha Wildner 		printf("Maxcontig raised to %d\n", sblock.fs_maxbsize);
2485978408cSSascha Wildner 	}
249811c2036SSascha Wildner #endif
2505978408cSSascha Wildner 
2515978408cSSascha Wildner 	if (sblock.fs_maxcontig > 1)
2525978408cSSascha Wildner 		sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG);
2535978408cSSascha Wildner 
2545978408cSSascha Wildner 	sblock.fs_bmask = ~(sblock.fs_bsize - 1);
2555978408cSSascha Wildner 	sblock.fs_fmask = ~(sblock.fs_fsize - 1);
2565978408cSSascha Wildner 	sblock.fs_qbmask = ~sblock.fs_bmask;
2575978408cSSascha Wildner 	sblock.fs_qfmask = ~sblock.fs_fmask;
2585978408cSSascha Wildner 	for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
2595978408cSSascha Wildner 		sblock.fs_bshift++;
2605978408cSSascha Wildner 	for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
2615978408cSSascha Wildner 		sblock.fs_fshift++;
2625978408cSSascha Wildner 	sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
2635978408cSSascha Wildner 	for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
2645978408cSSascha Wildner 		sblock.fs_fragshift++;
2655978408cSSascha Wildner 	if (sblock.fs_frag > MAXFRAG) {
2665978408cSSascha Wildner 		printf("fragment size %d is too small, "
2675978408cSSascha Wildner 			"minimum with block size %d is %d\n",
2685978408cSSascha Wildner 		    sblock.fs_fsize, sblock.fs_bsize,
2695978408cSSascha Wildner 		    sblock.fs_bsize / MAXFRAG);
2705978408cSSascha Wildner 		exit(21);
2715978408cSSascha Wildner 	}
2725978408cSSascha Wildner 	sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize);
273811c2036SSascha Wildner #ifndef __DragonFly__
2745978408cSSascha Wildner 	sblock.fs_size = sblock.fs_providersize = fssize =
2755978408cSSascha Wildner 	    dbtofsb(&sblock, fssize);
276811c2036SSascha Wildner #else
277811c2036SSascha Wildner 	sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
278811c2036SSascha Wildner #endif
2795978408cSSascha Wildner 
2805978408cSSascha Wildner 	if (Oflag <= 1) {
2815978408cSSascha Wildner 		sblock.fs_magic = FS_UFS1_MAGIC;
282811c2036SSascha Wildner #ifndef __DragonFly__
2835978408cSSascha Wildner 		sblock.fs_sblockloc = SBLOCK_UFS1;
284811c2036SSascha Wildner #endif
2855978408cSSascha Wildner 		sblock.fs_nindir = sblock.fs_bsize / sizeof(ufs1_daddr_t);
2865978408cSSascha Wildner 		sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode);
2875978408cSSascha Wildner 		sblock.fs_maxsymlinklen = ((UFS_NDADDR + UFS_NIADDR) *
2885978408cSSascha Wildner 		    sizeof (ufs1_daddr_t));
2895978408cSSascha Wildner 		sblock.fs_old_inodefmt = FS_44INODEFMT;
2905978408cSSascha Wildner 		sblock.fs_old_cgoffset = 0;
2915978408cSSascha Wildner 		sblock.fs_old_cgmask = 0xffffffff;
292811c2036SSascha Wildner #ifndef __DragonFly__
2935978408cSSascha Wildner 		sblock.fs_old_size = sblock.fs_size;
294811c2036SSascha Wildner #endif
2955978408cSSascha Wildner 		sblock.fs_old_rotdelay = 0;
2965978408cSSascha Wildner 		sblock.fs_old_rps = 60;
2975978408cSSascha Wildner 		sblock.fs_old_nspf = sblock.fs_fsize / sectorsize;
2985978408cSSascha Wildner 		sblock.fs_old_cpg = 1;
2995978408cSSascha Wildner 		sblock.fs_old_interleave = 1;
3005978408cSSascha Wildner 		sblock.fs_old_trackskew = 0;
3015978408cSSascha Wildner 		sblock.fs_old_cpc = 0;
3025978408cSSascha Wildner 		sblock.fs_old_postblformat = 1;
3035978408cSSascha Wildner 		sblock.fs_old_nrpos = 1;
304811c2036SSascha Wildner #ifdef __DragonFly__	/* softupdates support */
305811c2036SSascha Wildner 		if (ffs_opts->softupdates == 1)
306811c2036SSascha Wildner 			sblock.fs_flags |= FS_DOSOFTDEP;
307811c2036SSascha Wildner #else	/* XXX UFS2 */
3085978408cSSascha Wildner 	} else {
3095978408cSSascha Wildner 		sblock.fs_magic = FS_UFS2_MAGIC;
3105978408cSSascha Wildner 		sblock.fs_sblockloc = SBLOCK_UFS2;
3115978408cSSascha Wildner 		sblock.fs_nindir = sblock.fs_bsize / sizeof(ufs2_daddr_t);
3125978408cSSascha Wildner 		sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode);
3135978408cSSascha Wildner 		sblock.fs_maxsymlinklen = ((UFS_NDADDR + UFS_NIADDR) *
3145978408cSSascha Wildner 		    sizeof (ufs2_daddr_t));
3155978408cSSascha Wildner 		if (ffs_opts->softupdates == 1)
3165978408cSSascha Wildner 			sblock.fs_flags |= FS_DOSOFTDEP;
317811c2036SSascha Wildner #endif
3185978408cSSascha Wildner 	}
3195978408cSSascha Wildner 
3205978408cSSascha Wildner 	sblock.fs_sblkno =
321811c2036SSascha Wildner #ifndef __DragonFly__
3225978408cSSascha Wildner 	    roundup(howmany(sblock.fs_sblockloc + SBLOCKSIZE, sblock.fs_fsize),
323811c2036SSascha Wildner #else
324811c2036SSascha Wildner 	    roundup(howmany(8192 + SBLOCKSIZE, sblock.fs_fsize),
325811c2036SSascha Wildner #endif
3265978408cSSascha Wildner 		sblock.fs_frag);
327811c2036SSascha Wildner 	sblock.fs_cblkno = (makefs_daddr_t)(sblock.fs_sblkno +
3285978408cSSascha Wildner 	    roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag));
3295978408cSSascha Wildner 	sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
3305978408cSSascha Wildner 	sblock.fs_maxfilesize = sblock.fs_bsize * UFS_NDADDR - 1;
3315978408cSSascha Wildner 	for (sizepb = sblock.fs_bsize, i = 0; i < UFS_NIADDR; i++) {
3325978408cSSascha Wildner 		sizepb *= NINDIR(&sblock);
3335978408cSSascha Wildner 		sblock.fs_maxfilesize += sizepb;
3345978408cSSascha Wildner 	}
3355978408cSSascha Wildner 
3365978408cSSascha Wildner 	/*
3375978408cSSascha Wildner 	 * Calculate the number of blocks to put into each cylinder group.
3385978408cSSascha Wildner 	 *
3395978408cSSascha Wildner 	 * This algorithm selects the number of blocks per cylinder
3405978408cSSascha Wildner 	 * group. The first goal is to have at least enough data blocks
3415978408cSSascha Wildner 	 * in each cylinder group to meet the density requirement. Once
3425978408cSSascha Wildner 	 * this goal is achieved we try to expand to have at least
3435978408cSSascha Wildner 	 * 1 cylinder group. Once this goal is achieved, we pack as
3445978408cSSascha Wildner 	 * many blocks into each cylinder group map as will fit.
3455978408cSSascha Wildner 	 *
3465978408cSSascha Wildner 	 * We start by calculating the smallest number of blocks that we
3475978408cSSascha Wildner 	 * can put into each cylinder group. If this is too big, we reduce
3485978408cSSascha Wildner 	 * the density until it fits.
3495978408cSSascha Wildner 	 */
3507660903bSTomohiro Kusumi 	maxinum = (((int64_t)(1)) << 32) - INOPB(&sblock);
3517660903bSTomohiro Kusumi 	minfragsperinode = 1 + fssize / maxinum;
3527660903bSTomohiro Kusumi 	mindensity = minfragsperinode * fsize;
3537660903bSTomohiro Kusumi 	if (density == 0)
3547660903bSTomohiro Kusumi 		density = MAX(2, minfragsperinode) * fsize;
3557660903bSTomohiro Kusumi 	if (density < mindensity) {
3565978408cSSascha Wildner 		origdensity = density;
3577660903bSTomohiro Kusumi 		density = mindensity;
3587660903bSTomohiro Kusumi 		fprintf(stderr, "density increased from %d to %d\n",
3597660903bSTomohiro Kusumi 		    origdensity, density);
3607660903bSTomohiro Kusumi 	}
3617660903bSTomohiro Kusumi 	origdensity = density;
3627660903bSTomohiro Kusumi 	if (!ffs_opts->min_inodes)
3637660903bSTomohiro Kusumi 		density = MIN(density, MAX(2, minfragsperinode) * fsize);
3645978408cSSascha Wildner 	for (;;) {
3655978408cSSascha Wildner 		fragsperinode = MAX(numfrags(&sblock, density), 1);
3665978408cSSascha Wildner 		minfpg = fragsperinode * INOPB(&sblock);
3675978408cSSascha Wildner 		if (minfpg > sblock.fs_size)
3685978408cSSascha Wildner 			minfpg = sblock.fs_size;
3695978408cSSascha Wildner 		sblock.fs_ipg = INOPB(&sblock);
3705978408cSSascha Wildner 		sblock.fs_fpg = roundup(sblock.fs_iblkno +
3715978408cSSascha Wildner 		    sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
3725978408cSSascha Wildner 		if (sblock.fs_fpg < minfpg)
3735978408cSSascha Wildner 			sblock.fs_fpg = minfpg;
3745978408cSSascha Wildner 		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
3755978408cSSascha Wildner 		    INOPB(&sblock));
3765978408cSSascha Wildner 		sblock.fs_fpg = roundup(sblock.fs_iblkno +
3775978408cSSascha Wildner 		    sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
3785978408cSSascha Wildner 		if (sblock.fs_fpg < minfpg)
3795978408cSSascha Wildner 			sblock.fs_fpg = minfpg;
3805978408cSSascha Wildner 		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
3815978408cSSascha Wildner 		    INOPB(&sblock));
382811c2036SSascha Wildner #ifndef __DragonFly__
3835978408cSSascha Wildner 		if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
3845978408cSSascha Wildner 			break;
385811c2036SSascha Wildner #else
386811c2036SSascha Wildner 		if (FBSD_CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
387811c2036SSascha Wildner 			break;
388811c2036SSascha Wildner #endif
3895978408cSSascha Wildner 		density -= sblock.fs_fsize;
3905978408cSSascha Wildner 	}
3915978408cSSascha Wildner 	if (density != origdensity)
3925978408cSSascha Wildner 		printf("density reduced from %d to %d\n", origdensity, density);
3935978408cSSascha Wildner 
3945978408cSSascha Wildner 	if (maxblkspercg <= 0 || maxblkspercg >= fssize)
3955978408cSSascha Wildner 		maxblkspercg = fssize - 1;
3965978408cSSascha Wildner 	/*
3975978408cSSascha Wildner 	 * Start packing more blocks into the cylinder group until
3985978408cSSascha Wildner 	 * it cannot grow any larger, the number of cylinder groups
3995978408cSSascha Wildner 	 * drops below 1, or we reach the size requested.
4005978408cSSascha Wildner 	 */
4015978408cSSascha Wildner 	for ( ; sblock.fs_fpg < maxblkspercg; sblock.fs_fpg += sblock.fs_frag) {
4025978408cSSascha Wildner 		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
4035978408cSSascha Wildner 		    INOPB(&sblock));
4045978408cSSascha Wildner 		if (sblock.fs_size / sblock.fs_fpg < 1)
4055978408cSSascha Wildner 			break;
406811c2036SSascha Wildner #ifndef __DragonFly__
4075978408cSSascha Wildner 		if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
4085978408cSSascha Wildner 			continue;
4095978408cSSascha Wildner 		if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
4105978408cSSascha Wildner 			break;
411811c2036SSascha Wildner #else
412811c2036SSascha Wildner 		if (FBSD_CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
413811c2036SSascha Wildner 			continue;
414811c2036SSascha Wildner 		if (FBSD_CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
415811c2036SSascha Wildner 			break;
416811c2036SSascha Wildner #endif
4175978408cSSascha Wildner 		sblock.fs_fpg -= sblock.fs_frag;
4185978408cSSascha Wildner 		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
4195978408cSSascha Wildner 		    INOPB(&sblock));
4205978408cSSascha Wildner 		break;
4215978408cSSascha Wildner 	}
4225978408cSSascha Wildner 	/*
4235978408cSSascha Wildner 	 * Check to be sure that the last cylinder group has enough blocks
4245978408cSSascha Wildner 	 * to be viable. If it is too small, reduce the number of blocks
4255978408cSSascha Wildner 	 * per cylinder group which will have the effect of moving more
4265978408cSSascha Wildner 	 * blocks into the last cylinder group.
4275978408cSSascha Wildner 	 */
4285978408cSSascha Wildner 	optimalfpg = sblock.fs_fpg;
4295978408cSSascha Wildner 	for (;;) {
4305978408cSSascha Wildner 		sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
4315978408cSSascha Wildner 		lastminfpg = roundup(sblock.fs_iblkno +
4325978408cSSascha Wildner 		    sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
4335978408cSSascha Wildner 		if (sblock.fs_size < lastminfpg) {
4345978408cSSascha Wildner 			printf("Filesystem size %lld < minimum size of %d\n",
4355978408cSSascha Wildner 			    (long long)sblock.fs_size, lastminfpg);
4365978408cSSascha Wildner 			exit(28);
4375978408cSSascha Wildner 		}
4385978408cSSascha Wildner 		if (sblock.fs_size % sblock.fs_fpg >= lastminfpg ||
4395978408cSSascha Wildner 		    sblock.fs_size % sblock.fs_fpg == 0)
4405978408cSSascha Wildner 			break;
4415978408cSSascha Wildner 		sblock.fs_fpg -= sblock.fs_frag;
4425978408cSSascha Wildner 		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
4435978408cSSascha Wildner 		    INOPB(&sblock));
4445978408cSSascha Wildner 	}
4455978408cSSascha Wildner 	if (optimalfpg != sblock.fs_fpg)
4465978408cSSascha Wildner 		printf("Reduced frags per cylinder group from %d to %d %s\n",
4475978408cSSascha Wildner 		   optimalfpg, sblock.fs_fpg, "to enlarge last cyl group");
448811c2036SSascha Wildner #ifndef __DragonFly__
4495978408cSSascha Wildner 	sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
450811c2036SSascha Wildner #else
451811c2036SSascha Wildner 	sblock.fs_cgsize = fragroundup(&sblock, FBSD_CGSIZE(&sblock));
452811c2036SSascha Wildner #endif
4535978408cSSascha Wildner 	sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
4545978408cSSascha Wildner 	if (Oflag <= 1) {
4555978408cSSascha Wildner 		sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf;
4565978408cSSascha Wildner 		sblock.fs_old_nsect = sblock.fs_old_spc;
4575978408cSSascha Wildner 		sblock.fs_old_npsect = sblock.fs_old_spc;
4585978408cSSascha Wildner 		sblock.fs_old_ncyl = sblock.fs_ncg;
4595978408cSSascha Wildner 	}
4605978408cSSascha Wildner 
4615978408cSSascha Wildner 	/*
4625978408cSSascha Wildner 	 * fill in remaining fields of the super block
4635978408cSSascha Wildner 	 */
4645978408cSSascha Wildner 	sblock.fs_csaddr = cgdmin(&sblock, 0);
4655978408cSSascha Wildner 	sblock.fs_cssize =
4665978408cSSascha Wildner 	    fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
4675978408cSSascha Wildner 
4685978408cSSascha Wildner 	/*
4695978408cSSascha Wildner 	 * Setup memory for temporary in-core cylgroup summaries.
4705978408cSSascha Wildner 	 * Cribbed from ffs_mountfs().
4715978408cSSascha Wildner 	 */
4725978408cSSascha Wildner 	size = sblock.fs_cssize;
4735978408cSSascha Wildner 	if (sblock.fs_contigsumsize > 0)
4745978408cSSascha Wildner 		size += sblock.fs_ncg * sizeof(int32_t);
4755978408cSSascha Wildner 	space = ecalloc(1, size);
4765978408cSSascha Wildner 	sblock.fs_csp = space;
4775978408cSSascha Wildner 	space = (char *)space + sblock.fs_cssize;
4785978408cSSascha Wildner 	if (sblock.fs_contigsumsize > 0) {
4795978408cSSascha Wildner 		int32_t *lp;
4805978408cSSascha Wildner 
4815978408cSSascha Wildner 		sblock.fs_maxcluster = lp = space;
4825978408cSSascha Wildner 		for (i = 0; i < sblock.fs_ncg; i++)
4835978408cSSascha Wildner 		*lp++ = sblock.fs_contigsumsize;
4845978408cSSascha Wildner 	}
4855978408cSSascha Wildner 
4865978408cSSascha Wildner 	sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
4875978408cSSascha Wildner 	if (sblock.fs_sbsize > SBLOCKSIZE)
4885978408cSSascha Wildner 		sblock.fs_sbsize = SBLOCKSIZE;
4895978408cSSascha Wildner 	sblock.fs_minfree = minfree;
4905978408cSSascha Wildner 	sblock.fs_maxcontig = maxcontig;
4915978408cSSascha Wildner 	sblock.fs_maxbpg = maxbpg;
4925978408cSSascha Wildner 	sblock.fs_optim = opt;
4935978408cSSascha Wildner 	sblock.fs_cgrotor = 0;
4945978408cSSascha Wildner 	sblock.fs_pendingblocks = 0;
4955978408cSSascha Wildner 	sblock.fs_pendinginodes = 0;
4965978408cSSascha Wildner 	sblock.fs_cstotal.cs_ndir = 0;
4975978408cSSascha Wildner 	sblock.fs_cstotal.cs_nbfree = 0;
4985978408cSSascha Wildner 	sblock.fs_cstotal.cs_nifree = 0;
4995978408cSSascha Wildner 	sblock.fs_cstotal.cs_nffree = 0;
5005978408cSSascha Wildner 	sblock.fs_fmod = 0;
5015978408cSSascha Wildner 	sblock.fs_ronly = 0;
5025978408cSSascha Wildner 	sblock.fs_state = 0;
5035978408cSSascha Wildner 	sblock.fs_clean = FS_ISCLEAN;
5045978408cSSascha Wildner 	sblock.fs_ronly = 0;
5055978408cSSascha Wildner 	sblock.fs_id[0] = tstamp;
5065978408cSSascha Wildner 	sblock.fs_id[1] = random();
5075978408cSSascha Wildner 	sblock.fs_fsmnt[0] = '\0';
5085978408cSSascha Wildner 	csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize);
5095978408cSSascha Wildner 	sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno -
5105978408cSSascha Wildner 	    sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno);
5115978408cSSascha Wildner 	sblock.fs_cstotal.cs_nbfree =
5125978408cSSascha Wildner 	    fragstoblks(&sblock, sblock.fs_dsize) -
5135978408cSSascha Wildner 	    howmany(csfrags, sblock.fs_frag);
5145978408cSSascha Wildner 	sblock.fs_cstotal.cs_nffree =
5155978408cSSascha Wildner 	    fragnum(&sblock, sblock.fs_size) +
5165978408cSSascha Wildner 	    (fragnum(&sblock, csfrags) > 0 ?
5175978408cSSascha Wildner 	    sblock.fs_frag - fragnum(&sblock, csfrags) : 0);
5185978408cSSascha Wildner 	sblock.fs_cstotal.cs_nifree =
5195978408cSSascha Wildner 	    sblock.fs_ncg * sblock.fs_ipg - UFS_ROOTINO;
5205978408cSSascha Wildner 	sblock.fs_cstotal.cs_ndir = 0;
5215978408cSSascha Wildner 	sblock.fs_dsize -= csfrags;
5225978408cSSascha Wildner 	sblock.fs_time = tstamp;
523811c2036SSascha Wildner #ifndef __DragonFly__
5245978408cSSascha Wildner 	if (Oflag <= 1) {
5255978408cSSascha Wildner 		sblock.fs_old_time = tstamp;
5265978408cSSascha Wildner 		sblock.fs_old_dsize = sblock.fs_dsize;
5275978408cSSascha Wildner 		sblock.fs_old_csaddr = sblock.fs_csaddr;
5285978408cSSascha Wildner 		sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
5295978408cSSascha Wildner 		sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
5305978408cSSascha Wildner 		sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
5315978408cSSascha Wildner 		sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
5325978408cSSascha Wildner 	}
533811c2036SSascha Wildner #endif
5345978408cSSascha Wildner 	/*
5355978408cSSascha Wildner 	 * Dump out summary information about file system.
5365978408cSSascha Wildner 	 */
5375978408cSSascha Wildner #define	B2MBFACTOR (1 / (1024.0 * 1024.0))
5385978408cSSascha Wildner 	printf("%s: %.1fMB (%lld sectors) block size %d, "
5395978408cSSascha Wildner 	       "fragment size %d\n",
5405978408cSSascha Wildner 	    fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
5415978408cSSascha Wildner 	    (long long)fsbtodb(&sblock, sblock.fs_size),
5425978408cSSascha Wildner 	    sblock.fs_bsize, sblock.fs_fsize);
5435978408cSSascha Wildner 	printf("\tusing %d cylinder groups of %.2fMB, %d blks, "
5445978408cSSascha Wildner 	       "%d inodes.\n",
5455978408cSSascha Wildner 	    sblock.fs_ncg,
5465978408cSSascha Wildner 	    (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
5475978408cSSascha Wildner 	    sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
5485978408cSSascha Wildner #undef B2MBFACTOR
5495978408cSSascha Wildner 	/*
5505978408cSSascha Wildner 	 * Now determine how wide each column will be, and calculate how
5515978408cSSascha Wildner 	 * many columns will fit in a 76 char line. 76 is the width of the
5525978408cSSascha Wildner 	 * subwindows in sysinst.
5535978408cSSascha Wildner 	 */
5545978408cSSascha Wildner 	printcolwidth = count_digits(
5555978408cSSascha Wildner 			fsbtodb(&sblock, cgsblock(&sblock, sblock.fs_ncg -1)));
5565978408cSSascha Wildner 	nprintcols = 76 / (printcolwidth + 2);
5575978408cSSascha Wildner 
5585978408cSSascha Wildner 	/*
5595978408cSSascha Wildner 	 * allocate space for superblock, cylinder group map, and
5605978408cSSascha Wildner 	 * two sets of inode blocks.
5615978408cSSascha Wildner 	 */
5625978408cSSascha Wildner 	if (sblock.fs_bsize < SBLOCKSIZE)
5635978408cSSascha Wildner 		iobufsize = SBLOCKSIZE + 3 * sblock.fs_bsize;
5645978408cSSascha Wildner 	else
5655978408cSSascha Wildner 		iobufsize = 4 * sblock.fs_bsize;
5665978408cSSascha Wildner 	iobuf = ecalloc(1, iobufsize);
5675978408cSSascha Wildner 	/*
5685978408cSSascha Wildner 	 * Make a copy of the superblock into the buffer that we will be
5695978408cSSascha Wildner 	 * writing out in each cylinder group.
5705978408cSSascha Wildner 	 */
5715978408cSSascha Wildner 	memcpy(writebuf, &sblock, sbsize);
5725978408cSSascha Wildner 	if (fsopts->needswap)
5735978408cSSascha Wildner 		ffs_sb_swap(&sblock, (struct fs*)writebuf);
5745978408cSSascha Wildner 	memcpy(iobuf, writebuf, SBLOCKSIZE);
5755978408cSSascha Wildner 
5765978408cSSascha Wildner 	printf("super-block backups (for fsck -b #) at:");
5775978408cSSascha Wildner 	for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
5785978408cSSascha Wildner 		initcg(cylno, tstamp, fsopts);
5795978408cSSascha Wildner 		if (cylno % nprintcols == 0)
5805978408cSSascha Wildner 			printf("\n");
5815978408cSSascha Wildner 		printf(" %*lld,", printcolwidth,
5825978408cSSascha Wildner 			(long long)fsbtodb(&sblock, cgsblock(&sblock, cylno)));
5835978408cSSascha Wildner 		fflush(stdout);
5845978408cSSascha Wildner 	}
5855978408cSSascha Wildner 	printf("\n");
5865978408cSSascha Wildner 
5875978408cSSascha Wildner 	/*
5885978408cSSascha Wildner 	 * Now construct the initial file system,
5895978408cSSascha Wildner 	 * then write out the super-block.
5905978408cSSascha Wildner 	 */
5915978408cSSascha Wildner 	sblock.fs_time = tstamp;
592811c2036SSascha Wildner #ifndef __DragonFly__
5935978408cSSascha Wildner 	if (Oflag <= 1) {
5945978408cSSascha Wildner 		sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
5955978408cSSascha Wildner 		sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
5965978408cSSascha Wildner 		sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
5975978408cSSascha Wildner 		sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
5985978408cSSascha Wildner 	}
599811c2036SSascha Wildner #endif
6005978408cSSascha Wildner 	if (fsopts->needswap)
6015978408cSSascha Wildner 		sblock.fs_flags |= FS_SWAPPED;
6025978408cSSascha Wildner 	ffs_write_superblock(&sblock, fsopts);
6035978408cSSascha Wildner 	return (&sblock);
6045978408cSSascha Wildner }
6055978408cSSascha Wildner 
6065978408cSSascha Wildner /*
6075978408cSSascha Wildner  * Write out the superblock and its duplicates,
6085978408cSSascha Wildner  * and the cylinder group summaries
6095978408cSSascha Wildner  */
6105978408cSSascha Wildner void
ffs_write_superblock(struct fs * fs,const fsinfo_t * fsopts)6115978408cSSascha Wildner ffs_write_superblock(struct fs *fs, const fsinfo_t *fsopts)
6125978408cSSascha Wildner {
6135978408cSSascha Wildner 	int size, blks, i, saveflag;
6145978408cSSascha Wildner 	uint32_t cylno;
6155978408cSSascha Wildner 	void *space;
6165978408cSSascha Wildner 	char *wrbuf;
6175978408cSSascha Wildner 
6185978408cSSascha Wildner 	saveflag = fs->fs_flags & FS_INTERNAL;
6195978408cSSascha Wildner 	fs->fs_flags &= ~FS_INTERNAL;
6205978408cSSascha Wildner 
6215978408cSSascha Wildner         memcpy(writebuf, &sblock, sbsize);
6225978408cSSascha Wildner 	if (fsopts->needswap)
6235978408cSSascha Wildner 		ffs_sb_swap(fs, (struct fs*)writebuf);
624811c2036SSascha Wildner #ifndef __DragonFly__
6255978408cSSascha Wildner 	ffs_wtfs(fs->fs_sblockloc / sectorsize, sbsize, writebuf, fsopts);
626811c2036SSascha Wildner #else
627811c2036SSascha Wildner 	ffs_wtfs(8192 / sectorsize, sbsize, writebuf, fsopts);
628811c2036SSascha Wildner #endif
6295978408cSSascha Wildner 
6305978408cSSascha Wildner 	/* Write out the duplicate super blocks */
6315978408cSSascha Wildner 	for (cylno = 0; cylno < fs->fs_ncg; cylno++)
6325978408cSSascha Wildner 		ffs_wtfs(fsbtodb(fs, cgsblock(fs, cylno)),
6335978408cSSascha Wildner 		    sbsize, writebuf, fsopts);
6345978408cSSascha Wildner 
6355978408cSSascha Wildner 	/* Write out the cylinder group summaries */
6365978408cSSascha Wildner 	size = fs->fs_cssize;
6375978408cSSascha Wildner 	blks = howmany(size, fs->fs_fsize);
6385978408cSSascha Wildner 	space = (void *)fs->fs_csp;
6395978408cSSascha Wildner 	wrbuf = emalloc(size);
6405978408cSSascha Wildner 	for (i = 0; i < blks; i+= fs->fs_frag) {
6415978408cSSascha Wildner 		size = fs->fs_bsize;
6425978408cSSascha Wildner 		if (i + fs->fs_frag > blks)
6435978408cSSascha Wildner 			size = (blks - i) * fs->fs_fsize;
6445978408cSSascha Wildner 		if (fsopts->needswap)
6455978408cSSascha Wildner 			ffs_csum_swap((struct csum *)space,
6465978408cSSascha Wildner 			    (struct csum *)wrbuf, size);
6475978408cSSascha Wildner 		else
6485978408cSSascha Wildner 			memcpy(wrbuf, space, (u_int)size);
6495978408cSSascha Wildner 		ffs_wtfs(fsbtodb(fs, fs->fs_csaddr + i), size, wrbuf, fsopts);
6505978408cSSascha Wildner 		space = (char *)space + size;
6515978408cSSascha Wildner 	}
6525978408cSSascha Wildner 	free(wrbuf);
6535978408cSSascha Wildner 	fs->fs_flags |= saveflag;
6545978408cSSascha Wildner }
6555978408cSSascha Wildner 
6565978408cSSascha Wildner /*
6575978408cSSascha Wildner  * Initialize a cylinder group.
6585978408cSSascha Wildner  */
6595978408cSSascha Wildner static void
initcg(uint32_t cylno,time_t utime,const fsinfo_t * fsopts)6605978408cSSascha Wildner initcg(uint32_t cylno, time_t utime, const fsinfo_t *fsopts)
6615978408cSSascha Wildner {
662811c2036SSascha Wildner 	makefs_daddr_t cbase, dmax;
6635978408cSSascha Wildner 	int32_t blkno;
6645978408cSSascha Wildner 	uint32_t i, j, d, dlower, dupper;
6655978408cSSascha Wildner 	struct ufs1_dinode *dp1;
666811c2036SSascha Wildner #ifndef __DragonFly__ /* XXX UFS2 */
6675978408cSSascha Wildner 	struct ufs2_dinode *dp2;
668811c2036SSascha Wildner #endif
6695978408cSSascha Wildner 	int start;
6705978408cSSascha Wildner 
6715978408cSSascha Wildner 	/*
6725978408cSSascha Wildner 	 * Determine block bounds for cylinder group.
6735978408cSSascha Wildner 	 * Allow space for super block summary information in first
6745978408cSSascha Wildner 	 * cylinder group.
6755978408cSSascha Wildner 	 */
6765978408cSSascha Wildner 	cbase = cgbase(&sblock, cylno);
6775978408cSSascha Wildner 	dmax = cbase + sblock.fs_fpg;
6785978408cSSascha Wildner 	if (dmax > sblock.fs_size)
6795978408cSSascha Wildner 		dmax = sblock.fs_size;
6805978408cSSascha Wildner 	dlower = cgsblock(&sblock, cylno) - cbase;
6815978408cSSascha Wildner 	dupper = cgdmin(&sblock, cylno) - cbase;
6825978408cSSascha Wildner 	if (cylno == 0)
6835978408cSSascha Wildner 		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
6845978408cSSascha Wildner 	memset(&acg, 0, sblock.fs_cgsize);
6855978408cSSascha Wildner 	acg.cg_time = utime;
6865978408cSSascha Wildner 	acg.cg_magic = CG_MAGIC;
6875978408cSSascha Wildner 	acg.cg_cgx = cylno;
6885978408cSSascha Wildner 	acg.cg_niblk = sblock.fs_ipg;
689811c2036SSascha Wildner #ifndef __DragonFly__ /* XXX UFS2 */
6905978408cSSascha Wildner 	acg.cg_initediblk = MIN(sblock.fs_ipg, 2 * INOPB(&sblock));
691811c2036SSascha Wildner #endif
6925978408cSSascha Wildner 	acg.cg_ndblk = dmax - cbase;
6935978408cSSascha Wildner 	if (sblock.fs_contigsumsize > 0)
6945978408cSSascha Wildner 		acg.cg_nclusterblks = acg.cg_ndblk >> sblock.fs_fragshift;
6955978408cSSascha Wildner 	start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
696811c2036SSascha Wildner #ifndef __DragonFly__ /* XXX UFS2 */
6975978408cSSascha Wildner 	if (Oflag == 2) {
6985978408cSSascha Wildner 		acg.cg_iusedoff = start;
699811c2036SSascha Wildner 	} else
700811c2036SSascha Wildner #endif
701811c2036SSascha Wildner 	{
7025978408cSSascha Wildner 		if (cylno == sblock.fs_ncg - 1)
703811c2036SSascha Wildner #ifndef __DragonFly__
7045978408cSSascha Wildner 			acg.cg_old_ncyl = howmany(acg.cg_ndblk,
7055978408cSSascha Wildner 			    sblock.fs_fpg / sblock.fs_old_cpg);
706811c2036SSascha Wildner #else
707811c2036SSascha Wildner 			acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
708811c2036SSascha Wildner #endif
7095978408cSSascha Wildner 		else
7105978408cSSascha Wildner 			acg.cg_old_ncyl = sblock.fs_old_cpg;
711811c2036SSascha Wildner #ifndef __DragonFly__
7125978408cSSascha Wildner 		acg.cg_old_time = acg.cg_time;
7135978408cSSascha Wildner 		acg.cg_time = 0;
7145978408cSSascha Wildner 		acg.cg_old_niblk = acg.cg_niblk;
7155978408cSSascha Wildner 		acg.cg_niblk = 0;
7165978408cSSascha Wildner 		acg.cg_initediblk = 0;
717811c2036SSascha Wildner #endif
7185978408cSSascha Wildner 		acg.cg_old_btotoff = start;
7195978408cSSascha Wildner 		acg.cg_old_boff = acg.cg_old_btotoff +
7205978408cSSascha Wildner 		    sblock.fs_old_cpg * sizeof(int32_t);
7215978408cSSascha Wildner 		acg.cg_iusedoff = acg.cg_old_boff +
7225978408cSSascha Wildner 		    sblock.fs_old_cpg * sizeof(u_int16_t);
7235978408cSSascha Wildner 	}
7245978408cSSascha Wildner 	acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
7255978408cSSascha Wildner 	if (sblock.fs_contigsumsize <= 0) {
7265978408cSSascha Wildner 		acg.cg_nextfreeoff = acg.cg_freeoff +
7275978408cSSascha Wildner 		   howmany(sblock.fs_fpg, CHAR_BIT);
7285978408cSSascha Wildner 	} else {
7295978408cSSascha Wildner 		acg.cg_clustersumoff = acg.cg_freeoff +
7305978408cSSascha Wildner 		    howmany(sblock.fs_fpg, CHAR_BIT) - sizeof(int32_t);
7315978408cSSascha Wildner 		acg.cg_clustersumoff =
7325978408cSSascha Wildner 		    roundup(acg.cg_clustersumoff, sizeof(int32_t));
7335978408cSSascha Wildner 		acg.cg_clusteroff = acg.cg_clustersumoff +
7345978408cSSascha Wildner 		    (sblock.fs_contigsumsize + 1) * sizeof(int32_t);
7355978408cSSascha Wildner 		acg.cg_nextfreeoff = acg.cg_clusteroff +
7365978408cSSascha Wildner 		    howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
7375978408cSSascha Wildner 	}
7385978408cSSascha Wildner 	if (acg.cg_nextfreeoff > (uint32_t)sblock.fs_cgsize) {
7395978408cSSascha Wildner 		printf("Panic: cylinder group too big\n");
7405978408cSSascha Wildner 		exit(37);
7415978408cSSascha Wildner 	}
7425978408cSSascha Wildner 	acg.cg_cs.cs_nifree += sblock.fs_ipg;
7435978408cSSascha Wildner 	if (cylno == 0)
7445978408cSSascha Wildner 		for (i = 0; i < UFS_ROOTINO; i++) {
7455978408cSSascha Wildner 			setbit(cg_inosused_swap(&acg, 0), i);
7465978408cSSascha Wildner 			acg.cg_cs.cs_nifree--;
7475978408cSSascha Wildner 		}
7485978408cSSascha Wildner 	if (cylno > 0) {
7495978408cSSascha Wildner 		/*
7505978408cSSascha Wildner 		 * In cylno 0, beginning space is reserved
7515978408cSSascha Wildner 		 * for boot and super blocks.
7525978408cSSascha Wildner 		 */
7535978408cSSascha Wildner 		for (d = 0, blkno = 0; d < dlower;) {
7545978408cSSascha Wildner 			ffs_setblock(&sblock, cg_blksfree_swap(&acg, 0), blkno);
7555978408cSSascha Wildner 			if (sblock.fs_contigsumsize > 0)
7565978408cSSascha Wildner 				setbit(cg_clustersfree_swap(&acg, 0), blkno);
7575978408cSSascha Wildner 			acg.cg_cs.cs_nbfree++;
758811c2036SSascha Wildner #ifdef __DragonFly__ /* XXX swildner: our fsck checks these */
759811c2036SSascha Wildner 			cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
760811c2036SSascha Wildner 			cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
761811c2036SSascha Wildner 			    [cbtorpos(&sblock, d)]++;
762811c2036SSascha Wildner #endif
7635978408cSSascha Wildner 			d += sblock.fs_frag;
7645978408cSSascha Wildner 			blkno++;
7655978408cSSascha Wildner 		}
7665978408cSSascha Wildner 	}
7675978408cSSascha Wildner 	if ((i = (dupper & (sblock.fs_frag - 1))) != 0) {
7685978408cSSascha Wildner 		acg.cg_frsum[sblock.fs_frag - i]++;
7695978408cSSascha Wildner 		for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
7705978408cSSascha Wildner 			setbit(cg_blksfree_swap(&acg, 0), dupper);
7715978408cSSascha Wildner 			acg.cg_cs.cs_nffree++;
7725978408cSSascha Wildner 		}
7735978408cSSascha Wildner 	}
7745978408cSSascha Wildner 	for (d = dupper, blkno = dupper >> sblock.fs_fragshift;
7755978408cSSascha Wildner 	     d + sblock.fs_frag <= acg.cg_ndblk; ) {
7765978408cSSascha Wildner 		ffs_setblock(&sblock, cg_blksfree_swap(&acg, 0), blkno);
7775978408cSSascha Wildner 		if (sblock.fs_contigsumsize > 0)
7785978408cSSascha Wildner 			setbit(cg_clustersfree_swap(&acg, 0), blkno);
7795978408cSSascha Wildner 		acg.cg_cs.cs_nbfree++;
780811c2036SSascha Wildner #ifdef __DragonFly__ /* XXX swildner: our fsck checks these */
781811c2036SSascha Wildner 		cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
782811c2036SSascha Wildner 		cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
783811c2036SSascha Wildner 		    [cbtorpos(&sblock, d)]++;
784811c2036SSascha Wildner #endif
7855978408cSSascha Wildner 		d += sblock.fs_frag;
7865978408cSSascha Wildner 		blkno++;
7875978408cSSascha Wildner 	}
7885978408cSSascha Wildner 	if (d < acg.cg_ndblk) {
7895978408cSSascha Wildner 		acg.cg_frsum[acg.cg_ndblk - d]++;
7905978408cSSascha Wildner 		for (; d < acg.cg_ndblk; d++) {
7915978408cSSascha Wildner 			setbit(cg_blksfree_swap(&acg, 0), d);
7925978408cSSascha Wildner 			acg.cg_cs.cs_nffree++;
7935978408cSSascha Wildner 		}
7945978408cSSascha Wildner 	}
7955978408cSSascha Wildner 	if (sblock.fs_contigsumsize > 0) {
7965978408cSSascha Wildner 		int32_t *sump = cg_clustersum_swap(&acg, 0);
7975978408cSSascha Wildner 		u_char *mapp = cg_clustersfree_swap(&acg, 0);
7985978408cSSascha Wildner 		int map = *mapp++;
7995978408cSSascha Wildner 		int bit = 1;
8005978408cSSascha Wildner 		int run = 0;
8015978408cSSascha Wildner 
8025978408cSSascha Wildner 		for (i = 0; i < acg.cg_nclusterblks; i++) {
8035978408cSSascha Wildner 			if ((map & bit) != 0) {
8045978408cSSascha Wildner 				run++;
8055978408cSSascha Wildner 			} else if (run != 0) {
8065978408cSSascha Wildner 				if (run > sblock.fs_contigsumsize)
8075978408cSSascha Wildner 					run = sblock.fs_contigsumsize;
8085978408cSSascha Wildner 				sump[run]++;
8095978408cSSascha Wildner 				run = 0;
8105978408cSSascha Wildner 			}
8115978408cSSascha Wildner 			if ((i & (CHAR_BIT - 1)) != (CHAR_BIT - 1)) {
8125978408cSSascha Wildner 				bit <<= 1;
8135978408cSSascha Wildner 			} else {
8145978408cSSascha Wildner 				map = *mapp++;
8155978408cSSascha Wildner 				bit = 1;
8165978408cSSascha Wildner 			}
8175978408cSSascha Wildner 		}
8185978408cSSascha Wildner 		if (run != 0) {
8195978408cSSascha Wildner 			if (run > sblock.fs_contigsumsize)
8205978408cSSascha Wildner 				run = sblock.fs_contigsumsize;
8215978408cSSascha Wildner 			sump[run]++;
8225978408cSSascha Wildner 		}
8235978408cSSascha Wildner 	}
8245978408cSSascha Wildner 	sblock.fs_cs(&sblock, cylno) = acg.cg_cs;
8255978408cSSascha Wildner 	/*
8265978408cSSascha Wildner 	 * Write out the duplicate super block, the cylinder group map
8275978408cSSascha Wildner 	 * and two blocks worth of inodes in a single write.
8285978408cSSascha Wildner 	 */
8295978408cSSascha Wildner 	start = MAX(sblock.fs_bsize, SBLOCKSIZE);
8305978408cSSascha Wildner 	memcpy(&iobuf[start], &acg, sblock.fs_cgsize);
8315978408cSSascha Wildner 	if (fsopts->needswap)
8325978408cSSascha Wildner 		ffs_cg_swap(&acg, (struct cg*)&iobuf[start], &sblock);
8335978408cSSascha Wildner 	start += sblock.fs_bsize;
8345978408cSSascha Wildner 	dp1 = (struct ufs1_dinode *)(&iobuf[start]);
835811c2036SSascha Wildner #ifndef __DragonFly__ /* XXX UFS2 */
8365978408cSSascha Wildner 	dp2 = (struct ufs2_dinode *)(&iobuf[start]);
8375978408cSSascha Wildner 	for (i = 0; i < acg.cg_initediblk; i++) {
8385978408cSSascha Wildner 		if (sblock.fs_magic == FS_UFS1_MAGIC) {
8395978408cSSascha Wildner 			/* No need to swap, it'll stay random */
8405978408cSSascha Wildner 			dp1->di_gen = random();
8415978408cSSascha Wildner 			dp1++;
8425978408cSSascha Wildner 		} else {
8435978408cSSascha Wildner 			dp2->di_gen = random();
8445978408cSSascha Wildner 			dp2++;
8455978408cSSascha Wildner 		}
8465978408cSSascha Wildner 	}
847811c2036SSascha Wildner #endif
8485978408cSSascha Wildner 	ffs_wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf,
8495978408cSSascha Wildner 	    fsopts);
8505978408cSSascha Wildner 	/*
8515978408cSSascha Wildner 	 * For the old file system, we have to initialize all the inodes.
8525978408cSSascha Wildner 	 */
8535978408cSSascha Wildner 	if (Oflag <= 1) {
8545978408cSSascha Wildner 		for (i = 2 * sblock.fs_frag;
8555978408cSSascha Wildner 		     i < sblock.fs_ipg / INOPF(&sblock);
8565978408cSSascha Wildner 		     i += sblock.fs_frag) {
8575978408cSSascha Wildner 			dp1 = (struct ufs1_dinode *)(&iobuf[start]);
8585978408cSSascha Wildner 			for (j = 0; j < INOPB(&sblock); j++) {
8595978408cSSascha Wildner 				dp1->di_gen = random();
8605978408cSSascha Wildner 				dp1++;
8615978408cSSascha Wildner 			}
8625978408cSSascha Wildner 			ffs_wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
8635978408cSSascha Wildner 			    sblock.fs_bsize, &iobuf[start], fsopts);
8645978408cSSascha Wildner 		}
8655978408cSSascha Wildner 	}
8665978408cSSascha Wildner }
8675978408cSSascha Wildner 
8685978408cSSascha Wildner /*
8695978408cSSascha Wildner  * read a block from the file system
8705978408cSSascha Wildner  */
8715978408cSSascha Wildner void
ffs_rdfs(makefs_daddr_t bno,int size,void * bf,const fsinfo_t * fsopts)872811c2036SSascha Wildner ffs_rdfs(makefs_daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
8735978408cSSascha Wildner {
8745978408cSSascha Wildner 	int n;
8755978408cSSascha Wildner 	off_t offset;
8765978408cSSascha Wildner 
877*d0a13d2fSTomohiro Kusumi 	offset = (off_t)bno * fsopts->sectorsize + fsopts->offset;
8785978408cSSascha Wildner 	if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
8795978408cSSascha Wildner 		err(1, "%s: seek error for sector %lld", __func__,
8805978408cSSascha Wildner 		    (long long)bno);
8815978408cSSascha Wildner 	n = read(fsopts->fd, bf, size);
8825978408cSSascha Wildner 	if (n == -1) {
8835978408cSSascha Wildner 		abort();
8845978408cSSascha Wildner 		err(1, "%s: read error bno %lld size %d", __func__,
8855978408cSSascha Wildner 		    (long long)bno, size);
8865978408cSSascha Wildner 	}
8875978408cSSascha Wildner 	else if (n != size)
8885978408cSSascha Wildner 		errx(1, "%s: read error for sector %lld", __func__,
8895978408cSSascha Wildner 		    (long long)bno);
8905978408cSSascha Wildner }
8915978408cSSascha Wildner 
8925978408cSSascha Wildner /*
8935978408cSSascha Wildner  * write a block to the file system
8945978408cSSascha Wildner  */
8955978408cSSascha Wildner void
ffs_wtfs(makefs_daddr_t bno,int size,void * bf,const fsinfo_t * fsopts)896811c2036SSascha Wildner ffs_wtfs(makefs_daddr_t bno, int size, void *bf, const fsinfo_t *fsopts)
8975978408cSSascha Wildner {
8985978408cSSascha Wildner 	int n;
8995978408cSSascha Wildner 	off_t offset;
9005978408cSSascha Wildner 
901*d0a13d2fSTomohiro Kusumi 	offset = (off_t)bno * fsopts->sectorsize + fsopts->offset;
9025978408cSSascha Wildner 	if (lseek(fsopts->fd, offset, SEEK_SET) < 0)
9035978408cSSascha Wildner 		err(1, "%s: seek error for sector %lld", __func__,
9045978408cSSascha Wildner 		    (long long)bno);
9055978408cSSascha Wildner 	n = write(fsopts->fd, bf, size);
9065978408cSSascha Wildner 	if (n == -1)
9075978408cSSascha Wildner 		err(1, "%s: write error for sector %lld", __func__,
9085978408cSSascha Wildner 		    (long long)bno);
9095978408cSSascha Wildner 	else if (n != size)
9105978408cSSascha Wildner 		errx(1, "%s: write error for sector %lld", __func__,
9115978408cSSascha Wildner 		    (long long)bno);
9125978408cSSascha Wildner }
9135978408cSSascha Wildner 
9145978408cSSascha Wildner 
9155978408cSSascha Wildner /* Determine how many digits are needed to print a given integer */
9165978408cSSascha Wildner static int
count_digits(int num)9175978408cSSascha Wildner count_digits(int num)
9185978408cSSascha Wildner {
9195978408cSSascha Wildner 	int ndig;
9205978408cSSascha Wildner 
9215978408cSSascha Wildner 	for(ndig = 1; num > 9; num /=10, ndig++);
9225978408cSSascha Wildner 
9235978408cSSascha Wildner 	return (ndig);
9245978408cSSascha Wildner }
9255978408cSSascha Wildner 
9265978408cSSascha Wildner static int
ilog2(int val)9275978408cSSascha Wildner ilog2(int val)
9285978408cSSascha Wildner {
9295978408cSSascha Wildner 	u_int n;
9305978408cSSascha Wildner 
9315978408cSSascha Wildner 	for (n = 0; n < sizeof(n) * CHAR_BIT; n++)
9325978408cSSascha Wildner 		if (1 << n == val)
9335978408cSSascha Wildner 			return (n);
9345978408cSSascha Wildner 	errx(1, "%s: %d is not a power of 2", __func__, val);
9355978408cSSascha Wildner }
936