1 /* $NetBSD: mkfs.c,v 1.32 2013/10/19 17:16:37 christos Exp $ */
4 * Copyright (c) 2002 Networks Associates Technology, Inc.
7 * This software was developed for the FreeBSD Project by Marshall
8 * Kirk McKusick and Network Associates Laboratories, the Security
9 * Research Division of Network Associates, Inc. under DARPA/SPAWAR
10 * contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA CHATS
13 * Copyright (c) 1980, 1989, 1993
14 * The Regents of the University of California. All rights reserved.
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 * 3. Neither the name of the University nor the names of its contributors
25 * may be used to endorse or promote products derived from this software
26 * without specific prior written permission.
28 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
29 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
32 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
33 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
34 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
35 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
36 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
37 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 #if HAVE_NBTOOL_CONFIG_H
42 #include "nbtool_config.h"
45 #include <sys/cdefs.h>
48 static char sccsid
[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95";
51 __RCSID("$NetBSD: mkfs.c,v 1.32 2013/10/19 17:16:37 christos Exp $");
56 #include <sys/param.h>
58 #include <sys/resource.h>
70 #include <ufs/ufs/dinode.h>
71 #include <ufs/ufs/ufs_bswap.h>
72 #include <ufs/ffs/fs.h>
74 #include "ffs/ufs_inode.h"
75 #include "ffs/ffs_extern.h"
76 #include "ffs/newfs_extern.h"
78 static void initcg(int, time_t, const fsinfo_t
*);
79 static int ilog2(int);
81 static int count_digits(int);
84 * make file system for cylinder-group style file systems
87 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
93 #define sblock fsun.fs
98 char pad
[FFS_MAXBSIZE
];
105 char writebuf
[FFS_MAXBSIZE
];
107 static int Oflag
; /* format as an 4.3BSD file system */
108 static int64_t fssize
; /* file system size */
109 static int sectorsize
; /* bytes/sector */
110 static int fsize
; /* fragment size */
111 static int bsize
; /* block size */
112 static int maxbsize
; /* maximum clustering */
113 static int maxblkspercg
;
114 static int minfree
; /* free space threshold */
115 static int opt
; /* optimization preference (space or time) */
116 static int density
; /* number of bytes per inode */
117 static int maxcontig
; /* max contiguous blocks to allocate */
118 static int maxbpg
; /* maximum blocks per file in a cyl group */
119 static int bbsize
; /* boot block size */
120 static int sbsize
; /* superblock size */
121 static int avgfilesize
; /* expected average file size */
122 static int avgfpdir
; /* expected number of files per directory */
125 ffs_mkfs(const char *fsys
, const fsinfo_t
*fsopts
)
127 int fragsperinode
, optimalfpg
, origdensity
, minfpg
, lastminfpg
;
128 int32_t cylno
, i
, csfrags
;
132 int nprintcols
, printcolwidth
;
133 ffs_opt_t
*ffs_opts
= fsopts
->fs_specific
;
135 Oflag
= ffs_opts
->version
;
136 fssize
= fsopts
->size
/ fsopts
->sectorsize
;
137 sectorsize
= fsopts
->sectorsize
;
138 fsize
= ffs_opts
->fsize
;
139 bsize
= ffs_opts
->bsize
;
140 maxbsize
= ffs_opts
->maxbsize
;
141 maxblkspercg
= ffs_opts
->maxblkspercg
;
142 minfree
= ffs_opts
->minfree
;
143 opt
= ffs_opts
->optimization
;
144 density
= ffs_opts
->density
;
145 maxcontig
= ffs_opts
->maxcontig
;
146 maxbpg
= ffs_opts
->maxbpg
;
147 avgfilesize
= ffs_opts
->avgfilesize
;
148 avgfpdir
= ffs_opts
->avgfpdir
;
152 strlcpy((char *)sblock
.fs_volname
, ffs_opts
->label
,
153 sizeof(sblock
.fs_volname
));
156 sblock
.fs_old_inodefmt
= FS_42INODEFMT
;
157 sblock
.fs_maxsymlinklen
= 0;
158 sblock
.fs_old_flags
= 0;
160 sblock
.fs_old_inodefmt
= FS_44INODEFMT
;
161 sblock
.fs_maxsymlinklen
= (Oflag
== 1 ? UFS1_MAXSYMLINKLEN
:
163 sblock
.fs_old_flags
= FS_FLAGS_UPDATED
;
167 * Validate the given file system size.
168 * Verify that its last block can actually be accessed.
169 * Convert to file system fragment sized units.
172 printf("preposterous size %lld\n", (long long)fssize
);
175 ffs_wtfs(fssize
- 1, sectorsize
, (char *)&sblock
, fsopts
);
178 * collect and verify the filesystem density info
180 sblock
.fs_avgfilesize
= avgfilesize
;
181 sblock
.fs_avgfpdir
= avgfpdir
;
182 if (sblock
.fs_avgfilesize
<= 0)
183 printf("illegal expected average file size %d\n",
184 sblock
.fs_avgfilesize
), exit(14);
185 if (sblock
.fs_avgfpdir
<= 0)
186 printf("illegal expected number of files per directory %d\n",
187 sblock
.fs_avgfpdir
), exit(15);
189 * collect and verify the block and fragment sizes
191 sblock
.fs_bsize
= bsize
;
192 sblock
.fs_fsize
= fsize
;
193 if (!POWEROF2(sblock
.fs_bsize
)) {
194 printf("block size must be a power of 2, not %d\n",
198 if (!POWEROF2(sblock
.fs_fsize
)) {
199 printf("fragment size must be a power of 2, not %d\n",
203 if (sblock
.fs_fsize
< sectorsize
) {
204 printf("fragment size %d is too small, minimum is %d\n",
205 sblock
.fs_fsize
, sectorsize
);
208 if (sblock
.fs_bsize
< MINBSIZE
) {
209 printf("block size %d is too small, minimum is %d\n",
210 sblock
.fs_bsize
, MINBSIZE
);
213 if (sblock
.fs_bsize
> FFS_MAXBSIZE
) {
214 printf("block size %d is too large, maximum is %d\n",
215 sblock
.fs_bsize
, FFS_MAXBSIZE
);
218 if (sblock
.fs_bsize
< sblock
.fs_fsize
) {
219 printf("block size (%d) cannot be smaller than fragment size (%d)\n",
220 sblock
.fs_bsize
, sblock
.fs_fsize
);
224 if (maxbsize
< bsize
|| !POWEROF2(maxbsize
)) {
225 sblock
.fs_maxbsize
= sblock
.fs_bsize
;
226 printf("Extent size set to %d\n", sblock
.fs_maxbsize
);
227 } else if (sblock
.fs_maxbsize
> FS_MAXCONTIG
* sblock
.fs_bsize
) {
228 sblock
.fs_maxbsize
= FS_MAXCONTIG
* sblock
.fs_bsize
;
229 printf("Extent size reduced to %d\n", sblock
.fs_maxbsize
);
231 sblock
.fs_maxbsize
= maxbsize
;
233 sblock
.fs_maxcontig
= maxcontig
;
234 if (sblock
.fs_maxcontig
< sblock
.fs_maxbsize
/ sblock
.fs_bsize
) {
235 sblock
.fs_maxcontig
= sblock
.fs_maxbsize
/ sblock
.fs_bsize
;
236 printf("Maxcontig raised to %d\n", sblock
.fs_maxbsize
);
239 if (sblock
.fs_maxcontig
> 1)
240 sblock
.fs_contigsumsize
= MIN(sblock
.fs_maxcontig
,FS_MAXCONTIG
);
242 sblock
.fs_bmask
= ~(sblock
.fs_bsize
- 1);
243 sblock
.fs_fmask
= ~(sblock
.fs_fsize
- 1);
244 sblock
.fs_qbmask
= ~sblock
.fs_bmask
;
245 sblock
.fs_qfmask
= ~sblock
.fs_fmask
;
246 for (sblock
.fs_bshift
= 0, i
= sblock
.fs_bsize
; i
> 1; i
>>= 1)
248 for (sblock
.fs_fshift
= 0, i
= sblock
.fs_fsize
; i
> 1; i
>>= 1)
250 sblock
.fs_frag
= ffs_numfrags(&sblock
, sblock
.fs_bsize
);
251 for (sblock
.fs_fragshift
= 0, i
= sblock
.fs_frag
; i
> 1; i
>>= 1)
252 sblock
.fs_fragshift
++;
253 if (sblock
.fs_frag
> MAXFRAG
) {
254 printf("fragment size %d is too small, "
255 "minimum with block size %d is %d\n",
256 sblock
.fs_fsize
, sblock
.fs_bsize
,
257 sblock
.fs_bsize
/ MAXFRAG
);
260 sblock
.fs_fsbtodb
= ilog2(sblock
.fs_fsize
/ sectorsize
);
261 sblock
.fs_size
= fssize
= FFS_DBTOFSB(&sblock
, fssize
);
264 sblock
.fs_magic
= FS_UFS1_MAGIC
;
265 sblock
.fs_sblockloc
= SBLOCK_UFS1
;
266 sblock
.fs_nindir
= sblock
.fs_bsize
/ sizeof(int32_t);
267 sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof(struct ufs1_dinode
);
268 sblock
.fs_maxsymlinklen
= ((UFS_NDADDR
+ UFS_NIADDR
) *
270 sblock
.fs_old_inodefmt
= FS_44INODEFMT
;
271 sblock
.fs_old_cgoffset
= 0;
272 sblock
.fs_old_cgmask
= 0xffffffff;
273 sblock
.fs_old_size
= sblock
.fs_size
;
274 sblock
.fs_old_rotdelay
= 0;
275 sblock
.fs_old_rps
= 60;
276 sblock
.fs_old_nspf
= sblock
.fs_fsize
/ sectorsize
;
277 sblock
.fs_old_cpg
= 1;
278 sblock
.fs_old_interleave
= 1;
279 sblock
.fs_old_trackskew
= 0;
280 sblock
.fs_old_cpc
= 0;
281 sblock
.fs_old_postblformat
= 1;
282 sblock
.fs_old_nrpos
= 1;
284 sblock
.fs_magic
= FS_UFS2_MAGIC
;
285 #if 0 /* XXX makefs is used for small filesystems. */
286 sblock
.fs_sblockloc
= SBLOCK_UFS2
;
288 sblock
.fs_sblockloc
= SBLOCK_UFS1
;
290 sblock
.fs_nindir
= sblock
.fs_bsize
/ sizeof(int64_t);
291 sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof(struct ufs2_dinode
);
292 sblock
.fs_maxsymlinklen
= ((UFS_NDADDR
+ UFS_NIADDR
) *
297 roundup(howmany(sblock
.fs_sblockloc
+ SBLOCKSIZE
, sblock
.fs_fsize
),
299 sblock
.fs_cblkno
= (daddr_t
)(sblock
.fs_sblkno
+
300 roundup(howmany(SBLOCKSIZE
, sblock
.fs_fsize
), sblock
.fs_frag
));
301 sblock
.fs_iblkno
= sblock
.fs_cblkno
+ sblock
.fs_frag
;
302 sblock
.fs_maxfilesize
= sblock
.fs_bsize
* UFS_NDADDR
- 1;
303 for (sizepb
= sblock
.fs_bsize
, i
= 0; i
< UFS_NIADDR
; i
++) {
304 sizepb
*= FFS_NINDIR(&sblock
);
305 sblock
.fs_maxfilesize
+= sizepb
;
309 * Calculate the number of blocks to put into each cylinder group.
311 * This algorithm selects the number of blocks per cylinder
312 * group. The first goal is to have at least enough data blocks
313 * in each cylinder group to meet the density requirement. Once
314 * this goal is achieved we try to expand to have at least
315 * 1 cylinder group. Once this goal is achieved, we pack as
316 * many blocks into each cylinder group map as will fit.
318 * We start by calculating the smallest number of blocks that we
319 * can put into each cylinder group. If this is too big, we reduce
320 * the density until it fits.
322 origdensity
= density
;
324 fragsperinode
= MAX(ffs_numfrags(&sblock
, density
), 1);
325 minfpg
= fragsperinode
* FFS_INOPB(&sblock
);
326 if (minfpg
> sblock
.fs_size
)
327 minfpg
= sblock
.fs_size
;
328 sblock
.fs_ipg
= FFS_INOPB(&sblock
);
329 sblock
.fs_fpg
= roundup(sblock
.fs_iblkno
+
330 sblock
.fs_ipg
/ FFS_INOPF(&sblock
), sblock
.fs_frag
);
331 if (sblock
.fs_fpg
< minfpg
)
332 sblock
.fs_fpg
= minfpg
;
333 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
335 sblock
.fs_fpg
= roundup(sblock
.fs_iblkno
+
336 sblock
.fs_ipg
/ FFS_INOPF(&sblock
), sblock
.fs_frag
);
337 if (sblock
.fs_fpg
< minfpg
)
338 sblock
.fs_fpg
= minfpg
;
339 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
341 if (CGSIZE(&sblock
) < (unsigned long)sblock
.fs_bsize
)
343 density
-= sblock
.fs_fsize
;
345 if (density
!= origdensity
)
346 printf("density reduced from %d to %d\n", origdensity
, density
);
348 if (maxblkspercg
<= 0 || maxblkspercg
>= fssize
)
349 maxblkspercg
= fssize
- 1;
351 * Start packing more blocks into the cylinder group until
352 * it cannot grow any larger, the number of cylinder groups
353 * drops below 1, or we reach the size requested.
355 for ( ; sblock
.fs_fpg
< maxblkspercg
; sblock
.fs_fpg
+= sblock
.fs_frag
) {
356 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
358 if (sblock
.fs_size
/ sblock
.fs_fpg
< 1)
360 if (CGSIZE(&sblock
) < (unsigned long)sblock
.fs_bsize
)
362 if (CGSIZE(&sblock
) == (unsigned long)sblock
.fs_bsize
)
364 sblock
.fs_fpg
-= sblock
.fs_frag
;
365 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
370 * Check to be sure that the last cylinder group has enough blocks
371 * to be viable. If it is too small, reduce the number of blocks
372 * per cylinder group which will have the effect of moving more
373 * blocks into the last cylinder group.
375 optimalfpg
= sblock
.fs_fpg
;
377 sblock
.fs_ncg
= howmany(sblock
.fs_size
, sblock
.fs_fpg
);
378 lastminfpg
= roundup(sblock
.fs_iblkno
+
379 sblock
.fs_ipg
/ FFS_INOPF(&sblock
), sblock
.fs_frag
);
380 if (sblock
.fs_size
< lastminfpg
) {
381 printf("Filesystem size %lld < minimum size of %d\n",
382 (long long)sblock
.fs_size
, lastminfpg
);
385 if (sblock
.fs_size
% sblock
.fs_fpg
>= lastminfpg
||
386 sblock
.fs_size
% sblock
.fs_fpg
== 0)
388 sblock
.fs_fpg
-= sblock
.fs_frag
;
389 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
392 if (optimalfpg
!= sblock
.fs_fpg
)
393 printf("Reduced frags per cylinder group from %d to %d %s\n",
394 optimalfpg
, sblock
.fs_fpg
, "to enlarge last cyl group");
395 sblock
.fs_cgsize
= ffs_fragroundup(&sblock
, CGSIZE(&sblock
));
396 sblock
.fs_dblkno
= sblock
.fs_iblkno
+ sblock
.fs_ipg
/ FFS_INOPF(&sblock
);
398 sblock
.fs_old_spc
= sblock
.fs_fpg
* sblock
.fs_old_nspf
;
399 sblock
.fs_old_nsect
= sblock
.fs_old_spc
;
400 sblock
.fs_old_npsect
= sblock
.fs_old_spc
;
401 sblock
.fs_old_ncyl
= sblock
.fs_ncg
;
405 * fill in remaining fields of the super block
407 sblock
.fs_csaddr
= cgdmin(&sblock
, 0);
409 ffs_fragroundup(&sblock
, sblock
.fs_ncg
* sizeof(struct csum
));
412 * Setup memory for temporary in-core cylgroup summaries.
413 * Cribbed from ffs_mountfs().
415 size
= sblock
.fs_cssize
;
416 if (sblock
.fs_contigsumsize
> 0)
417 size
+= sblock
.fs_ncg
* sizeof(int32_t);
418 space
= ecalloc(1, size
);
419 sblock
.fs_csp
= space
;
420 space
= (char *)space
+ sblock
.fs_cssize
;
421 if (sblock
.fs_contigsumsize
> 0) {
424 sblock
.fs_maxcluster
= lp
= space
;
425 for (i
= 0; i
< sblock
.fs_ncg
; i
++)
426 *lp
++ = sblock
.fs_contigsumsize
;
429 sblock
.fs_sbsize
= ffs_fragroundup(&sblock
, sizeof(struct fs
));
430 if (sblock
.fs_sbsize
> SBLOCKSIZE
)
431 sblock
.fs_sbsize
= SBLOCKSIZE
;
432 sblock
.fs_minfree
= minfree
;
433 sblock
.fs_maxcontig
= maxcontig
;
434 sblock
.fs_maxbpg
= maxbpg
;
435 sblock
.fs_optim
= opt
;
436 sblock
.fs_cgrotor
= 0;
437 sblock
.fs_pendingblocks
= 0;
438 sblock
.fs_pendinginodes
= 0;
439 sblock
.fs_cstotal
.cs_ndir
= 0;
440 sblock
.fs_cstotal
.cs_nbfree
= 0;
441 sblock
.fs_cstotal
.cs_nifree
= 0;
442 sblock
.fs_cstotal
.cs_nffree
= 0;
446 sblock
.fs_clean
= FS_ISCLEAN
;
448 sblock
.fs_id
[0] = start_time
.tv_sec
;
449 sblock
.fs_id
[1] = random();
450 sblock
.fs_fsmnt
[0] = '\0';
451 csfrags
= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
452 sblock
.fs_dsize
= sblock
.fs_size
- sblock
.fs_sblkno
-
453 sblock
.fs_ncg
* (sblock
.fs_dblkno
- sblock
.fs_sblkno
);
454 sblock
.fs_cstotal
.cs_nbfree
=
455 ffs_fragstoblks(&sblock
, sblock
.fs_dsize
) -
456 howmany(csfrags
, sblock
.fs_frag
);
457 sblock
.fs_cstotal
.cs_nffree
=
458 ffs_fragnum(&sblock
, sblock
.fs_size
) +
459 (ffs_fragnum(&sblock
, csfrags
) > 0 ?
460 sblock
.fs_frag
- ffs_fragnum(&sblock
, csfrags
) : 0);
461 sblock
.fs_cstotal
.cs_nifree
= sblock
.fs_ncg
* sblock
.fs_ipg
- UFS_ROOTINO
;
462 sblock
.fs_cstotal
.cs_ndir
= 0;
463 sblock
.fs_dsize
-= csfrags
;
464 sblock
.fs_time
= start_time
.tv_sec
;
466 sblock
.fs_old_time
= start_time
.tv_sec
;
467 sblock
.fs_old_dsize
= sblock
.fs_dsize
;
468 sblock
.fs_old_csaddr
= sblock
.fs_csaddr
;
469 sblock
.fs_old_cstotal
.cs_ndir
= sblock
.fs_cstotal
.cs_ndir
;
470 sblock
.fs_old_cstotal
.cs_nbfree
= sblock
.fs_cstotal
.cs_nbfree
;
471 sblock
.fs_old_cstotal
.cs_nifree
= sblock
.fs_cstotal
.cs_nifree
;
472 sblock
.fs_old_cstotal
.cs_nffree
= sblock
.fs_cstotal
.cs_nffree
;
475 * Dump out summary information about file system.
477 #define B2MBFACTOR (1 / (1024.0 * 1024.0))
478 printf("%s: %.1fMB (%lld sectors) block size %d, "
479 "fragment size %d\n",
480 fsys
, (float)sblock
.fs_size
* sblock
.fs_fsize
* B2MBFACTOR
,
481 (long long)FFS_FSBTODB(&sblock
, sblock
.fs_size
),
482 sblock
.fs_bsize
, sblock
.fs_fsize
);
483 printf("\tusing %d cylinder groups of %.2fMB, %d blks, "
486 (float)sblock
.fs_fpg
* sblock
.fs_fsize
* B2MBFACTOR
,
487 sblock
.fs_fpg
/ sblock
.fs_frag
, sblock
.fs_ipg
);
490 * Now determine how wide each column will be, and calculate how
491 * many columns will fit in a 76 char line. 76 is the width of the
492 * subwindows in sysinst.
494 printcolwidth
= count_digits(
495 FFS_FSBTODB(&sblock
, cgsblock(&sblock
, sblock
.fs_ncg
-1)));
496 nprintcols
= 76 / (printcolwidth
+ 2);
499 * allocate space for superblock, cylinder group map, and
500 * two sets of inode blocks.
502 if (sblock
.fs_bsize
< SBLOCKSIZE
)
503 iobufsize
= SBLOCKSIZE
+ 3 * sblock
.fs_bsize
;
505 iobufsize
= 4 * sblock
.fs_bsize
;
506 iobuf
= ecalloc(1, iobufsize
);
508 * Make a copy of the superblock into the buffer that we will be
509 * writing out in each cylinder group.
511 memcpy(writebuf
, &sblock
, sbsize
);
512 if (fsopts
->needswap
)
513 ffs_sb_swap(&sblock
, (struct fs
*)writebuf
);
514 memcpy(iobuf
, writebuf
, SBLOCKSIZE
);
516 printf("super-block backups (for fsck -b #) at:");
517 for (cylno
= 0; cylno
< sblock
.fs_ncg
; cylno
++) {
518 initcg(cylno
, start_time
.tv_sec
, fsopts
);
519 if (cylno
% nprintcols
== 0)
521 printf(" %*lld,", printcolwidth
,
522 (long long)FFS_FSBTODB(&sblock
, cgsblock(&sblock
, cylno
)));
528 * Now construct the initial file system,
529 * then write out the super-block.
531 sblock
.fs_time
= start_time
.tv_sec
;
533 sblock
.fs_old_cstotal
.cs_ndir
= sblock
.fs_cstotal
.cs_ndir
;
534 sblock
.fs_old_cstotal
.cs_nbfree
= sblock
.fs_cstotal
.cs_nbfree
;
535 sblock
.fs_old_cstotal
.cs_nifree
= sblock
.fs_cstotal
.cs_nifree
;
536 sblock
.fs_old_cstotal
.cs_nffree
= sblock
.fs_cstotal
.cs_nffree
;
538 if (fsopts
->needswap
)
539 sblock
.fs_flags
|= FS_SWAPPED
;
540 ffs_write_superblock(&sblock
, fsopts
);
545 * Write out the superblock and its duplicates,
546 * and the cylinder group summaries
549 ffs_write_superblock(struct fs
*fs
, const fsinfo_t
*fsopts
)
551 int cylno
, size
, blks
, i
, saveflag
;
555 saveflag
= fs
->fs_flags
& FS_INTERNAL
;
556 fs
->fs_flags
&= ~FS_INTERNAL
;
558 memcpy(writebuf
, &sblock
, sbsize
);
559 if (fsopts
->needswap
)
560 ffs_sb_swap(fs
, (struct fs
*)writebuf
);
561 ffs_wtfs(fs
->fs_sblockloc
/ sectorsize
, sbsize
, writebuf
, fsopts
);
563 /* Write out the duplicate super blocks */
564 for (cylno
= 0; cylno
< fs
->fs_ncg
; cylno
++)
565 ffs_wtfs(FFS_FSBTODB(fs
, cgsblock(fs
, cylno
)),
566 sbsize
, writebuf
, fsopts
);
568 /* Write out the cylinder group summaries */
569 size
= fs
->fs_cssize
;
570 blks
= howmany(size
, fs
->fs_fsize
);
571 space
= (void *)fs
->fs_csp
;
572 wrbuf
= emalloc(size
);
573 for (i
= 0; i
< blks
; i
+= fs
->fs_frag
) {
575 if (i
+ fs
->fs_frag
> blks
)
576 size
= (blks
- i
) * fs
->fs_fsize
;
577 if (fsopts
->needswap
)
578 ffs_csum_swap((struct csum
*)space
,
579 (struct csum
*)wrbuf
, size
);
581 memcpy(wrbuf
, space
, (u_int
)size
);
582 ffs_wtfs(FFS_FSBTODB(fs
, fs
->fs_csaddr
+ i
), size
, wrbuf
, fsopts
);
583 space
= (char *)space
+ size
;
586 fs
->fs_flags
|= saveflag
;
590 * Initialize a cylinder group.
593 initcg(int cylno
, time_t utime
, const fsinfo_t
*fsopts
)
596 int i
, j
, d
, dlower
, dupper
, blkno
;
597 struct ufs1_dinode
*dp1
;
598 struct ufs2_dinode
*dp2
;
602 * Determine block bounds for cylinder group.
603 * Allow space for super block summary information in first
606 cbase
= cgbase(&sblock
, cylno
);
607 dmax
= cbase
+ sblock
.fs_fpg
;
608 if (dmax
> sblock
.fs_size
)
609 dmax
= sblock
.fs_size
;
610 dlower
= cgsblock(&sblock
, cylno
) - cbase
;
611 dupper
= cgdmin(&sblock
, cylno
) - cbase
;
613 dupper
+= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
614 memset(&acg
, 0, sblock
.fs_cgsize
);
616 acg
.cg_magic
= CG_MAGIC
;
618 acg
.cg_niblk
= sblock
.fs_ipg
;
619 acg
.cg_initediblk
= sblock
.fs_ipg
< 2 * FFS_INOPB(&sblock
) ?
620 sblock
.fs_ipg
: 2 * FFS_INOPB(&sblock
);
621 acg
.cg_ndblk
= dmax
- cbase
;
622 if (sblock
.fs_contigsumsize
> 0)
623 acg
.cg_nclusterblks
= acg
.cg_ndblk
>> sblock
.fs_fragshift
;
624 start
= &acg
.cg_space
[0] - (u_char
*)(&acg
.cg_firstfield
);
626 acg
.cg_iusedoff
= start
;
628 if (cylno
== sblock
.fs_ncg
- 1)
629 acg
.cg_old_ncyl
= howmany(acg
.cg_ndblk
,
630 sblock
.fs_fpg
/ sblock
.fs_old_cpg
);
632 acg
.cg_old_ncyl
= sblock
.fs_old_cpg
;
633 acg
.cg_old_time
= acg
.cg_time
;
635 acg
.cg_old_niblk
= acg
.cg_niblk
;
637 acg
.cg_initediblk
= 0;
638 acg
.cg_old_btotoff
= start
;
639 acg
.cg_old_boff
= acg
.cg_old_btotoff
+
640 sblock
.fs_old_cpg
* sizeof(int32_t);
641 acg
.cg_iusedoff
= acg
.cg_old_boff
+
642 sblock
.fs_old_cpg
* sizeof(u_int16_t
);
644 acg
.cg_freeoff
= acg
.cg_iusedoff
+ howmany(sblock
.fs_ipg
, CHAR_BIT
);
645 if (sblock
.fs_contigsumsize
<= 0) {
646 acg
.cg_nextfreeoff
= acg
.cg_freeoff
+
647 howmany(sblock
.fs_fpg
, CHAR_BIT
);
649 acg
.cg_clustersumoff
= acg
.cg_freeoff
+
650 howmany(sblock
.fs_fpg
, CHAR_BIT
) - sizeof(int32_t);
651 acg
.cg_clustersumoff
=
652 roundup(acg
.cg_clustersumoff
, sizeof(int32_t));
653 acg
.cg_clusteroff
= acg
.cg_clustersumoff
+
654 (sblock
.fs_contigsumsize
+ 1) * sizeof(int32_t);
655 acg
.cg_nextfreeoff
= acg
.cg_clusteroff
+
656 howmany(ffs_fragstoblks(&sblock
, sblock
.fs_fpg
), CHAR_BIT
);
658 if (acg
.cg_nextfreeoff
> sblock
.fs_cgsize
) {
659 printf("Panic: cylinder group too big\n");
662 acg
.cg_cs
.cs_nifree
+= sblock
.fs_ipg
;
666 for (r
= 0; r
< UFS_ROOTINO
; r
++) {
667 setbit(cg_inosused(&acg
, 0), r
);
668 acg
.cg_cs
.cs_nifree
--;
673 * In cylno 0, beginning space is reserved
674 * for boot and super blocks.
676 for (d
= 0, blkno
= 0; d
< dlower
;) {
677 ffs_setblock(&sblock
, cg_blksfree(&acg
, 0), blkno
);
678 if (sblock
.fs_contigsumsize
> 0)
679 setbit(cg_clustersfree(&acg
, 0), blkno
);
680 acg
.cg_cs
.cs_nbfree
++;
685 if ((i
= (dupper
& (sblock
.fs_frag
- 1))) != 0) {
686 acg
.cg_frsum
[sblock
.fs_frag
- i
]++;
687 for (d
= dupper
+ sblock
.fs_frag
- i
; dupper
< d
; dupper
++) {
688 setbit(cg_blksfree(&acg
, 0), dupper
);
689 acg
.cg_cs
.cs_nffree
++;
692 for (d
= dupper
, blkno
= dupper
>> sblock
.fs_fragshift
;
693 d
+ sblock
.fs_frag
<= acg
.cg_ndblk
; ) {
694 ffs_setblock(&sblock
, cg_blksfree(&acg
, 0), blkno
);
695 if (sblock
.fs_contigsumsize
> 0)
696 setbit(cg_clustersfree(&acg
, 0), blkno
);
697 acg
.cg_cs
.cs_nbfree
++;
701 if (d
< acg
.cg_ndblk
) {
702 acg
.cg_frsum
[acg
.cg_ndblk
- d
]++;
703 for (; d
< acg
.cg_ndblk
; d
++) {
704 setbit(cg_blksfree(&acg
, 0), d
);
705 acg
.cg_cs
.cs_nffree
++;
708 if (sblock
.fs_contigsumsize
> 0) {
709 int32_t *sump
= cg_clustersum(&acg
, 0);
710 u_char
*mapp
= cg_clustersfree(&acg
, 0);
715 for (i
= 0; i
< acg
.cg_nclusterblks
; i
++) {
716 if ((map
& bit
) != 0) {
718 } else if (run
!= 0) {
719 if (run
> sblock
.fs_contigsumsize
)
720 run
= sblock
.fs_contigsumsize
;
724 if ((i
& (CHAR_BIT
- 1)) != (CHAR_BIT
- 1)) {
732 if (run
> sblock
.fs_contigsumsize
)
733 run
= sblock
.fs_contigsumsize
;
737 sblock
.fs_cs(&sblock
, cylno
) = acg
.cg_cs
;
739 * Write out the duplicate super block, the cylinder group map
740 * and two blocks worth of inodes in a single write.
742 start
= sblock
.fs_bsize
> SBLOCKSIZE
? sblock
.fs_bsize
: SBLOCKSIZE
;
743 memcpy(&iobuf
[start
], &acg
, sblock
.fs_cgsize
);
744 if (fsopts
->needswap
)
745 ffs_cg_swap(&acg
, (struct cg
*)&iobuf
[start
], &sblock
);
746 start
+= sblock
.fs_bsize
;
747 dp1
= (struct ufs1_dinode
*)(&iobuf
[start
]);
748 dp2
= (struct ufs2_dinode
*)(&iobuf
[start
]);
749 for (i
= 0; i
< acg
.cg_initediblk
; i
++) {
750 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
751 /* No need to swap, it'll stay random */
752 dp1
->di_gen
= random();
755 dp2
->di_gen
= random();
759 ffs_wtfs(FFS_FSBTODB(&sblock
, cgsblock(&sblock
, cylno
)), iobufsize
, iobuf
,
762 * For the old file system, we have to initialize all the inodes.
765 for (i
= 2 * sblock
.fs_frag
;
766 i
< sblock
.fs_ipg
/ FFS_INOPF(&sblock
);
767 i
+= sblock
.fs_frag
) {
768 dp1
= (struct ufs1_dinode
*)(&iobuf
[start
]);
769 for (j
= 0; j
< FFS_INOPB(&sblock
); j
++) {
770 dp1
->di_gen
= random();
773 ffs_wtfs(FFS_FSBTODB(&sblock
, cgimin(&sblock
, cylno
) + i
),
774 sblock
.fs_bsize
, &iobuf
[start
], fsopts
);
780 * read a block from the file system
783 ffs_rdfs(daddr_t bno
, int size
, void *bf
, const fsinfo_t
*fsopts
)
788 offset
= bno
* fsopts
->sectorsize
+ fsopts
->offset
;
789 if (lseek(fsopts
->fd
, offset
, SEEK_SET
) < 0)
790 err(1, "%s: seek error for sector %lld", __func__
,
792 n
= read(fsopts
->fd
, bf
, size
);
794 err(1, "%s: read error bno %lld size %d", __func__
,
795 (long long)bno
, size
);
798 errx(1, "%s: short read error for sector %lld", __func__
,
803 * write a block to the file system
806 ffs_wtfs(daddr_t bno
, int size
, void *bf
, const fsinfo_t
*fsopts
)
811 offset
= bno
* fsopts
->sectorsize
+ fsopts
->offset
;
812 if (lseek(fsopts
->fd
, offset
, SEEK_SET
) == -1)
813 err(1, "%s: seek error for sector %lld", __func__
,
815 n
= write(fsopts
->fd
, bf
, size
);
817 err(1, "%s: write error for sector %lld", __func__
,
820 errx(1, "%s: short write error for sector %lld", __func__
,
825 /* Determine how many digits are needed to print a given integer */
827 count_digits(int num
)
831 for(ndig
= 1; num
> 9; num
/=10, ndig
++);
841 for (n
= 0; n
< sizeof(n
) * CHAR_BIT
; n
++)
844 errx(1, "%s: %d is not a power of 2", __func__
, val
);