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