2 * Copyright (c) 2002 Networks Associates Technology, Inc.
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
11 * Copyright (c) 1980, 1989, 1993
12 * The Regents of the University of California. All rights reserved.
14 * Redistribution and use in source and binary forms, with or without
15 * modification, are permitted provided that the following conditions
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 * 2. Redistributions in binary form must reproduce the above copyright
20 * notice, this list of conditions and the following disclaimer in the
21 * documentation and/or other materials provided with the distribution.
22 * 4. Neither the name of the University nor the names of its contributors
23 * may be used to endorse or promote products derived from this software
24 * without specific prior written permission.
26 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
41 static char sccsid
[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95";
44 #include <sys/cdefs.h>
45 __FBSDID("$FreeBSD$");
47 #include <sys/param.h>
48 #include <sys/disklabel.h>
50 #include <sys/ioctl.h>
52 #include <sys/resource.h>
65 #include <ufs/ufs/dinode.h>
66 #include <ufs/ufs/dir.h>
67 #include <ufs/ffs/fs.h>
71 * make file system for cylinder-group style file systems
74 #define POWEROF2(num) (((num) & ((num) - 1)) == 0)
76 static struct csum
*fscs
;
77 #define sblock disk.d_fs
81 struct ufs1_dinode dp1
;
82 struct ufs2_dinode dp2
;
84 #define DIP(dp, field) \
85 ((sblock.fs_magic == FS_UFS1_MAGIC) ? \
86 (dp)->dp1.field : (dp)->dp2.field)
89 static long iobufsize
;
90 static ufs2_daddr_t
alloc(int size
, int mode
);
91 static int charsperline(void);
92 static void clrblock(struct fs
*, unsigned char *, int);
93 static void fsinit(time_t);
94 static int ilog2(int);
95 static void initcg(int, time_t);
96 static int isblock(struct fs
*, unsigned char *, int);
97 static void iput(union dinode
*, ino_t
);
98 static int makedir(struct direct
*, int);
99 static void setblock(struct fs
*, unsigned char *, int);
100 static void wtfs(ufs2_daddr_t
, int, char *);
101 static u_int32_t
newfs_random(void);
104 do_sbwrite(struct uufsd
*disk
)
107 disk
->d_sblock
= disk
->d_fs
.fs_sblockloc
/ disk
->d_bsize
;
108 return (pwrite(disk
->d_fd
, &disk
->d_fs
, SBLOCKSIZE
, (off_t
)((part_ofs
+
109 disk
->d_sblock
) * disk
->d_bsize
)));
113 mkfs(struct partition
*pp
, char *fsys
)
115 int fragsperinode
, optimalfpg
, origdensity
, minfpg
, lastminfpg
;
122 int minfragsperinode
; /* minimum ratio of frags to inodes */
123 char tmpbuf
[100]; /* XXX this will break in about 2,500 years */
126 char cdummy
[SBLOCKSIZE
];
128 #define fsdummy dummy.fdummy
129 #define chdummy dummy.cdummy
132 * Our blocks == sector size, and the version of UFS we are using is
133 * specified by Oflag.
135 disk
.d_bsize
= sectorsize
;
141 sblock
.fs_old_flags
= FS_FLAGS_UPDATED
;
144 sblock
.fs_flags
|= FS_DOSOFTDEP
;
146 strlcpy(sblock
.fs_volname
, volumelabel
, MAXVOLLEN
);
148 sblock
.fs_flags
|= FS_GJOURNAL
;
150 sblock
.fs_flags
|= FS_MULTILABEL
;
152 sblock
.fs_flags
|= FS_TRIM
;
154 * Validate the given file system size.
155 * Verify that its last block can actually be accessed.
156 * Convert to file system fragment sized units.
159 printf("preposterous size %jd\n", (intmax_t)fssize
);
162 wtfs(fssize
- (realsectorsize
/ DEV_BSIZE
), realsectorsize
,
165 * collect and verify the file system density info
167 sblock
.fs_avgfilesize
= avgfilesize
;
168 sblock
.fs_avgfpdir
= avgfilesperdir
;
169 if (sblock
.fs_avgfilesize
<= 0)
170 printf("illegal expected average file size %d\n",
171 sblock
.fs_avgfilesize
), exit(14);
172 if (sblock
.fs_avgfpdir
<= 0)
173 printf("illegal expected number of files per directory %d\n",
174 sblock
.fs_avgfpdir
), exit(15);
178 * collect and verify the block and fragment sizes
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",
187 if (!POWEROF2(sblock
.fs_fsize
)) {
188 printf("fragment size must be a power of 2, not %d\n",
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
;
197 if (sblock
.fs_bsize
> MAXBSIZE
) {
198 printf("decreasing block size from %d to maximum (%d)\n",
199 sblock
.fs_bsize
, MAXBSIZE
);
200 sblock
.fs_bsize
= MAXBSIZE
;
202 if (sblock
.fs_bsize
< MINBSIZE
) {
203 printf("increasing block size from %d to minimum (%d)\n",
204 sblock
.fs_bsize
, MINBSIZE
);
205 sblock
.fs_bsize
= MINBSIZE
;
207 if (sblock
.fs_fsize
> MAXBSIZE
) {
208 printf("decreasing fragment size from %d to maximum (%d)\n",
209 sblock
.fs_fsize
, MAXBSIZE
);
210 sblock
.fs_fsize
= MAXBSIZE
;
212 if (sblock
.fs_bsize
< sblock
.fs_fsize
) {
213 printf("increasing block size from %d to fragment size (%d)\n",
214 sblock
.fs_bsize
, sblock
.fs_fsize
);
215 sblock
.fs_bsize
= sblock
.fs_fsize
;
217 if (sblock
.fs_fsize
* MAXFRAG
< sblock
.fs_bsize
) {
219 "increasing fragment size from %d to block size / %d (%d)\n",
220 sblock
.fs_fsize
, MAXFRAG
, sblock
.fs_bsize
/ MAXFRAG
);
221 sblock
.fs_fsize
= sblock
.fs_bsize
/ MAXFRAG
;
225 if (maxbsize
< bsize
|| !POWEROF2(maxbsize
)) {
226 sblock
.fs_maxbsize
= sblock
.fs_bsize
;
227 printf("Extent size set to %d\n", sblock
.fs_maxbsize
);
228 } else if (sblock
.fs_maxbsize
> FS_MAXCONTIG
* sblock
.fs_bsize
) {
229 sblock
.fs_maxbsize
= FS_MAXCONTIG
* sblock
.fs_bsize
;
230 printf("Extent size reduced to %d\n", sblock
.fs_maxbsize
);
232 sblock
.fs_maxbsize
= maxbsize
;
235 * Maxcontig sets the default for the maximum number of blocks
236 * that may be allocated sequentially. With file system clustering
237 * it is possible to allocate contiguous blocks up to the maximum
238 * transfer size permitted by the controller or buffering.
241 maxcontig
= MAX(1, MAXPHYS
/ bsize
);
242 sblock
.fs_maxcontig
= maxcontig
;
243 if (sblock
.fs_maxcontig
< sblock
.fs_maxbsize
/ sblock
.fs_bsize
) {
244 sblock
.fs_maxcontig
= sblock
.fs_maxbsize
/ sblock
.fs_bsize
;
245 printf("Maxcontig raised to %d\n", sblock
.fs_maxbsize
);
247 if (sblock
.fs_maxcontig
> 1)
248 sblock
.fs_contigsumsize
= MIN(sblock
.fs_maxcontig
,FS_MAXCONTIG
);
249 sblock
.fs_bmask
= ~(sblock
.fs_bsize
- 1);
250 sblock
.fs_fmask
= ~(sblock
.fs_fsize
- 1);
251 sblock
.fs_qbmask
= ~sblock
.fs_bmask
;
252 sblock
.fs_qfmask
= ~sblock
.fs_fmask
;
253 sblock
.fs_bshift
= ilog2(sblock
.fs_bsize
);
254 sblock
.fs_fshift
= ilog2(sblock
.fs_fsize
);
255 sblock
.fs_frag
= numfrags(&sblock
, sblock
.fs_bsize
);
256 sblock
.fs_fragshift
= ilog2(sblock
.fs_frag
);
257 if (sblock
.fs_frag
> MAXFRAG
) {
258 printf("fragment size %d is still too small (can't happen)\n",
259 sblock
.fs_bsize
/ MAXFRAG
);
262 sblock
.fs_fsbtodb
= ilog2(sblock
.fs_fsize
/ sectorsize
);
263 sblock
.fs_size
= fssize
= dbtofsb(&sblock
, fssize
);
264 sblock
.fs_providersize
= dbtofsb(&sblock
, mediasize
/ sectorsize
);
267 * Before the filesystem is finally initialized, mark it
268 * as incompletely initialized.
270 sblock
.fs_magic
= FS_BAD_MAGIC
;
273 sblock
.fs_sblockloc
= SBLOCK_UFS1
;
274 sblock
.fs_nindir
= sblock
.fs_bsize
/ sizeof(ufs1_daddr_t
);
275 sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof(struct ufs1_dinode
);
276 sblock
.fs_maxsymlinklen
= ((NDADDR
+ NIADDR
) *
277 sizeof(ufs1_daddr_t
));
278 sblock
.fs_old_inodefmt
= FS_44INODEFMT
;
279 sblock
.fs_old_cgoffset
= 0;
280 sblock
.fs_old_cgmask
= 0xffffffff;
281 sblock
.fs_old_size
= sblock
.fs_size
;
282 sblock
.fs_old_rotdelay
= 0;
283 sblock
.fs_old_rps
= 60;
284 sblock
.fs_old_nspf
= sblock
.fs_fsize
/ sectorsize
;
285 sblock
.fs_old_cpg
= 1;
286 sblock
.fs_old_interleave
= 1;
287 sblock
.fs_old_trackskew
= 0;
288 sblock
.fs_old_cpc
= 0;
289 sblock
.fs_old_postblformat
= 1;
290 sblock
.fs_old_nrpos
= 1;
292 sblock
.fs_sblockloc
= SBLOCK_UFS2
;
293 sblock
.fs_nindir
= sblock
.fs_bsize
/ sizeof(ufs2_daddr_t
);
294 sblock
.fs_inopb
= sblock
.fs_bsize
/ sizeof(struct ufs2_dinode
);
295 sblock
.fs_maxsymlinklen
= ((NDADDR
+ NIADDR
) *
296 sizeof(ufs2_daddr_t
));
299 roundup(howmany(sblock
.fs_sblockloc
+ SBLOCKSIZE
, sblock
.fs_fsize
),
301 sblock
.fs_cblkno
= sblock
.fs_sblkno
+
302 roundup(howmany(SBLOCKSIZE
, sblock
.fs_fsize
), sblock
.fs_frag
);
303 sblock
.fs_iblkno
= sblock
.fs_cblkno
+ sblock
.fs_frag
;
304 sblock
.fs_maxfilesize
= sblock
.fs_bsize
* NDADDR
- 1;
305 for (sizepb
= sblock
.fs_bsize
, i
= 0; i
< NIADDR
; i
++) {
306 sizepb
*= NINDIR(&sblock
);
307 sblock
.fs_maxfilesize
+= sizepb
;
311 * It's impossible to create a snapshot in case that fs_maxfilesize
312 * is smaller than the fssize.
314 if (sblock
.fs_maxfilesize
< (u_quad_t
)fssize
) {
315 warnx("WARNING: You will be unable to create snapshots on this "
316 "file system. Correct by using a larger blocksize.");
320 * Calculate the number of blocks to put into each cylinder group.
322 * This algorithm selects the number of blocks per cylinder
323 * group. The first goal is to have at least enough data blocks
324 * in each cylinder group to meet the density requirement. Once
325 * this goal is achieved we try to expand to have at least
326 * MINCYLGRPS cylinder groups. Once this goal is achieved, we
327 * pack as many blocks into each cylinder group map as will fit.
329 * We start by calculating the smallest number of blocks that we
330 * can put into each cylinder group. If this is too big, we reduce
331 * the density until it fits.
333 maxinum
= (((int64_t)(1)) << 32) - INOPB(&sblock
);
334 minfragsperinode
= 1 + fssize
/ maxinum
;
336 density
= MAX(NFPI
, minfragsperinode
) * fsize
;
337 } else if (density
< minfragsperinode
* fsize
) {
338 origdensity
= density
;
339 density
= minfragsperinode
* fsize
;
340 fprintf(stderr
, "density increased from %d to %d\n",
341 origdensity
, density
);
343 origdensity
= density
;
345 fragsperinode
= MAX(numfrags(&sblock
, density
), 1);
346 if (fragsperinode
< minfragsperinode
) {
349 printf("Block size too small for a file system %s %d\n",
350 "of this size. Increasing blocksize to", bsize
);
353 minfpg
= fragsperinode
* INOPB(&sblock
);
354 if (minfpg
> sblock
.fs_size
)
355 minfpg
= sblock
.fs_size
;
356 sblock
.fs_ipg
= INOPB(&sblock
);
357 sblock
.fs_fpg
= roundup(sblock
.fs_iblkno
+
358 sblock
.fs_ipg
/ INOPF(&sblock
), sblock
.fs_frag
);
359 if (sblock
.fs_fpg
< minfpg
)
360 sblock
.fs_fpg
= minfpg
;
361 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
363 sblock
.fs_fpg
= roundup(sblock
.fs_iblkno
+
364 sblock
.fs_ipg
/ INOPF(&sblock
), sblock
.fs_frag
);
365 if (sblock
.fs_fpg
< minfpg
)
366 sblock
.fs_fpg
= minfpg
;
367 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
369 if (CGSIZE(&sblock
) < (unsigned long)sblock
.fs_bsize
)
371 density
-= sblock
.fs_fsize
;
373 if (density
!= origdensity
)
374 printf("density reduced from %d to %d\n", origdensity
, density
);
376 * Start packing more blocks into the cylinder group until
377 * it cannot grow any larger, the number of cylinder groups
378 * drops below MINCYLGRPS, or we reach the size requested.
379 * For UFS1 inodes per cylinder group are stored in an int16_t
380 * so fs_ipg is limited to 2^15 - 1.
382 for ( ; sblock
.fs_fpg
< maxblkspercg
; sblock
.fs_fpg
+= sblock
.fs_frag
) {
383 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
385 if (Oflag
> 1 || (Oflag
== 1 && sblock
.fs_ipg
<= 0x7fff)) {
386 if (sblock
.fs_size
/ sblock
.fs_fpg
< MINCYLGRPS
)
388 if (CGSIZE(&sblock
) < (unsigned long)sblock
.fs_bsize
)
390 if (CGSIZE(&sblock
) == (unsigned long)sblock
.fs_bsize
)
393 sblock
.fs_fpg
-= sblock
.fs_frag
;
394 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
399 * Check to be sure that the last cylinder group has enough blocks
400 * to be viable. If it is too small, reduce the number of blocks
401 * per cylinder group which will have the effect of moving more
402 * blocks into the last cylinder group.
404 optimalfpg
= sblock
.fs_fpg
;
406 sblock
.fs_ncg
= howmany(sblock
.fs_size
, sblock
.fs_fpg
);
407 lastminfpg
= roundup(sblock
.fs_iblkno
+
408 sblock
.fs_ipg
/ INOPF(&sblock
), sblock
.fs_frag
);
409 if (sblock
.fs_size
< lastminfpg
) {
410 printf("Filesystem size %jd < minimum size of %d\n",
411 (intmax_t)sblock
.fs_size
, lastminfpg
);
414 if (sblock
.fs_size
% sblock
.fs_fpg
>= lastminfpg
||
415 sblock
.fs_size
% sblock
.fs_fpg
== 0)
417 sblock
.fs_fpg
-= sblock
.fs_frag
;
418 sblock
.fs_ipg
= roundup(howmany(sblock
.fs_fpg
, fragsperinode
),
421 if (optimalfpg
!= sblock
.fs_fpg
)
422 printf("Reduced frags per cylinder group from %d to %d %s\n",
423 optimalfpg
, sblock
.fs_fpg
, "to enlarge last cyl group");
424 sblock
.fs_cgsize
= fragroundup(&sblock
, CGSIZE(&sblock
));
425 sblock
.fs_dblkno
= sblock
.fs_iblkno
+ sblock
.fs_ipg
/ INOPF(&sblock
);
427 sblock
.fs_old_spc
= sblock
.fs_fpg
* sblock
.fs_old_nspf
;
428 sblock
.fs_old_nsect
= sblock
.fs_old_spc
;
429 sblock
.fs_old_npsect
= sblock
.fs_old_spc
;
430 sblock
.fs_old_ncyl
= sblock
.fs_ncg
;
433 * fill in remaining fields of the super block
435 sblock
.fs_csaddr
= cgdmin(&sblock
, 0);
437 fragroundup(&sblock
, sblock
.fs_ncg
* sizeof(struct csum
));
438 fscs
= (struct csum
*)calloc(1, sblock
.fs_cssize
);
440 errx(31, "calloc failed");
441 sblock
.fs_sbsize
= fragroundup(&sblock
, sizeof(struct fs
));
442 if (sblock
.fs_sbsize
> SBLOCKSIZE
)
443 sblock
.fs_sbsize
= SBLOCKSIZE
;
444 sblock
.fs_minfree
= minfree
;
445 if (metaspace
> 0 && metaspace
< sblock
.fs_fpg
/ 2)
446 sblock
.fs_metaspace
= blknum(&sblock
, metaspace
);
447 else if (metaspace
!= -1)
448 /* reserve half of minfree for metadata blocks */
449 sblock
.fs_metaspace
= blknum(&sblock
,
450 (sblock
.fs_fpg
* minfree
) / 200);
452 sblock
.fs_maxbpg
= MAXBLKPG(sblock
.fs_bsize
);
454 sblock
.fs_maxbpg
= maxbpg
;
455 sblock
.fs_optim
= opt
;
456 sblock
.fs_cgrotor
= 0;
457 sblock
.fs_pendingblocks
= 0;
458 sblock
.fs_pendinginodes
= 0;
463 sblock
.fs_id
[0] = (long)utime
;
464 sblock
.fs_id
[1] = newfs_random();
465 sblock
.fs_fsmnt
[0] = '\0';
466 csfrags
= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
467 sblock
.fs_dsize
= sblock
.fs_size
- sblock
.fs_sblkno
-
468 sblock
.fs_ncg
* (sblock
.fs_dblkno
- sblock
.fs_sblkno
);
469 sblock
.fs_cstotal
.cs_nbfree
=
470 fragstoblks(&sblock
, sblock
.fs_dsize
) -
471 howmany(csfrags
, sblock
.fs_frag
);
472 sblock
.fs_cstotal
.cs_nffree
=
473 fragnum(&sblock
, sblock
.fs_size
) +
474 (fragnum(&sblock
, csfrags
) > 0 ?
475 sblock
.fs_frag
- fragnum(&sblock
, csfrags
) : 0);
476 sblock
.fs_cstotal
.cs_nifree
= sblock
.fs_ncg
* sblock
.fs_ipg
- ROOTINO
;
477 sblock
.fs_cstotal
.cs_ndir
= 0;
478 sblock
.fs_dsize
-= csfrags
;
479 sblock
.fs_time
= utime
;
481 sblock
.fs_old_time
= utime
;
482 sblock
.fs_old_dsize
= sblock
.fs_dsize
;
483 sblock
.fs_old_csaddr
= sblock
.fs_csaddr
;
484 sblock
.fs_old_cstotal
.cs_ndir
= sblock
.fs_cstotal
.cs_ndir
;
485 sblock
.fs_old_cstotal
.cs_nbfree
= sblock
.fs_cstotal
.cs_nbfree
;
486 sblock
.fs_old_cstotal
.cs_nifree
= sblock
.fs_cstotal
.cs_nifree
;
487 sblock
.fs_old_cstotal
.cs_nffree
= sblock
.fs_cstotal
.cs_nffree
;
491 * Dump out summary information about file system.
493 # define B2MBFACTOR (1 / (1024.0 * 1024.0))
494 printf("%s: %.1fMB (%jd sectors) block size %d, fragment size %d\n",
495 fsys
, (float)sblock
.fs_size
* sblock
.fs_fsize
* B2MBFACTOR
,
496 (intmax_t)fsbtodb(&sblock
, sblock
.fs_size
), sblock
.fs_bsize
,
498 printf("\tusing %d cylinder groups of %.2fMB, %d blks, %d inodes.\n",
499 sblock
.fs_ncg
, (float)sblock
.fs_fpg
* sblock
.fs_fsize
* B2MBFACTOR
,
500 sblock
.fs_fpg
/ sblock
.fs_frag
, sblock
.fs_ipg
);
501 if (sblock
.fs_flags
& FS_DOSOFTDEP
)
502 printf("\twith soft updates\n");
505 if (Eflag
&& !Nflag
) {
506 printf("Erasing sectors [%jd...%jd]\n",
507 sblock
.fs_sblockloc
/ disk
.d_bsize
,
508 fsbtodb(&sblock
, sblock
.fs_size
) - 1);
509 berase(&disk
, sblock
.fs_sblockloc
/ disk
.d_bsize
,
510 sblock
.fs_size
* sblock
.fs_fsize
- sblock
.fs_sblockloc
);
513 * Wipe out old UFS1 superblock(s) if necessary.
515 if (!Nflag
&& Oflag
!= 1) {
516 i
= bread(&disk
, part_ofs
+ SBLOCK_UFS1
/ disk
.d_bsize
, chdummy
, SBLOCKSIZE
);
518 err(1, "can't read old UFS1 superblock: %s", disk
.d_error
);
520 if (fsdummy
.fs_magic
== FS_UFS1_MAGIC
) {
521 fsdummy
.fs_magic
= 0;
522 bwrite(&disk
, part_ofs
+ SBLOCK_UFS1
/ disk
.d_bsize
,
523 chdummy
, SBLOCKSIZE
);
524 for (cg
= 0; cg
< fsdummy
.fs_ncg
; cg
++) {
525 if (fsbtodb(&fsdummy
, cgsblock(&fsdummy
, cg
)) > fssize
)
527 bwrite(&disk
, part_ofs
+ fsbtodb(&fsdummy
,
528 cgsblock(&fsdummy
, cg
)), chdummy
, SBLOCKSIZE
);
535 printf("** Exiting on Xflag 1\n");
539 printf("** Leaving BAD MAGIC on Xflag 2\n");
541 sblock
.fs_magic
= (Oflag
!= 1) ? FS_UFS2_MAGIC
: FS_UFS1_MAGIC
;
544 * Now build the cylinders group blocks and
545 * then print out indices of cylinder groups.
547 printf("super-block backups (for fsck_ffs -b #) at:\n");
549 width
= charsperline();
551 * allocate space for superblock, cylinder group map, and
552 * two sets of inode blocks.
554 if (sblock
.fs_bsize
< SBLOCKSIZE
)
555 iobufsize
= SBLOCKSIZE
+ 3 * sblock
.fs_bsize
;
557 iobufsize
= 4 * sblock
.fs_bsize
;
558 if ((iobuf
= calloc(1, iobufsize
)) == 0) {
559 printf("Cannot allocate I/O buffer\n");
563 * Make a copy of the superblock into the buffer that we will be
564 * writing out in each cylinder group.
566 bcopy((char *)&sblock
, iobuf
, SBLOCKSIZE
);
567 for (cg
= 0; cg
< sblock
.fs_ncg
; cg
++) {
569 j
= snprintf(tmpbuf
, sizeof(tmpbuf
), " %jd%s",
570 (intmax_t)fsbtodb(&sblock
, cgsblock(&sblock
, cg
)),
571 cg
< (sblock
.fs_ncg
-1) ? "," : "");
573 tmpbuf
[j
= 0] = '\0';
574 if (i
+ j
>= width
) {
579 printf("%s", tmpbuf
);
586 * Now construct the initial file system,
587 * then write out the super-block.
591 sblock
.fs_old_cstotal
.cs_ndir
= sblock
.fs_cstotal
.cs_ndir
;
592 sblock
.fs_old_cstotal
.cs_nbfree
= sblock
.fs_cstotal
.cs_nbfree
;
593 sblock
.fs_old_cstotal
.cs_nifree
= sblock
.fs_cstotal
.cs_nifree
;
594 sblock
.fs_old_cstotal
.cs_nffree
= sblock
.fs_cstotal
.cs_nffree
;
597 printf("** Exiting on Xflag 3\n");
603 * For UFS1 filesystems with a blocksize of 64K, the first
604 * alternate superblock resides at the location used for
605 * the default UFS2 superblock. As there is a valid
606 * superblock at this location, the boot code will use
607 * it as its first choice. Thus we have to ensure that
608 * all of its statistcs on usage are correct.
610 if (Oflag
== 1 && sblock
.fs_bsize
== 65536)
611 wtfs(fsbtodb(&sblock
, cgsblock(&sblock
, 0)),
612 sblock
.fs_bsize
, (char *)&sblock
);
614 for (i
= 0; i
< sblock
.fs_cssize
; i
+= sblock
.fs_bsize
)
615 wtfs(fsbtodb(&sblock
, sblock
.fs_csaddr
+ numfrags(&sblock
, i
)),
616 MIN(sblock
.fs_cssize
- i
, sblock
.fs_bsize
),
619 * Update information about this partition in pack
620 * label, to that it may be updated on disk.
623 pp
->p_fstype
= FS_BSDFFS
;
624 pp
->p_fsize
= sblock
.fs_fsize
;
625 pp
->p_frag
= sblock
.fs_frag
;
626 pp
->p_cpg
= sblock
.fs_fpg
;
631 * Initialize a cylinder group.
634 initcg(int cylno
, time_t utime
)
637 uint i
, j
, d
, dlower
, dupper
;
638 ufs2_daddr_t cbase
, dmax
;
639 struct ufs1_dinode
*dp1
;
640 struct ufs2_dinode
*dp2
;
644 * Determine block bounds for cylinder group.
645 * Allow space for super block summary information in first
648 cbase
= cgbase(&sblock
, cylno
);
649 dmax
= cbase
+ sblock
.fs_fpg
;
650 if (dmax
> sblock
.fs_size
)
651 dmax
= sblock
.fs_size
;
652 dlower
= cgsblock(&sblock
, cylno
) - cbase
;
653 dupper
= cgdmin(&sblock
, cylno
) - cbase
;
655 dupper
+= howmany(sblock
.fs_cssize
, sblock
.fs_fsize
);
657 memset(&acg
, 0, sblock
.fs_cgsize
);
659 acg
.cg_magic
= CG_MAGIC
;
661 acg
.cg_niblk
= sblock
.fs_ipg
;
662 acg
.cg_initediblk
= MIN(sblock
.fs_ipg
, 2 * INOPB(&sblock
));
663 acg
.cg_ndblk
= dmax
- cbase
;
664 if (sblock
.fs_contigsumsize
> 0)
665 acg
.cg_nclusterblks
= acg
.cg_ndblk
/ sblock
.fs_frag
;
666 start
= &acg
.cg_space
[0] - (u_char
*)(&acg
.cg_firstfield
);
668 acg
.cg_iusedoff
= start
;
670 acg
.cg_old_ncyl
= sblock
.fs_old_cpg
;
671 acg
.cg_old_time
= acg
.cg_time
;
673 acg
.cg_old_niblk
= acg
.cg_niblk
;
675 acg
.cg_initediblk
= 0;
676 acg
.cg_old_btotoff
= start
;
677 acg
.cg_old_boff
= acg
.cg_old_btotoff
+
678 sblock
.fs_old_cpg
* sizeof(int32_t);
679 acg
.cg_iusedoff
= acg
.cg_old_boff
+
680 sblock
.fs_old_cpg
* sizeof(u_int16_t
);
682 acg
.cg_freeoff
= acg
.cg_iusedoff
+ howmany(sblock
.fs_ipg
, CHAR_BIT
);
683 acg
.cg_nextfreeoff
= acg
.cg_freeoff
+ howmany(sblock
.fs_fpg
, CHAR_BIT
);
684 if (sblock
.fs_contigsumsize
> 0) {
685 acg
.cg_clustersumoff
=
686 roundup(acg
.cg_nextfreeoff
, sizeof(u_int32_t
));
687 acg
.cg_clustersumoff
-= sizeof(u_int32_t
);
688 acg
.cg_clusteroff
= acg
.cg_clustersumoff
+
689 (sblock
.fs_contigsumsize
+ 1) * sizeof(u_int32_t
);
690 acg
.cg_nextfreeoff
= acg
.cg_clusteroff
+
691 howmany(fragstoblks(&sblock
, sblock
.fs_fpg
), CHAR_BIT
);
693 if (acg
.cg_nextfreeoff
> (unsigned)sblock
.fs_cgsize
) {
694 printf("Panic: cylinder group too big\n");
697 acg
.cg_cs
.cs_nifree
+= sblock
.fs_ipg
;
699 for (i
= 0; i
< (long)ROOTINO
; i
++) {
700 setbit(cg_inosused(&acg
), i
);
701 acg
.cg_cs
.cs_nifree
--;
705 * In cylno 0, beginning space is reserved
706 * for boot and super blocks.
708 for (d
= 0; d
< dlower
; d
+= sblock
.fs_frag
) {
709 blkno
= d
/ sblock
.fs_frag
;
710 setblock(&sblock
, cg_blksfree(&acg
), blkno
);
711 if (sblock
.fs_contigsumsize
> 0)
712 setbit(cg_clustersfree(&acg
), blkno
);
713 acg
.cg_cs
.cs_nbfree
++;
716 if ((i
= dupper
% sblock
.fs_frag
)) {
717 acg
.cg_frsum
[sblock
.fs_frag
- i
]++;
718 for (d
= dupper
+ sblock
.fs_frag
- i
; dupper
< d
; dupper
++) {
719 setbit(cg_blksfree(&acg
), dupper
);
720 acg
.cg_cs
.cs_nffree
++;
723 for (d
= dupper
; d
+ sblock
.fs_frag
<= acg
.cg_ndblk
;
724 d
+= sblock
.fs_frag
) {
725 blkno
= d
/ sblock
.fs_frag
;
726 setblock(&sblock
, cg_blksfree(&acg
), blkno
);
727 if (sblock
.fs_contigsumsize
> 0)
728 setbit(cg_clustersfree(&acg
), blkno
);
729 acg
.cg_cs
.cs_nbfree
++;
731 if (d
< acg
.cg_ndblk
) {
732 acg
.cg_frsum
[acg
.cg_ndblk
- d
]++;
733 for (; d
< acg
.cg_ndblk
; d
++) {
734 setbit(cg_blksfree(&acg
), d
);
735 acg
.cg_cs
.cs_nffree
++;
738 if (sblock
.fs_contigsumsize
> 0) {
739 int32_t *sump
= cg_clustersum(&acg
);
740 u_char
*mapp
= cg_clustersfree(&acg
);
745 for (i
= 0; i
< acg
.cg_nclusterblks
; i
++) {
746 if ((map
& bit
) != 0)
749 if (run
> sblock
.fs_contigsumsize
)
750 run
= sblock
.fs_contigsumsize
;
754 if ((i
& (CHAR_BIT
- 1)) != CHAR_BIT
- 1)
762 if (run
> sblock
.fs_contigsumsize
)
763 run
= sblock
.fs_contigsumsize
;
769 * Write out the duplicate super block, the cylinder group map
770 * and two blocks worth of inodes in a single write.
772 start
= MAX(sblock
.fs_bsize
, SBLOCKSIZE
);
773 bcopy((char *)&acg
, &iobuf
[start
], sblock
.fs_cgsize
);
774 start
+= sblock
.fs_bsize
;
775 dp1
= (struct ufs1_dinode
*)(&iobuf
[start
]);
776 dp2
= (struct ufs2_dinode
*)(&iobuf
[start
]);
777 for (i
= 0; i
< acg
.cg_initediblk
; i
++) {
778 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
779 dp1
->di_gen
= newfs_random();
782 dp2
->di_gen
= newfs_random();
786 wtfs(fsbtodb(&sblock
, cgsblock(&sblock
, cylno
)), iobufsize
, iobuf
);
788 * For the old file system, we have to initialize all the inodes.
791 for (i
= 2 * sblock
.fs_frag
;
792 i
< sblock
.fs_ipg
/ INOPF(&sblock
);
793 i
+= sblock
.fs_frag
) {
794 dp1
= (struct ufs1_dinode
*)(&iobuf
[start
]);
795 for (j
= 0; j
< INOPB(&sblock
); j
++) {
796 dp1
->di_gen
= newfs_random();
799 wtfs(fsbtodb(&sblock
, cgimin(&sblock
, cylno
) + i
),
800 sblock
.fs_bsize
, &iobuf
[start
]);
806 * initialize the file system
808 #define ROOTLINKCNT 3
810 static struct direct root_dir
[] = {
811 { ROOTINO
, sizeof(struct direct
), DT_DIR
, 1, "." },
812 { ROOTINO
, sizeof(struct direct
), DT_DIR
, 2, ".." },
813 { ROOTINO
+ 1, sizeof(struct direct
), DT_DIR
, 5, ".snap" },
816 #define SNAPLINKCNT 2
818 static struct direct snap_dir
[] = {
819 { ROOTINO
+ 1, sizeof(struct direct
), DT_DIR
, 1, "." },
820 { ROOTINO
, sizeof(struct direct
), DT_DIR
, 2, ".." },
831 memset(&node
, 0, sizeof node
);
832 if ((grp
= getgrnam("operator")) != NULL
) {
835 warnx("Cannot retrieve operator gid, using gid 0.");
838 entries
= (nflag
) ? ROOTLINKCNT
- 1: ROOTLINKCNT
;
839 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
841 * initialize the node
843 node
.dp1
.di_atime
= utime
;
844 node
.dp1
.di_mtime
= utime
;
845 node
.dp1
.di_ctime
= utime
;
847 * create the root directory
849 node
.dp1
.di_mode
= IFDIR
| UMASK
;
850 node
.dp1
.di_nlink
= entries
;
851 node
.dp1
.di_size
= makedir(root_dir
, entries
);
852 node
.dp1
.di_db
[0] = alloc(sblock
.fs_fsize
, node
.dp1
.di_mode
);
854 btodb(fragroundup(&sblock
, node
.dp1
.di_size
));
855 wtfs(fsbtodb(&sblock
, node
.dp1
.di_db
[0]), sblock
.fs_fsize
,
857 iput(&node
, ROOTINO
);
860 * create the .snap directory
862 node
.dp1
.di_mode
|= 020;
863 node
.dp1
.di_gid
= gid
;
864 node
.dp1
.di_nlink
= SNAPLINKCNT
;
865 node
.dp1
.di_size
= makedir(snap_dir
, SNAPLINKCNT
);
867 alloc(sblock
.fs_fsize
, node
.dp1
.di_mode
);
869 btodb(fragroundup(&sblock
, node
.dp1
.di_size
));
870 wtfs(fsbtodb(&sblock
, node
.dp1
.di_db
[0]),
871 sblock
.fs_fsize
, iobuf
);
872 iput(&node
, ROOTINO
+ 1);
876 * initialize the node
878 node
.dp2
.di_atime
= utime
;
879 node
.dp2
.di_mtime
= utime
;
880 node
.dp2
.di_ctime
= utime
;
881 node
.dp2
.di_birthtime
= utime
;
883 * create the root directory
885 node
.dp2
.di_mode
= IFDIR
| UMASK
;
886 node
.dp2
.di_nlink
= entries
;
887 node
.dp2
.di_size
= makedir(root_dir
, entries
);
888 node
.dp2
.di_db
[0] = alloc(sblock
.fs_fsize
, node
.dp2
.di_mode
);
890 btodb(fragroundup(&sblock
, node
.dp2
.di_size
));
891 wtfs(fsbtodb(&sblock
, node
.dp2
.di_db
[0]), sblock
.fs_fsize
,
893 iput(&node
, ROOTINO
);
896 * create the .snap directory
898 node
.dp2
.di_mode
|= 020;
899 node
.dp2
.di_gid
= gid
;
900 node
.dp2
.di_nlink
= SNAPLINKCNT
;
901 node
.dp2
.di_size
= makedir(snap_dir
, SNAPLINKCNT
);
903 alloc(sblock
.fs_fsize
, node
.dp2
.di_mode
);
905 btodb(fragroundup(&sblock
, node
.dp2
.di_size
));
906 wtfs(fsbtodb(&sblock
, node
.dp2
.di_db
[0]),
907 sblock
.fs_fsize
, iobuf
);
908 iput(&node
, ROOTINO
+ 1);
914 * construct a set of directory entries in "iobuf".
915 * return size of directory.
918 makedir(struct direct
*protodir
, int entries
)
924 memset(iobuf
, 0, DIRBLKSIZ
);
925 for (cp
= iobuf
, i
= 0; i
< entries
- 1; i
++) {
926 protodir
[i
].d_reclen
= DIRSIZ(0, &protodir
[i
]);
927 memmove(cp
, &protodir
[i
], protodir
[i
].d_reclen
);
928 cp
+= protodir
[i
].d_reclen
;
929 spcleft
-= protodir
[i
].d_reclen
;
931 protodir
[i
].d_reclen
= spcleft
;
932 memmove(cp
, &protodir
[i
], DIRSIZ(0, &protodir
[i
]));
937 * allocate a block or frag
940 alloc(int size
, int mode
)
945 bread(&disk
, part_ofs
+ fsbtodb(&sblock
, cgtod(&sblock
, 0)), (char *)&acg
,
947 if (acg
.cg_magic
!= CG_MAGIC
) {
948 printf("cg 0: bad magic number\n");
951 if (acg
.cg_cs
.cs_nbfree
== 0) {
952 printf("first cylinder group ran out of space\n");
955 for (d
= 0; d
< acg
.cg_ndblk
; d
+= sblock
.fs_frag
)
956 if (isblock(&sblock
, cg_blksfree(&acg
), d
/ sblock
.fs_frag
))
958 printf("internal error: can't find block in cyl 0\n");
961 blkno
= fragstoblks(&sblock
, d
);
962 clrblock(&sblock
, cg_blksfree(&acg
), blkno
);
963 if (sblock
.fs_contigsumsize
> 0)
964 clrbit(cg_clustersfree(&acg
), blkno
);
965 acg
.cg_cs
.cs_nbfree
--;
966 sblock
.fs_cstotal
.cs_nbfree
--;
970 sblock
.fs_cstotal
.cs_ndir
++;
973 if (size
!= sblock
.fs_bsize
) {
974 frag
= howmany(size
, sblock
.fs_fsize
);
975 fscs
[0].cs_nffree
+= sblock
.fs_frag
- frag
;
976 sblock
.fs_cstotal
.cs_nffree
+= sblock
.fs_frag
- frag
;
977 acg
.cg_cs
.cs_nffree
+= sblock
.fs_frag
- frag
;
978 acg
.cg_frsum
[sblock
.fs_frag
- frag
]++;
979 for (i
= frag
; i
< sblock
.fs_frag
; i
++)
980 setbit(cg_blksfree(&acg
), d
+ i
);
982 /* XXX cgwrite(&disk, 0)??? */
983 wtfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
985 return ((ufs2_daddr_t
)d
);
989 * Allocate an inode on the disk
992 iput(union dinode
*ip
, ino_t ino
)
996 bread(&disk
, part_ofs
+ fsbtodb(&sblock
, cgtod(&sblock
, 0)), (char *)&acg
,
998 if (acg
.cg_magic
!= CG_MAGIC
) {
999 printf("cg 0: bad magic number\n");
1002 acg
.cg_cs
.cs_nifree
--;
1003 setbit(cg_inosused(&acg
), ino
);
1004 wtfs(fsbtodb(&sblock
, cgtod(&sblock
, 0)), sblock
.fs_cgsize
,
1006 sblock
.fs_cstotal
.cs_nifree
--;
1007 fscs
[0].cs_nifree
--;
1008 if (ino
>= (unsigned long)sblock
.fs_ipg
* sblock
.fs_ncg
) {
1009 printf("fsinit: inode value out of range (%ju).\n",
1013 d
= fsbtodb(&sblock
, ino_to_fsba(&sblock
, ino
));
1014 bread(&disk
, part_ofs
+ d
, (char *)iobuf
, sblock
.fs_bsize
);
1015 if (sblock
.fs_magic
== FS_UFS1_MAGIC
)
1016 ((struct ufs1_dinode
*)iobuf
)[ino_to_fsbo(&sblock
, ino
)] =
1019 ((struct ufs2_dinode
*)iobuf
)[ino_to_fsbo(&sblock
, ino
)] =
1021 wtfs(d
, sblock
.fs_bsize
, (char *)iobuf
);
1025 * possibly write to disk
1028 wtfs(ufs2_daddr_t bno
, int size
, char *bf
)
1032 if (bwrite(&disk
, part_ofs
+ bno
, bf
, size
) < 0)
1033 err(36, "wtfs: %d bytes at sector %jd", size
, (intmax_t)bno
);
1037 * check if a block is available
1040 isblock(struct fs
*fs
, unsigned char *cp
, int h
)
1044 switch (fs
->fs_frag
) {
1046 return (cp
[h
] == 0xff);
1048 mask
= 0x0f << ((h
& 0x1) << 2);
1049 return ((cp
[h
>> 1] & mask
) == mask
);
1051 mask
= 0x03 << ((h
& 0x3) << 1);
1052 return ((cp
[h
>> 2] & mask
) == mask
);
1054 mask
= 0x01 << (h
& 0x7);
1055 return ((cp
[h
>> 3] & mask
) == mask
);
1057 fprintf(stderr
, "isblock bad fs_frag %d\n", fs
->fs_frag
);
1063 * take a block out of the map
1066 clrblock(struct fs
*fs
, unsigned char *cp
, int h
)
1068 switch ((fs
)->fs_frag
) {
1073 cp
[h
>> 1] &= ~(0x0f << ((h
& 0x1) << 2));
1076 cp
[h
>> 2] &= ~(0x03 << ((h
& 0x3) << 1));
1079 cp
[h
>> 3] &= ~(0x01 << (h
& 0x7));
1082 fprintf(stderr
, "clrblock bad fs_frag %d\n", fs
->fs_frag
);
1088 * put a block into the map
1091 setblock(struct fs
*fs
, unsigned char *cp
, int h
)
1093 switch (fs
->fs_frag
) {
1098 cp
[h
>> 1] |= (0x0f << ((h
& 0x1) << 2));
1101 cp
[h
>> 2] |= (0x03 << ((h
& 0x3) << 1));
1104 cp
[h
>> 3] |= (0x01 << (h
& 0x7));
1107 fprintf(stderr
, "setblock bad fs_frag %d\n", fs
->fs_frag
);
1113 * Determine the number of characters in a
1125 if (ioctl(0, TIOCGWINSZ
, &ws
) != -1)
1126 columns
= ws
.ws_col
;
1127 if (columns
== 0 && (cp
= getenv("COLUMNS")))
1130 columns
= 80; /* last resort */
1139 for (n
= 0; n
< sizeof(n
) * CHAR_BIT
; n
++)
1142 errx(1, "ilog2: %d is not a power of 2\n", val
);
1146 * For the regression test, return predictable random values.
1147 * Otherwise use a true random number generator.
1152 static int nextnum
= 1;
1156 return (arc4random());