tunefs.c revision 208241
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1983, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 4. Neither the name of the University nor the names of its contributors 141558Srgrimes * may be used to endorse or promote products derived from this software 151558Srgrimes * without specific prior written permission. 161558Srgrimes * 171558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 181558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 191558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 201558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 211558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 221558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 231558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 241558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 251558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 261558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 271558Srgrimes * SUCH DAMAGE. 281558Srgrimes */ 291558Srgrimes 30114589Sobrien#if 0 311558Srgrimes#ifndef lint 3238040Scharnierstatic const char copyright[] = 331558Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 341558Srgrimes The Regents of the University of California. All rights reserved.\n"; 351558Srgrimes#endif /* not lint */ 361558Srgrimes 371558Srgrimes#ifndef lint 381558Srgrimesstatic char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94"; 39114589Sobrien#endif /* not lint */ 4038040Scharnier#endif 41114589Sobrien#include <sys/cdefs.h> 42114589Sobrien__FBSDID("$FreeBSD: head/sbin/tunefs/tunefs.c 208241 2010-05-18 01:45:28Z jeff $"); 431558Srgrimes 441558Srgrimes/* 45102231Strhodes * tunefs: change layout parameters to an existing file system. 461558Srgrimes */ 471558Srgrimes#include <sys/param.h> 4842873Sluoqi#include <sys/mount.h> 4996478Sphk#include <sys/disklabel.h> 501558Srgrimes#include <sys/stat.h> 511558Srgrimes 5298542Smckusick#include <ufs/ufs/ufsmount.h> 5398542Smckusick#include <ufs/ufs/dinode.h> 541558Srgrimes#include <ufs/ffs/fs.h> 55207141Sjeff#include <ufs/ufs/dir.h> 561558Srgrimes 57110174Sgordon#include <ctype.h> 581558Srgrimes#include <err.h> 591558Srgrimes#include <fcntl.h> 601558Srgrimes#include <fstab.h> 61109597Sjmallett#include <libufs.h> 6238040Scharnier#include <paths.h> 631558Srgrimes#include <stdio.h> 641558Srgrimes#include <stdlib.h> 65207141Sjeff#include <stdint.h> 6658047Ssheldonh#include <string.h> 671558Srgrimes#include <unistd.h> 681558Srgrimes 691558Srgrimes/* the optimization warning string template */ 701558Srgrimes#define OPTWARN "should optimize for %s with minfree %s %d%%" 711558Srgrimes 72109597Sjmallettstruct uufsd disk; 73109597Sjmallett#define sblock disk.d_fs 741558Srgrimes 7592883Simpvoid usage(void); 7692883Simpvoid printfs(void); 77207141Sjeffint journal_alloc(int64_t size); 78207141Sjeffvoid journal_clear(void); 79207141Sjeffvoid sbdirty(void); 801558Srgrimes 811558Srgrimesint 82109597Sjmallettmain(int argc, char *argv[]) 831558Srgrimes{ 84207141Sjeff char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue; 85109963Sjmallett const char *special, *on; 8679750Sdd const char *name; 87127455Sbde int active; 88207141Sjeff int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, Lflag; 89207141Sjeff int lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue, pflag, sflag; 90207141Sjeff int svalue, Sflag, Svalue; 91127441Sbde int ch, found_arg, i; 9279750Sdd const char *chg[2]; 9342873Sluoqi struct ufs_args args; 9442873Sluoqi struct statfs stfs; 951558Srgrimes 96127441Sbde if (argc < 3) 97127441Sbde usage(); 98207141Sjeff Aflag = aflag = eflag = fflag = jflag = Jflag = Lflag = lflag = 0; 99207141Sjeff mflag = Nflag = nflag = oflag = pflag = sflag = 0; 100207141Sjeff avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL; 101207141Sjeff evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0; 102127455Sbde active = 0; 103127441Sbde found_arg = 0; /* At least one arg is required. */ 104207141Sjeff while ((ch = getopt(argc, argv, "Aa:e:f:j:J:L:l:m:N:n:o:ps:S:")) != -1) 105127441Sbde switch (ch) { 106127441Sbde 107127441Sbde case 'A': 108127441Sbde found_arg = 1; 109127441Sbde Aflag++; 110127441Sbde break; 111127441Sbde 112127441Sbde case 'a': 113127441Sbde found_arg = 1; 114200796Strasz name = "POSIX.1e ACLs"; 115127441Sbde avalue = optarg; 116127441Sbde if (strcmp(avalue, "enable") && 117127441Sbde strcmp(avalue, "disable")) { 118127441Sbde errx(10, "bad %s (options are %s)", 119127441Sbde name, "`enable' or `disable'"); 120127441Sbde } 121127441Sbde aflag = 1; 122127441Sbde break; 123127441Sbde 124127441Sbde case 'e': 125127441Sbde found_arg = 1; 126127441Sbde name = "maximum blocks per file in a cylinder group"; 127127441Sbde evalue = atoi(optarg); 128127441Sbde if (evalue < 1) 129127441Sbde errx(10, "%s must be >= 1 (was %s)", 130127441Sbde name, optarg); 131127441Sbde eflag = 1; 132127441Sbde break; 133127441Sbde 134127441Sbde case 'f': 135127441Sbde found_arg = 1; 136127441Sbde name = "average file size"; 137127441Sbde fvalue = atoi(optarg); 138127441Sbde if (fvalue < 1) 139127441Sbde errx(10, "%s must be >= 1 (was %s)", 140127441Sbde name, optarg); 141127441Sbde fflag = 1; 142127441Sbde break; 143127441Sbde 144207141Sjeff case 'j': 145207141Sjeff found_arg = 1; 146207141Sjeff name = "softdep journaled file system"; 147207141Sjeff jvalue = optarg; 148207141Sjeff if (strcmp(jvalue, "enable") && 149207141Sjeff strcmp(jvalue, "disable")) { 150207141Sjeff errx(10, "bad %s (options are %s)", 151207141Sjeff name, "`enable' or `disable'"); 152207141Sjeff } 153207141Sjeff jflag = 1; 154207141Sjeff break; 155207141Sjeff 156163842Spjd case 'J': 157163842Spjd found_arg = 1; 158163842Spjd name = "gjournaled file system"; 159163842Spjd Jvalue = optarg; 160163842Spjd if (strcmp(Jvalue, "enable") && 161163842Spjd strcmp(Jvalue, "disable")) { 162163842Spjd errx(10, "bad %s (options are %s)", 163163842Spjd name, "`enable' or `disable'"); 164163842Spjd } 165163842Spjd Jflag = 1; 166163842Spjd break; 167163842Spjd 168163842Spjd 169127441Sbde case 'L': 170127441Sbde found_arg = 1; 171127441Sbde name = "volume label"; 172127441Sbde Lvalue = optarg; 173127441Sbde i = -1; 174127441Sbde while (isalnum(Lvalue[++i])); 175127441Sbde if (Lvalue[i] != '\0') { 176127441Sbde errx(10, 177127441Sbde "bad %s. Valid characters are alphanumerics.", 178127441Sbde name); 179127441Sbde } 180127441Sbde if (strlen(Lvalue) >= MAXVOLLEN) { 181127441Sbde errx(10, "bad %s. Length is longer than %d.", 182127441Sbde name, MAXVOLLEN - 1); 183127441Sbde } 184127441Sbde Lflag = 1; 185127441Sbde break; 186127441Sbde 187127441Sbde case 'l': 188127441Sbde found_arg = 1; 189127441Sbde name = "multilabel MAC file system"; 190127441Sbde lvalue = optarg; 191127441Sbde if (strcmp(lvalue, "enable") && 192127441Sbde strcmp(lvalue, "disable")) { 193127441Sbde errx(10, "bad %s (options are %s)", 194127441Sbde name, "`enable' or `disable'"); 195127441Sbde } 196127441Sbde lflag = 1; 197127441Sbde break; 198127441Sbde 199127441Sbde case 'm': 200127441Sbde found_arg = 1; 201127441Sbde name = "minimum percentage of free space"; 202127441Sbde mvalue = atoi(optarg); 203127441Sbde if (mvalue < 0 || mvalue > 99) 204127441Sbde errx(10, "bad %s (%s)", name, optarg); 205127441Sbde mflag = 1; 206127441Sbde break; 207127441Sbde 208200796Strasz case 'N': 209200796Strasz found_arg = 1; 210200796Strasz name = "NFSv4 ACLs"; 211200796Strasz Nvalue = optarg; 212200796Strasz if (strcmp(Nvalue, "enable") && 213200796Strasz strcmp(Nvalue, "disable")) { 214200796Strasz errx(10, "bad %s (options are %s)", 215200796Strasz name, "`enable' or `disable'"); 216200796Strasz } 217200796Strasz Nflag = 1; 218200796Strasz break; 219200796Strasz 220127441Sbde case 'n': 221127441Sbde found_arg = 1; 222127441Sbde name = "soft updates"; 223127441Sbde nvalue = optarg; 224127455Sbde if (strcmp(nvalue, "enable") != 0 && 225127455Sbde strcmp(nvalue, "disable") != 0) { 226127441Sbde errx(10, "bad %s (options are %s)", 227127441Sbde name, "`enable' or `disable'"); 228127441Sbde } 229127441Sbde nflag = 1; 230127441Sbde break; 231127441Sbde 232127441Sbde case 'o': 233127441Sbde found_arg = 1; 234127441Sbde name = "optimization preference"; 235127455Sbde if (strcmp(optarg, "space") == 0) 236127441Sbde ovalue = FS_OPTSPACE; 237127455Sbde else if (strcmp(optarg, "time") == 0) 238127441Sbde ovalue = FS_OPTTIME; 239127441Sbde else 240127441Sbde errx(10, 241127441Sbde "bad %s (options are `space' or `time')", 242127441Sbde name); 243127441Sbde oflag = 1; 244127441Sbde break; 245127441Sbde 246127441Sbde case 'p': 247127441Sbde found_arg = 1; 248127441Sbde pflag = 1; 249127441Sbde break; 250127441Sbde 251127441Sbde case 's': 252127441Sbde found_arg = 1; 253127441Sbde name = "expected number of files per directory"; 254127441Sbde svalue = atoi(optarg); 255127441Sbde if (svalue < 1) 256127441Sbde errx(10, "%s must be >= 1 (was %s)", 257127441Sbde name, optarg); 258127441Sbde sflag = 1; 259127441Sbde break; 260127441Sbde 261207141Sjeff case 'S': 262207141Sjeff found_arg = 1; 263207141Sjeff name = "Softdep Journal Size"; 264207141Sjeff Svalue = atoi(optarg); 265207141Sjeff if (Svalue < SUJ_MIN) 266207141Sjeff errx(10, "%s must be >= %d (was %s)", 267207141Sjeff name, SUJ_MIN, optarg); 268207141Sjeff Sflag = 1; 269207141Sjeff break; 270207141Sjeff 271127441Sbde default: 272127441Sbde usage(); 273105120Srwatson } 27469314Scharnier argc -= optind; 27569314Scharnier argv += optind; 27669314Scharnier if (found_arg == 0 || argc != 1) 277127441Sbde usage(); 27869314Scharnier 279109963Sjmallett on = special = argv[0]; 280109963Sjmallett if (ufs_disk_fillout(&disk, special) == -1) 281109963Sjmallett goto err; 282109963Sjmallett if (disk.d_name != special) { 283207421Sjeff if (statfs(special, &stfs) != 0) 284207421Sjeff warn("Can't stat %s", special); 285207421Sjeff if (strcmp(special, stfs.f_mntonname) == 0) 28669829Scharnier active = 1; 28769829Scharnier } 28869829Scharnier 28969829Scharnier if (pflag) { 29069829Scharnier printfs(); 29169829Scharnier exit(0); 29269829Scharnier } 293110174Sgordon if (Lflag) { 294110174Sgordon name = "volume label"; 295110174Sgordon strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN); 296110174Sgordon } 297105120Srwatson if (aflag) { 298200796Strasz name = "POSIX.1e ACLs"; 299105120Srwatson if (strcmp(avalue, "enable") == 0) { 300105120Srwatson if (sblock.fs_flags & FS_ACLS) { 301105120Srwatson warnx("%s remains unchanged as enabled", name); 302200796Strasz } else if (sblock.fs_flags & FS_NFS4ACLS) { 303200796Strasz warnx("%s and NFSv4 ACLs are mutually " 304200796Strasz "exclusive", name); 305105120Srwatson } else { 306105120Srwatson sblock.fs_flags |= FS_ACLS; 307105120Srwatson warnx("%s set", name); 308105120Srwatson } 309105120Srwatson } else if (strcmp(avalue, "disable") == 0) { 310105120Srwatson if ((~sblock.fs_flags & FS_ACLS) == 311105120Srwatson FS_ACLS) { 312105120Srwatson warnx("%s remains unchanged as disabled", 313105120Srwatson name); 314105120Srwatson } else { 315105120Srwatson sblock.fs_flags &= ~FS_ACLS; 316105206Srwatson warnx("%s cleared", name); 317105120Srwatson } 318105120Srwatson } 319105120Srwatson } 32069829Scharnier if (eflag) { 32169829Scharnier name = "maximum blocks per file in a cylinder group"; 322127455Sbde if (sblock.fs_maxbpg == evalue) 32369829Scharnier warnx("%s remains unchanged as %d", name, evalue); 32469829Scharnier else { 32569829Scharnier warnx("%s changes from %d to %d", 326127455Sbde name, sblock.fs_maxbpg, evalue); 32769829Scharnier sblock.fs_maxbpg = evalue; 32869829Scharnier } 32969829Scharnier } 33075377Smckusick if (fflag) { 33175377Smckusick name = "average file size"; 332203769Smckusick if (sblock.fs_avgfilesize == (unsigned)fvalue) { 33375377Smckusick warnx("%s remains unchanged as %d", name, fvalue); 33475377Smckusick } 33575377Smckusick else { 33675377Smckusick warnx("%s changes from %d to %d", 33775377Smckusick name, sblock.fs_avgfilesize, fvalue); 33875377Smckusick sblock.fs_avgfilesize = fvalue; 33975377Smckusick } 34075377Smckusick } 341207141Sjeff if (jflag) { 342207141Sjeff name = "soft updates journaling"; 343207141Sjeff if (strcmp(jvalue, "enable") == 0) { 344207141Sjeff if ((sblock.fs_flags & (FS_DOSOFTDEP | FS_SUJ)) == 345207141Sjeff (FS_DOSOFTDEP | FS_SUJ)) { 346207141Sjeff warnx("%s remains unchanged as enabled", name); 347207141Sjeff } else if (sblock.fs_clean == 0) { 348207141Sjeff warnx("%s cannot be enabled until fsck is run", 349207141Sjeff name); 350207141Sjeff } else if (journal_alloc(Svalue) != 0) { 351207141Sjeff warnx("%s can not be enabled", name); 352207141Sjeff } else { 353207141Sjeff sblock.fs_flags |= FS_DOSOFTDEP | FS_SUJ; 354207141Sjeff warnx("%s set", name); 355207141Sjeff } 356207141Sjeff } else if (strcmp(jvalue, "disable") == 0) { 357207141Sjeff if ((~sblock.fs_flags & FS_SUJ) == FS_SUJ) { 358207141Sjeff warnx("%s remains unchanged as disabled", name); 359207141Sjeff } else { 360207141Sjeff journal_clear(); 361208241Sjeff sblock.fs_flags &= ~FS_SUJ; 362207141Sjeff sblock.fs_sujfree = 0; 363208241Sjeff warnx("%s cleared but soft updates still set.", 364208241Sjeff name); 365208241Sjeff 366208241Sjeff warnx("remove .sujournal to reclaim space"); 367207141Sjeff } 368207141Sjeff } 369207141Sjeff } 370163842Spjd if (Jflag) { 371163842Spjd name = "gjournal"; 372163842Spjd if (strcmp(Jvalue, "enable") == 0) { 373163842Spjd if (sblock.fs_flags & FS_GJOURNAL) { 374163842Spjd warnx("%s remains unchanged as enabled", name); 375163842Spjd } else { 376163842Spjd sblock.fs_flags |= FS_GJOURNAL; 377163842Spjd warnx("%s set", name); 378163842Spjd } 379163842Spjd } else if (strcmp(Jvalue, "disable") == 0) { 380163842Spjd if ((~sblock.fs_flags & FS_GJOURNAL) == 381163842Spjd FS_GJOURNAL) { 382163842Spjd warnx("%s remains unchanged as disabled", 383163842Spjd name); 384163842Spjd } else { 385163842Spjd sblock.fs_flags &= ~FS_GJOURNAL; 386163842Spjd warnx("%s cleared", name); 387163842Spjd } 388163842Spjd } 389163842Spjd } 390105120Srwatson if (lflag) { 391105120Srwatson name = "multilabel"; 392105120Srwatson if (strcmp(lvalue, "enable") == 0) { 393105120Srwatson if (sblock.fs_flags & FS_MULTILABEL) { 394105120Srwatson warnx("%s remains unchanged as enabled", name); 395105120Srwatson } else { 396105120Srwatson sblock.fs_flags |= FS_MULTILABEL; 397105120Srwatson warnx("%s set", name); 398105120Srwatson } 399105120Srwatson } else if (strcmp(lvalue, "disable") == 0) { 400105120Srwatson if ((~sblock.fs_flags & FS_MULTILABEL) == 401105120Srwatson FS_MULTILABEL) { 402105120Srwatson warnx("%s remains unchanged as disabled", 403105120Srwatson name); 404105120Srwatson } else { 405105120Srwatson sblock.fs_flags &= ~FS_MULTILABEL; 406105206Srwatson warnx("%s cleared", name); 407105120Srwatson } 408105120Srwatson } 409105120Srwatson } 41069829Scharnier if (mflag) { 41169829Scharnier name = "minimum percentage of free space"; 412127455Sbde if (sblock.fs_minfree == mvalue) 41369829Scharnier warnx("%s remains unchanged as %d%%", name, mvalue); 41469829Scharnier else { 41569829Scharnier warnx("%s changes from %d%% to %d%%", 41669829Scharnier name, sblock.fs_minfree, mvalue); 41769829Scharnier sblock.fs_minfree = mvalue; 41869829Scharnier if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE) 41969829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 42069829Scharnier if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME) 42169829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 42269829Scharnier } 42369829Scharnier } 424200796Strasz if (Nflag) { 425200796Strasz name = "NFSv4 ACLs"; 426200796Strasz if (strcmp(Nvalue, "enable") == 0) { 427200796Strasz if (sblock.fs_flags & FS_NFS4ACLS) { 428200796Strasz warnx("%s remains unchanged as enabled", name); 429200796Strasz } else if (sblock.fs_flags & FS_ACLS) { 430200796Strasz warnx("%s and POSIX.1e ACLs are mutually " 431200796Strasz "exclusive", name); 432200796Strasz } else { 433200796Strasz sblock.fs_flags |= FS_NFS4ACLS; 434200796Strasz warnx("%s set", name); 435200796Strasz } 436200796Strasz } else if (strcmp(Nvalue, "disable") == 0) { 437200796Strasz if ((~sblock.fs_flags & FS_NFS4ACLS) == 438200796Strasz FS_NFS4ACLS) { 439200796Strasz warnx("%s remains unchanged as disabled", 440200796Strasz name); 441200796Strasz } else { 442200796Strasz sblock.fs_flags &= ~FS_NFS4ACLS; 443200796Strasz warnx("%s cleared", name); 444200796Strasz } 445200796Strasz } 446200796Strasz } 44769829Scharnier if (nflag) { 44869829Scharnier name = "soft updates"; 44969829Scharnier if (strcmp(nvalue, "enable") == 0) { 450127455Sbde if (sblock.fs_flags & FS_DOSOFTDEP) 45169829Scharnier warnx("%s remains unchanged as enabled", name); 452127455Sbde else if (sblock.fs_clean == 0) { 45375498Smckusick warnx("%s cannot be enabled until fsck is run", 45475498Smckusick name); 45569829Scharnier } else { 45669829Scharnier sblock.fs_flags |= FS_DOSOFTDEP; 45769829Scharnier warnx("%s set", name); 45869829Scharnier } 45969829Scharnier } else if (strcmp(nvalue, "disable") == 0) { 460127455Sbde if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) 46169829Scharnier warnx("%s remains unchanged as disabled", name); 462127455Sbde else { 46369829Scharnier sblock.fs_flags &= ~FS_DOSOFTDEP; 46469829Scharnier warnx("%s cleared", name); 46569829Scharnier } 46669829Scharnier } 46769829Scharnier } 46869829Scharnier if (oflag) { 46969829Scharnier name = "optimization preference"; 47069829Scharnier chg[FS_OPTSPACE] = "space"; 47169829Scharnier chg[FS_OPTTIME] = "time"; 472127455Sbde if (sblock.fs_optim == ovalue) 47369829Scharnier warnx("%s remains unchanged as %s", name, chg[ovalue]); 47469829Scharnier else { 47569829Scharnier warnx("%s changes from %s to %s", 47669829Scharnier name, chg[sblock.fs_optim], chg[ovalue]); 47769829Scharnier sblock.fs_optim = ovalue; 47869829Scharnier if (sblock.fs_minfree >= MINFREE && 479127455Sbde ovalue == FS_OPTSPACE) 48069829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 481127455Sbde if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME) 48269829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 48369829Scharnier } 48469829Scharnier } 48575377Smckusick if (sflag) { 48675377Smckusick name = "expected number of files per directory"; 487203769Smckusick if (sblock.fs_avgfpdir == (unsigned)svalue) { 48875377Smckusick warnx("%s remains unchanged as %d", name, svalue); 48975377Smckusick } 49075377Smckusick else { 49175377Smckusick warnx("%s changes from %d to %d", 49275377Smckusick name, sblock.fs_avgfpdir, svalue); 49375377Smckusick sblock.fs_avgfpdir = svalue; 49475377Smckusick } 49575377Smckusick } 49669829Scharnier 497109963Sjmallett if (sbwrite(&disk, Aflag) == -1) 498109963Sjmallett goto err; 499109963Sjmallett ufs_disk_close(&disk); 50042873Sluoqi if (active) { 50142873Sluoqi bzero(&args, sizeof(args)); 502109963Sjmallett if (mount("ufs", on, 50342873Sluoqi stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) 50442873Sluoqi err(9, "%s: reload", special); 505102231Strhodes warnx("file system reloaded"); 50642873Sluoqi } 5071558Srgrimes exit(0); 508109963Sjmalletterr: 509109963Sjmallett if (disk.d_error != NULL) 510109963Sjmallett errx(11, "%s: %s", special, disk.d_error); 511109963Sjmallett else 512109963Sjmallett err(12, "%s", special); 5131558Srgrimes} 5141558Srgrimes 5151558Srgrimesvoid 516207141Sjeffsbdirty(void) 517207141Sjeff{ 518207141Sjeff disk.d_fs.fs_flags |= FS_UNCLEAN | FS_NEEDSFSCK; 519207141Sjeff disk.d_fs.fs_clean = 0; 520207141Sjeff} 521207141Sjeff 522207141Sjeffint blocks; 523207141Sjeffstatic char clrbuf[MAXBSIZE]; 524207141Sjeff 525207141Sjeffstatic ufs2_daddr_t 526207141Sjeffjournal_balloc(void) 527207141Sjeff{ 528207141Sjeff ufs2_daddr_t blk; 529207141Sjeff struct cg *cgp; 530207141Sjeff int valid; 531207141Sjeff static int contig = 1; 532207141Sjeff 533207141Sjeff cgp = &disk.d_cg; 534207141Sjeff for (;;) { 535207141Sjeff blk = cgballoc(&disk); 536207141Sjeff if (blk > 0) 537207141Sjeff break; 538207141Sjeff /* 539207141Sjeff * If we failed to allocate a block from this cg, move to 540207141Sjeff * the next. 541207141Sjeff */ 542207141Sjeff if (cgwrite(&disk) < 0) { 543207141Sjeff warn("Failed to write updated cg"); 544207141Sjeff return (-1); 545207141Sjeff } 546207141Sjeff while ((valid = cgread(&disk)) == 1) { 547207141Sjeff /* 548207141Sjeff * Try to minimize fragmentation by requiring a minimum 549207141Sjeff * number of blocks present. 550207141Sjeff */ 551208241Sjeff if (cgp->cg_cs.cs_nbfree > 256 * 1024) 552207141Sjeff break; 553207141Sjeff if (contig == 0 && cgp->cg_cs.cs_nbfree) 554207141Sjeff break; 555207141Sjeff } 556207141Sjeff if (valid) 557207141Sjeff continue; 558207141Sjeff /* 559207141Sjeff * Try once through looking only for large contiguous regions 560207141Sjeff * and again taking any space we can find. 561207141Sjeff */ 562207141Sjeff if (contig) { 563207141Sjeff contig = 0; 564207141Sjeff disk.d_ccg = 0; 565207141Sjeff warnx("Journal file fragmented."); 566207141Sjeff continue; 567207141Sjeff } 568207141Sjeff warnx("Failed to find sufficient free blocks for the journal"); 569207141Sjeff return -1; 570207141Sjeff } 571207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), clrbuf, 572207141Sjeff sblock.fs_bsize) <= 0) { 573207141Sjeff warn("Failed to initialize new block"); 574207141Sjeff return -1; 575207141Sjeff } 576207141Sjeff return (blk); 577207141Sjeff} 578207141Sjeff 579207141Sjeff/* 580207141Sjeff * Search a directory block for the SUJ_FILE. 581207141Sjeff */ 582207141Sjeffstatic ino_t 583207141Sjeffdir_search(ufs2_daddr_t blk, int bytes) 584207141Sjeff{ 585207141Sjeff char block[MAXBSIZE]; 586207141Sjeff struct direct *dp; 587207141Sjeff int off; 588207141Sjeff 589207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, bytes) <= 0) { 590207141Sjeff warn("Failed to read dir block"); 591207141Sjeff return (-1); 592207141Sjeff } 593207141Sjeff for (off = 0; off < bytes; off += dp->d_reclen) { 594207141Sjeff dp = (struct direct *)&block[off]; 595207141Sjeff if (dp->d_reclen == 0) 596207141Sjeff break; 597207141Sjeff if (dp->d_ino == 0) 598207141Sjeff continue; 599207141Sjeff if (dp->d_namlen != strlen(SUJ_FILE)) 600207141Sjeff continue; 601207141Sjeff if (bcmp(dp->d_name, SUJ_FILE, dp->d_namlen) != 0) 602207141Sjeff continue; 603207141Sjeff return (dp->d_ino); 604207141Sjeff } 605207141Sjeff 606207141Sjeff return (0); 607207141Sjeff} 608207141Sjeff 609207141Sjeff/* 610207141Sjeff * Search in the ROOTINO for the SUJ_FILE. If it exists we can not enable 611207141Sjeff * journaling. 612207141Sjeff */ 613207141Sjeffstatic ino_t 614207141Sjeffjournal_findfile(void) 615207141Sjeff{ 616207141Sjeff struct ufs1_dinode *dp1; 617207141Sjeff struct ufs2_dinode *dp2; 618207141Sjeff ino_t ino; 619207141Sjeff int mode; 620207141Sjeff void *ip; 621207141Sjeff int i; 622207141Sjeff 623207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 624207141Sjeff warn("Failed to get root inode"); 625207141Sjeff return (-1); 626207141Sjeff } 627207141Sjeff dp2 = ip; 628207141Sjeff dp1 = ip; 629207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 630207141Sjeff if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { 631207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 632207141Sjeff return (-1); 633207141Sjeff } 634207141Sjeff for (i = 0; i < NDADDR; i++) { 635207141Sjeff if (dp1->di_db[i] == 0) 636207141Sjeff break; 637207141Sjeff if ((ino = dir_search(dp1->di_db[i], 638207141Sjeff sblksize(&sblock, (off_t)dp1->di_size, i))) != 0) 639207141Sjeff return (ino); 640207141Sjeff } 641207141Sjeff } else { 642207141Sjeff if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { 643207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 644207141Sjeff return (-1); 645207141Sjeff } 646207141Sjeff for (i = 0; i < NDADDR; i++) { 647207141Sjeff if (dp2->di_db[i] == 0) 648207141Sjeff break; 649207141Sjeff if ((ino = dir_search(dp2->di_db[i], 650207141Sjeff sblksize(&sblock, (off_t)dp2->di_size, i))) != 0) 651207141Sjeff return (ino); 652207141Sjeff } 653207141Sjeff } 654207141Sjeff 655207141Sjeff return (0); 656207141Sjeff} 657207141Sjeff 658207141Sjeff/* 659207141Sjeff * Insert the journal at inode 'ino' into directory blk 'blk' at the first 660207141Sjeff * free offset of 'off'. DIRBLKSIZ blocks after off are initialized as 661207141Sjeff * empty. 662207141Sjeff */ 663207141Sjeffstatic int 664207141Sjeffdir_insert(ufs2_daddr_t blk, off_t off, ino_t ino) 665207141Sjeff{ 666207141Sjeff struct direct *dp; 667207141Sjeff char block[MAXBSIZE]; 668207141Sjeff 669207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 670207141Sjeff warn("Failed to read dir block"); 671207141Sjeff return (-1); 672207141Sjeff } 673207141Sjeff bzero(&block[off], sblock.fs_bsize - off); 674207141Sjeff dp = (struct direct *)&block[off]; 675207141Sjeff dp->d_ino = ino; 676207141Sjeff dp->d_reclen = DIRBLKSIZ; 677207141Sjeff dp->d_type = DT_REG; 678207141Sjeff dp->d_namlen = strlen(SUJ_FILE); 679207141Sjeff bcopy(SUJ_FILE, &dp->d_name, strlen(SUJ_FILE)); 680207141Sjeff off += DIRBLKSIZ; 681207141Sjeff for (; off < sblock.fs_bsize; off += DIRBLKSIZ) { 682207141Sjeff dp = (struct direct *)&block[off]; 683207141Sjeff dp->d_ino = 0; 684207141Sjeff dp->d_reclen = DIRBLKSIZ; 685207141Sjeff dp->d_type = DT_UNKNOWN; 686207141Sjeff } 687207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 688207141Sjeff warn("Failed to write dir block"); 689207141Sjeff return (-1); 690207141Sjeff } 691207141Sjeff return (0); 692207141Sjeff} 693207141Sjeff 694207141Sjeff/* 695207141Sjeff * Extend a directory block in 'blk' by copying it to a full size block 696207141Sjeff * and inserting the new journal inode into .sujournal. 697207141Sjeff */ 698207141Sjeffstatic int 699207141Sjeffdir_extend(ufs2_daddr_t blk, ufs2_daddr_t nblk, off_t size, ino_t ino) 700207141Sjeff{ 701207141Sjeff char block[MAXBSIZE]; 702207141Sjeff 703207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, size) <= 0) { 704207141Sjeff warn("Failed to read dir block"); 705207141Sjeff return (-1); 706207141Sjeff } 707207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, nblk), block, size) <= 0) { 708207141Sjeff warn("Failed to write dir block"); 709207141Sjeff return (-1); 710207141Sjeff } 711207141Sjeff 712207141Sjeff return dir_insert(nblk, size, ino); 713207141Sjeff} 714207141Sjeff 715207141Sjeff/* 716207141Sjeff * Insert the journal file into the ROOTINO directory. We always extend the 717207141Sjeff * last frag 718207141Sjeff */ 719207141Sjeffstatic int 720207141Sjeffjournal_insertfile(ino_t ino) 721207141Sjeff{ 722207141Sjeff struct ufs1_dinode *dp1; 723207141Sjeff struct ufs2_dinode *dp2; 724207141Sjeff void *ip; 725207141Sjeff ufs2_daddr_t nblk; 726207141Sjeff ufs2_daddr_t blk; 727207141Sjeff ufs_lbn_t lbn; 728207141Sjeff int size; 729207141Sjeff int mode; 730207141Sjeff int off; 731207141Sjeff 732207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 733207141Sjeff warn("Failed to get root inode"); 734207141Sjeff sbdirty(); 735207141Sjeff return (-1); 736207141Sjeff } 737207141Sjeff dp2 = ip; 738207141Sjeff dp1 = ip; 739207141Sjeff blk = 0; 740207141Sjeff size = 0; 741207141Sjeff nblk = journal_balloc(); 742207141Sjeff if (nblk <= 0) 743207141Sjeff return (-1); 744207141Sjeff /* 745207141Sjeff * For simplicity sake we aways extend the ROOTINO into a new 746207141Sjeff * directory block rather than searching for space and inserting 747207141Sjeff * into an existing block. However, if the rootino has frags 748207141Sjeff * have to free them and extend the block. 749207141Sjeff */ 750207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 751207141Sjeff lbn = lblkno(&sblock, dp1->di_size); 752207141Sjeff off = blkoff(&sblock, dp1->di_size); 753207141Sjeff blk = dp1->di_db[lbn]; 754207141Sjeff size = sblksize(&sblock, (off_t)dp1->di_size, lbn); 755207141Sjeff } else { 756207141Sjeff lbn = lblkno(&sblock, dp2->di_size); 757207141Sjeff off = blkoff(&sblock, dp2->di_size); 758207141Sjeff blk = dp2->di_db[lbn]; 759207141Sjeff size = sblksize(&sblock, (off_t)dp2->di_size, lbn); 760207141Sjeff } 761207141Sjeff if (off != 0) { 762207141Sjeff if (dir_extend(blk, nblk, off, ino) == -1) 763207141Sjeff return (-1); 764207141Sjeff } else { 765207141Sjeff blk = 0; 766207141Sjeff if (dir_insert(nblk, 0, ino) == -1) 767207141Sjeff return (-1); 768207141Sjeff } 769207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 770207141Sjeff dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 771207141Sjeff dp1->di_db[lbn] = nblk; 772207141Sjeff dp1->di_size = lblktosize(&sblock, lbn+1); 773207141Sjeff } else { 774207141Sjeff dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 775207141Sjeff dp2->di_db[lbn] = nblk; 776207141Sjeff dp2->di_size = lblktosize(&sblock, lbn+1); 777207141Sjeff } 778207141Sjeff if (putino(&disk) < 0) { 779207141Sjeff warn("Failed to write root inode"); 780207141Sjeff return (-1); 781207141Sjeff } 782207141Sjeff if (cgwrite(&disk) < 0) { 783207141Sjeff warn("Failed to write updated cg"); 784207141Sjeff sbdirty(); 785207141Sjeff return (-1); 786207141Sjeff } 787207141Sjeff if (blk) { 788207141Sjeff if (cgbfree(&disk, blk, size) < 0) { 789207141Sjeff warn("Failed to write cg"); 790207141Sjeff return (-1); 791207141Sjeff } 792207141Sjeff } 793207141Sjeff 794207141Sjeff return (0); 795207141Sjeff} 796207141Sjeff 797207141Sjeffstatic int 798207141Sjeffindir_fill(ufs2_daddr_t blk, int level, int *resid) 799207141Sjeff{ 800207141Sjeff char indirbuf[MAXBSIZE]; 801207141Sjeff ufs1_daddr_t *bap1; 802207141Sjeff ufs2_daddr_t *bap2; 803207141Sjeff ufs2_daddr_t nblk; 804207141Sjeff int ncnt; 805207141Sjeff int cnt; 806207141Sjeff int i; 807207141Sjeff 808207141Sjeff bzero(indirbuf, sizeof(indirbuf)); 809207141Sjeff bap1 = (ufs1_daddr_t *)indirbuf; 810207141Sjeff bap2 = (void *)bap1; 811207141Sjeff cnt = 0; 812207141Sjeff for (i = 0; i < NINDIR(&sblock) && *resid != 0; i++) { 813207141Sjeff nblk = journal_balloc(); 814207141Sjeff if (nblk <= 0) 815207141Sjeff return (-1); 816207141Sjeff cnt++; 817207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 818207141Sjeff *bap1++ = nblk; 819207141Sjeff else 820207141Sjeff *bap2++ = nblk; 821207141Sjeff if (level != 0) { 822207141Sjeff ncnt = indir_fill(nblk, level - 1, resid); 823207141Sjeff if (ncnt <= 0) 824207141Sjeff return (-1); 825207141Sjeff cnt += ncnt; 826207141Sjeff } else 827207141Sjeff (*resid)--; 828207141Sjeff } 829207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), indirbuf, 830207141Sjeff sblock.fs_bsize) <= 0) { 831207141Sjeff warn("Failed to write indirect"); 832207141Sjeff return (-1); 833207141Sjeff } 834207141Sjeff return (cnt); 835207141Sjeff} 836207141Sjeff 837207141Sjeff/* 838207141Sjeff * Clear the flag bits so the journal can be removed. 839207141Sjeff */ 840207141Sjeffvoid 841207141Sjeffjournal_clear(void) 842207141Sjeff{ 843207141Sjeff struct ufs1_dinode *dp1; 844207141Sjeff struct ufs2_dinode *dp2; 845207141Sjeff ino_t ino; 846207141Sjeff int mode; 847207141Sjeff void *ip; 848207141Sjeff 849207141Sjeff ino = journal_findfile(); 850207141Sjeff if (ino == (ino_t)-1 || ino == 0) { 851207141Sjeff warnx("Journal file does not exist"); 852207141Sjeff return; 853207141Sjeff } 854207141Sjeff printf("Clearing journal flags from inode %d\n", ino); 855207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 856207141Sjeff warn("Failed to get journal inode"); 857207141Sjeff return; 858207141Sjeff } 859207141Sjeff dp2 = ip; 860207141Sjeff dp1 = ip; 861207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 862207141Sjeff dp1->di_flags = 0; 863207141Sjeff else 864207141Sjeff dp2->di_flags = 0; 865207141Sjeff if (putino(&disk) < 0) { 866207141Sjeff warn("Failed to write journal inode"); 867207141Sjeff return; 868207141Sjeff } 869207141Sjeff} 870207141Sjeff 871207141Sjeffint 872207141Sjeffjournal_alloc(int64_t size) 873207141Sjeff{ 874207141Sjeff struct ufs1_dinode *dp1; 875207141Sjeff struct ufs2_dinode *dp2; 876207141Sjeff ufs2_daddr_t blk; 877207141Sjeff void *ip; 878207141Sjeff struct cg *cgp; 879207141Sjeff int resid; 880207141Sjeff ino_t ino; 881207141Sjeff int blks; 882207141Sjeff int mode; 883207141Sjeff int i; 884207141Sjeff 885207141Sjeff cgp = &disk.d_cg; 886207141Sjeff ino = 0; 887207141Sjeff 888207141Sjeff /* 889207141Sjeff * If the journal file exists we can't allocate it. 890207141Sjeff */ 891207141Sjeff ino = journal_findfile(); 892207141Sjeff if (ino == (ino_t)-1) 893207141Sjeff return (-1); 894207141Sjeff if (ino > 0) { 895207141Sjeff warnx("Journal file %s already exists, please remove.", 896207141Sjeff SUJ_FILE); 897207141Sjeff return (-1); 898207141Sjeff } 899207141Sjeff /* 900207141Sjeff * If the user didn't supply a size pick one based on the filesystem 901207141Sjeff * size constrained with hardcoded MIN and MAX values. We opt for 902207141Sjeff * 1/1024th of the filesystem up to MAX but not exceeding one CG and 903207141Sjeff * not less than the MIN. 904207141Sjeff */ 905207141Sjeff if (size == 0) { 906207141Sjeff size = (sblock.fs_size * sblock.fs_bsize) / 1024; 907207141Sjeff size = MIN(SUJ_MAX, size); 908207141Sjeff if (size / sblock.fs_fsize > sblock.fs_fpg) 909207141Sjeff size = sblock.fs_fpg * sblock.fs_fsize; 910207141Sjeff size = MAX(SUJ_MIN, size); 911208241Sjeff /* fsck does not support fragments in journal files. */ 912208241Sjeff size = roundup(size, sblock.fs_bsize); 913207141Sjeff } 914207141Sjeff resid = blocks = size / sblock.fs_bsize; 915207141Sjeff if (sblock.fs_cstotal.cs_nbfree < blocks) { 916207141Sjeff warn("Insufficient free space for %jd byte journal", size); 917207141Sjeff return (-1); 918207141Sjeff } 919207141Sjeff /* 920207141Sjeff * Find a cg with enough blocks to satisfy the journal 921207141Sjeff * size. Presently the journal does not span cgs. 922207141Sjeff */ 923207141Sjeff while (cgread(&disk) == 1) { 924207141Sjeff if (cgp->cg_cs.cs_nifree == 0) 925207141Sjeff continue; 926207141Sjeff ino = cgialloc(&disk); 927207141Sjeff if (ino <= 0) 928207141Sjeff break; 929207141Sjeff printf("Using inode %d in cg %d for %jd byte journal\n", 930207141Sjeff ino, cgp->cg_cgx, size); 931207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 932207141Sjeff warn("Failed to get allocated inode"); 933207141Sjeff sbdirty(); 934207141Sjeff goto out; 935207141Sjeff } 936207141Sjeff /* 937207141Sjeff * We leave fields unrelated to the number of allocated 938207141Sjeff * blocks and size uninitialized. This causes legacy 939207141Sjeff * fsck implementations to clear the inode. 940207141Sjeff */ 941207141Sjeff dp2 = ip; 942207141Sjeff dp1 = ip; 943207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 944207141Sjeff bzero(dp1, sizeof(*dp1)); 945207141Sjeff dp1->di_size = size; 946207141Sjeff dp1->di_mode = IFREG | IREAD; 947207141Sjeff dp1->di_nlink = 1; 948207141Sjeff dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 949207141Sjeff } else { 950207141Sjeff bzero(dp2, sizeof(*dp2)); 951207141Sjeff dp2->di_size = size; 952207141Sjeff dp2->di_mode = IFREG | IREAD; 953207141Sjeff dp2->di_nlink = 1; 954207141Sjeff dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 955207141Sjeff } 956207141Sjeff for (i = 0; i < NDADDR && resid; i++, resid--) { 957207141Sjeff blk = journal_balloc(); 958207141Sjeff if (blk <= 0) 959207141Sjeff goto out; 960207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 961207141Sjeff dp1->di_db[i] = blk; 962207141Sjeff dp1->di_blocks++; 963207141Sjeff } else { 964207141Sjeff dp2->di_db[i] = blk; 965207141Sjeff dp2->di_blocks++; 966207141Sjeff } 967207141Sjeff } 968207141Sjeff for (i = 0; i < NIADDR && resid; i++) { 969207141Sjeff blk = journal_balloc(); 970207141Sjeff if (blk <= 0) 971207141Sjeff goto out; 972207141Sjeff blks = indir_fill(blk, i, &resid) + 1; 973207141Sjeff if (blks <= 0) { 974207141Sjeff sbdirty(); 975207141Sjeff goto out; 976207141Sjeff } 977207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 978207141Sjeff dp1->di_ib[i] = blk; 979207141Sjeff dp1->di_blocks += blks; 980207141Sjeff } else { 981207141Sjeff dp2->di_ib[i] = blk; 982207141Sjeff dp2->di_blocks += blks; 983207141Sjeff } 984207141Sjeff } 985207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 986207141Sjeff dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize; 987207141Sjeff else 988207141Sjeff dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize; 989207141Sjeff if (putino(&disk) < 0) { 990207141Sjeff warn("Failed to write inode"); 991207141Sjeff sbdirty(); 992207141Sjeff return (-1); 993207141Sjeff } 994207141Sjeff if (cgwrite(&disk) < 0) { 995207141Sjeff warn("Failed to write updated cg"); 996207141Sjeff sbdirty(); 997207141Sjeff return (-1); 998207141Sjeff } 999207141Sjeff if (journal_insertfile(ino) < 0) { 1000207141Sjeff sbdirty(); 1001207141Sjeff return (-1); 1002207141Sjeff } 1003207141Sjeff sblock.fs_sujfree = 0; 1004207141Sjeff return (0); 1005207141Sjeff } 1006207141Sjeff warnx("Insufficient free space for the journal."); 1007207141Sjeffout: 1008207141Sjeff return (-1); 1009207141Sjeff} 1010207141Sjeff 1011207141Sjeffvoid 1012109597Sjmallettusage(void) 10131558Srgrimes{ 1014207462Sedwin fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n", 1015111287Sru"usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]", 1016207462Sedwin" [-J enable | disable] [-j enable | disable]", 1017207462Sedwin" [-L volname] [-l enable | disable] [-m minfree]", 1018207462Sedwin" [-N enable | disable] [-n enable | disable]", 1019200796Strasz" [-o space | time] [-p] [-s avgfpdir] special | filesystem"); 10201558Srgrimes exit(2); 10211558Srgrimes} 10221558Srgrimes 10231558Srgrimesvoid 1024109597Sjmallettprintfs(void) 10251558Srgrimes{ 1026200796Strasz warnx("POSIX.1e ACLs: (-a) %s", 1027105162Srwatson (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled"); 1028200796Strasz warnx("NFSv4 ACLs: (-N) %s", 1029200796Strasz (sblock.fs_flags & FS_NFS4ACLS)? "enabled" : "disabled"); 1030105162Srwatson warnx("MAC multilabel: (-l) %s", 1031105162Srwatson (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled"); 1032109468Sjmallett warnx("soft updates: (-n) %s", 103334266Sjulian (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); 1034207141Sjeff warnx("soft update journaling: (-j) %s", 1035207141Sjeff (sblock.fs_flags & FS_SUJ)? "enabled" : "disabled"); 1036163842Spjd warnx("gjournal: (-J) %s", 1037163842Spjd (sblock.fs_flags & FS_GJOURNAL)? "enabled" : "disabled"); 10389315Sjoerg warnx("maximum blocks per file in a cylinder group: (-e) %d", 10399315Sjoerg sblock.fs_maxbpg); 104075377Smckusick warnx("average file size: (-f) %d", 104175377Smckusick sblock.fs_avgfilesize); 104275377Smckusick warnx("average number of files in a directory: (-s) %d", 104375377Smckusick sblock.fs_avgfpdir); 10449315Sjoerg warnx("minimum percentage of free space: (-m) %d%%", 10459315Sjoerg sblock.fs_minfree); 10469315Sjoerg warnx("optimization preference: (-o) %s", 10479315Sjoerg sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); 10489315Sjoerg if (sblock.fs_minfree >= MINFREE && 10499315Sjoerg sblock.fs_optim == FS_OPTSPACE) 10509315Sjoerg warnx(OPTWARN, "time", ">=", MINFREE); 10519315Sjoerg if (sblock.fs_minfree < MINFREE && 10529315Sjoerg sblock.fs_optim == FS_OPTTIME) 10539315Sjoerg warnx(OPTWARN, "space", "<", MINFREE); 1054110174Sgordon warnx("volume label: (-L) %s", 1055110174Sgordon sblock.fs_volname); 10569315Sjoerg} 1057