tunefs.c revision 227081
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 227081 2011-11-04 13:36:02Z ed $"); 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> 67226266Smckusick#include <time.h> 681558Srgrimes#include <unistd.h> 691558Srgrimes 701558Srgrimes/* the optimization warning string template */ 711558Srgrimes#define OPTWARN "should optimize for %s with minfree %s %d%%" 721558Srgrimes 73227081Sedstatic struct uufsd disk; 74109597Sjmallett#define sblock disk.d_fs 751558Srgrimes 7692883Simpvoid usage(void); 7792883Simpvoid printfs(void); 78207141Sjeffint journal_alloc(int64_t size); 79207141Sjeffvoid journal_clear(void); 80207141Sjeffvoid sbdirty(void); 811558Srgrimes 821558Srgrimesint 83109597Sjmallettmain(int argc, char *argv[]) 841558Srgrimes{ 85207141Sjeff char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue; 86216798Skib char *tvalue; 87109963Sjmallett const char *special, *on; 8879750Sdd const char *name; 89127455Sbde int active; 90207141Sjeff int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, Lflag; 91207141Sjeff int lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue, pflag, sflag; 92216798Skib int tflag; 93207141Sjeff int svalue, Sflag, Svalue; 94127441Sbde int ch, found_arg, i; 9579750Sdd const char *chg[2]; 9642873Sluoqi struct ufs_args args; 9742873Sluoqi struct statfs stfs; 981558Srgrimes 99127441Sbde if (argc < 3) 100127441Sbde usage(); 101207141Sjeff Aflag = aflag = eflag = fflag = jflag = Jflag = Lflag = lflag = 0; 102216798Skib mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0; 103207141Sjeff avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL; 104207141Sjeff evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0; 105127455Sbde active = 0; 106127441Sbde found_arg = 0; /* At least one arg is required. */ 107216798Skib while ((ch = getopt(argc, argv, "Aa:e:f:j:J:L:l:m:N:n:o:ps:S:t:")) 108216798Skib != -1) 109127441Sbde switch (ch) { 110127441Sbde 111127441Sbde case 'A': 112127441Sbde found_arg = 1; 113127441Sbde Aflag++; 114127441Sbde break; 115127441Sbde 116127441Sbde case 'a': 117127441Sbde found_arg = 1; 118200796Strasz name = "POSIX.1e ACLs"; 119127441Sbde avalue = optarg; 120127441Sbde if (strcmp(avalue, "enable") && 121127441Sbde strcmp(avalue, "disable")) { 122127441Sbde errx(10, "bad %s (options are %s)", 123127441Sbde name, "`enable' or `disable'"); 124127441Sbde } 125127441Sbde aflag = 1; 126127441Sbde break; 127127441Sbde 128127441Sbde case 'e': 129127441Sbde found_arg = 1; 130127441Sbde name = "maximum blocks per file in a cylinder group"; 131127441Sbde evalue = atoi(optarg); 132127441Sbde if (evalue < 1) 133127441Sbde errx(10, "%s must be >= 1 (was %s)", 134127441Sbde name, optarg); 135127441Sbde eflag = 1; 136127441Sbde break; 137127441Sbde 138127441Sbde case 'f': 139127441Sbde found_arg = 1; 140127441Sbde name = "average file size"; 141127441Sbde fvalue = atoi(optarg); 142127441Sbde if (fvalue < 1) 143127441Sbde errx(10, "%s must be >= 1 (was %s)", 144127441Sbde name, optarg); 145127441Sbde fflag = 1; 146127441Sbde break; 147127441Sbde 148207141Sjeff case 'j': 149207141Sjeff found_arg = 1; 150207141Sjeff name = "softdep journaled file system"; 151207141Sjeff jvalue = optarg; 152207141Sjeff if (strcmp(jvalue, "enable") && 153207141Sjeff strcmp(jvalue, "disable")) { 154207141Sjeff errx(10, "bad %s (options are %s)", 155207141Sjeff name, "`enable' or `disable'"); 156207141Sjeff } 157207141Sjeff jflag = 1; 158207141Sjeff break; 159207141Sjeff 160163842Spjd case 'J': 161163842Spjd found_arg = 1; 162163842Spjd name = "gjournaled file system"; 163163842Spjd Jvalue = optarg; 164163842Spjd if (strcmp(Jvalue, "enable") && 165163842Spjd strcmp(Jvalue, "disable")) { 166163842Spjd errx(10, "bad %s (options are %s)", 167163842Spjd name, "`enable' or `disable'"); 168163842Spjd } 169163842Spjd Jflag = 1; 170163842Spjd break; 171163842Spjd 172163842Spjd 173127441Sbde case 'L': 174127441Sbde found_arg = 1; 175127441Sbde name = "volume label"; 176127441Sbde Lvalue = optarg; 177127441Sbde i = -1; 178127441Sbde while (isalnum(Lvalue[++i])); 179127441Sbde if (Lvalue[i] != '\0') { 180127441Sbde errx(10, 181127441Sbde "bad %s. Valid characters are alphanumerics.", 182127441Sbde name); 183127441Sbde } 184127441Sbde if (strlen(Lvalue) >= MAXVOLLEN) { 185127441Sbde errx(10, "bad %s. Length is longer than %d.", 186127441Sbde name, MAXVOLLEN - 1); 187127441Sbde } 188127441Sbde Lflag = 1; 189127441Sbde break; 190127441Sbde 191127441Sbde case 'l': 192127441Sbde found_arg = 1; 193127441Sbde name = "multilabel MAC file system"; 194127441Sbde lvalue = optarg; 195127441Sbde if (strcmp(lvalue, "enable") && 196127441Sbde strcmp(lvalue, "disable")) { 197127441Sbde errx(10, "bad %s (options are %s)", 198127441Sbde name, "`enable' or `disable'"); 199127441Sbde } 200127441Sbde lflag = 1; 201127441Sbde break; 202127441Sbde 203127441Sbde case 'm': 204127441Sbde found_arg = 1; 205127441Sbde name = "minimum percentage of free space"; 206127441Sbde mvalue = atoi(optarg); 207127441Sbde if (mvalue < 0 || mvalue > 99) 208127441Sbde errx(10, "bad %s (%s)", name, optarg); 209127441Sbde mflag = 1; 210127441Sbde break; 211127441Sbde 212200796Strasz case 'N': 213200796Strasz found_arg = 1; 214200796Strasz name = "NFSv4 ACLs"; 215200796Strasz Nvalue = optarg; 216200796Strasz if (strcmp(Nvalue, "enable") && 217200796Strasz strcmp(Nvalue, "disable")) { 218200796Strasz errx(10, "bad %s (options are %s)", 219200796Strasz name, "`enable' or `disable'"); 220200796Strasz } 221200796Strasz Nflag = 1; 222200796Strasz break; 223200796Strasz 224127441Sbde case 'n': 225127441Sbde found_arg = 1; 226127441Sbde name = "soft updates"; 227127441Sbde nvalue = optarg; 228127455Sbde if (strcmp(nvalue, "enable") != 0 && 229127455Sbde strcmp(nvalue, "disable") != 0) { 230127441Sbde errx(10, "bad %s (options are %s)", 231127441Sbde name, "`enable' or `disable'"); 232127441Sbde } 233127441Sbde nflag = 1; 234127441Sbde break; 235127441Sbde 236127441Sbde case 'o': 237127441Sbde found_arg = 1; 238127441Sbde name = "optimization preference"; 239127455Sbde if (strcmp(optarg, "space") == 0) 240127441Sbde ovalue = FS_OPTSPACE; 241127455Sbde else if (strcmp(optarg, "time") == 0) 242127441Sbde ovalue = FS_OPTTIME; 243127441Sbde else 244127441Sbde errx(10, 245127441Sbde "bad %s (options are `space' or `time')", 246127441Sbde name); 247127441Sbde oflag = 1; 248127441Sbde break; 249127441Sbde 250127441Sbde case 'p': 251127441Sbde found_arg = 1; 252127441Sbde pflag = 1; 253127441Sbde break; 254127441Sbde 255127441Sbde case 's': 256127441Sbde found_arg = 1; 257127441Sbde name = "expected number of files per directory"; 258127441Sbde svalue = atoi(optarg); 259127441Sbde if (svalue < 1) 260127441Sbde errx(10, "%s must be >= 1 (was %s)", 261127441Sbde name, optarg); 262127441Sbde sflag = 1; 263127441Sbde break; 264127441Sbde 265207141Sjeff case 'S': 266207141Sjeff found_arg = 1; 267207141Sjeff name = "Softdep Journal Size"; 268207141Sjeff Svalue = atoi(optarg); 269207141Sjeff if (Svalue < SUJ_MIN) 270207141Sjeff errx(10, "%s must be >= %d (was %s)", 271207141Sjeff name, SUJ_MIN, optarg); 272207141Sjeff Sflag = 1; 273207141Sjeff break; 274207141Sjeff 275216798Skib case 't': 276216798Skib found_arg = 1; 277216798Skib name = "trim"; 278216798Skib tvalue = optarg; 279216798Skib if (strcmp(tvalue, "enable") != 0 && 280216798Skib strcmp(tvalue, "disable") != 0) { 281216798Skib errx(10, "bad %s (options are %s)", 282216798Skib name, "`enable' or `disable'"); 283216798Skib } 284216798Skib tflag = 1; 285216798Skib break; 286216798Skib 287127441Sbde default: 288127441Sbde usage(); 289105120Srwatson } 29069314Scharnier argc -= optind; 29169314Scharnier argv += optind; 29269314Scharnier if (found_arg == 0 || argc != 1) 293127441Sbde usage(); 29469314Scharnier 295109963Sjmallett on = special = argv[0]; 296109963Sjmallett if (ufs_disk_fillout(&disk, special) == -1) 297109963Sjmallett goto err; 298109963Sjmallett if (disk.d_name != special) { 299207421Sjeff if (statfs(special, &stfs) != 0) 300207421Sjeff warn("Can't stat %s", special); 301207421Sjeff if (strcmp(special, stfs.f_mntonname) == 0) 30269829Scharnier active = 1; 30369829Scharnier } 30469829Scharnier 30569829Scharnier if (pflag) { 30669829Scharnier printfs(); 30769829Scharnier exit(0); 30869829Scharnier } 309110174Sgordon if (Lflag) { 310110174Sgordon name = "volume label"; 311110174Sgordon strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN); 312110174Sgordon } 313105120Srwatson if (aflag) { 314200796Strasz name = "POSIX.1e ACLs"; 315105120Srwatson if (strcmp(avalue, "enable") == 0) { 316105120Srwatson if (sblock.fs_flags & FS_ACLS) { 317105120Srwatson warnx("%s remains unchanged as enabled", name); 318200796Strasz } else if (sblock.fs_flags & FS_NFS4ACLS) { 319200796Strasz warnx("%s and NFSv4 ACLs are mutually " 320200796Strasz "exclusive", name); 321105120Srwatson } else { 322105120Srwatson sblock.fs_flags |= FS_ACLS; 323105120Srwatson warnx("%s set", name); 324105120Srwatson } 325105120Srwatson } else if (strcmp(avalue, "disable") == 0) { 326105120Srwatson if ((~sblock.fs_flags & FS_ACLS) == 327105120Srwatson FS_ACLS) { 328105120Srwatson warnx("%s remains unchanged as disabled", 329105120Srwatson name); 330105120Srwatson } else { 331105120Srwatson sblock.fs_flags &= ~FS_ACLS; 332105206Srwatson warnx("%s cleared", name); 333105120Srwatson } 334105120Srwatson } 335105120Srwatson } 33669829Scharnier if (eflag) { 33769829Scharnier name = "maximum blocks per file in a cylinder group"; 338127455Sbde if (sblock.fs_maxbpg == evalue) 33969829Scharnier warnx("%s remains unchanged as %d", name, evalue); 34069829Scharnier else { 34169829Scharnier warnx("%s changes from %d to %d", 342127455Sbde name, sblock.fs_maxbpg, evalue); 34369829Scharnier sblock.fs_maxbpg = evalue; 34469829Scharnier } 34569829Scharnier } 34675377Smckusick if (fflag) { 34775377Smckusick name = "average file size"; 348203769Smckusick if (sblock.fs_avgfilesize == (unsigned)fvalue) { 34975377Smckusick warnx("%s remains unchanged as %d", name, fvalue); 35075377Smckusick } 35175377Smckusick else { 35275377Smckusick warnx("%s changes from %d to %d", 35375377Smckusick name, sblock.fs_avgfilesize, fvalue); 35475377Smckusick sblock.fs_avgfilesize = fvalue; 35575377Smckusick } 35675377Smckusick } 357207141Sjeff if (jflag) { 358207141Sjeff name = "soft updates journaling"; 359207141Sjeff if (strcmp(jvalue, "enable") == 0) { 360207141Sjeff if ((sblock.fs_flags & (FS_DOSOFTDEP | FS_SUJ)) == 361207141Sjeff (FS_DOSOFTDEP | FS_SUJ)) { 362207141Sjeff warnx("%s remains unchanged as enabled", name); 363207141Sjeff } else if (sblock.fs_clean == 0) { 364207141Sjeff warnx("%s cannot be enabled until fsck is run", 365207141Sjeff name); 366207141Sjeff } else if (journal_alloc(Svalue) != 0) { 367207141Sjeff warnx("%s can not be enabled", name); 368207141Sjeff } else { 369207141Sjeff sblock.fs_flags |= FS_DOSOFTDEP | FS_SUJ; 370207141Sjeff warnx("%s set", name); 371207141Sjeff } 372207141Sjeff } else if (strcmp(jvalue, "disable") == 0) { 373207141Sjeff if ((~sblock.fs_flags & FS_SUJ) == FS_SUJ) { 374207141Sjeff warnx("%s remains unchanged as disabled", name); 375207141Sjeff } else { 376207141Sjeff journal_clear(); 377208241Sjeff sblock.fs_flags &= ~FS_SUJ; 378207141Sjeff sblock.fs_sujfree = 0; 379208241Sjeff warnx("%s cleared but soft updates still set.", 380208241Sjeff name); 381208241Sjeff 382208241Sjeff warnx("remove .sujournal to reclaim space"); 383207141Sjeff } 384207141Sjeff } 385207141Sjeff } 386163842Spjd if (Jflag) { 387163842Spjd name = "gjournal"; 388163842Spjd if (strcmp(Jvalue, "enable") == 0) { 389163842Spjd if (sblock.fs_flags & FS_GJOURNAL) { 390163842Spjd warnx("%s remains unchanged as enabled", name); 391163842Spjd } else { 392163842Spjd sblock.fs_flags |= FS_GJOURNAL; 393163842Spjd warnx("%s set", name); 394163842Spjd } 395163842Spjd } else if (strcmp(Jvalue, "disable") == 0) { 396163842Spjd if ((~sblock.fs_flags & FS_GJOURNAL) == 397163842Spjd FS_GJOURNAL) { 398163842Spjd warnx("%s remains unchanged as disabled", 399163842Spjd name); 400163842Spjd } else { 401163842Spjd sblock.fs_flags &= ~FS_GJOURNAL; 402163842Spjd warnx("%s cleared", name); 403163842Spjd } 404163842Spjd } 405163842Spjd } 406105120Srwatson if (lflag) { 407105120Srwatson name = "multilabel"; 408105120Srwatson if (strcmp(lvalue, "enable") == 0) { 409105120Srwatson if (sblock.fs_flags & FS_MULTILABEL) { 410105120Srwatson warnx("%s remains unchanged as enabled", name); 411105120Srwatson } else { 412105120Srwatson sblock.fs_flags |= FS_MULTILABEL; 413105120Srwatson warnx("%s set", name); 414105120Srwatson } 415105120Srwatson } else if (strcmp(lvalue, "disable") == 0) { 416105120Srwatson if ((~sblock.fs_flags & FS_MULTILABEL) == 417105120Srwatson FS_MULTILABEL) { 418105120Srwatson warnx("%s remains unchanged as disabled", 419105120Srwatson name); 420105120Srwatson } else { 421105120Srwatson sblock.fs_flags &= ~FS_MULTILABEL; 422105206Srwatson warnx("%s cleared", name); 423105120Srwatson } 424105120Srwatson } 425105120Srwatson } 42669829Scharnier if (mflag) { 42769829Scharnier name = "minimum percentage of free space"; 428127455Sbde if (sblock.fs_minfree == mvalue) 42969829Scharnier warnx("%s remains unchanged as %d%%", name, mvalue); 43069829Scharnier else { 43169829Scharnier warnx("%s changes from %d%% to %d%%", 43269829Scharnier name, sblock.fs_minfree, mvalue); 43369829Scharnier sblock.fs_minfree = mvalue; 43469829Scharnier if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE) 43569829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 43669829Scharnier if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME) 43769829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 43869829Scharnier } 43969829Scharnier } 440200796Strasz if (Nflag) { 441200796Strasz name = "NFSv4 ACLs"; 442200796Strasz if (strcmp(Nvalue, "enable") == 0) { 443200796Strasz if (sblock.fs_flags & FS_NFS4ACLS) { 444200796Strasz warnx("%s remains unchanged as enabled", name); 445200796Strasz } else if (sblock.fs_flags & FS_ACLS) { 446200796Strasz warnx("%s and POSIX.1e ACLs are mutually " 447200796Strasz "exclusive", name); 448200796Strasz } else { 449200796Strasz sblock.fs_flags |= FS_NFS4ACLS; 450200796Strasz warnx("%s set", name); 451200796Strasz } 452200796Strasz } else if (strcmp(Nvalue, "disable") == 0) { 453200796Strasz if ((~sblock.fs_flags & FS_NFS4ACLS) == 454200796Strasz FS_NFS4ACLS) { 455200796Strasz warnx("%s remains unchanged as disabled", 456200796Strasz name); 457200796Strasz } else { 458200796Strasz sblock.fs_flags &= ~FS_NFS4ACLS; 459200796Strasz warnx("%s cleared", name); 460200796Strasz } 461200796Strasz } 462200796Strasz } 46369829Scharnier if (nflag) { 46469829Scharnier name = "soft updates"; 46569829Scharnier if (strcmp(nvalue, "enable") == 0) { 466127455Sbde if (sblock.fs_flags & FS_DOSOFTDEP) 46769829Scharnier warnx("%s remains unchanged as enabled", name); 468127455Sbde else if (sblock.fs_clean == 0) { 46975498Smckusick warnx("%s cannot be enabled until fsck is run", 47075498Smckusick name); 47169829Scharnier } else { 47269829Scharnier sblock.fs_flags |= FS_DOSOFTDEP; 47369829Scharnier warnx("%s set", name); 47469829Scharnier } 47569829Scharnier } else if (strcmp(nvalue, "disable") == 0) { 476127455Sbde if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) 47769829Scharnier warnx("%s remains unchanged as disabled", name); 478127455Sbde else { 47969829Scharnier sblock.fs_flags &= ~FS_DOSOFTDEP; 48069829Scharnier warnx("%s cleared", name); 48169829Scharnier } 48269829Scharnier } 48369829Scharnier } 48469829Scharnier if (oflag) { 48569829Scharnier name = "optimization preference"; 48669829Scharnier chg[FS_OPTSPACE] = "space"; 48769829Scharnier chg[FS_OPTTIME] = "time"; 488127455Sbde if (sblock.fs_optim == ovalue) 48969829Scharnier warnx("%s remains unchanged as %s", name, chg[ovalue]); 49069829Scharnier else { 49169829Scharnier warnx("%s changes from %s to %s", 49269829Scharnier name, chg[sblock.fs_optim], chg[ovalue]); 49369829Scharnier sblock.fs_optim = ovalue; 49469829Scharnier if (sblock.fs_minfree >= MINFREE && 495127455Sbde ovalue == FS_OPTSPACE) 49669829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 497127455Sbde if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME) 49869829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 49969829Scharnier } 50069829Scharnier } 50175377Smckusick if (sflag) { 50275377Smckusick name = "expected number of files per directory"; 503203769Smckusick if (sblock.fs_avgfpdir == (unsigned)svalue) { 50475377Smckusick warnx("%s remains unchanged as %d", name, svalue); 50575377Smckusick } 50675377Smckusick else { 50775377Smckusick warnx("%s changes from %d to %d", 50875377Smckusick name, sblock.fs_avgfpdir, svalue); 50975377Smckusick sblock.fs_avgfpdir = svalue; 51075377Smckusick } 51175377Smckusick } 512216798Skib if (tflag) { 513216798Skib name = "issue TRIM to the disk"; 514216798Skib if (strcmp(tvalue, "enable") == 0) { 515216798Skib if (sblock.fs_flags & FS_TRIM) 516216798Skib warnx("%s remains unchanged as enabled", name); 517216798Skib else { 518216798Skib sblock.fs_flags |= FS_TRIM; 519216798Skib warnx("%s set", name); 520216798Skib } 521216798Skib } else if (strcmp(tvalue, "disable") == 0) { 522216798Skib if ((~sblock.fs_flags & FS_TRIM) == FS_TRIM) 523216798Skib warnx("%s remains unchanged as disabled", name); 524216798Skib else { 525216798Skib sblock.fs_flags &= ~FS_TRIM; 526216798Skib warnx("%s cleared", name); 527216798Skib } 528216798Skib } 529216798Skib } 53069829Scharnier 531109963Sjmallett if (sbwrite(&disk, Aflag) == -1) 532109963Sjmallett goto err; 533109963Sjmallett ufs_disk_close(&disk); 53442873Sluoqi if (active) { 53542873Sluoqi bzero(&args, sizeof(args)); 536109963Sjmallett if (mount("ufs", on, 53742873Sluoqi stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) 53842873Sluoqi err(9, "%s: reload", special); 539102231Strhodes warnx("file system reloaded"); 54042873Sluoqi } 5411558Srgrimes exit(0); 542109963Sjmalletterr: 543109963Sjmallett if (disk.d_error != NULL) 544109963Sjmallett errx(11, "%s: %s", special, disk.d_error); 545109963Sjmallett else 546109963Sjmallett err(12, "%s", special); 5471558Srgrimes} 5481558Srgrimes 5491558Srgrimesvoid 550207141Sjeffsbdirty(void) 551207141Sjeff{ 552207141Sjeff disk.d_fs.fs_flags |= FS_UNCLEAN | FS_NEEDSFSCK; 553207141Sjeff disk.d_fs.fs_clean = 0; 554207141Sjeff} 555207141Sjeff 556227081Sedstatic int blocks; 557207141Sjeffstatic char clrbuf[MAXBSIZE]; 558207141Sjeff 559207141Sjeffstatic ufs2_daddr_t 560207141Sjeffjournal_balloc(void) 561207141Sjeff{ 562207141Sjeff ufs2_daddr_t blk; 563207141Sjeff struct cg *cgp; 564207141Sjeff int valid; 565207141Sjeff static int contig = 1; 566207141Sjeff 567207141Sjeff cgp = &disk.d_cg; 568207141Sjeff for (;;) { 569207141Sjeff blk = cgballoc(&disk); 570207141Sjeff if (blk > 0) 571207141Sjeff break; 572207141Sjeff /* 573207141Sjeff * If we failed to allocate a block from this cg, move to 574207141Sjeff * the next. 575207141Sjeff */ 576207141Sjeff if (cgwrite(&disk) < 0) { 577207141Sjeff warn("Failed to write updated cg"); 578207141Sjeff return (-1); 579207141Sjeff } 580207141Sjeff while ((valid = cgread(&disk)) == 1) { 581207141Sjeff /* 582207141Sjeff * Try to minimize fragmentation by requiring a minimum 583207141Sjeff * number of blocks present. 584207141Sjeff */ 585208241Sjeff if (cgp->cg_cs.cs_nbfree > 256 * 1024) 586207141Sjeff break; 587207141Sjeff if (contig == 0 && cgp->cg_cs.cs_nbfree) 588207141Sjeff break; 589207141Sjeff } 590207141Sjeff if (valid) 591207141Sjeff continue; 592207141Sjeff /* 593207141Sjeff * Try once through looking only for large contiguous regions 594207141Sjeff * and again taking any space we can find. 595207141Sjeff */ 596207141Sjeff if (contig) { 597207141Sjeff contig = 0; 598207141Sjeff disk.d_ccg = 0; 599207141Sjeff warnx("Journal file fragmented."); 600207141Sjeff continue; 601207141Sjeff } 602207141Sjeff warnx("Failed to find sufficient free blocks for the journal"); 603207141Sjeff return -1; 604207141Sjeff } 605207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), clrbuf, 606207141Sjeff sblock.fs_bsize) <= 0) { 607207141Sjeff warn("Failed to initialize new block"); 608207141Sjeff return -1; 609207141Sjeff } 610207141Sjeff return (blk); 611207141Sjeff} 612207141Sjeff 613207141Sjeff/* 614207141Sjeff * Search a directory block for the SUJ_FILE. 615207141Sjeff */ 616207141Sjeffstatic ino_t 617207141Sjeffdir_search(ufs2_daddr_t blk, int bytes) 618207141Sjeff{ 619207141Sjeff char block[MAXBSIZE]; 620207141Sjeff struct direct *dp; 621207141Sjeff int off; 622207141Sjeff 623207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, bytes) <= 0) { 624207141Sjeff warn("Failed to read dir block"); 625207141Sjeff return (-1); 626207141Sjeff } 627207141Sjeff for (off = 0; off < bytes; off += dp->d_reclen) { 628207141Sjeff dp = (struct direct *)&block[off]; 629207141Sjeff if (dp->d_reclen == 0) 630207141Sjeff break; 631207141Sjeff if (dp->d_ino == 0) 632207141Sjeff continue; 633207141Sjeff if (dp->d_namlen != strlen(SUJ_FILE)) 634207141Sjeff continue; 635207141Sjeff if (bcmp(dp->d_name, SUJ_FILE, dp->d_namlen) != 0) 636207141Sjeff continue; 637207141Sjeff return (dp->d_ino); 638207141Sjeff } 639207141Sjeff 640207141Sjeff return (0); 641207141Sjeff} 642207141Sjeff 643207141Sjeff/* 644207141Sjeff * Search in the ROOTINO for the SUJ_FILE. If it exists we can not enable 645207141Sjeff * journaling. 646207141Sjeff */ 647207141Sjeffstatic ino_t 648207141Sjeffjournal_findfile(void) 649207141Sjeff{ 650207141Sjeff struct ufs1_dinode *dp1; 651207141Sjeff struct ufs2_dinode *dp2; 652207141Sjeff ino_t ino; 653207141Sjeff int mode; 654207141Sjeff void *ip; 655207141Sjeff int i; 656207141Sjeff 657207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 658207141Sjeff warn("Failed to get root inode"); 659207141Sjeff return (-1); 660207141Sjeff } 661207141Sjeff dp2 = ip; 662207141Sjeff dp1 = ip; 663207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 664207141Sjeff if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { 665207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 666207141Sjeff return (-1); 667207141Sjeff } 668207141Sjeff for (i = 0; i < NDADDR; i++) { 669207141Sjeff if (dp1->di_db[i] == 0) 670207141Sjeff break; 671207141Sjeff if ((ino = dir_search(dp1->di_db[i], 672207141Sjeff sblksize(&sblock, (off_t)dp1->di_size, i))) != 0) 673207141Sjeff return (ino); 674207141Sjeff } 675207141Sjeff } else { 676207141Sjeff if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { 677207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 678207141Sjeff return (-1); 679207141Sjeff } 680207141Sjeff for (i = 0; i < NDADDR; i++) { 681207141Sjeff if (dp2->di_db[i] == 0) 682207141Sjeff break; 683207141Sjeff if ((ino = dir_search(dp2->di_db[i], 684207141Sjeff sblksize(&sblock, (off_t)dp2->di_size, i))) != 0) 685207141Sjeff return (ino); 686207141Sjeff } 687207141Sjeff } 688207141Sjeff 689207141Sjeff return (0); 690207141Sjeff} 691207141Sjeff 692218603Skibstatic void 693218603Skibdir_clear_block(char *block, off_t off) 694218603Skib{ 695218603Skib struct direct *dp; 696218603Skib 697218603Skib for (; off < sblock.fs_bsize; off += DIRBLKSIZ) { 698218603Skib dp = (struct direct *)&block[off]; 699218603Skib dp->d_ino = 0; 700218603Skib dp->d_reclen = DIRBLKSIZ; 701218603Skib dp->d_type = DT_UNKNOWN; 702218603Skib } 703218603Skib} 704218603Skib 705207141Sjeff/* 706207141Sjeff * Insert the journal at inode 'ino' into directory blk 'blk' at the first 707207141Sjeff * free offset of 'off'. DIRBLKSIZ blocks after off are initialized as 708207141Sjeff * empty. 709207141Sjeff */ 710207141Sjeffstatic int 711207141Sjeffdir_insert(ufs2_daddr_t blk, off_t off, ino_t ino) 712207141Sjeff{ 713207141Sjeff struct direct *dp; 714207141Sjeff char block[MAXBSIZE]; 715207141Sjeff 716207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 717207141Sjeff warn("Failed to read dir block"); 718207141Sjeff return (-1); 719207141Sjeff } 720207141Sjeff bzero(&block[off], sblock.fs_bsize - off); 721207141Sjeff dp = (struct direct *)&block[off]; 722207141Sjeff dp->d_ino = ino; 723207141Sjeff dp->d_reclen = DIRBLKSIZ; 724207141Sjeff dp->d_type = DT_REG; 725207141Sjeff dp->d_namlen = strlen(SUJ_FILE); 726207141Sjeff bcopy(SUJ_FILE, &dp->d_name, strlen(SUJ_FILE)); 727218603Skib dir_clear_block(block, off + DIRBLKSIZ); 728207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 729207141Sjeff warn("Failed to write dir block"); 730207141Sjeff return (-1); 731207141Sjeff } 732207141Sjeff return (0); 733207141Sjeff} 734207141Sjeff 735207141Sjeff/* 736207141Sjeff * Extend a directory block in 'blk' by copying it to a full size block 737207141Sjeff * and inserting the new journal inode into .sujournal. 738207141Sjeff */ 739207141Sjeffstatic int 740207141Sjeffdir_extend(ufs2_daddr_t blk, ufs2_daddr_t nblk, off_t size, ino_t ino) 741207141Sjeff{ 742207141Sjeff char block[MAXBSIZE]; 743207141Sjeff 744218603Skib if (bread(&disk, fsbtodb(&sblock, blk), block, 745218603Skib roundup(size, sblock.fs_fsize)) <= 0) { 746207141Sjeff warn("Failed to read dir block"); 747207141Sjeff return (-1); 748207141Sjeff } 749218603Skib dir_clear_block(block, size); 750218603Skib if (bwrite(&disk, fsbtodb(&sblock, nblk), block, sblock.fs_bsize) 751218603Skib <= 0) { 752207141Sjeff warn("Failed to write dir block"); 753207141Sjeff return (-1); 754207141Sjeff } 755207141Sjeff 756218603Skib return (dir_insert(nblk, size, ino)); 757207141Sjeff} 758207141Sjeff 759207141Sjeff/* 760207141Sjeff * Insert the journal file into the ROOTINO directory. We always extend the 761207141Sjeff * last frag 762207141Sjeff */ 763207141Sjeffstatic int 764207141Sjeffjournal_insertfile(ino_t ino) 765207141Sjeff{ 766207141Sjeff struct ufs1_dinode *dp1; 767207141Sjeff struct ufs2_dinode *dp2; 768207141Sjeff void *ip; 769207141Sjeff ufs2_daddr_t nblk; 770207141Sjeff ufs2_daddr_t blk; 771207141Sjeff ufs_lbn_t lbn; 772207141Sjeff int size; 773207141Sjeff int mode; 774207141Sjeff int off; 775207141Sjeff 776207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 777207141Sjeff warn("Failed to get root inode"); 778207141Sjeff sbdirty(); 779207141Sjeff return (-1); 780207141Sjeff } 781207141Sjeff dp2 = ip; 782207141Sjeff dp1 = ip; 783207141Sjeff blk = 0; 784207141Sjeff size = 0; 785207141Sjeff nblk = journal_balloc(); 786207141Sjeff if (nblk <= 0) 787207141Sjeff return (-1); 788207141Sjeff /* 789207141Sjeff * For simplicity sake we aways extend the ROOTINO into a new 790207141Sjeff * directory block rather than searching for space and inserting 791207141Sjeff * into an existing block. However, if the rootino has frags 792207141Sjeff * have to free them and extend the block. 793207141Sjeff */ 794207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 795207141Sjeff lbn = lblkno(&sblock, dp1->di_size); 796207141Sjeff off = blkoff(&sblock, dp1->di_size); 797207141Sjeff blk = dp1->di_db[lbn]; 798207141Sjeff size = sblksize(&sblock, (off_t)dp1->di_size, lbn); 799207141Sjeff } else { 800207141Sjeff lbn = lblkno(&sblock, dp2->di_size); 801207141Sjeff off = blkoff(&sblock, dp2->di_size); 802207141Sjeff blk = dp2->di_db[lbn]; 803207141Sjeff size = sblksize(&sblock, (off_t)dp2->di_size, lbn); 804207141Sjeff } 805207141Sjeff if (off != 0) { 806207141Sjeff if (dir_extend(blk, nblk, off, ino) == -1) 807207141Sjeff return (-1); 808207141Sjeff } else { 809207141Sjeff blk = 0; 810207141Sjeff if (dir_insert(nblk, 0, ino) == -1) 811207141Sjeff return (-1); 812207141Sjeff } 813207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 814207141Sjeff dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 815207141Sjeff dp1->di_db[lbn] = nblk; 816207141Sjeff dp1->di_size = lblktosize(&sblock, lbn+1); 817207141Sjeff } else { 818207141Sjeff dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 819207141Sjeff dp2->di_db[lbn] = nblk; 820207141Sjeff dp2->di_size = lblktosize(&sblock, lbn+1); 821207141Sjeff } 822207141Sjeff if (putino(&disk) < 0) { 823207141Sjeff warn("Failed to write root inode"); 824207141Sjeff return (-1); 825207141Sjeff } 826207141Sjeff if (cgwrite(&disk) < 0) { 827207141Sjeff warn("Failed to write updated cg"); 828207141Sjeff sbdirty(); 829207141Sjeff return (-1); 830207141Sjeff } 831207141Sjeff if (blk) { 832207141Sjeff if (cgbfree(&disk, blk, size) < 0) { 833207141Sjeff warn("Failed to write cg"); 834207141Sjeff return (-1); 835207141Sjeff } 836207141Sjeff } 837207141Sjeff 838207141Sjeff return (0); 839207141Sjeff} 840207141Sjeff 841207141Sjeffstatic int 842207141Sjeffindir_fill(ufs2_daddr_t blk, int level, int *resid) 843207141Sjeff{ 844207141Sjeff char indirbuf[MAXBSIZE]; 845207141Sjeff ufs1_daddr_t *bap1; 846207141Sjeff ufs2_daddr_t *bap2; 847207141Sjeff ufs2_daddr_t nblk; 848207141Sjeff int ncnt; 849207141Sjeff int cnt; 850207141Sjeff int i; 851207141Sjeff 852207141Sjeff bzero(indirbuf, sizeof(indirbuf)); 853207141Sjeff bap1 = (ufs1_daddr_t *)indirbuf; 854207141Sjeff bap2 = (void *)bap1; 855207141Sjeff cnt = 0; 856207141Sjeff for (i = 0; i < NINDIR(&sblock) && *resid != 0; i++) { 857207141Sjeff nblk = journal_balloc(); 858207141Sjeff if (nblk <= 0) 859207141Sjeff return (-1); 860207141Sjeff cnt++; 861207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 862207141Sjeff *bap1++ = nblk; 863207141Sjeff else 864207141Sjeff *bap2++ = nblk; 865207141Sjeff if (level != 0) { 866207141Sjeff ncnt = indir_fill(nblk, level - 1, resid); 867207141Sjeff if (ncnt <= 0) 868207141Sjeff return (-1); 869207141Sjeff cnt += ncnt; 870207141Sjeff } else 871207141Sjeff (*resid)--; 872207141Sjeff } 873207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), indirbuf, 874207141Sjeff sblock.fs_bsize) <= 0) { 875207141Sjeff warn("Failed to write indirect"); 876207141Sjeff return (-1); 877207141Sjeff } 878207141Sjeff return (cnt); 879207141Sjeff} 880207141Sjeff 881207141Sjeff/* 882207141Sjeff * Clear the flag bits so the journal can be removed. 883207141Sjeff */ 884207141Sjeffvoid 885207141Sjeffjournal_clear(void) 886207141Sjeff{ 887207141Sjeff struct ufs1_dinode *dp1; 888207141Sjeff struct ufs2_dinode *dp2; 889207141Sjeff ino_t ino; 890207141Sjeff int mode; 891207141Sjeff void *ip; 892207141Sjeff 893207141Sjeff ino = journal_findfile(); 894207141Sjeff if (ino == (ino_t)-1 || ino == 0) { 895207141Sjeff warnx("Journal file does not exist"); 896207141Sjeff return; 897207141Sjeff } 898207141Sjeff printf("Clearing journal flags from inode %d\n", ino); 899207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 900207141Sjeff warn("Failed to get journal inode"); 901207141Sjeff return; 902207141Sjeff } 903207141Sjeff dp2 = ip; 904207141Sjeff dp1 = ip; 905207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 906207141Sjeff dp1->di_flags = 0; 907207141Sjeff else 908207141Sjeff dp2->di_flags = 0; 909207141Sjeff if (putino(&disk) < 0) { 910207141Sjeff warn("Failed to write journal inode"); 911207141Sjeff return; 912207141Sjeff } 913207141Sjeff} 914207141Sjeff 915207141Sjeffint 916207141Sjeffjournal_alloc(int64_t size) 917207141Sjeff{ 918207141Sjeff struct ufs1_dinode *dp1; 919207141Sjeff struct ufs2_dinode *dp2; 920207141Sjeff ufs2_daddr_t blk; 921207141Sjeff void *ip; 922207141Sjeff struct cg *cgp; 923207141Sjeff int resid; 924207141Sjeff ino_t ino; 925207141Sjeff int blks; 926207141Sjeff int mode; 927226266Smckusick time_t utime; 928207141Sjeff int i; 929207141Sjeff 930207141Sjeff cgp = &disk.d_cg; 931207141Sjeff ino = 0; 932207141Sjeff 933207141Sjeff /* 934207141Sjeff * If the journal file exists we can't allocate it. 935207141Sjeff */ 936207141Sjeff ino = journal_findfile(); 937207141Sjeff if (ino == (ino_t)-1) 938207141Sjeff return (-1); 939207141Sjeff if (ino > 0) { 940207141Sjeff warnx("Journal file %s already exists, please remove.", 941207141Sjeff SUJ_FILE); 942207141Sjeff return (-1); 943207141Sjeff } 944207141Sjeff /* 945207141Sjeff * If the user didn't supply a size pick one based on the filesystem 946207141Sjeff * size constrained with hardcoded MIN and MAX values. We opt for 947207141Sjeff * 1/1024th of the filesystem up to MAX but not exceeding one CG and 948207141Sjeff * not less than the MIN. 949207141Sjeff */ 950207141Sjeff if (size == 0) { 951207141Sjeff size = (sblock.fs_size * sblock.fs_bsize) / 1024; 952207141Sjeff size = MIN(SUJ_MAX, size); 953207141Sjeff if (size / sblock.fs_fsize > sblock.fs_fpg) 954207141Sjeff size = sblock.fs_fpg * sblock.fs_fsize; 955207141Sjeff size = MAX(SUJ_MIN, size); 956208241Sjeff /* fsck does not support fragments in journal files. */ 957208241Sjeff size = roundup(size, sblock.fs_bsize); 958207141Sjeff } 959207141Sjeff resid = blocks = size / sblock.fs_bsize; 960207141Sjeff if (sblock.fs_cstotal.cs_nbfree < blocks) { 961207141Sjeff warn("Insufficient free space for %jd byte journal", size); 962207141Sjeff return (-1); 963207141Sjeff } 964207141Sjeff /* 965207141Sjeff * Find a cg with enough blocks to satisfy the journal 966207141Sjeff * size. Presently the journal does not span cgs. 967207141Sjeff */ 968207141Sjeff while (cgread(&disk) == 1) { 969207141Sjeff if (cgp->cg_cs.cs_nifree == 0) 970207141Sjeff continue; 971207141Sjeff ino = cgialloc(&disk); 972207141Sjeff if (ino <= 0) 973207141Sjeff break; 974207141Sjeff printf("Using inode %d in cg %d for %jd byte journal\n", 975207141Sjeff ino, cgp->cg_cgx, size); 976207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 977207141Sjeff warn("Failed to get allocated inode"); 978207141Sjeff sbdirty(); 979207141Sjeff goto out; 980207141Sjeff } 981207141Sjeff /* 982207141Sjeff * We leave fields unrelated to the number of allocated 983207141Sjeff * blocks and size uninitialized. This causes legacy 984207141Sjeff * fsck implementations to clear the inode. 985207141Sjeff */ 986207141Sjeff dp2 = ip; 987207141Sjeff dp1 = ip; 988226266Smckusick time(&utime); 989207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 990207141Sjeff bzero(dp1, sizeof(*dp1)); 991207141Sjeff dp1->di_size = size; 992207141Sjeff dp1->di_mode = IFREG | IREAD; 993207141Sjeff dp1->di_nlink = 1; 994207141Sjeff dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 995226266Smckusick dp1->di_atime = utime; 996226266Smckusick dp1->di_mtime = utime; 997226266Smckusick dp1->di_ctime = utime; 998207141Sjeff } else { 999207141Sjeff bzero(dp2, sizeof(*dp2)); 1000207141Sjeff dp2->di_size = size; 1001207141Sjeff dp2->di_mode = IFREG | IREAD; 1002207141Sjeff dp2->di_nlink = 1; 1003207141Sjeff dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 1004226266Smckusick dp2->di_atime = utime; 1005226266Smckusick dp2->di_mtime = utime; 1006226266Smckusick dp2->di_ctime = utime; 1007226266Smckusick dp2->di_birthtime = utime; 1008207141Sjeff } 1009207141Sjeff for (i = 0; i < NDADDR && resid; i++, resid--) { 1010207141Sjeff blk = journal_balloc(); 1011207141Sjeff if (blk <= 0) 1012207141Sjeff goto out; 1013207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1014207141Sjeff dp1->di_db[i] = blk; 1015207141Sjeff dp1->di_blocks++; 1016207141Sjeff } else { 1017207141Sjeff dp2->di_db[i] = blk; 1018207141Sjeff dp2->di_blocks++; 1019207141Sjeff } 1020207141Sjeff } 1021207141Sjeff for (i = 0; i < NIADDR && resid; i++) { 1022207141Sjeff blk = journal_balloc(); 1023207141Sjeff if (blk <= 0) 1024207141Sjeff goto out; 1025207141Sjeff blks = indir_fill(blk, i, &resid) + 1; 1026207141Sjeff if (blks <= 0) { 1027207141Sjeff sbdirty(); 1028207141Sjeff goto out; 1029207141Sjeff } 1030207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1031207141Sjeff dp1->di_ib[i] = blk; 1032207141Sjeff dp1->di_blocks += blks; 1033207141Sjeff } else { 1034207141Sjeff dp2->di_ib[i] = blk; 1035207141Sjeff dp2->di_blocks += blks; 1036207141Sjeff } 1037207141Sjeff } 1038207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 1039207141Sjeff dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize; 1040207141Sjeff else 1041207141Sjeff dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize; 1042207141Sjeff if (putino(&disk) < 0) { 1043207141Sjeff warn("Failed to write inode"); 1044207141Sjeff sbdirty(); 1045207141Sjeff return (-1); 1046207141Sjeff } 1047207141Sjeff if (cgwrite(&disk) < 0) { 1048207141Sjeff warn("Failed to write updated cg"); 1049207141Sjeff sbdirty(); 1050207141Sjeff return (-1); 1051207141Sjeff } 1052207141Sjeff if (journal_insertfile(ino) < 0) { 1053207141Sjeff sbdirty(); 1054207141Sjeff return (-1); 1055207141Sjeff } 1056207141Sjeff sblock.fs_sujfree = 0; 1057207141Sjeff return (0); 1058207141Sjeff } 1059207141Sjeff warnx("Insufficient free space for the journal."); 1060207141Sjeffout: 1061207141Sjeff return (-1); 1062207141Sjeff} 1063207141Sjeff 1064207141Sjeffvoid 1065109597Sjmallettusage(void) 10661558Srgrimes{ 1067216798Skib fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n", 1068111287Sru"usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]", 1069207462Sedwin" [-J enable | disable] [-j enable | disable]", 1070207462Sedwin" [-L volname] [-l enable | disable] [-m minfree]", 1071207462Sedwin" [-N enable | disable] [-n enable | disable]", 1072216798Skib" [-o space | time] [-p] [-s avgfpdir] [-t enable | disable]", 1073216798Skib" special | filesystem"); 10741558Srgrimes exit(2); 10751558Srgrimes} 10761558Srgrimes 10771558Srgrimesvoid 1078109597Sjmallettprintfs(void) 10791558Srgrimes{ 1080200796Strasz warnx("POSIX.1e ACLs: (-a) %s", 1081105162Srwatson (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled"); 1082200796Strasz warnx("NFSv4 ACLs: (-N) %s", 1083200796Strasz (sblock.fs_flags & FS_NFS4ACLS)? "enabled" : "disabled"); 1084105162Srwatson warnx("MAC multilabel: (-l) %s", 1085105162Srwatson (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled"); 1086109468Sjmallett warnx("soft updates: (-n) %s", 108734266Sjulian (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); 1088207141Sjeff warnx("soft update journaling: (-j) %s", 1089207141Sjeff (sblock.fs_flags & FS_SUJ)? "enabled" : "disabled"); 1090163842Spjd warnx("gjournal: (-J) %s", 1091163842Spjd (sblock.fs_flags & FS_GJOURNAL)? "enabled" : "disabled"); 1092216798Skib warnx("trim: (-t) %s", 1093216798Skib (sblock.fs_flags & FS_TRIM)? "enabled" : "disabled"); 10949315Sjoerg warnx("maximum blocks per file in a cylinder group: (-e) %d", 10959315Sjoerg sblock.fs_maxbpg); 109675377Smckusick warnx("average file size: (-f) %d", 109775377Smckusick sblock.fs_avgfilesize); 109875377Smckusick warnx("average number of files in a directory: (-s) %d", 109975377Smckusick sblock.fs_avgfpdir); 11009315Sjoerg warnx("minimum percentage of free space: (-m) %d%%", 11019315Sjoerg sblock.fs_minfree); 11029315Sjoerg warnx("optimization preference: (-o) %s", 11039315Sjoerg sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); 11049315Sjoerg if (sblock.fs_minfree >= MINFREE && 11059315Sjoerg sblock.fs_optim == FS_OPTSPACE) 11069315Sjoerg warnx(OPTWARN, "time", ">=", MINFREE); 11079315Sjoerg if (sblock.fs_minfree < MINFREE && 11089315Sjoerg sblock.fs_optim == FS_OPTTIME) 11099315Sjoerg warnx(OPTWARN, "space", "<", MINFREE); 1110110174Sgordon warnx("volume label: (-L) %s", 1111110174Sgordon sblock.fs_volname); 11129315Sjoerg} 1113