mkfs.c revision 103949
1/*
2 * Copyright (c) 2002 Networks Associates Technology, Inc.
3 * All rights reserved.
4 *
5 * This software was developed for the FreeBSD Project by Marshall
6 * Kirk McKusick and Network Associates Laboratories, the Security
7 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
8 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
9 * research program
10 *
11 * Copyright (c) 1982, 1989, 1993
12 *	The Regents of the University of California.  All rights reserved.
13 * (c) UNIX System Laboratories, Inc.
14 * Copyright (c) 1980, 1989, 1993
15 *	The Regents of the University of California.  All rights reserved.
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 * 3. All advertising materials mentioning features or use of this software
26 *    must display the following acknowledgement:
27 *	This product includes software developed by the University of
28 *	California, Berkeley and its contributors.
29 * 4. Neither the name of the University nor the names of its contributors
30 *    may be used to endorse or promote products derived from this software
31 *    without specific prior written permission.
32 *
33 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
34 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
35 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
36 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
37 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
38 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
39 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
40 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
41 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
42 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
43 * SUCH DAMAGE.
44 */
45
46#ifndef lint
47#if 0
48static char sccsid[] = "@(#)mkfs.c	8.11 (Berkeley) 5/3/95";
49#endif
50static const char rcsid[] =
51  "$FreeBSD: head/sbin/newfs/mkfs.c 103949 2002-09-25 04:06:37Z mike $";
52#endif /* not lint */
53
54#include <err.h>
55#include <limits.h>
56#include <signal.h>
57#include <stdlib.h>
58#include <string.h>
59#include <stdint.h>
60#include <stdio.h>
61#include <unistd.h>
62#include <sys/param.h>
63#include <sys/time.h>
64#include <sys/types.h>
65#include <sys/wait.h>
66#include <sys/resource.h>
67#include <sys/stat.h>
68#include <ufs/ufs/dinode.h>
69#include <ufs/ufs/dir.h>
70#include <ufs/ffs/fs.h>
71#include <sys/disklabel.h>
72#include <sys/file.h>
73#include <sys/mman.h>
74#include <sys/ioctl.h>
75#include "newfs.h"
76
77/*
78 * make file system for cylinder-group style file systems
79 */
80#define UMASK		0755
81#define POWEROF2(num)	(((num) & ((num) - 1)) == 0)
82
83static union {
84	struct fs fs;
85	char pad[SBLOCKSIZE];
86} fsun;
87#define	sblock	fsun.fs
88static struct	csum *fscs;
89
90static union {
91	struct cg cg;
92	char pad[MAXBSIZE];
93} cgun;
94#define	acg	cgun.cg
95
96union dinode {
97	struct ufs1_dinode dp1;
98	struct ufs2_dinode dp2;
99};
100#define DIP(dp, field) \
101	((sblock.fs_magic == FS_UFS1_MAGIC) ? \
102	(dp)->dp1.field : (dp)->dp2.field)
103
104static int randinit;
105static caddr_t iobuf;
106static long iobufsize;
107static ufs2_daddr_t alloc(int size, int mode);
108static int charsperline(void);
109static void clrblock(struct fs *, unsigned char *, int);
110static void fsinit(time_t);
111static int ilog2(int);
112static void initcg(int, time_t);
113static int isblock(struct fs *, unsigned char *, int);
114static void iput(union dinode *, ino_t);
115static int makedir(struct direct *, int);
116static void rdfs(ufs2_daddr_t, int, char *);
117static void setblock(struct fs *, unsigned char *, int);
118static void wtfs(ufs2_daddr_t, int, char *);
119static void wtfsflush(void);
120
121void
122mkfs(struct partition *pp, char *fsys)
123{
124	int fragsperinode, optimalfpg, origdensity, minfpg, lastminfpg;
125	long i, j, cylno, csfrags;
126	time_t utime;
127	quad_t sizepb;
128	int width;
129	char tmpbuf[100];	/* XXX this will break in about 2,500 years */
130
131	if (Rflag)
132		utime = 1000000000;
133	else
134		time(&utime);
135	if (!Rflag && !randinit) {
136		randinit = 1;
137		srandomdev();
138	}
139	/*
140	 * allocate space for superblock, cylinder group map, and
141	 * two sets of inode blocks.
142	 */
143	if (bsize < SBLOCKSIZE)
144		iobufsize = SBLOCKSIZE + 3 * bsize;
145	else
146		iobufsize = 4 * bsize;
147	if ((iobuf = malloc(iobufsize)) == 0) {
148		printf("Cannot allocate I/O buffer\n");
149		exit(38);
150	}
151	bzero(iobuf, iobufsize);
152	sblock.fs_flags = 0;
153	if (Uflag)
154		sblock.fs_flags |= FS_DOSOFTDEP;
155	/*
156	 * Validate the given file system size.
157	 * Verify that its last block can actually be accessed.
158	 * Convert to file system fragment sized units.
159	 */
160	if (fssize <= 0) {
161		printf("preposterous size %jd\n", (intmax_t)fssize);
162		exit(13);
163	}
164	wtfs(fssize - (realsectorsize / DEV_BSIZE), realsectorsize,
165	    (char *)&sblock);
166	/*
167	 * collect and verify the file system density info
168	 */
169	sblock.fs_avgfilesize = avgfilesize;
170	sblock.fs_avgfpdir = avgfilesperdir;
171	if (sblock.fs_avgfilesize <= 0)
172		printf("illegal expected average file size %d\n",
173		    sblock.fs_avgfilesize), exit(14);
174	if (sblock.fs_avgfpdir <= 0)
175		printf("illegal expected number of files per directory %d\n",
176		    sblock.fs_avgfpdir), exit(15);
177	/*
178	 * collect and verify the block and fragment sizes
179	 */
180	sblock.fs_bsize = bsize;
181	sblock.fs_fsize = fsize;
182	if (!POWEROF2(sblock.fs_bsize)) {
183		printf("block size must be a power of 2, not %d\n",
184		    sblock.fs_bsize);
185		exit(16);
186	}
187	if (!POWEROF2(sblock.fs_fsize)) {
188		printf("fragment size must be a power of 2, not %d\n",
189		    sblock.fs_fsize);
190		exit(17);
191	}
192	if (sblock.fs_fsize < sectorsize) {
193		printf("increasing fragment size from %d to sector size (%d)\n",
194		    sblock.fs_fsize, sectorsize);
195		sblock.fs_fsize = sectorsize;
196	}
197	if (sblock.fs_bsize < MINBSIZE) {
198		printf("increasing block size from %d to minimum (%d)\n",
199		    sblock.fs_bsize, MINBSIZE);
200		sblock.fs_bsize = MINBSIZE;
201	}
202	if (sblock.fs_bsize < sblock.fs_fsize) {
203		printf("increasing block size from %d to fragment size (%d)\n",
204		    sblock.fs_bsize, sblock.fs_fsize);
205		sblock.fs_bsize = sblock.fs_fsize;
206	}
207	if (sblock.fs_fsize * MAXFRAG < sblock.fs_bsize) {
208		printf(
209		"increasing fragment size from %d to block size / %d (%d)\n",
210		    sblock.fs_fsize, MAXFRAG, sblock.fs_bsize / MAXFRAG);
211		sblock.fs_fsize = sblock.fs_bsize / MAXFRAG;
212	}
213	if (maxbsize < bsize || !POWEROF2(maxbsize)) {
214		sblock.fs_maxbsize = sblock.fs_bsize;
215		printf("Extent size set to %d\n", sblock.fs_maxbsize);
216	} else if (sblock.fs_maxbsize > FS_MAXCONTIG * sblock.fs_bsize) {
217		sblock.fs_maxbsize = FS_MAXCONTIG * sblock.fs_bsize;
218		printf("Extent size reduced to %d\n", sblock.fs_maxbsize);
219	} else {
220		sblock.fs_maxbsize = maxbsize;
221	}
222	sblock.fs_maxcontig = maxcontig;
223	if (sblock.fs_maxcontig < sblock.fs_maxbsize / sblock.fs_bsize) {
224		sblock.fs_maxcontig = sblock.fs_maxbsize / sblock.fs_bsize;
225		printf("Maxcontig raised to %d\n", sblock.fs_maxbsize);
226	}
227	if (sblock.fs_maxcontig > 1)
228		sblock.fs_contigsumsize = MIN(sblock.fs_maxcontig,FS_MAXCONTIG);
229	sblock.fs_bmask = ~(sblock.fs_bsize - 1);
230	sblock.fs_fmask = ~(sblock.fs_fsize - 1);
231	sblock.fs_qbmask = ~sblock.fs_bmask;
232	sblock.fs_qfmask = ~sblock.fs_fmask;
233	sblock.fs_bshift = ilog2(sblock.fs_bsize);
234	sblock.fs_fshift = ilog2(sblock.fs_fsize);
235	sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
236	sblock.fs_fragshift = ilog2(sblock.fs_frag);
237	if (sblock.fs_frag > MAXFRAG) {
238		printf("fragment size %d is still too small (can't happen)\n",
239		    sblock.fs_bsize / MAXFRAG);
240		exit(21);
241	}
242	sblock.fs_fsbtodb = ilog2(sblock.fs_fsize / sectorsize);
243	sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
244	if (Oflag == 1) {
245		sblock.fs_magic = FS_UFS1_MAGIC;
246		sblock.fs_sblockloc = numfrags(&sblock, SBLOCK_UFS1);
247		sblock.fs_nindir = sblock.fs_bsize / sizeof(ufs1_daddr_t);
248		sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode);
249		sblock.fs_maxsymlinklen = ((NDADDR + NIADDR) *
250		    sizeof(ufs1_daddr_t));
251		sblock.fs_old_inodefmt = FS_44INODEFMT;
252		sblock.fs_old_cgoffset = 0;
253		sblock.fs_old_cgmask = 0xffffffff;
254		sblock.fs_old_size = sblock.fs_size;
255		sblock.fs_old_rotdelay = 0;
256		sblock.fs_old_rps = 60;
257		sblock.fs_old_nspf = sblock.fs_fsize / sectorsize;
258		sblock.fs_old_cpg = 1;
259		sblock.fs_old_interleave = 1;
260		sblock.fs_old_trackskew = 0;
261		sblock.fs_old_cpc = 0;
262		sblock.fs_old_postblformat = 1;
263		sblock.fs_old_nrpos = 1;
264	} else {
265		sblock.fs_magic = FS_UFS2_MAGIC;
266		sblock.fs_sblockloc = numfrags(&sblock, SBLOCK_UFS2);
267		sblock.fs_nindir = sblock.fs_bsize / sizeof(ufs2_daddr_t);
268		sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs2_dinode);
269		sblock.fs_maxsymlinklen = ((NDADDR + NIADDR) *
270		    sizeof(ufs2_daddr_t));
271	}
272	sblock.fs_sblkno =
273	    roundup(howmany(lfragtosize(&sblock, sblock.fs_sblockloc) +
274		SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag);
275	sblock.fs_cblkno = sblock.fs_sblkno +
276	    roundup(howmany(SBLOCKSIZE, sblock.fs_fsize), sblock.fs_frag);
277	sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
278	sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1;
279	for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) {
280		sizepb *= NINDIR(&sblock);
281		sblock.fs_maxfilesize += sizepb;
282	}
283	/*
284	 * Calculate the number of blocks to put into each cylinder group.
285	 *
286	 * This algorithm selects the number of blocks per cylinder
287	 * group. The first goal is to have at least enough data blocks
288	 * in each cylinder group to meet the density requirement. Once
289	 * this goal is achieved we try to expand to have at least
290	 * MINCYLGRPS cylinder groups. Once this goal is achieved, we
291	 * pack as many blocks into each cylinder group map as will fit.
292	 *
293	 * We start by calculating the smallest number of blocks that we
294	 * can put into each cylinder group. If this is too big, we reduce
295	 * the density until it fits.
296	 */
297	origdensity = density;
298	for (;;) {
299		fragsperinode = numfrags(&sblock, density);
300		minfpg = fragsperinode * INOPB(&sblock);
301		if (minfpg > sblock.fs_size)
302			minfpg = sblock.fs_size;
303		sblock.fs_ipg = INOPB(&sblock);
304		sblock.fs_fpg = roundup(sblock.fs_iblkno +
305		    sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
306		if (sblock.fs_fpg < minfpg)
307			sblock.fs_fpg = minfpg;
308		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
309		    INOPB(&sblock));
310		sblock.fs_fpg = roundup(sblock.fs_iblkno +
311		    sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
312		if (sblock.fs_fpg < minfpg)
313			sblock.fs_fpg = minfpg;
314		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
315		    INOPB(&sblock));
316		if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
317			break;
318		density -= sblock.fs_fsize;
319	}
320	if (density != origdensity)
321		printf("density reduced from %d to %d\n", origdensity, density);
322	/*
323	 * Start packing more blocks into the cylinder group until
324	 * it cannot grow any larger, the number of cylinder groups
325	 * drops below MINCYLGRPS, or we reach the size requested.
326	 */
327	for ( ; sblock.fs_fpg < maxblkspercg; sblock.fs_fpg += sblock.fs_frag) {
328		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
329		    INOPB(&sblock));
330		if (sblock.fs_size / sblock.fs_fpg < MINCYLGRPS)
331			break;
332		if (CGSIZE(&sblock) < (unsigned long)sblock.fs_bsize)
333			continue;
334		if (CGSIZE(&sblock) == (unsigned long)sblock.fs_bsize)
335			break;
336		sblock.fs_fpg -= sblock.fs_frag;
337		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
338		    INOPB(&sblock));
339		break;
340	}
341	/*
342	 * Check to be sure that the last cylinder group has enough blocks
343	 * to be viable. If it is too small, reduce the number of blocks
344	 * per cylinder group which will have the effect of moving more
345	 * blocks into the last cylinder group.
346	 */
347	optimalfpg = sblock.fs_fpg;
348	for (;;) {
349		sblock.fs_ncg = howmany(sblock.fs_size, sblock.fs_fpg);
350		lastminfpg = roundup(sblock.fs_iblkno +
351		    sblock.fs_ipg / INOPF(&sblock), sblock.fs_frag);
352		if (sblock.fs_size < lastminfpg) {
353			printf("Filesystem size %jd < minimum size of %d\n",
354			    (intmax_t)sblock.fs_size, lastminfpg);
355			exit(28);
356		}
357		if (sblock.fs_size % sblock.fs_fpg >= lastminfpg ||
358		    sblock.fs_size % sblock.fs_fpg == 0)
359			break;
360		sblock.fs_fpg -= sblock.fs_frag;
361		sblock.fs_ipg = roundup(howmany(sblock.fs_fpg, fragsperinode),
362		    INOPB(&sblock));
363	}
364	if (optimalfpg != sblock.fs_fpg)
365		printf("Reduced frags per cylinder group from %d to %d %s\n",
366		   optimalfpg, sblock.fs_fpg, "to enlarge last cyl group");
367	sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
368	sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
369	if (Oflag == 1) {
370		sblock.fs_old_spc = sblock.fs_fpg * sblock.fs_old_nspf;
371		sblock.fs_old_nsect = sblock.fs_old_spc;
372		sblock.fs_old_npsect = sblock.fs_old_spc;
373		sblock.fs_old_ncyl = sblock.fs_ncg;
374	}
375	/*
376	 * fill in remaining fields of the super block
377	 */
378	sblock.fs_csaddr = cgdmin(&sblock, 0);
379	sblock.fs_cssize =
380	    fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
381	fscs = (struct csum *)calloc(1, sblock.fs_cssize);
382	if (fscs == NULL)
383		errx(31, "calloc failed");
384	sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
385	sblock.fs_minfree = minfree;
386	sblock.fs_maxbpg = maxbpg;
387	sblock.fs_optim = opt;
388	sblock.fs_cgrotor = 0;
389	sblock.fs_pendingblocks = 0;
390	sblock.fs_pendinginodes = 0;
391	sblock.fs_fmod = 0;
392	sblock.fs_ronly = 0;
393	sblock.fs_state = 0;
394	sblock.fs_clean = 1;
395	sblock.fs_id[0] = (long)utime;
396	sblock.fs_id[1] = random();
397	sblock.fs_fsmnt[0] = '\0';
398	csfrags = howmany(sblock.fs_cssize, sblock.fs_fsize);
399	sblock.fs_dsize = sblock.fs_size - sblock.fs_sblkno -
400	    sblock.fs_ncg * (sblock.fs_dblkno - sblock.fs_sblkno);
401	sblock.fs_cstotal.cs_nbfree =
402	    fragstoblks(&sblock, sblock.fs_dsize) -
403	    howmany(csfrags, sblock.fs_frag);
404	sblock.fs_cstotal.cs_nffree =
405	    fragnum(&sblock, sblock.fs_size) +
406	    (csfrags > 0 ? sblock.fs_frag - csfrags : 0);
407	sblock.fs_cstotal.cs_nifree = sblock.fs_ncg * sblock.fs_ipg - ROOTINO;
408	sblock.fs_cstotal.cs_ndir = 0;
409	sblock.fs_dsize -= csfrags;
410	sblock.fs_time = utime;
411	if (Oflag == 1) {
412		sblock.fs_old_time = utime;
413		sblock.fs_old_dsize = sblock.fs_dsize;
414		sblock.fs_old_csaddr = sblock.fs_csaddr;
415		sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
416		sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
417		sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
418		sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
419	}
420
421	/*
422	 * Dump out summary information about file system.
423	 */
424#	define B2MBFACTOR (1 / (1024.0 * 1024.0))
425	printf("%s: %.1fMB (%jd sectors) block size %d, fragment size %d\n",
426	    fsys, (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
427	    (intmax_t)fsbtodb(&sblock, sblock.fs_size), sblock.fs_bsize,
428	    sblock.fs_fsize);
429	printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n",
430	    sblock.fs_ncg, (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
431	    sblock.fs_fpg / sblock.fs_frag, sblock.fs_ipg);
432	if (sblock.fs_flags & FS_DOSOFTDEP)
433		printf("\twith soft updates\n");
434#	undef B2MBFACTOR
435	/*
436	 * Now build the cylinders group blocks and
437	 * then print out indices of cylinder groups.
438	 */
439	printf("super-block backups (for fsck -b #) at:\n");
440	i = 0;
441	width = charsperline();
442	/*
443	 * Make a copy of the superblock into the buffer that we will be
444	 * writing out in each cylinder group.
445	 */
446	bcopy((char *)&sblock, iobuf, SBLOCKSIZE);
447	for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
448		initcg(cylno, utime);
449		j = snprintf(tmpbuf, sizeof(tmpbuf), " %jd%s",
450		    (intmax_t)fsbtodb(&sblock, cgsblock(&sblock, cylno)),
451		    cylno < (sblock.fs_ncg-1) ? "," : "");
452		if (j < 0)
453			tmpbuf[j = 0] = '\0';
454		if (i + j >= width) {
455			printf("\n");
456			i = 0;
457		}
458		i += j;
459		printf("%s", tmpbuf);
460		fflush(stdout);
461	}
462	printf("\n");
463	if (Nflag)
464		exit(0);
465	/*
466	 * Now construct the initial file system,
467	 * then write out the super-block.
468	 */
469	fsinit(utime);
470	if (Oflag == 1) {
471		sblock.fs_old_cstotal.cs_ndir = sblock.fs_cstotal.cs_ndir;
472		sblock.fs_old_cstotal.cs_nbfree = sblock.fs_cstotal.cs_nbfree;
473		sblock.fs_old_cstotal.cs_nifree = sblock.fs_cstotal.cs_nifree;
474		sblock.fs_old_cstotal.cs_nffree = sblock.fs_cstotal.cs_nffree;
475	}
476	wtfs(lfragtosize(&sblock, sblock.fs_sblockloc) / sectorsize,
477	    SBLOCKSIZE, (char *)&sblock);
478	for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
479		wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
480			sblock.fs_cssize - i < sblock.fs_bsize ?
481			sblock.fs_cssize - i : sblock.fs_bsize,
482			((char *)fscs) + i);
483	wtfsflush();
484	/*
485	 * Update information about this partion in pack
486	 * label, to that it may be updated on disk.
487	 */
488	if (pp != NULL) {
489		pp->p_fstype = FS_BSDFFS;
490		pp->p_fsize = sblock.fs_fsize;
491		pp->p_frag = sblock.fs_frag;
492		pp->p_cpg = sblock.fs_fpg;
493	}
494}
495
496/*
497 * Initialize a cylinder group.
498 */
499void
500initcg(int cylno, time_t utime)
501{
502	long i, j, d, dlower, dupper, blkno, start;
503	ufs2_daddr_t cbase, dmax;
504	struct ufs1_dinode *dp1;
505	struct ufs2_dinode *dp2;
506	struct csum *cs;
507
508	/*
509	 * Determine block bounds for cylinder group.
510	 * Allow space for super block summary information in first
511	 * cylinder group.
512	 */
513	cbase = cgbase(&sblock, cylno);
514	dmax = cbase + sblock.fs_fpg;
515	if (dmax > sblock.fs_size)
516		dmax = sblock.fs_size;
517	dlower = cgsblock(&sblock, cylno) - cbase;
518	dupper = cgdmin(&sblock, cylno) - cbase;
519	if (cylno == 0)
520		dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
521	cs = &fscs[cylno];
522	memset(&acg, 0, sblock.fs_cgsize);
523	acg.cg_time = utime;
524	acg.cg_magic = CG_MAGIC;
525	acg.cg_cgx = cylno;
526	acg.cg_niblk = sblock.fs_ipg;
527	acg.cg_initediblk = sblock.fs_ipg < 2 * INOPB(&sblock) ?
528	    sblock.fs_ipg : 2 * INOPB(&sblock);
529	acg.cg_ndblk = dmax - cbase;
530	if (sblock.fs_contigsumsize > 0)
531		acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
532	start = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
533	if (Oflag == 2) {
534		acg.cg_iusedoff = start;
535	} else {
536		acg.cg_old_ncyl = sblock.fs_old_cpg;
537		acg.cg_old_time = acg.cg_time;
538		acg.cg_time = 0;
539		acg.cg_old_niblk = acg.cg_niblk;
540		acg.cg_niblk = 0;
541		acg.cg_initediblk = 0;
542		acg.cg_old_btotoff = start;
543		acg.cg_old_boff = acg.cg_old_btotoff +
544		    sblock.fs_old_cpg * sizeof(int32_t);
545		acg.cg_iusedoff = acg.cg_old_boff +
546		    sblock.fs_old_cpg * sizeof(u_int16_t);
547	}
548	acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, CHAR_BIT);
549	acg.cg_nextfreeoff = acg.cg_freeoff + howmany(sblock.fs_fpg, CHAR_BIT);
550	if (sblock.fs_contigsumsize > 0) {
551		acg.cg_clustersumoff =
552		    roundup(acg.cg_nextfreeoff, sizeof(u_int32_t));
553		acg.cg_clustersumoff -= sizeof(u_int32_t);
554		acg.cg_clusteroff = acg.cg_clustersumoff +
555		    (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
556		acg.cg_nextfreeoff = acg.cg_clusteroff +
557		    howmany(fragstoblks(&sblock, sblock.fs_fpg), CHAR_BIT);
558	}
559	if (acg.cg_nextfreeoff > sblock.fs_cgsize) {
560		printf("Panic: cylinder group too big\n");
561		exit(37);
562	}
563	acg.cg_cs.cs_nifree += sblock.fs_ipg;
564	if (cylno == 0)
565		for (i = 0; i < (long)ROOTINO; i++) {
566			setbit(cg_inosused(&acg), i);
567			acg.cg_cs.cs_nifree--;
568		}
569	if (cylno > 0) {
570		/*
571		 * In cylno 0, beginning space is reserved
572		 * for boot and super blocks.
573		 */
574		for (d = 0; d < dlower; d += sblock.fs_frag) {
575			blkno = d / sblock.fs_frag;
576			setblock(&sblock, cg_blksfree(&acg), blkno);
577			if (sblock.fs_contigsumsize > 0)
578				setbit(cg_clustersfree(&acg), blkno);
579			acg.cg_cs.cs_nbfree++;
580		}
581	}
582	if ((i = dupper % sblock.fs_frag)) {
583		acg.cg_frsum[sblock.fs_frag - i]++;
584		for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
585			setbit(cg_blksfree(&acg), dupper);
586			acg.cg_cs.cs_nffree++;
587		}
588	}
589	for (d = dupper; d + sblock.fs_frag <= acg.cg_ndblk;
590	     d += sblock.fs_frag) {
591		blkno = d / sblock.fs_frag;
592		setblock(&sblock, cg_blksfree(&acg), blkno);
593		if (sblock.fs_contigsumsize > 0)
594			setbit(cg_clustersfree(&acg), blkno);
595		acg.cg_cs.cs_nbfree++;
596	}
597	if (d < acg.cg_ndblk) {
598		acg.cg_frsum[acg.cg_ndblk - d]++;
599		for (; d < acg.cg_ndblk; d++) {
600			setbit(cg_blksfree(&acg), d);
601			acg.cg_cs.cs_nffree++;
602		}
603	}
604	if (sblock.fs_contigsumsize > 0) {
605		int32_t *sump = cg_clustersum(&acg);
606		u_char *mapp = cg_clustersfree(&acg);
607		int map = *mapp++;
608		int bit = 1;
609		int run = 0;
610
611		for (i = 0; i < acg.cg_nclusterblks; i++) {
612			if ((map & bit) != 0)
613				run++;
614			else if (run != 0) {
615				if (run > sblock.fs_contigsumsize)
616					run = sblock.fs_contigsumsize;
617				sump[run]++;
618				run = 0;
619			}
620			if ((i & (CHAR_BIT - 1)) != CHAR_BIT - 1)
621				bit <<= 1;
622			else {
623				map = *mapp++;
624				bit = 1;
625			}
626		}
627		if (run != 0) {
628			if (run > sblock.fs_contigsumsize)
629				run = sblock.fs_contigsumsize;
630			sump[run]++;
631		}
632	}
633	*cs = acg.cg_cs;
634	/*
635	 * Write out the duplicate super block, the cylinder group map
636	 * and two blocks worth of inodes in a single write.
637	 */
638	start = sblock.fs_bsize > SBLOCKSIZE ? sblock.fs_bsize : SBLOCKSIZE;
639	bcopy((char *)&acg, &iobuf[start], sblock.fs_cgsize);
640	start += sblock.fs_bsize;
641	dp1 = (struct ufs1_dinode *)(&iobuf[start]);
642	dp2 = (struct ufs2_dinode *)(&iobuf[start]);
643	for (i = 0; i < acg.cg_initediblk; i++) {
644		if (sblock.fs_magic == FS_UFS1_MAGIC) {
645			dp1->di_gen = random();
646			dp1++;
647		} else {
648			dp2->di_gen = random();
649			dp2++;
650		}
651	}
652	wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), iobufsize, iobuf);
653	/*
654	 * For the old file system, we have to initialize all the inodes.
655	 */
656	if (Oflag == 1) {
657		for (i = 2 * sblock.fs_frag;
658		     i < sblock.fs_ipg / INOPF(&sblock);
659		     i += sblock.fs_frag) {
660			dp1 = (struct ufs1_dinode *)(&iobuf[start]);
661			for (j = 0; j < INOPB(&sblock); j++) {
662				dp1->di_gen = random();
663				dp1++;
664			}
665			wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
666			    sblock.fs_bsize, &iobuf[start]);
667		}
668	}
669}
670
671/*
672 * initialize the file system
673 */
674#define PREDEFDIR 2
675
676struct direct root_dir[] = {
677	{ ROOTINO, sizeof(struct direct), DT_DIR, 1, "." },
678	{ ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." },
679};
680
681void
682fsinit(time_t utime)
683{
684	union dinode node;
685
686	memset(&node, 0, sizeof node);
687	if (sblock.fs_magic == FS_UFS1_MAGIC) {
688		/*
689		 * initialize the node
690		 */
691		node.dp1.di_atime = utime;
692		node.dp1.di_mtime = utime;
693		node.dp1.di_ctime = utime;
694		/*
695		 * create the root directory
696		 */
697		node.dp1.di_mode = IFDIR | UMASK;
698		node.dp1.di_nlink = PREDEFDIR;
699		node.dp1.di_size = makedir(root_dir, PREDEFDIR);
700		node.dp1.di_db[0] = alloc(sblock.fs_fsize, node.dp1.di_mode);
701		node.dp1.di_blocks =
702		    btodb(fragroundup(&sblock, node.dp1.di_size));
703		wtfs(fsbtodb(&sblock, node.dp1.di_db[0]), sblock.fs_fsize,
704		    iobuf);
705	} else {
706		/*
707		 * initialize the node
708		 */
709		node.dp2.di_atime = utime;
710		node.dp2.di_mtime = utime;
711		node.dp2.di_ctime = utime;
712		node.dp2.di_birthtime = utime;
713		/*
714		 * create the root directory
715		 */
716		node.dp2.di_mode = IFDIR | UMASK;
717		node.dp2.di_nlink = PREDEFDIR;
718		node.dp2.di_size = makedir(root_dir, PREDEFDIR);
719		node.dp2.di_db[0] = alloc(sblock.fs_fsize, node.dp2.di_mode);
720		node.dp2.di_blocks =
721		    btodb(fragroundup(&sblock, node.dp2.di_size));
722		wtfs(fsbtodb(&sblock, node.dp2.di_db[0]), sblock.fs_fsize,
723		    iobuf);
724	}
725	iput(&node, ROOTINO);
726}
727
728/*
729 * construct a set of directory entries in "iobuf".
730 * return size of directory.
731 */
732int
733makedir(struct direct *protodir, int entries)
734{
735	char *cp;
736	int i, spcleft;
737
738	spcleft = DIRBLKSIZ;
739	memset(iobuf, 0, DIRBLKSIZ);
740	for (cp = iobuf, i = 0; i < entries - 1; i++) {
741		protodir[i].d_reclen = DIRSIZ(0, &protodir[i]);
742		memmove(cp, &protodir[i], protodir[i].d_reclen);
743		cp += protodir[i].d_reclen;
744		spcleft -= protodir[i].d_reclen;
745	}
746	protodir[i].d_reclen = spcleft;
747	memmove(cp, &protodir[i], DIRSIZ(0, &protodir[i]));
748	return (DIRBLKSIZ);
749}
750
751/*
752 * allocate a block or frag
753 */
754ufs2_daddr_t
755alloc(int size, int mode)
756{
757	int i, d, blkno, frag;
758
759	rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
760	    (char *)&acg);
761	if (acg.cg_magic != CG_MAGIC) {
762		printf("cg 0: bad magic number\n");
763		return (0);
764	}
765	if (acg.cg_cs.cs_nbfree == 0) {
766		printf("first cylinder group ran out of space\n");
767		return (0);
768	}
769	for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
770		if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
771			goto goth;
772	printf("internal error: can't find block in cyl 0\n");
773	return (0);
774goth:
775	blkno = fragstoblks(&sblock, d);
776	clrblock(&sblock, cg_blksfree(&acg), blkno);
777	if (sblock.fs_contigsumsize > 0)
778		clrbit(cg_clustersfree(&acg), blkno);
779	acg.cg_cs.cs_nbfree--;
780	sblock.fs_cstotal.cs_nbfree--;
781	fscs[0].cs_nbfree--;
782	if (mode & IFDIR) {
783		acg.cg_cs.cs_ndir++;
784		sblock.fs_cstotal.cs_ndir++;
785		fscs[0].cs_ndir++;
786	}
787	if (size != sblock.fs_bsize) {
788		frag = howmany(size, sblock.fs_fsize);
789		fscs[0].cs_nffree += sblock.fs_frag - frag;
790		sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
791		acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
792		acg.cg_frsum[sblock.fs_frag - frag]++;
793		for (i = frag; i < sblock.fs_frag; i++)
794			setbit(cg_blksfree(&acg), d + i);
795	}
796	wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
797	    (char *)&acg);
798	return ((ufs2_daddr_t)d);
799}
800
801/*
802 * Allocate an inode on the disk
803 */
804void
805iput(union dinode *ip, ino_t ino)
806{
807	ufs2_daddr_t d;
808	int c;
809
810	c = ino_to_cg(&sblock, ino);
811	rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
812	    (char *)&acg);
813	if (acg.cg_magic != CG_MAGIC) {
814		printf("cg 0: bad magic number\n");
815		exit(31);
816	}
817	acg.cg_cs.cs_nifree--;
818	setbit(cg_inosused(&acg), ino);
819	wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
820	    (char *)&acg);
821	sblock.fs_cstotal.cs_nifree--;
822	fscs[0].cs_nifree--;
823	if (ino >= (unsigned long)sblock.fs_ipg * sblock.fs_ncg) {
824		printf("fsinit: inode value out of range (%d).\n", ino);
825		exit(32);
826	}
827	d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino));
828	rdfs(d, sblock.fs_bsize, (char *)iobuf);
829	if (sblock.fs_magic == FS_UFS1_MAGIC)
830		((struct ufs1_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
831		    ip->dp1;
832	else
833		((struct ufs2_dinode *)iobuf)[ino_to_fsbo(&sblock, ino)] =
834		    ip->dp2;
835	wtfs(d, sblock.fs_bsize, (char *)iobuf);
836}
837
838/*
839 * read a block from the file system
840 */
841void
842rdfs(ufs2_daddr_t bno, int size, char *bf)
843{
844	int n;
845
846	wtfsflush();
847	if (lseek(fso, (off_t)bno * sectorsize, 0) < 0) {
848		printf("seek error: %ld\n", (long)bno);
849		err(33, "rdfs");
850	}
851	n = read(fso, bf, size);
852	if (n != size) {
853		printf("read error: %ld\n", (long)bno);
854		err(34, "rdfs");
855	}
856}
857
858#define WCSIZE (128 * 1024)
859ufs2_daddr_t wc_sect;		/* units of sectorsize */
860int wc_end;			/* bytes */
861static char wc[WCSIZE];		/* bytes */
862
863/*
864 * Flush dirty write behind buffer.
865 */
866static void
867wtfsflush()
868{
869	int n;
870	if (wc_end) {
871		if (lseek(fso, (off_t)wc_sect * sectorsize, SEEK_SET) < 0) {
872			printf("seek error: %ld\n", (long)wc_sect);
873			err(35, "wtfs - writecombine");
874		}
875		n = write(fso, wc, wc_end);
876		if (n != wc_end) {
877			printf("write error: %ld\n", (long)wc_sect);
878			err(36, "wtfs - writecombine");
879		}
880		wc_end = 0;
881	}
882}
883
884/*
885 * write a block to the file system
886 */
887static void
888wtfs(ufs2_daddr_t bno, int size, char *bf)
889{
890	int done, n;
891
892	if (Nflag)
893		return;
894	done = 0;
895	if (wc_end == 0 && size <= WCSIZE) {
896		wc_sect = bno;
897		bcopy(bf, wc, size);
898		wc_end = size;
899		if (wc_end < WCSIZE)
900			return;
901		done = 1;
902	}
903	if ((off_t)wc_sect * sectorsize + wc_end == (off_t)bno * sectorsize &&
904	    wc_end + size <= WCSIZE) {
905		bcopy(bf, wc + wc_end, size);
906		wc_end += size;
907		if (wc_end < WCSIZE)
908			return;
909		done = 1;
910	}
911	wtfsflush();
912	if (done)
913		return;
914	if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) {
915		printf("seek error: %ld\n", (long)bno);
916		err(35, "wtfs");
917	}
918	n = write(fso, bf, size);
919	if (n != size) {
920		printf("write error: %ld\n", (long)bno);
921		err(36, "wtfs");
922	}
923}
924
925/*
926 * check if a block is available
927 */
928static int
929isblock(struct fs *fs, unsigned char *cp, int h)
930{
931	unsigned char mask;
932
933	switch (fs->fs_frag) {
934	case 8:
935		return (cp[h] == 0xff);
936	case 4:
937		mask = 0x0f << ((h & 0x1) << 2);
938		return ((cp[h >> 1] & mask) == mask);
939	case 2:
940		mask = 0x03 << ((h & 0x3) << 1);
941		return ((cp[h >> 2] & mask) == mask);
942	case 1:
943		mask = 0x01 << (h & 0x7);
944		return ((cp[h >> 3] & mask) == mask);
945	default:
946		fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
947		return (0);
948	}
949}
950
951/*
952 * take a block out of the map
953 */
954static void
955clrblock(struct fs *fs, unsigned char *cp, int h)
956{
957	switch ((fs)->fs_frag) {
958	case 8:
959		cp[h] = 0;
960		return;
961	case 4:
962		cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
963		return;
964	case 2:
965		cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
966		return;
967	case 1:
968		cp[h >> 3] &= ~(0x01 << (h & 0x7));
969		return;
970	default:
971		fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
972		return;
973	}
974}
975
976/*
977 * put a block into the map
978 */
979static void
980setblock(struct fs *fs, unsigned char *cp, int h)
981{
982	switch (fs->fs_frag) {
983	case 8:
984		cp[h] = 0xff;
985		return;
986	case 4:
987		cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
988		return;
989	case 2:
990		cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
991		return;
992	case 1:
993		cp[h >> 3] |= (0x01 << (h & 0x7));
994		return;
995	default:
996		fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
997		return;
998	}
999}
1000
1001/*
1002 * Determine the number of characters in a
1003 * single line.
1004 */
1005
1006static int
1007charsperline(void)
1008{
1009	int columns;
1010	char *cp;
1011	struct winsize ws;
1012
1013	columns = 0;
1014	if (ioctl(0, TIOCGWINSZ, &ws) != -1)
1015		columns = ws.ws_col;
1016	if (columns == 0 && (cp = getenv("COLUMNS")))
1017		columns = atoi(cp);
1018	if (columns == 0)
1019		columns = 80;	/* last resort */
1020	return (columns);
1021}
1022
1023static int
1024ilog2(int val)
1025{
1026	u_int n;
1027
1028	for (n = 0; n < sizeof(n) * CHAR_BIT; n++)
1029		if (1 << n == val)
1030			return (n);
1031	errx(1, "ilog2: %d is not a power of 2\n", val);
1032}
1033