tunefs.c revision 247399
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 247399 2013-02-27 18:12:04Z pho $"); 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 73242265Straszstatic int blocks; 74242265Straszstatic char clrbuf[MAXBSIZE]; 75227081Sedstatic struct uufsd disk; 76109597Sjmallett#define sblock disk.d_fs 771558Srgrimes 78242265Straszstatic void usage(void); 79242265Straszstatic void printfs(void); 80242265Straszstatic int journal_alloc(int64_t size); 81242265Straszstatic void journal_clear(void); 82242265Straszstatic void sbdirty(void); 831558Srgrimes 841558Srgrimesint 85109597Sjmallettmain(int argc, char *argv[]) 861558Srgrimes{ 87207141Sjeff char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue; 88216798Skib char *tvalue; 89109963Sjmallett const char *special, *on; 9079750Sdd const char *name; 91127455Sbde int active; 92207141Sjeff int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, Lflag; 93207141Sjeff int lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue, pflag, sflag; 94216798Skib int tflag; 95229911Seadler int svalue, Svalue; 96127441Sbde int ch, found_arg, i; 9779750Sdd const char *chg[2]; 9842873Sluoqi struct ufs_args args; 9942873Sluoqi struct statfs stfs; 1001558Srgrimes 101127441Sbde if (argc < 3) 102127441Sbde usage(); 103207141Sjeff Aflag = aflag = eflag = fflag = jflag = Jflag = Lflag = lflag = 0; 104216798Skib mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0; 105207141Sjeff avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL; 106207141Sjeff evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0; 107127455Sbde active = 0; 108127441Sbde found_arg = 0; /* At least one arg is required. */ 109216798Skib while ((ch = getopt(argc, argv, "Aa:e:f:j:J:L:l:m:N:n:o:ps:S:t:")) 110216798Skib != -1) 111127441Sbde switch (ch) { 112127441Sbde 113127441Sbde case 'A': 114127441Sbde found_arg = 1; 115127441Sbde Aflag++; 116127441Sbde break; 117127441Sbde 118127441Sbde case 'a': 119127441Sbde found_arg = 1; 120200796Strasz name = "POSIX.1e ACLs"; 121127441Sbde avalue = optarg; 122127441Sbde if (strcmp(avalue, "enable") && 123127441Sbde strcmp(avalue, "disable")) { 124127441Sbde errx(10, "bad %s (options are %s)", 125127441Sbde name, "`enable' or `disable'"); 126127441Sbde } 127127441Sbde aflag = 1; 128127441Sbde break; 129127441Sbde 130127441Sbde case 'e': 131127441Sbde found_arg = 1; 132127441Sbde name = "maximum blocks per file in a cylinder group"; 133127441Sbde evalue = atoi(optarg); 134127441Sbde if (evalue < 1) 135127441Sbde errx(10, "%s must be >= 1 (was %s)", 136127441Sbde name, optarg); 137127441Sbde eflag = 1; 138127441Sbde break; 139127441Sbde 140127441Sbde case 'f': 141127441Sbde found_arg = 1; 142127441Sbde name = "average file size"; 143127441Sbde fvalue = atoi(optarg); 144127441Sbde if (fvalue < 1) 145127441Sbde errx(10, "%s must be >= 1 (was %s)", 146127441Sbde name, optarg); 147127441Sbde fflag = 1; 148127441Sbde break; 149127441Sbde 150207141Sjeff case 'j': 151207141Sjeff found_arg = 1; 152207141Sjeff name = "softdep journaled file system"; 153207141Sjeff jvalue = optarg; 154207141Sjeff if (strcmp(jvalue, "enable") && 155207141Sjeff strcmp(jvalue, "disable")) { 156207141Sjeff errx(10, "bad %s (options are %s)", 157207141Sjeff name, "`enable' or `disable'"); 158207141Sjeff } 159207141Sjeff jflag = 1; 160207141Sjeff break; 161207141Sjeff 162163842Spjd case 'J': 163163842Spjd found_arg = 1; 164163842Spjd name = "gjournaled file system"; 165163842Spjd Jvalue = optarg; 166163842Spjd if (strcmp(Jvalue, "enable") && 167163842Spjd strcmp(Jvalue, "disable")) { 168163842Spjd errx(10, "bad %s (options are %s)", 169163842Spjd name, "`enable' or `disable'"); 170163842Spjd } 171163842Spjd Jflag = 1; 172163842Spjd break; 173163842Spjd 174163842Spjd 175127441Sbde case 'L': 176127441Sbde found_arg = 1; 177127441Sbde name = "volume label"; 178127441Sbde Lvalue = optarg; 179127441Sbde i = -1; 180127441Sbde while (isalnum(Lvalue[++i])); 181127441Sbde if (Lvalue[i] != '\0') { 182127441Sbde errx(10, 183127441Sbde "bad %s. Valid characters are alphanumerics.", 184127441Sbde name); 185127441Sbde } 186127441Sbde if (strlen(Lvalue) >= MAXVOLLEN) { 187127441Sbde errx(10, "bad %s. Length is longer than %d.", 188127441Sbde name, MAXVOLLEN - 1); 189127441Sbde } 190127441Sbde Lflag = 1; 191127441Sbde break; 192127441Sbde 193127441Sbde case 'l': 194127441Sbde found_arg = 1; 195127441Sbde name = "multilabel MAC file system"; 196127441Sbde lvalue = optarg; 197127441Sbde if (strcmp(lvalue, "enable") && 198127441Sbde strcmp(lvalue, "disable")) { 199127441Sbde errx(10, "bad %s (options are %s)", 200127441Sbde name, "`enable' or `disable'"); 201127441Sbde } 202127441Sbde lflag = 1; 203127441Sbde break; 204127441Sbde 205127441Sbde case 'm': 206127441Sbde found_arg = 1; 207127441Sbde name = "minimum percentage of free space"; 208127441Sbde mvalue = atoi(optarg); 209127441Sbde if (mvalue < 0 || mvalue > 99) 210127441Sbde errx(10, "bad %s (%s)", name, optarg); 211127441Sbde mflag = 1; 212127441Sbde break; 213127441Sbde 214200796Strasz case 'N': 215200796Strasz found_arg = 1; 216200796Strasz name = "NFSv4 ACLs"; 217200796Strasz Nvalue = optarg; 218200796Strasz if (strcmp(Nvalue, "enable") && 219200796Strasz strcmp(Nvalue, "disable")) { 220200796Strasz errx(10, "bad %s (options are %s)", 221200796Strasz name, "`enable' or `disable'"); 222200796Strasz } 223200796Strasz Nflag = 1; 224200796Strasz break; 225200796Strasz 226127441Sbde case 'n': 227127441Sbde found_arg = 1; 228127441Sbde name = "soft updates"; 229127441Sbde nvalue = optarg; 230127455Sbde if (strcmp(nvalue, "enable") != 0 && 231127455Sbde strcmp(nvalue, "disable") != 0) { 232127441Sbde errx(10, "bad %s (options are %s)", 233127441Sbde name, "`enable' or `disable'"); 234127441Sbde } 235127441Sbde nflag = 1; 236127441Sbde break; 237127441Sbde 238127441Sbde case 'o': 239127441Sbde found_arg = 1; 240127441Sbde name = "optimization preference"; 241127455Sbde if (strcmp(optarg, "space") == 0) 242127441Sbde ovalue = FS_OPTSPACE; 243127455Sbde else if (strcmp(optarg, "time") == 0) 244127441Sbde ovalue = FS_OPTTIME; 245127441Sbde else 246127441Sbde errx(10, 247127441Sbde "bad %s (options are `space' or `time')", 248127441Sbde name); 249127441Sbde oflag = 1; 250127441Sbde break; 251127441Sbde 252127441Sbde case 'p': 253127441Sbde found_arg = 1; 254127441Sbde pflag = 1; 255127441Sbde break; 256127441Sbde 257127441Sbde case 's': 258127441Sbde found_arg = 1; 259127441Sbde name = "expected number of files per directory"; 260127441Sbde svalue = atoi(optarg); 261127441Sbde if (svalue < 1) 262127441Sbde errx(10, "%s must be >= 1 (was %s)", 263127441Sbde name, optarg); 264127441Sbde sflag = 1; 265127441Sbde break; 266127441Sbde 267207141Sjeff case 'S': 268207141Sjeff found_arg = 1; 269207141Sjeff name = "Softdep Journal Size"; 270207141Sjeff Svalue = atoi(optarg); 271207141Sjeff if (Svalue < SUJ_MIN) 272207141Sjeff errx(10, "%s must be >= %d (was %s)", 273207141Sjeff name, SUJ_MIN, optarg); 274207141Sjeff break; 275207141Sjeff 276216798Skib case 't': 277216798Skib found_arg = 1; 278216798Skib name = "trim"; 279216798Skib tvalue = optarg; 280216798Skib if (strcmp(tvalue, "enable") != 0 && 281216798Skib strcmp(tvalue, "disable") != 0) { 282216798Skib errx(10, "bad %s (options are %s)", 283216798Skib name, "`enable' or `disable'"); 284216798Skib } 285216798Skib tflag = 1; 286216798Skib break; 287216798Skib 288127441Sbde default: 289127441Sbde usage(); 290105120Srwatson } 29169314Scharnier argc -= optind; 29269314Scharnier argv += optind; 29369314Scharnier if (found_arg == 0 || argc != 1) 294127441Sbde usage(); 29569314Scharnier 296109963Sjmallett on = special = argv[0]; 297109963Sjmallett if (ufs_disk_fillout(&disk, special) == -1) 298109963Sjmallett goto err; 299109963Sjmallett if (disk.d_name != special) { 300207421Sjeff if (statfs(special, &stfs) != 0) 301207421Sjeff warn("Can't stat %s", special); 302207421Sjeff if (strcmp(special, stfs.f_mntonname) == 0) 30369829Scharnier active = 1; 30469829Scharnier } 30569829Scharnier 30669829Scharnier if (pflag) { 30769829Scharnier printfs(); 30869829Scharnier exit(0); 30969829Scharnier } 310110174Sgordon if (Lflag) { 311110174Sgordon name = "volume label"; 312110174Sgordon strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN); 313110174Sgordon } 314105120Srwatson if (aflag) { 315200796Strasz name = "POSIX.1e ACLs"; 316105120Srwatson if (strcmp(avalue, "enable") == 0) { 317105120Srwatson if (sblock.fs_flags & FS_ACLS) { 318105120Srwatson warnx("%s remains unchanged as enabled", name); 319200796Strasz } else if (sblock.fs_flags & FS_NFS4ACLS) { 320200796Strasz warnx("%s and NFSv4 ACLs are mutually " 321200796Strasz "exclusive", name); 322105120Srwatson } else { 323105120Srwatson sblock.fs_flags |= FS_ACLS; 324105120Srwatson warnx("%s set", name); 325105120Srwatson } 326105120Srwatson } else if (strcmp(avalue, "disable") == 0) { 327105120Srwatson if ((~sblock.fs_flags & FS_ACLS) == 328105120Srwatson FS_ACLS) { 329105120Srwatson warnx("%s remains unchanged as disabled", 330105120Srwatson name); 331105120Srwatson } else { 332105120Srwatson sblock.fs_flags &= ~FS_ACLS; 333105206Srwatson warnx("%s cleared", name); 334105120Srwatson } 335105120Srwatson } 336105120Srwatson } 33769829Scharnier if (eflag) { 33869829Scharnier name = "maximum blocks per file in a cylinder group"; 339127455Sbde if (sblock.fs_maxbpg == evalue) 34069829Scharnier warnx("%s remains unchanged as %d", name, evalue); 34169829Scharnier else { 34269829Scharnier warnx("%s changes from %d to %d", 343127455Sbde name, sblock.fs_maxbpg, evalue); 34469829Scharnier sblock.fs_maxbpg = evalue; 34569829Scharnier } 34669829Scharnier } 34775377Smckusick if (fflag) { 34875377Smckusick name = "average file size"; 349203769Smckusick if (sblock.fs_avgfilesize == (unsigned)fvalue) { 35075377Smckusick warnx("%s remains unchanged as %d", name, fvalue); 35175377Smckusick } 35275377Smckusick else { 35375377Smckusick warnx("%s changes from %d to %d", 35475377Smckusick name, sblock.fs_avgfilesize, fvalue); 35575377Smckusick sblock.fs_avgfilesize = fvalue; 35675377Smckusick } 35775377Smckusick } 358207141Sjeff if (jflag) { 359207141Sjeff name = "soft updates journaling"; 360207141Sjeff if (strcmp(jvalue, "enable") == 0) { 361207141Sjeff if ((sblock.fs_flags & (FS_DOSOFTDEP | FS_SUJ)) == 362207141Sjeff (FS_DOSOFTDEP | FS_SUJ)) { 363207141Sjeff warnx("%s remains unchanged as enabled", name); 364207141Sjeff } else if (sblock.fs_clean == 0) { 365207141Sjeff warnx("%s cannot be enabled until fsck is run", 366207141Sjeff name); 367207141Sjeff } else if (journal_alloc(Svalue) != 0) { 368207141Sjeff warnx("%s can not be enabled", name); 369207141Sjeff } else { 370207141Sjeff sblock.fs_flags |= FS_DOSOFTDEP | FS_SUJ; 371207141Sjeff warnx("%s set", name); 372207141Sjeff } 373207141Sjeff } else if (strcmp(jvalue, "disable") == 0) { 374207141Sjeff if ((~sblock.fs_flags & FS_SUJ) == FS_SUJ) { 375207141Sjeff warnx("%s remains unchanged as disabled", name); 376207141Sjeff } else { 377207141Sjeff journal_clear(); 378208241Sjeff sblock.fs_flags &= ~FS_SUJ; 379207141Sjeff sblock.fs_sujfree = 0; 380208241Sjeff warnx("%s cleared but soft updates still set.", 381208241Sjeff name); 382208241Sjeff 383208241Sjeff warnx("remove .sujournal to reclaim space"); 384207141Sjeff } 385207141Sjeff } 386207141Sjeff } 387163842Spjd if (Jflag) { 388163842Spjd name = "gjournal"; 389163842Spjd if (strcmp(Jvalue, "enable") == 0) { 390163842Spjd if (sblock.fs_flags & FS_GJOURNAL) { 391163842Spjd warnx("%s remains unchanged as enabled", name); 392163842Spjd } else { 393163842Spjd sblock.fs_flags |= FS_GJOURNAL; 394163842Spjd warnx("%s set", name); 395163842Spjd } 396163842Spjd } else if (strcmp(Jvalue, "disable") == 0) { 397163842Spjd if ((~sblock.fs_flags & FS_GJOURNAL) == 398163842Spjd FS_GJOURNAL) { 399163842Spjd warnx("%s remains unchanged as disabled", 400163842Spjd name); 401163842Spjd } else { 402163842Spjd sblock.fs_flags &= ~FS_GJOURNAL; 403163842Spjd warnx("%s cleared", name); 404163842Spjd } 405163842Spjd } 406163842Spjd } 407105120Srwatson if (lflag) { 408105120Srwatson name = "multilabel"; 409105120Srwatson if (strcmp(lvalue, "enable") == 0) { 410105120Srwatson if (sblock.fs_flags & FS_MULTILABEL) { 411105120Srwatson warnx("%s remains unchanged as enabled", name); 412105120Srwatson } else { 413105120Srwatson sblock.fs_flags |= FS_MULTILABEL; 414105120Srwatson warnx("%s set", name); 415105120Srwatson } 416105120Srwatson } else if (strcmp(lvalue, "disable") == 0) { 417105120Srwatson if ((~sblock.fs_flags & FS_MULTILABEL) == 418105120Srwatson FS_MULTILABEL) { 419105120Srwatson warnx("%s remains unchanged as disabled", 420105120Srwatson name); 421105120Srwatson } else { 422105120Srwatson sblock.fs_flags &= ~FS_MULTILABEL; 423105206Srwatson warnx("%s cleared", name); 424105120Srwatson } 425105120Srwatson } 426105120Srwatson } 42769829Scharnier if (mflag) { 42869829Scharnier name = "minimum percentage of free space"; 429127455Sbde if (sblock.fs_minfree == mvalue) 43069829Scharnier warnx("%s remains unchanged as %d%%", name, mvalue); 43169829Scharnier else { 43269829Scharnier warnx("%s changes from %d%% to %d%%", 43369829Scharnier name, sblock.fs_minfree, mvalue); 43469829Scharnier sblock.fs_minfree = mvalue; 43569829Scharnier if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE) 43669829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 43769829Scharnier if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME) 43869829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 43969829Scharnier } 44069829Scharnier } 441200796Strasz if (Nflag) { 442200796Strasz name = "NFSv4 ACLs"; 443200796Strasz if (strcmp(Nvalue, "enable") == 0) { 444200796Strasz if (sblock.fs_flags & FS_NFS4ACLS) { 445200796Strasz warnx("%s remains unchanged as enabled", name); 446200796Strasz } else if (sblock.fs_flags & FS_ACLS) { 447200796Strasz warnx("%s and POSIX.1e ACLs are mutually " 448200796Strasz "exclusive", name); 449200796Strasz } else { 450200796Strasz sblock.fs_flags |= FS_NFS4ACLS; 451200796Strasz warnx("%s set", name); 452200796Strasz } 453200796Strasz } else if (strcmp(Nvalue, "disable") == 0) { 454200796Strasz if ((~sblock.fs_flags & FS_NFS4ACLS) == 455200796Strasz FS_NFS4ACLS) { 456200796Strasz warnx("%s remains unchanged as disabled", 457200796Strasz name); 458200796Strasz } else { 459200796Strasz sblock.fs_flags &= ~FS_NFS4ACLS; 460200796Strasz warnx("%s cleared", name); 461200796Strasz } 462200796Strasz } 463200796Strasz } 46469829Scharnier if (nflag) { 46569829Scharnier name = "soft updates"; 46669829Scharnier if (strcmp(nvalue, "enable") == 0) { 467127455Sbde if (sblock.fs_flags & FS_DOSOFTDEP) 46869829Scharnier warnx("%s remains unchanged as enabled", name); 469127455Sbde else if (sblock.fs_clean == 0) { 47075498Smckusick warnx("%s cannot be enabled until fsck is run", 47175498Smckusick name); 47269829Scharnier } else { 47369829Scharnier sblock.fs_flags |= FS_DOSOFTDEP; 47469829Scharnier warnx("%s set", name); 47569829Scharnier } 47669829Scharnier } else if (strcmp(nvalue, "disable") == 0) { 477127455Sbde if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) 47869829Scharnier warnx("%s remains unchanged as disabled", name); 479127455Sbde else { 48069829Scharnier sblock.fs_flags &= ~FS_DOSOFTDEP; 48169829Scharnier warnx("%s cleared", name); 48269829Scharnier } 48369829Scharnier } 48469829Scharnier } 48569829Scharnier if (oflag) { 48669829Scharnier name = "optimization preference"; 48769829Scharnier chg[FS_OPTSPACE] = "space"; 48869829Scharnier chg[FS_OPTTIME] = "time"; 489127455Sbde if (sblock.fs_optim == ovalue) 49069829Scharnier warnx("%s remains unchanged as %s", name, chg[ovalue]); 49169829Scharnier else { 49269829Scharnier warnx("%s changes from %s to %s", 49369829Scharnier name, chg[sblock.fs_optim], chg[ovalue]); 49469829Scharnier sblock.fs_optim = ovalue; 49569829Scharnier if (sblock.fs_minfree >= MINFREE && 496127455Sbde ovalue == FS_OPTSPACE) 49769829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 498127455Sbde if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME) 49969829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 50069829Scharnier } 50169829Scharnier } 50275377Smckusick if (sflag) { 50375377Smckusick name = "expected number of files per directory"; 504203769Smckusick if (sblock.fs_avgfpdir == (unsigned)svalue) { 50575377Smckusick warnx("%s remains unchanged as %d", name, svalue); 50675377Smckusick } 50775377Smckusick else { 50875377Smckusick warnx("%s changes from %d to %d", 50975377Smckusick name, sblock.fs_avgfpdir, svalue); 51075377Smckusick sblock.fs_avgfpdir = svalue; 51175377Smckusick } 51275377Smckusick } 513216798Skib if (tflag) { 514216798Skib name = "issue TRIM to the disk"; 515216798Skib if (strcmp(tvalue, "enable") == 0) { 516216798Skib if (sblock.fs_flags & FS_TRIM) 517216798Skib warnx("%s remains unchanged as enabled", name); 518216798Skib else { 519216798Skib sblock.fs_flags |= FS_TRIM; 520216798Skib warnx("%s set", name); 521216798Skib } 522216798Skib } else if (strcmp(tvalue, "disable") == 0) { 523216798Skib if ((~sblock.fs_flags & FS_TRIM) == FS_TRIM) 524216798Skib warnx("%s remains unchanged as disabled", name); 525216798Skib else { 526216798Skib sblock.fs_flags &= ~FS_TRIM; 527216798Skib warnx("%s cleared", name); 528216798Skib } 529216798Skib } 530216798Skib } 53169829Scharnier 532109963Sjmallett if (sbwrite(&disk, Aflag) == -1) 533109963Sjmallett goto err; 534109963Sjmallett ufs_disk_close(&disk); 53542873Sluoqi if (active) { 53642873Sluoqi bzero(&args, sizeof(args)); 537109963Sjmallett if (mount("ufs", on, 53842873Sluoqi stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) 53942873Sluoqi err(9, "%s: reload", special); 540102231Strhodes warnx("file system reloaded"); 54142873Sluoqi } 5421558Srgrimes exit(0); 543109963Sjmalletterr: 544109963Sjmallett if (disk.d_error != NULL) 545109963Sjmallett errx(11, "%s: %s", special, disk.d_error); 546109963Sjmallett else 547109963Sjmallett err(12, "%s", special); 5481558Srgrimes} 5491558Srgrimes 550242265Straszstatic void 551207141Sjeffsbdirty(void) 552207141Sjeff{ 553207141Sjeff disk.d_fs.fs_flags |= FS_UNCLEAN | FS_NEEDSFSCK; 554207141Sjeff disk.d_fs.fs_clean = 0; 555207141Sjeff} 556207141Sjeff 557207141Sjeffstatic ufs2_daddr_t 558207141Sjeffjournal_balloc(void) 559207141Sjeff{ 560207141Sjeff ufs2_daddr_t blk; 561207141Sjeff struct cg *cgp; 562207141Sjeff int valid; 563207141Sjeff static int contig = 1; 564207141Sjeff 565207141Sjeff cgp = &disk.d_cg; 566207141Sjeff for (;;) { 567207141Sjeff blk = cgballoc(&disk); 568207141Sjeff if (blk > 0) 569207141Sjeff break; 570207141Sjeff /* 571207141Sjeff * If we failed to allocate a block from this cg, move to 572207141Sjeff * the next. 573207141Sjeff */ 574207141Sjeff if (cgwrite(&disk) < 0) { 575207141Sjeff warn("Failed to write updated cg"); 576207141Sjeff return (-1); 577207141Sjeff } 578207141Sjeff while ((valid = cgread(&disk)) == 1) { 579207141Sjeff /* 580207141Sjeff * Try to minimize fragmentation by requiring a minimum 581207141Sjeff * number of blocks present. 582207141Sjeff */ 583208241Sjeff if (cgp->cg_cs.cs_nbfree > 256 * 1024) 584207141Sjeff break; 585207141Sjeff if (contig == 0 && cgp->cg_cs.cs_nbfree) 586207141Sjeff break; 587207141Sjeff } 588207141Sjeff if (valid) 589207141Sjeff continue; 590207141Sjeff /* 591207141Sjeff * Try once through looking only for large contiguous regions 592207141Sjeff * and again taking any space we can find. 593207141Sjeff */ 594207141Sjeff if (contig) { 595207141Sjeff contig = 0; 596207141Sjeff disk.d_ccg = 0; 597207141Sjeff warnx("Journal file fragmented."); 598207141Sjeff continue; 599207141Sjeff } 600207141Sjeff warnx("Failed to find sufficient free blocks for the journal"); 601207141Sjeff return -1; 602207141Sjeff } 603207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), clrbuf, 604207141Sjeff sblock.fs_bsize) <= 0) { 605207141Sjeff warn("Failed to initialize new block"); 606207141Sjeff return -1; 607207141Sjeff } 608207141Sjeff return (blk); 609207141Sjeff} 610207141Sjeff 611207141Sjeff/* 612207141Sjeff * Search a directory block for the SUJ_FILE. 613207141Sjeff */ 614207141Sjeffstatic ino_t 615207141Sjeffdir_search(ufs2_daddr_t blk, int bytes) 616207141Sjeff{ 617207141Sjeff char block[MAXBSIZE]; 618207141Sjeff struct direct *dp; 619207141Sjeff int off; 620207141Sjeff 621207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, bytes) <= 0) { 622207141Sjeff warn("Failed to read dir block"); 623207141Sjeff return (-1); 624207141Sjeff } 625207141Sjeff for (off = 0; off < bytes; off += dp->d_reclen) { 626207141Sjeff dp = (struct direct *)&block[off]; 627207141Sjeff if (dp->d_reclen == 0) 628207141Sjeff break; 629207141Sjeff if (dp->d_ino == 0) 630207141Sjeff continue; 631207141Sjeff if (dp->d_namlen != strlen(SUJ_FILE)) 632207141Sjeff continue; 633207141Sjeff if (bcmp(dp->d_name, SUJ_FILE, dp->d_namlen) != 0) 634207141Sjeff continue; 635207141Sjeff return (dp->d_ino); 636207141Sjeff } 637207141Sjeff 638207141Sjeff return (0); 639207141Sjeff} 640207141Sjeff 641207141Sjeff/* 642207141Sjeff * Search in the ROOTINO for the SUJ_FILE. If it exists we can not enable 643207141Sjeff * journaling. 644207141Sjeff */ 645207141Sjeffstatic ino_t 646207141Sjeffjournal_findfile(void) 647207141Sjeff{ 648207141Sjeff struct ufs1_dinode *dp1; 649207141Sjeff struct ufs2_dinode *dp2; 650207141Sjeff ino_t ino; 651207141Sjeff int mode; 652207141Sjeff void *ip; 653207141Sjeff int i; 654207141Sjeff 655207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 656207141Sjeff warn("Failed to get root inode"); 657207141Sjeff return (-1); 658207141Sjeff } 659207141Sjeff dp2 = ip; 660207141Sjeff dp1 = ip; 661207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 662207141Sjeff if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { 663207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 664207141Sjeff return (-1); 665207141Sjeff } 666207141Sjeff for (i = 0; i < NDADDR; i++) { 667207141Sjeff if (dp1->di_db[i] == 0) 668207141Sjeff break; 669207141Sjeff if ((ino = dir_search(dp1->di_db[i], 670207141Sjeff sblksize(&sblock, (off_t)dp1->di_size, i))) != 0) 671207141Sjeff return (ino); 672207141Sjeff } 673207141Sjeff } else { 674247399Spho if ((off_t)dp2->di_size >= lblktosize(&sblock, NDADDR)) { 675207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 676207141Sjeff return (-1); 677207141Sjeff } 678207141Sjeff for (i = 0; i < NDADDR; i++) { 679207141Sjeff if (dp2->di_db[i] == 0) 680207141Sjeff break; 681207141Sjeff if ((ino = dir_search(dp2->di_db[i], 682207141Sjeff sblksize(&sblock, (off_t)dp2->di_size, i))) != 0) 683207141Sjeff return (ino); 684207141Sjeff } 685207141Sjeff } 686207141Sjeff 687207141Sjeff return (0); 688207141Sjeff} 689207141Sjeff 690218603Skibstatic void 691218603Skibdir_clear_block(char *block, off_t off) 692218603Skib{ 693218603Skib struct direct *dp; 694218603Skib 695218603Skib for (; off < sblock.fs_bsize; off += DIRBLKSIZ) { 696218603Skib dp = (struct direct *)&block[off]; 697218603Skib dp->d_ino = 0; 698218603Skib dp->d_reclen = DIRBLKSIZ; 699218603Skib dp->d_type = DT_UNKNOWN; 700218603Skib } 701218603Skib} 702218603Skib 703207141Sjeff/* 704207141Sjeff * Insert the journal at inode 'ino' into directory blk 'blk' at the first 705207141Sjeff * free offset of 'off'. DIRBLKSIZ blocks after off are initialized as 706207141Sjeff * empty. 707207141Sjeff */ 708207141Sjeffstatic int 709207141Sjeffdir_insert(ufs2_daddr_t blk, off_t off, ino_t ino) 710207141Sjeff{ 711207141Sjeff struct direct *dp; 712207141Sjeff char block[MAXBSIZE]; 713207141Sjeff 714207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 715207141Sjeff warn("Failed to read dir block"); 716207141Sjeff return (-1); 717207141Sjeff } 718207141Sjeff bzero(&block[off], sblock.fs_bsize - off); 719207141Sjeff dp = (struct direct *)&block[off]; 720207141Sjeff dp->d_ino = ino; 721207141Sjeff dp->d_reclen = DIRBLKSIZ; 722207141Sjeff dp->d_type = DT_REG; 723207141Sjeff dp->d_namlen = strlen(SUJ_FILE); 724207141Sjeff bcopy(SUJ_FILE, &dp->d_name, strlen(SUJ_FILE)); 725218603Skib dir_clear_block(block, off + DIRBLKSIZ); 726207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 727207141Sjeff warn("Failed to write dir block"); 728207141Sjeff return (-1); 729207141Sjeff } 730207141Sjeff return (0); 731207141Sjeff} 732207141Sjeff 733207141Sjeff/* 734207141Sjeff * Extend a directory block in 'blk' by copying it to a full size block 735207141Sjeff * and inserting the new journal inode into .sujournal. 736207141Sjeff */ 737207141Sjeffstatic int 738207141Sjeffdir_extend(ufs2_daddr_t blk, ufs2_daddr_t nblk, off_t size, ino_t ino) 739207141Sjeff{ 740207141Sjeff char block[MAXBSIZE]; 741207141Sjeff 742218603Skib if (bread(&disk, fsbtodb(&sblock, blk), block, 743218603Skib roundup(size, sblock.fs_fsize)) <= 0) { 744207141Sjeff warn("Failed to read dir block"); 745207141Sjeff return (-1); 746207141Sjeff } 747218603Skib dir_clear_block(block, size); 748218603Skib if (bwrite(&disk, fsbtodb(&sblock, nblk), block, sblock.fs_bsize) 749218603Skib <= 0) { 750207141Sjeff warn("Failed to write dir block"); 751207141Sjeff return (-1); 752207141Sjeff } 753207141Sjeff 754218603Skib return (dir_insert(nblk, size, ino)); 755207141Sjeff} 756207141Sjeff 757207141Sjeff/* 758207141Sjeff * Insert the journal file into the ROOTINO directory. We always extend the 759207141Sjeff * last frag 760207141Sjeff */ 761207141Sjeffstatic int 762207141Sjeffjournal_insertfile(ino_t ino) 763207141Sjeff{ 764207141Sjeff struct ufs1_dinode *dp1; 765207141Sjeff struct ufs2_dinode *dp2; 766207141Sjeff void *ip; 767207141Sjeff ufs2_daddr_t nblk; 768207141Sjeff ufs2_daddr_t blk; 769207141Sjeff ufs_lbn_t lbn; 770207141Sjeff int size; 771207141Sjeff int mode; 772207141Sjeff int off; 773207141Sjeff 774207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 775207141Sjeff warn("Failed to get root inode"); 776207141Sjeff sbdirty(); 777207141Sjeff return (-1); 778207141Sjeff } 779207141Sjeff dp2 = ip; 780207141Sjeff dp1 = ip; 781207141Sjeff blk = 0; 782207141Sjeff size = 0; 783207141Sjeff nblk = journal_balloc(); 784207141Sjeff if (nblk <= 0) 785207141Sjeff return (-1); 786207141Sjeff /* 787207141Sjeff * For simplicity sake we aways extend the ROOTINO into a new 788207141Sjeff * directory block rather than searching for space and inserting 789207141Sjeff * into an existing block. However, if the rootino has frags 790207141Sjeff * have to free them and extend the block. 791207141Sjeff */ 792207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 793207141Sjeff lbn = lblkno(&sblock, dp1->di_size); 794207141Sjeff off = blkoff(&sblock, dp1->di_size); 795207141Sjeff blk = dp1->di_db[lbn]; 796207141Sjeff size = sblksize(&sblock, (off_t)dp1->di_size, lbn); 797207141Sjeff } else { 798207141Sjeff lbn = lblkno(&sblock, dp2->di_size); 799207141Sjeff off = blkoff(&sblock, dp2->di_size); 800207141Sjeff blk = dp2->di_db[lbn]; 801207141Sjeff size = sblksize(&sblock, (off_t)dp2->di_size, lbn); 802207141Sjeff } 803207141Sjeff if (off != 0) { 804207141Sjeff if (dir_extend(blk, nblk, off, ino) == -1) 805207141Sjeff return (-1); 806207141Sjeff } else { 807207141Sjeff blk = 0; 808207141Sjeff if (dir_insert(nblk, 0, ino) == -1) 809207141Sjeff return (-1); 810207141Sjeff } 811207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 812207141Sjeff dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 813207141Sjeff dp1->di_db[lbn] = nblk; 814207141Sjeff dp1->di_size = lblktosize(&sblock, lbn+1); 815207141Sjeff } else { 816207141Sjeff dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 817207141Sjeff dp2->di_db[lbn] = nblk; 818207141Sjeff dp2->di_size = lblktosize(&sblock, lbn+1); 819207141Sjeff } 820207141Sjeff if (putino(&disk) < 0) { 821207141Sjeff warn("Failed to write root inode"); 822207141Sjeff return (-1); 823207141Sjeff } 824207141Sjeff if (cgwrite(&disk) < 0) { 825207141Sjeff warn("Failed to write updated cg"); 826207141Sjeff sbdirty(); 827207141Sjeff return (-1); 828207141Sjeff } 829207141Sjeff if (blk) { 830207141Sjeff if (cgbfree(&disk, blk, size) < 0) { 831207141Sjeff warn("Failed to write cg"); 832207141Sjeff return (-1); 833207141Sjeff } 834207141Sjeff } 835207141Sjeff 836207141Sjeff return (0); 837207141Sjeff} 838207141Sjeff 839207141Sjeffstatic int 840207141Sjeffindir_fill(ufs2_daddr_t blk, int level, int *resid) 841207141Sjeff{ 842207141Sjeff char indirbuf[MAXBSIZE]; 843207141Sjeff ufs1_daddr_t *bap1; 844207141Sjeff ufs2_daddr_t *bap2; 845207141Sjeff ufs2_daddr_t nblk; 846207141Sjeff int ncnt; 847207141Sjeff int cnt; 848207141Sjeff int i; 849207141Sjeff 850207141Sjeff bzero(indirbuf, sizeof(indirbuf)); 851207141Sjeff bap1 = (ufs1_daddr_t *)indirbuf; 852207141Sjeff bap2 = (void *)bap1; 853207141Sjeff cnt = 0; 854207141Sjeff for (i = 0; i < NINDIR(&sblock) && *resid != 0; i++) { 855207141Sjeff nblk = journal_balloc(); 856207141Sjeff if (nblk <= 0) 857207141Sjeff return (-1); 858207141Sjeff cnt++; 859207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 860207141Sjeff *bap1++ = nblk; 861207141Sjeff else 862207141Sjeff *bap2++ = nblk; 863207141Sjeff if (level != 0) { 864207141Sjeff ncnt = indir_fill(nblk, level - 1, resid); 865207141Sjeff if (ncnt <= 0) 866207141Sjeff return (-1); 867207141Sjeff cnt += ncnt; 868207141Sjeff } else 869207141Sjeff (*resid)--; 870207141Sjeff } 871207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), indirbuf, 872207141Sjeff sblock.fs_bsize) <= 0) { 873207141Sjeff warn("Failed to write indirect"); 874207141Sjeff return (-1); 875207141Sjeff } 876207141Sjeff return (cnt); 877207141Sjeff} 878207141Sjeff 879207141Sjeff/* 880207141Sjeff * Clear the flag bits so the journal can be removed. 881207141Sjeff */ 882242265Straszstatic void 883207141Sjeffjournal_clear(void) 884207141Sjeff{ 885207141Sjeff struct ufs1_dinode *dp1; 886207141Sjeff struct ufs2_dinode *dp2; 887207141Sjeff ino_t ino; 888207141Sjeff int mode; 889207141Sjeff void *ip; 890207141Sjeff 891207141Sjeff ino = journal_findfile(); 892207141Sjeff if (ino == (ino_t)-1 || ino == 0) { 893207141Sjeff warnx("Journal file does not exist"); 894207141Sjeff return; 895207141Sjeff } 896241013Smdf printf("Clearing journal flags from inode %ju\n", (uintmax_t)ino); 897207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 898207141Sjeff warn("Failed to get journal inode"); 899207141Sjeff return; 900207141Sjeff } 901207141Sjeff dp2 = ip; 902207141Sjeff dp1 = ip; 903207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 904207141Sjeff dp1->di_flags = 0; 905207141Sjeff else 906207141Sjeff dp2->di_flags = 0; 907207141Sjeff if (putino(&disk) < 0) { 908207141Sjeff warn("Failed to write journal inode"); 909207141Sjeff return; 910207141Sjeff } 911207141Sjeff} 912207141Sjeff 913242265Straszstatic int 914207141Sjeffjournal_alloc(int64_t size) 915207141Sjeff{ 916207141Sjeff struct ufs1_dinode *dp1; 917207141Sjeff struct ufs2_dinode *dp2; 918207141Sjeff ufs2_daddr_t blk; 919207141Sjeff void *ip; 920207141Sjeff struct cg *cgp; 921207141Sjeff int resid; 922207141Sjeff ino_t ino; 923207141Sjeff int blks; 924207141Sjeff int mode; 925226266Smckusick time_t utime; 926207141Sjeff int i; 927207141Sjeff 928207141Sjeff cgp = &disk.d_cg; 929207141Sjeff ino = 0; 930207141Sjeff 931207141Sjeff /* 932207141Sjeff * If the journal file exists we can't allocate it. 933207141Sjeff */ 934207141Sjeff ino = journal_findfile(); 935207141Sjeff if (ino == (ino_t)-1) 936207141Sjeff return (-1); 937207141Sjeff if (ino > 0) { 938207141Sjeff warnx("Journal file %s already exists, please remove.", 939207141Sjeff SUJ_FILE); 940207141Sjeff return (-1); 941207141Sjeff } 942207141Sjeff /* 943207141Sjeff * If the user didn't supply a size pick one based on the filesystem 944207141Sjeff * size constrained with hardcoded MIN and MAX values. We opt for 945207141Sjeff * 1/1024th of the filesystem up to MAX but not exceeding one CG and 946207141Sjeff * not less than the MIN. 947207141Sjeff */ 948207141Sjeff if (size == 0) { 949207141Sjeff size = (sblock.fs_size * sblock.fs_bsize) / 1024; 950207141Sjeff size = MIN(SUJ_MAX, size); 951207141Sjeff if (size / sblock.fs_fsize > sblock.fs_fpg) 952207141Sjeff size = sblock.fs_fpg * sblock.fs_fsize; 953207141Sjeff size = MAX(SUJ_MIN, size); 954208241Sjeff /* fsck does not support fragments in journal files. */ 955208241Sjeff size = roundup(size, sblock.fs_bsize); 956207141Sjeff } 957207141Sjeff resid = blocks = size / sblock.fs_bsize; 958207141Sjeff if (sblock.fs_cstotal.cs_nbfree < blocks) { 959207141Sjeff warn("Insufficient free space for %jd byte journal", size); 960207141Sjeff return (-1); 961207141Sjeff } 962207141Sjeff /* 963207141Sjeff * Find a cg with enough blocks to satisfy the journal 964207141Sjeff * size. Presently the journal does not span cgs. 965207141Sjeff */ 966207141Sjeff while (cgread(&disk) == 1) { 967207141Sjeff if (cgp->cg_cs.cs_nifree == 0) 968207141Sjeff continue; 969207141Sjeff ino = cgialloc(&disk); 970207141Sjeff if (ino <= 0) 971207141Sjeff break; 972241013Smdf printf("Using inode %ju in cg %d for %jd byte journal\n", 973241013Smdf (uintmax_t)ino, cgp->cg_cgx, size); 974207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 975207141Sjeff warn("Failed to get allocated inode"); 976207141Sjeff sbdirty(); 977207141Sjeff goto out; 978207141Sjeff } 979207141Sjeff /* 980207141Sjeff * We leave fields unrelated to the number of allocated 981207141Sjeff * blocks and size uninitialized. This causes legacy 982207141Sjeff * fsck implementations to clear the inode. 983207141Sjeff */ 984207141Sjeff dp2 = ip; 985207141Sjeff dp1 = ip; 986226266Smckusick time(&utime); 987207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 988207141Sjeff bzero(dp1, sizeof(*dp1)); 989207141Sjeff dp1->di_size = size; 990207141Sjeff dp1->di_mode = IFREG | IREAD; 991207141Sjeff dp1->di_nlink = 1; 992207141Sjeff dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 993226266Smckusick dp1->di_atime = utime; 994226266Smckusick dp1->di_mtime = utime; 995226266Smckusick dp1->di_ctime = utime; 996207141Sjeff } else { 997207141Sjeff bzero(dp2, sizeof(*dp2)); 998207141Sjeff dp2->di_size = size; 999207141Sjeff dp2->di_mode = IFREG | IREAD; 1000207141Sjeff dp2->di_nlink = 1; 1001207141Sjeff dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 1002226266Smckusick dp2->di_atime = utime; 1003226266Smckusick dp2->di_mtime = utime; 1004226266Smckusick dp2->di_ctime = utime; 1005226266Smckusick dp2->di_birthtime = utime; 1006207141Sjeff } 1007207141Sjeff for (i = 0; i < NDADDR && resid; i++, resid--) { 1008207141Sjeff blk = journal_balloc(); 1009207141Sjeff if (blk <= 0) 1010207141Sjeff goto out; 1011207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1012207141Sjeff dp1->di_db[i] = blk; 1013207141Sjeff dp1->di_blocks++; 1014207141Sjeff } else { 1015207141Sjeff dp2->di_db[i] = blk; 1016207141Sjeff dp2->di_blocks++; 1017207141Sjeff } 1018207141Sjeff } 1019207141Sjeff for (i = 0; i < NIADDR && resid; i++) { 1020207141Sjeff blk = journal_balloc(); 1021207141Sjeff if (blk <= 0) 1022207141Sjeff goto out; 1023207141Sjeff blks = indir_fill(blk, i, &resid) + 1; 1024207141Sjeff if (blks <= 0) { 1025207141Sjeff sbdirty(); 1026207141Sjeff goto out; 1027207141Sjeff } 1028207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1029207141Sjeff dp1->di_ib[i] = blk; 1030207141Sjeff dp1->di_blocks += blks; 1031207141Sjeff } else { 1032207141Sjeff dp2->di_ib[i] = blk; 1033207141Sjeff dp2->di_blocks += blks; 1034207141Sjeff } 1035207141Sjeff } 1036207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 1037207141Sjeff dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize; 1038207141Sjeff else 1039207141Sjeff dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize; 1040207141Sjeff if (putino(&disk) < 0) { 1041207141Sjeff warn("Failed to write inode"); 1042207141Sjeff sbdirty(); 1043207141Sjeff return (-1); 1044207141Sjeff } 1045207141Sjeff if (cgwrite(&disk) < 0) { 1046207141Sjeff warn("Failed to write updated cg"); 1047207141Sjeff sbdirty(); 1048207141Sjeff return (-1); 1049207141Sjeff } 1050207141Sjeff if (journal_insertfile(ino) < 0) { 1051207141Sjeff sbdirty(); 1052207141Sjeff return (-1); 1053207141Sjeff } 1054207141Sjeff sblock.fs_sujfree = 0; 1055207141Sjeff return (0); 1056207141Sjeff } 1057207141Sjeff warnx("Insufficient free space for the journal."); 1058207141Sjeffout: 1059207141Sjeff return (-1); 1060207141Sjeff} 1061207141Sjeff 1062242265Straszstatic void 1063109597Sjmallettusage(void) 10641558Srgrimes{ 1065216798Skib fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n", 1066111287Sru"usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]", 1067207462Sedwin" [-J enable | disable] [-j enable | disable]", 1068207462Sedwin" [-L volname] [-l enable | disable] [-m minfree]", 1069207462Sedwin" [-N enable | disable] [-n enable | disable]", 1070216798Skib" [-o space | time] [-p] [-s avgfpdir] [-t enable | disable]", 1071216798Skib" special | filesystem"); 10721558Srgrimes exit(2); 10731558Srgrimes} 10741558Srgrimes 1075242265Straszstatic void 1076109597Sjmallettprintfs(void) 10771558Srgrimes{ 1078200796Strasz warnx("POSIX.1e ACLs: (-a) %s", 1079105162Srwatson (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled"); 1080200796Strasz warnx("NFSv4 ACLs: (-N) %s", 1081200796Strasz (sblock.fs_flags & FS_NFS4ACLS)? "enabled" : "disabled"); 1082105162Srwatson warnx("MAC multilabel: (-l) %s", 1083105162Srwatson (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled"); 1084109468Sjmallett warnx("soft updates: (-n) %s", 108534266Sjulian (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); 1086207141Sjeff warnx("soft update journaling: (-j) %s", 1087207141Sjeff (sblock.fs_flags & FS_SUJ)? "enabled" : "disabled"); 1088163842Spjd warnx("gjournal: (-J) %s", 1089163842Spjd (sblock.fs_flags & FS_GJOURNAL)? "enabled" : "disabled"); 1090216798Skib warnx("trim: (-t) %s", 1091216798Skib (sblock.fs_flags & FS_TRIM)? "enabled" : "disabled"); 10929315Sjoerg warnx("maximum blocks per file in a cylinder group: (-e) %d", 10939315Sjoerg sblock.fs_maxbpg); 109475377Smckusick warnx("average file size: (-f) %d", 109575377Smckusick sblock.fs_avgfilesize); 109675377Smckusick warnx("average number of files in a directory: (-s) %d", 109775377Smckusick sblock.fs_avgfpdir); 10989315Sjoerg warnx("minimum percentage of free space: (-m) %d%%", 10999315Sjoerg sblock.fs_minfree); 11009315Sjoerg warnx("optimization preference: (-o) %s", 11019315Sjoerg sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); 11029315Sjoerg if (sblock.fs_minfree >= MINFREE && 11039315Sjoerg sblock.fs_optim == FS_OPTSPACE) 11049315Sjoerg warnx(OPTWARN, "time", ">=", MINFREE); 11059315Sjoerg if (sblock.fs_minfree < MINFREE && 11069315Sjoerg sblock.fs_optim == FS_OPTTIME) 11079315Sjoerg warnx(OPTWARN, "space", "<", MINFREE); 1108110174Sgordon warnx("volume label: (-L) %s", 1109110174Sgordon sblock.fs_volname); 11109315Sjoerg} 1111