2 * Copyright (c) 1983, 1993
3 * The Regents of the University of California. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 4. Neither the name of the University nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 static const char copyright
[] =
33 "@(#) Copyright (c) 1983, 1993\n\
34 The Regents of the University of California. All rights reserved.\n";
38 static char sccsid
[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94";
41 #include <sys/cdefs.h>
42 __FBSDID("$FreeBSD$");
45 * tunefs: change layout parameters to an existing file system.
47 #include <sys/param.h>
48 #include <sys/mount.h>
49 #include <sys/disklabel.h>
52 #include <ufs/ufs/ufsmount.h>
53 #include <ufs/ufs/dinode.h>
54 #include <ufs/ffs/fs.h>
55 #include <ufs/ufs/dir.h>
70 /* the optimization warning string template */
71 #define OPTWARN "should optimize for %s with minfree %s %d%%"
74 static char clrbuf
[MAXBSIZE
];
75 static struct uufsd disk
;
76 #define sblock disk.d_fs
78 static void usage(void);
79 static void printfs(void);
80 static int journal_alloc(int64_t size
);
81 static void journal_clear(void);
82 static void sbdirty(void);
85 main(int argc
, char *argv
[])
87 const char *avalue
, *jvalue
, *Jvalue
, *Lvalue
, *lvalue
, *Nvalue
, *nvalue
;
89 const char *special
, *on
;
92 int Aflag
, aflag
, eflag
, evalue
, fflag
, fvalue
, jflag
, Jflag
, kflag
;
93 int kvalue
, Lflag
, lflag
, mflag
, mvalue
, Nflag
, nflag
, oflag
, ovalue
;
94 int pflag
, sflag
, svalue
, Svalue
, tflag
;
102 Aflag
= aflag
= eflag
= fflag
= jflag
= Jflag
= kflag
= Lflag
= 0;
103 lflag
= mflag
= Nflag
= nflag
= oflag
= pflag
= sflag
= tflag
= 0;
104 avalue
= jvalue
= Jvalue
= Lvalue
= lvalue
= Nvalue
= nvalue
= NULL
;
105 evalue
= fvalue
= mvalue
= ovalue
= svalue
= Svalue
= 0;
107 found_arg
= 0; /* At least one arg is required. */
108 while ((ch
= getopt(argc
, argv
, "Aa:e:f:j:J:k:L:l:m:N:n:o:ps:S:t:"))
119 name
= "POSIX.1e ACLs";
121 if (strcmp(avalue
, "enable") &&
122 strcmp(avalue
, "disable")) {
123 errx(10, "bad %s (options are %s)",
124 name
, "`enable' or `disable'");
131 name
= "maximum blocks per file in a cylinder group";
132 evalue
= atoi(optarg
);
134 errx(10, "%s must be >= 1 (was %s)",
141 name
= "average file size";
142 fvalue
= atoi(optarg
);
144 errx(10, "%s must be >= 1 (was %s)",
151 name
= "softdep journaled file system";
153 if (strcmp(jvalue
, "enable") &&
154 strcmp(jvalue
, "disable")) {
155 errx(10, "bad %s (options are %s)",
156 name
, "`enable' or `disable'");
163 name
= "gjournaled file system";
165 if (strcmp(Jvalue
, "enable") &&
166 strcmp(Jvalue
, "disable")) {
167 errx(10, "bad %s (options are %s)",
168 name
, "`enable' or `disable'");
175 name
= "space to hold for metadata blocks";
176 kvalue
= atoi(optarg
);
178 errx(10, "bad %s (%s)", name
, optarg
);
184 name
= "volume label";
187 while (isalnum(Lvalue
[++i
]));
188 if (Lvalue
[i
] != '\0') {
190 "bad %s. Valid characters are alphanumerics.",
193 if (strlen(Lvalue
) >= MAXVOLLEN
) {
194 errx(10, "bad %s. Length is longer than %d.",
195 name
, MAXVOLLEN
- 1);
202 name
= "multilabel MAC file system";
204 if (strcmp(lvalue
, "enable") &&
205 strcmp(lvalue
, "disable")) {
206 errx(10, "bad %s (options are %s)",
207 name
, "`enable' or `disable'");
214 name
= "minimum percentage of free space";
215 mvalue
= atoi(optarg
);
216 if (mvalue
< 0 || mvalue
> 99)
217 errx(10, "bad %s (%s)", name
, optarg
);
225 if (strcmp(Nvalue
, "enable") &&
226 strcmp(Nvalue
, "disable")) {
227 errx(10, "bad %s (options are %s)",
228 name
, "`enable' or `disable'");
235 name
= "soft updates";
237 if (strcmp(nvalue
, "enable") != 0 &&
238 strcmp(nvalue
, "disable") != 0) {
239 errx(10, "bad %s (options are %s)",
240 name
, "`enable' or `disable'");
247 name
= "optimization preference";
248 if (strcmp(optarg
, "space") == 0)
249 ovalue
= FS_OPTSPACE
;
250 else if (strcmp(optarg
, "time") == 0)
254 "bad %s (options are `space' or `time')",
266 name
= "expected number of files per directory";
267 svalue
= atoi(optarg
);
269 errx(10, "%s must be >= 1 (was %s)",
276 name
= "Softdep Journal Size";
277 Svalue
= atoi(optarg
);
278 if (Svalue
< SUJ_MIN
)
279 errx(10, "%s must be >= %d (was %s)",
280 name
, SUJ_MIN
, optarg
);
287 if (strcmp(tvalue
, "enable") != 0 &&
288 strcmp(tvalue
, "disable") != 0) {
289 errx(10, "bad %s (options are %s)",
290 name
, "`enable' or `disable'");
300 if (found_arg
== 0 || argc
!= 1)
303 on
= special
= argv
[0];
304 if (ufs_disk_fillout(&disk
, special
) == -1)
306 if (disk
.d_name
!= special
) {
307 if (statfs(special
, &stfs
) != 0)
308 warn("Can't stat %s", special
);
309 if (strcmp(special
, stfs
.f_mntonname
) == 0)
318 name
= "volume label";
319 strncpy(sblock
.fs_volname
, Lvalue
, MAXVOLLEN
);
322 name
= "POSIX.1e ACLs";
323 if (strcmp(avalue
, "enable") == 0) {
324 if (sblock
.fs_flags
& FS_ACLS
) {
325 warnx("%s remains unchanged as enabled", name
);
326 } else if (sblock
.fs_flags
& FS_NFS4ACLS
) {
327 warnx("%s and NFSv4 ACLs are mutually "
330 sblock
.fs_flags
|= FS_ACLS
;
331 warnx("%s set", name
);
333 } else if (strcmp(avalue
, "disable") == 0) {
334 if ((~sblock
.fs_flags
& FS_ACLS
) ==
336 warnx("%s remains unchanged as disabled",
339 sblock
.fs_flags
&= ~FS_ACLS
;
340 warnx("%s cleared", name
);
345 name
= "maximum blocks per file in a cylinder group";
346 if (sblock
.fs_maxbpg
== evalue
)
347 warnx("%s remains unchanged as %d", name
, evalue
);
349 warnx("%s changes from %d to %d",
350 name
, sblock
.fs_maxbpg
, evalue
);
351 sblock
.fs_maxbpg
= evalue
;
355 name
= "average file size";
356 if (sblock
.fs_avgfilesize
== (unsigned)fvalue
) {
357 warnx("%s remains unchanged as %d", name
, fvalue
);
360 warnx("%s changes from %d to %d",
361 name
, sblock
.fs_avgfilesize
, fvalue
);
362 sblock
.fs_avgfilesize
= fvalue
;
366 name
= "soft updates journaling";
367 if (strcmp(jvalue
, "enable") == 0) {
368 if ((sblock
.fs_flags
& (FS_DOSOFTDEP
| FS_SUJ
)) ==
369 (FS_DOSOFTDEP
| FS_SUJ
)) {
370 warnx("%s remains unchanged as enabled", name
);
371 } else if (sblock
.fs_clean
== 0) {
372 warnx("%s cannot be enabled until fsck is run",
374 } else if (journal_alloc(Svalue
) != 0) {
375 warnx("%s can not be enabled", name
);
377 sblock
.fs_flags
|= FS_DOSOFTDEP
| FS_SUJ
;
378 warnx("%s set", name
);
380 } else if (strcmp(jvalue
, "disable") == 0) {
381 if ((~sblock
.fs_flags
& FS_SUJ
) == FS_SUJ
) {
382 warnx("%s remains unchanged as disabled", name
);
385 sblock
.fs_flags
&= ~FS_SUJ
;
386 sblock
.fs_sujfree
= 0;
387 warnx("%s cleared but soft updates still set.",
390 warnx("remove .sujournal to reclaim space");
396 if (strcmp(Jvalue
, "enable") == 0) {
397 if (sblock
.fs_flags
& FS_GJOURNAL
) {
398 warnx("%s remains unchanged as enabled", name
);
400 sblock
.fs_flags
|= FS_GJOURNAL
;
401 warnx("%s set", name
);
403 } else if (strcmp(Jvalue
, "disable") == 0) {
404 if ((~sblock
.fs_flags
& FS_GJOURNAL
) ==
406 warnx("%s remains unchanged as disabled",
409 sblock
.fs_flags
&= ~FS_GJOURNAL
;
410 warnx("%s cleared", name
);
415 name
= "space to hold for metadata blocks";
416 if (sblock
.fs_metaspace
== kvalue
)
417 warnx("%s remains unchanged as %d", name
, kvalue
);
419 kvalue
= blknum(&sblock
, kvalue
);
420 if (kvalue
> sblock
.fs_fpg
/ 2) {
421 kvalue
= blknum(&sblock
, sblock
.fs_fpg
/ 2);
422 warnx("%s cannot exceed half the file system "
425 warnx("%s changes from %jd to %d",
426 name
, sblock
.fs_metaspace
, kvalue
);
427 sblock
.fs_metaspace
= kvalue
;
432 if (strcmp(lvalue
, "enable") == 0) {
433 if (sblock
.fs_flags
& FS_MULTILABEL
) {
434 warnx("%s remains unchanged as enabled", name
);
436 sblock
.fs_flags
|= FS_MULTILABEL
;
437 warnx("%s set", name
);
439 } else if (strcmp(lvalue
, "disable") == 0) {
440 if ((~sblock
.fs_flags
& FS_MULTILABEL
) ==
442 warnx("%s remains unchanged as disabled",
445 sblock
.fs_flags
&= ~FS_MULTILABEL
;
446 warnx("%s cleared", name
);
451 name
= "minimum percentage of free space";
452 if (sblock
.fs_minfree
== mvalue
)
453 warnx("%s remains unchanged as %d%%", name
, mvalue
);
455 warnx("%s changes from %d%% to %d%%",
456 name
, sblock
.fs_minfree
, mvalue
);
457 sblock
.fs_minfree
= mvalue
;
458 if (mvalue
>= MINFREE
&& sblock
.fs_optim
== FS_OPTSPACE
)
459 warnx(OPTWARN
, "time", ">=", MINFREE
);
460 if (mvalue
< MINFREE
&& sblock
.fs_optim
== FS_OPTTIME
)
461 warnx(OPTWARN
, "space", "<", MINFREE
);
466 if (strcmp(Nvalue
, "enable") == 0) {
467 if (sblock
.fs_flags
& FS_NFS4ACLS
) {
468 warnx("%s remains unchanged as enabled", name
);
469 } else if (sblock
.fs_flags
& FS_ACLS
) {
470 warnx("%s and POSIX.1e ACLs are mutually "
473 sblock
.fs_flags
|= FS_NFS4ACLS
;
474 warnx("%s set", name
);
476 } else if (strcmp(Nvalue
, "disable") == 0) {
477 if ((~sblock
.fs_flags
& FS_NFS4ACLS
) ==
479 warnx("%s remains unchanged as disabled",
482 sblock
.fs_flags
&= ~FS_NFS4ACLS
;
483 warnx("%s cleared", name
);
488 name
= "soft updates";
489 if (strcmp(nvalue
, "enable") == 0) {
490 if (sblock
.fs_flags
& FS_DOSOFTDEP
)
491 warnx("%s remains unchanged as enabled", name
);
492 else if (sblock
.fs_clean
== 0) {
493 warnx("%s cannot be enabled until fsck is run",
496 sblock
.fs_flags
|= FS_DOSOFTDEP
;
497 warnx("%s set", name
);
499 } else if (strcmp(nvalue
, "disable") == 0) {
500 if ((~sblock
.fs_flags
& FS_DOSOFTDEP
) == FS_DOSOFTDEP
)
501 warnx("%s remains unchanged as disabled", name
);
503 sblock
.fs_flags
&= ~FS_DOSOFTDEP
;
504 warnx("%s cleared", name
);
509 name
= "optimization preference";
510 chg
[FS_OPTSPACE
] = "space";
511 chg
[FS_OPTTIME
] = "time";
512 if (sblock
.fs_optim
== ovalue
)
513 warnx("%s remains unchanged as %s", name
, chg
[ovalue
]);
515 warnx("%s changes from %s to %s",
516 name
, chg
[sblock
.fs_optim
], chg
[ovalue
]);
517 sblock
.fs_optim
= ovalue
;
518 if (sblock
.fs_minfree
>= MINFREE
&&
519 ovalue
== FS_OPTSPACE
)
520 warnx(OPTWARN
, "time", ">=", MINFREE
);
521 if (sblock
.fs_minfree
< MINFREE
&& ovalue
== FS_OPTTIME
)
522 warnx(OPTWARN
, "space", "<", MINFREE
);
526 name
= "expected number of files per directory";
527 if (sblock
.fs_avgfpdir
== (unsigned)svalue
) {
528 warnx("%s remains unchanged as %d", name
, svalue
);
531 warnx("%s changes from %d to %d",
532 name
, sblock
.fs_avgfpdir
, svalue
);
533 sblock
.fs_avgfpdir
= svalue
;
537 name
= "issue TRIM to the disk";
538 if (strcmp(tvalue
, "enable") == 0) {
539 if (sblock
.fs_flags
& FS_TRIM
)
540 warnx("%s remains unchanged as enabled", name
);
542 sblock
.fs_flags
|= FS_TRIM
;
543 warnx("%s set", name
);
545 } else if (strcmp(tvalue
, "disable") == 0) {
546 if ((~sblock
.fs_flags
& FS_TRIM
) == FS_TRIM
)
547 warnx("%s remains unchanged as disabled", name
);
549 sblock
.fs_flags
&= ~FS_TRIM
;
550 warnx("%s cleared", name
);
555 if (sbwrite(&disk
, Aflag
) == -1)
557 ufs_disk_close(&disk
);
559 bzero(&args
, sizeof(args
));
561 stfs
.f_flags
| MNT_UPDATE
| MNT_RELOAD
, &args
) < 0)
562 err(9, "%s: reload", special
);
563 warnx("file system reloaded");
567 if (disk
.d_error
!= NULL
)
568 errx(11, "%s: %s", special
, disk
.d_error
);
570 err(12, "%s", special
);
576 disk
.d_fs
.fs_flags
|= FS_UNCLEAN
| FS_NEEDSFSCK
;
577 disk
.d_fs
.fs_clean
= 0;
586 static int contig
= 1;
590 blk
= cgballoc(&disk
);
594 * If we failed to allocate a block from this cg, move to
597 if (cgwrite(&disk
) < 0) {
598 warn("Failed to write updated cg");
601 while ((valid
= cgread(&disk
)) == 1) {
603 * Try to minimize fragmentation by requiring a minimum
604 * number of blocks present.
606 if (cgp
->cg_cs
.cs_nbfree
> 256 * 1024)
608 if (contig
== 0 && cgp
->cg_cs
.cs_nbfree
)
614 * Try once through looking only for large contiguous regions
615 * and again taking any space we can find.
620 warnx("Journal file fragmented.");
623 warnx("Failed to find sufficient free blocks for the journal");
626 if (bwrite(&disk
, fsbtodb(&sblock
, blk
), clrbuf
,
627 sblock
.fs_bsize
) <= 0) {
628 warn("Failed to initialize new block");
635 * Search a directory block for the SUJ_FILE.
638 dir_search(ufs2_daddr_t blk
, int bytes
)
640 char block
[MAXBSIZE
];
644 if (bread(&disk
, fsbtodb(&sblock
, blk
), block
, bytes
) <= 0) {
645 warn("Failed to read dir block");
648 for (off
= 0; off
< bytes
; off
+= dp
->d_reclen
) {
649 dp
= (struct direct
*)&block
[off
];
650 if (dp
->d_reclen
== 0)
654 if (dp
->d_namlen
!= strlen(SUJ_FILE
))
656 if (bcmp(dp
->d_name
, SUJ_FILE
, dp
->d_namlen
) != 0)
665 * Search in the ROOTINO for the SUJ_FILE. If it exists we can not enable
669 journal_findfile(void)
671 struct ufs1_dinode
*dp1
;
672 struct ufs2_dinode
*dp2
;
678 if (getino(&disk
, &ip
, ROOTINO
, &mode
) != 0) {
679 warn("Failed to get root inode");
684 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
685 if ((off_t
)dp1
->di_size
>= lblktosize(&sblock
, NDADDR
)) {
686 warnx("ROOTINO extends beyond direct blocks.");
689 for (i
= 0; i
< NDADDR
; i
++) {
690 if (dp1
->di_db
[i
] == 0)
692 if ((ino
= dir_search(dp1
->di_db
[i
],
693 sblksize(&sblock
, (off_t
)dp1
->di_size
, i
))) != 0)
697 if ((off_t
)dp2
->di_size
>= lblktosize(&sblock
, NDADDR
)) {
698 warnx("ROOTINO extends beyond direct blocks.");
701 for (i
= 0; i
< NDADDR
; i
++) {
702 if (dp2
->di_db
[i
] == 0)
704 if ((ino
= dir_search(dp2
->di_db
[i
],
705 sblksize(&sblock
, (off_t
)dp2
->di_size
, i
))) != 0)
714 dir_clear_block(const char *block
, off_t off
)
718 for (; off
< sblock
.fs_bsize
; off
+= DIRBLKSIZ
) {
719 dp
= (struct direct
*)&block
[off
];
721 dp
->d_reclen
= DIRBLKSIZ
;
722 dp
->d_type
= DT_UNKNOWN
;
727 * Insert the journal at inode 'ino' into directory blk 'blk' at the first
728 * free offset of 'off'. DIRBLKSIZ blocks after off are initialized as
732 dir_insert(ufs2_daddr_t blk
, off_t off
, ino_t ino
)
735 char block
[MAXBSIZE
];
737 if (bread(&disk
, fsbtodb(&sblock
, blk
), block
, sblock
.fs_bsize
) <= 0) {
738 warn("Failed to read dir block");
741 bzero(&block
[off
], sblock
.fs_bsize
- off
);
742 dp
= (struct direct
*)&block
[off
];
744 dp
->d_reclen
= DIRBLKSIZ
;
746 dp
->d_namlen
= strlen(SUJ_FILE
);
747 bcopy(SUJ_FILE
, &dp
->d_name
, strlen(SUJ_FILE
));
748 dir_clear_block(block
, off
+ DIRBLKSIZ
);
749 if (bwrite(&disk
, fsbtodb(&sblock
, blk
), block
, sblock
.fs_bsize
) <= 0) {
750 warn("Failed to write dir block");
757 * Extend a directory block in 'blk' by copying it to a full size block
758 * and inserting the new journal inode into .sujournal.
761 dir_extend(ufs2_daddr_t blk
, ufs2_daddr_t nblk
, off_t size
, ino_t ino
)
763 char block
[MAXBSIZE
];
765 if (bread(&disk
, fsbtodb(&sblock
, blk
), block
,
766 roundup(size
, sblock
.fs_fsize
)) <= 0) {
767 warn("Failed to read dir block");
770 dir_clear_block(block
, size
);
771 if (bwrite(&disk
, fsbtodb(&sblock
, nblk
), block
, sblock
.fs_bsize
)
773 warn("Failed to write dir block");
777 return (dir_insert(nblk
, size
, ino
));
781 * Insert the journal file into the ROOTINO directory. We always extend the
785 journal_insertfile(ino_t ino
)
787 struct ufs1_dinode
*dp1
;
788 struct ufs2_dinode
*dp2
;
797 if (getino(&disk
, &ip
, ROOTINO
, &mode
) != 0) {
798 warn("Failed to get root inode");
806 nblk
= journal_balloc();
810 * For simplicity sake we aways extend the ROOTINO into a new
811 * directory block rather than searching for space and inserting
812 * into an existing block. However, if the rootino has frags
813 * have to free them and extend the block.
815 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
816 lbn
= lblkno(&sblock
, dp1
->di_size
);
817 off
= blkoff(&sblock
, dp1
->di_size
);
818 blk
= dp1
->di_db
[lbn
];
819 size
= sblksize(&sblock
, (off_t
)dp1
->di_size
, lbn
);
821 lbn
= lblkno(&sblock
, dp2
->di_size
);
822 off
= blkoff(&sblock
, dp2
->di_size
);
823 blk
= dp2
->di_db
[lbn
];
824 size
= sblksize(&sblock
, (off_t
)dp2
->di_size
, lbn
);
827 if (dir_extend(blk
, nblk
, off
, ino
) == -1)
831 if (dir_insert(nblk
, 0, ino
) == -1)
834 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
835 dp1
->di_blocks
+= (sblock
.fs_bsize
- size
) / DEV_BSIZE
;
836 dp1
->di_db
[lbn
] = nblk
;
837 dp1
->di_size
= lblktosize(&sblock
, lbn
+1);
839 dp2
->di_blocks
+= (sblock
.fs_bsize
- size
) / DEV_BSIZE
;
840 dp2
->di_db
[lbn
] = nblk
;
841 dp2
->di_size
= lblktosize(&sblock
, lbn
+1);
843 if (putino(&disk
) < 0) {
844 warn("Failed to write root inode");
847 if (cgwrite(&disk
) < 0) {
848 warn("Failed to write updated cg");
853 if (cgbfree(&disk
, blk
, size
) < 0) {
854 warn("Failed to write cg");
863 indir_fill(ufs2_daddr_t blk
, int level
, int *resid
)
865 char indirbuf
[MAXBSIZE
];
873 bzero(indirbuf
, sizeof(indirbuf
));
874 bap1
= (ufs1_daddr_t
*)indirbuf
;
877 for (i
= 0; i
< NINDIR(&sblock
) && *resid
!= 0; i
++) {
878 nblk
= journal_balloc();
882 if (sblock
.fs_magic
== FS_UFS1_MAGIC
)
887 ncnt
= indir_fill(nblk
, level
- 1, resid
);
894 if (bwrite(&disk
, fsbtodb(&sblock
, blk
), indirbuf
,
895 sblock
.fs_bsize
) <= 0) {
896 warn("Failed to write indirect");
903 * Clear the flag bits so the journal can be removed.
908 struct ufs1_dinode
*dp1
;
909 struct ufs2_dinode
*dp2
;
914 ino
= journal_findfile();
915 if (ino
== (ino_t
)-1 || ino
== 0) {
916 warnx("Journal file does not exist");
919 printf("Clearing journal flags from inode %ju\n", (uintmax_t)ino
);
920 if (getino(&disk
, &ip
, ino
, &mode
) != 0) {
921 warn("Failed to get journal inode");
926 if (sblock
.fs_magic
== FS_UFS1_MAGIC
)
930 if (putino(&disk
) < 0) {
931 warn("Failed to write journal inode");
937 journal_alloc(int64_t size
)
939 struct ufs1_dinode
*dp1
;
940 struct ufs2_dinode
*dp2
;
955 * If the journal file exists we can't allocate it.
957 ino
= journal_findfile();
958 if (ino
== (ino_t
)-1)
961 warnx("Journal file %s already exists, please remove.",
966 * If the user didn't supply a size pick one based on the filesystem
967 * size constrained with hardcoded MIN and MAX values. We opt for
968 * 1/1024th of the filesystem up to MAX but not exceeding one CG and
969 * not less than the MIN.
972 size
= (sblock
.fs_size
* sblock
.fs_bsize
) / 1024;
973 size
= MIN(SUJ_MAX
, size
);
974 if (size
/ sblock
.fs_fsize
> sblock
.fs_fpg
)
975 size
= sblock
.fs_fpg
* sblock
.fs_fsize
;
976 size
= MAX(SUJ_MIN
, size
);
977 /* fsck does not support fragments in journal files. */
978 size
= roundup(size
, sblock
.fs_bsize
);
980 resid
= blocks
= size
/ sblock
.fs_bsize
;
981 if (sblock
.fs_cstotal
.cs_nbfree
< blocks
) {
982 warn("Insufficient free space for %jd byte journal", size
);
986 * Find a cg with enough blocks to satisfy the journal
987 * size. Presently the journal does not span cgs.
989 while (cgread(&disk
) == 1) {
990 if (cgp
->cg_cs
.cs_nifree
== 0)
992 ino
= cgialloc(&disk
);
995 printf("Using inode %ju in cg %d for %jd byte journal\n",
996 (uintmax_t)ino
, cgp
->cg_cgx
, size
);
997 if (getino(&disk
, &ip
, ino
, &mode
) != 0) {
998 warn("Failed to get allocated inode");
1003 * We leave fields unrelated to the number of allocated
1004 * blocks and size uninitialized. This causes legacy
1005 * fsck implementations to clear the inode.
1010 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
1011 bzero(dp1
, sizeof(*dp1
));
1012 dp1
->di_size
= size
;
1013 dp1
->di_mode
= IFREG
| IREAD
;
1015 dp1
->di_flags
= SF_IMMUTABLE
| SF_NOUNLINK
| UF_NODUMP
;
1016 dp1
->di_atime
= utime
;
1017 dp1
->di_mtime
= utime
;
1018 dp1
->di_ctime
= utime
;
1020 bzero(dp2
, sizeof(*dp2
));
1021 dp2
->di_size
= size
;
1022 dp2
->di_mode
= IFREG
| IREAD
;
1024 dp2
->di_flags
= SF_IMMUTABLE
| SF_NOUNLINK
| UF_NODUMP
;
1025 dp2
->di_atime
= utime
;
1026 dp2
->di_mtime
= utime
;
1027 dp2
->di_ctime
= utime
;
1028 dp2
->di_birthtime
= utime
;
1030 for (i
= 0; i
< NDADDR
&& resid
; i
++, resid
--) {
1031 blk
= journal_balloc();
1034 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
1035 dp1
->di_db
[i
] = blk
;
1038 dp2
->di_db
[i
] = blk
;
1042 for (i
= 0; i
< NIADDR
&& resid
; i
++) {
1043 blk
= journal_balloc();
1046 blks
= indir_fill(blk
, i
, &resid
) + 1;
1051 if (sblock
.fs_magic
== FS_UFS1_MAGIC
) {
1052 dp1
->di_ib
[i
] = blk
;
1053 dp1
->di_blocks
+= blks
;
1055 dp2
->di_ib
[i
] = blk
;
1056 dp2
->di_blocks
+= blks
;
1059 if (sblock
.fs_magic
== FS_UFS1_MAGIC
)
1060 dp1
->di_blocks
*= sblock
.fs_bsize
/ disk
.d_bsize
;
1062 dp2
->di_blocks
*= sblock
.fs_bsize
/ disk
.d_bsize
;
1063 if (putino(&disk
) < 0) {
1064 warn("Failed to write inode");
1068 if (cgwrite(&disk
) < 0) {
1069 warn("Failed to write updated cg");
1073 if (journal_insertfile(ino
) < 0) {
1077 sblock
.fs_sujfree
= 0;
1080 warnx("Insufficient free space for the journal.");
1088 fprintf(stderr
, "%s\n%s\n%s\n%s\n%s\n%s\n",
1089 "usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]",
1090 " [-J enable | disable] [-j enable | disable] [-k metaspace]",
1091 " [-L volname] [-l enable | disable] [-m minfree]",
1092 " [-N enable | disable] [-n enable | disable]",
1093 " [-o space | time] [-p] [-s avgfpdir] [-t enable | disable]",
1094 " special | filesystem");
1101 warnx("POSIX.1e ACLs: (-a) %s",
1102 (sblock
.fs_flags
& FS_ACLS
)? "enabled" : "disabled");
1103 warnx("NFSv4 ACLs: (-N) %s",
1104 (sblock
.fs_flags
& FS_NFS4ACLS
)? "enabled" : "disabled");
1105 warnx("MAC multilabel: (-l) %s",
1106 (sblock
.fs_flags
& FS_MULTILABEL
)? "enabled" : "disabled");
1107 warnx("soft updates: (-n) %s",
1108 (sblock
.fs_flags
& FS_DOSOFTDEP
)? "enabled" : "disabled");
1109 warnx("soft update journaling: (-j) %s",
1110 (sblock
.fs_flags
& FS_SUJ
)? "enabled" : "disabled");
1111 warnx("gjournal: (-J) %s",
1112 (sblock
.fs_flags
& FS_GJOURNAL
)? "enabled" : "disabled");
1113 warnx("trim: (-t) %s",
1114 (sblock
.fs_flags
& FS_TRIM
)? "enabled" : "disabled");
1115 warnx("maximum blocks per file in a cylinder group: (-e) %d",
1117 warnx("average file size: (-f) %d",
1118 sblock
.fs_avgfilesize
);
1119 warnx("average number of files in a directory: (-s) %d",
1120 sblock
.fs_avgfpdir
);
1121 warnx("minimum percentage of free space: (-m) %d%%",
1123 warnx("space to hold for metadata blocks: (-k) %jd",
1124 sblock
.fs_metaspace
);
1125 warnx("optimization preference: (-o) %s",
1126 sblock
.fs_optim
== FS_OPTSPACE
? "space" : "time");
1127 if (sblock
.fs_minfree
>= MINFREE
&&
1128 sblock
.fs_optim
== FS_OPTSPACE
)
1129 warnx(OPTWARN
, "time", ">=", MINFREE
);
1130 if (sblock
.fs_minfree
< MINFREE
&&
1131 sblock
.fs_optim
== FS_OPTTIME
)
1132 warnx(OPTWARN
, "space", "<", MINFREE
);
1133 warnx("volume label: (-L) %s",