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: releng/10.2/sbin/tunefs/tunefs.c 250718 2013-05-16 21:04:56Z delphij $"); 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{ 87250718Sdelphij const char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue; 88250718Sdelphij const char *tvalue; 89109963Sjmallett const char *special, *on; 9079750Sdd const char *name; 91127455Sbde int active; 92248623Smckusick int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, kflag; 93248623Smckusick int kvalue, Lflag, lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue; 94248623Smckusick int pflag, sflag, svalue, Svalue, tflag; 95127441Sbde int ch, found_arg, i; 9679750Sdd const char *chg[2]; 9742873Sluoqi struct ufs_args args; 9842873Sluoqi struct statfs stfs; 991558Srgrimes 100127441Sbde if (argc < 3) 101127441Sbde usage(); 102248623Smckusick Aflag = aflag = eflag = fflag = jflag = Jflag = kflag = Lflag = 0; 103248623Smckusick lflag = mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0; 104207141Sjeff avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL; 105207141Sjeff evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0; 106127455Sbde active = 0; 107127441Sbde found_arg = 0; /* At least one arg is required. */ 108248623Smckusick while ((ch = getopt(argc, argv, "Aa:e:f:j:J:k:L:l:m:N:n:o:ps:S:t:")) 109216798Skib != -1) 110127441Sbde switch (ch) { 111127441Sbde 112127441Sbde case 'A': 113127441Sbde found_arg = 1; 114127441Sbde Aflag++; 115127441Sbde break; 116127441Sbde 117127441Sbde case 'a': 118127441Sbde found_arg = 1; 119200796Strasz name = "POSIX.1e ACLs"; 120127441Sbde avalue = optarg; 121127441Sbde if (strcmp(avalue, "enable") && 122127441Sbde strcmp(avalue, "disable")) { 123127441Sbde errx(10, "bad %s (options are %s)", 124127441Sbde name, "`enable' or `disable'"); 125127441Sbde } 126127441Sbde aflag = 1; 127127441Sbde break; 128127441Sbde 129127441Sbde case 'e': 130127441Sbde found_arg = 1; 131127441Sbde name = "maximum blocks per file in a cylinder group"; 132127441Sbde evalue = atoi(optarg); 133127441Sbde if (evalue < 1) 134127441Sbde errx(10, "%s must be >= 1 (was %s)", 135127441Sbde name, optarg); 136127441Sbde eflag = 1; 137127441Sbde break; 138127441Sbde 139127441Sbde case 'f': 140127441Sbde found_arg = 1; 141127441Sbde name = "average file size"; 142127441Sbde fvalue = atoi(optarg); 143127441Sbde if (fvalue < 1) 144127441Sbde errx(10, "%s must be >= 1 (was %s)", 145127441Sbde name, optarg); 146127441Sbde fflag = 1; 147127441Sbde break; 148127441Sbde 149207141Sjeff case 'j': 150207141Sjeff found_arg = 1; 151207141Sjeff name = "softdep journaled file system"; 152207141Sjeff jvalue = optarg; 153207141Sjeff if (strcmp(jvalue, "enable") && 154207141Sjeff strcmp(jvalue, "disable")) { 155207141Sjeff errx(10, "bad %s (options are %s)", 156207141Sjeff name, "`enable' or `disable'"); 157207141Sjeff } 158207141Sjeff jflag = 1; 159207141Sjeff break; 160207141Sjeff 161163842Spjd case 'J': 162163842Spjd found_arg = 1; 163163842Spjd name = "gjournaled file system"; 164163842Spjd Jvalue = optarg; 165163842Spjd if (strcmp(Jvalue, "enable") && 166163842Spjd strcmp(Jvalue, "disable")) { 167163842Spjd errx(10, "bad %s (options are %s)", 168163842Spjd name, "`enable' or `disable'"); 169163842Spjd } 170163842Spjd Jflag = 1; 171163842Spjd break; 172163842Spjd 173248623Smckusick case 'k': 174248623Smckusick found_arg = 1; 175248623Smckusick name = "space to hold for metadata blocks"; 176248623Smckusick kvalue = atoi(optarg); 177249789Smckusick if (kvalue < 0) 178248623Smckusick errx(10, "bad %s (%s)", name, optarg); 179248623Smckusick kflag = 1; 180248623Smckusick break; 181163842Spjd 182127441Sbde case 'L': 183127441Sbde found_arg = 1; 184127441Sbde name = "volume label"; 185127441Sbde Lvalue = optarg; 186127441Sbde i = -1; 187127441Sbde while (isalnum(Lvalue[++i])); 188127441Sbde if (Lvalue[i] != '\0') { 189127441Sbde errx(10, 190127441Sbde "bad %s. Valid characters are alphanumerics.", 191127441Sbde name); 192127441Sbde } 193127441Sbde if (strlen(Lvalue) >= MAXVOLLEN) { 194127441Sbde errx(10, "bad %s. Length is longer than %d.", 195127441Sbde name, MAXVOLLEN - 1); 196127441Sbde } 197127441Sbde Lflag = 1; 198127441Sbde break; 199127441Sbde 200127441Sbde case 'l': 201127441Sbde found_arg = 1; 202127441Sbde name = "multilabel MAC file system"; 203127441Sbde lvalue = optarg; 204127441Sbde if (strcmp(lvalue, "enable") && 205127441Sbde strcmp(lvalue, "disable")) { 206127441Sbde errx(10, "bad %s (options are %s)", 207127441Sbde name, "`enable' or `disable'"); 208127441Sbde } 209127441Sbde lflag = 1; 210127441Sbde break; 211127441Sbde 212127441Sbde case 'm': 213127441Sbde found_arg = 1; 214127441Sbde name = "minimum percentage of free space"; 215127441Sbde mvalue = atoi(optarg); 216127441Sbde if (mvalue < 0 || mvalue > 99) 217127441Sbde errx(10, "bad %s (%s)", name, optarg); 218127441Sbde mflag = 1; 219127441Sbde break; 220127441Sbde 221200796Strasz case 'N': 222200796Strasz found_arg = 1; 223200796Strasz name = "NFSv4 ACLs"; 224200796Strasz Nvalue = optarg; 225200796Strasz if (strcmp(Nvalue, "enable") && 226200796Strasz strcmp(Nvalue, "disable")) { 227200796Strasz errx(10, "bad %s (options are %s)", 228200796Strasz name, "`enable' or `disable'"); 229200796Strasz } 230200796Strasz Nflag = 1; 231200796Strasz break; 232200796Strasz 233127441Sbde case 'n': 234127441Sbde found_arg = 1; 235127441Sbde name = "soft updates"; 236127441Sbde nvalue = optarg; 237127455Sbde if (strcmp(nvalue, "enable") != 0 && 238127455Sbde strcmp(nvalue, "disable") != 0) { 239127441Sbde errx(10, "bad %s (options are %s)", 240127441Sbde name, "`enable' or `disable'"); 241127441Sbde } 242127441Sbde nflag = 1; 243127441Sbde break; 244127441Sbde 245127441Sbde case 'o': 246127441Sbde found_arg = 1; 247127441Sbde name = "optimization preference"; 248127455Sbde if (strcmp(optarg, "space") == 0) 249127441Sbde ovalue = FS_OPTSPACE; 250127455Sbde else if (strcmp(optarg, "time") == 0) 251127441Sbde ovalue = FS_OPTTIME; 252127441Sbde else 253127441Sbde errx(10, 254127441Sbde "bad %s (options are `space' or `time')", 255127441Sbde name); 256127441Sbde oflag = 1; 257127441Sbde break; 258127441Sbde 259127441Sbde case 'p': 260127441Sbde found_arg = 1; 261127441Sbde pflag = 1; 262127441Sbde break; 263127441Sbde 264127441Sbde case 's': 265127441Sbde found_arg = 1; 266127441Sbde name = "expected number of files per directory"; 267127441Sbde svalue = atoi(optarg); 268127441Sbde if (svalue < 1) 269127441Sbde errx(10, "%s must be >= 1 (was %s)", 270127441Sbde name, optarg); 271127441Sbde sflag = 1; 272127441Sbde break; 273127441Sbde 274207141Sjeff case 'S': 275207141Sjeff found_arg = 1; 276207141Sjeff name = "Softdep Journal Size"; 277207141Sjeff Svalue = atoi(optarg); 278207141Sjeff if (Svalue < SUJ_MIN) 279207141Sjeff errx(10, "%s must be >= %d (was %s)", 280207141Sjeff name, SUJ_MIN, optarg); 281207141Sjeff break; 282207141Sjeff 283216798Skib case 't': 284216798Skib found_arg = 1; 285216798Skib name = "trim"; 286216798Skib tvalue = optarg; 287216798Skib if (strcmp(tvalue, "enable") != 0 && 288216798Skib strcmp(tvalue, "disable") != 0) { 289216798Skib errx(10, "bad %s (options are %s)", 290216798Skib name, "`enable' or `disable'"); 291216798Skib } 292216798Skib tflag = 1; 293216798Skib break; 294216798Skib 295127441Sbde default: 296127441Sbde usage(); 297105120Srwatson } 29869314Scharnier argc -= optind; 29969314Scharnier argv += optind; 30069314Scharnier if (found_arg == 0 || argc != 1) 301127441Sbde usage(); 30269314Scharnier 303109963Sjmallett on = special = argv[0]; 304109963Sjmallett if (ufs_disk_fillout(&disk, special) == -1) 305109963Sjmallett goto err; 306109963Sjmallett if (disk.d_name != special) { 307207421Sjeff if (statfs(special, &stfs) != 0) 308207421Sjeff warn("Can't stat %s", special); 309207421Sjeff if (strcmp(special, stfs.f_mntonname) == 0) 31069829Scharnier active = 1; 31169829Scharnier } 31269829Scharnier 31369829Scharnier if (pflag) { 31469829Scharnier printfs(); 31569829Scharnier exit(0); 31669829Scharnier } 317110174Sgordon if (Lflag) { 318110174Sgordon name = "volume label"; 319110174Sgordon strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN); 320110174Sgordon } 321105120Srwatson if (aflag) { 322200796Strasz name = "POSIX.1e ACLs"; 323105120Srwatson if (strcmp(avalue, "enable") == 0) { 324105120Srwatson if (sblock.fs_flags & FS_ACLS) { 325105120Srwatson warnx("%s remains unchanged as enabled", name); 326200796Strasz } else if (sblock.fs_flags & FS_NFS4ACLS) { 327200796Strasz warnx("%s and NFSv4 ACLs are mutually " 328200796Strasz "exclusive", name); 329105120Srwatson } else { 330105120Srwatson sblock.fs_flags |= FS_ACLS; 331105120Srwatson warnx("%s set", name); 332105120Srwatson } 333105120Srwatson } else if (strcmp(avalue, "disable") == 0) { 334105120Srwatson if ((~sblock.fs_flags & FS_ACLS) == 335105120Srwatson FS_ACLS) { 336105120Srwatson warnx("%s remains unchanged as disabled", 337105120Srwatson name); 338105120Srwatson } else { 339105120Srwatson sblock.fs_flags &= ~FS_ACLS; 340105206Srwatson warnx("%s cleared", name); 341105120Srwatson } 342105120Srwatson } 343105120Srwatson } 34469829Scharnier if (eflag) { 34569829Scharnier name = "maximum blocks per file in a cylinder group"; 346127455Sbde if (sblock.fs_maxbpg == evalue) 34769829Scharnier warnx("%s remains unchanged as %d", name, evalue); 34869829Scharnier else { 34969829Scharnier warnx("%s changes from %d to %d", 350127455Sbde name, sblock.fs_maxbpg, evalue); 35169829Scharnier sblock.fs_maxbpg = evalue; 35269829Scharnier } 35369829Scharnier } 35475377Smckusick if (fflag) { 35575377Smckusick name = "average file size"; 356203769Smckusick if (sblock.fs_avgfilesize == (unsigned)fvalue) { 35775377Smckusick warnx("%s remains unchanged as %d", name, fvalue); 35875377Smckusick } 35975377Smckusick else { 36075377Smckusick warnx("%s changes from %d to %d", 36175377Smckusick name, sblock.fs_avgfilesize, fvalue); 36275377Smckusick sblock.fs_avgfilesize = fvalue; 36375377Smckusick } 36475377Smckusick } 365207141Sjeff if (jflag) { 366207141Sjeff name = "soft updates journaling"; 367207141Sjeff if (strcmp(jvalue, "enable") == 0) { 368207141Sjeff if ((sblock.fs_flags & (FS_DOSOFTDEP | FS_SUJ)) == 369207141Sjeff (FS_DOSOFTDEP | FS_SUJ)) { 370207141Sjeff warnx("%s remains unchanged as enabled", name); 371207141Sjeff } else if (sblock.fs_clean == 0) { 372207141Sjeff warnx("%s cannot be enabled until fsck is run", 373207141Sjeff name); 374207141Sjeff } else if (journal_alloc(Svalue) != 0) { 375207141Sjeff warnx("%s can not be enabled", name); 376207141Sjeff } else { 377207141Sjeff sblock.fs_flags |= FS_DOSOFTDEP | FS_SUJ; 378207141Sjeff warnx("%s set", name); 379207141Sjeff } 380207141Sjeff } else if (strcmp(jvalue, "disable") == 0) { 381207141Sjeff if ((~sblock.fs_flags & FS_SUJ) == FS_SUJ) { 382207141Sjeff warnx("%s remains unchanged as disabled", name); 383207141Sjeff } else { 384207141Sjeff journal_clear(); 385208241Sjeff sblock.fs_flags &= ~FS_SUJ; 386207141Sjeff sblock.fs_sujfree = 0; 387208241Sjeff warnx("%s cleared but soft updates still set.", 388208241Sjeff name); 389208241Sjeff 390208241Sjeff warnx("remove .sujournal to reclaim space"); 391207141Sjeff } 392207141Sjeff } 393207141Sjeff } 394163842Spjd if (Jflag) { 395163842Spjd name = "gjournal"; 396163842Spjd if (strcmp(Jvalue, "enable") == 0) { 397163842Spjd if (sblock.fs_flags & FS_GJOURNAL) { 398163842Spjd warnx("%s remains unchanged as enabled", name); 399163842Spjd } else { 400163842Spjd sblock.fs_flags |= FS_GJOURNAL; 401163842Spjd warnx("%s set", name); 402163842Spjd } 403163842Spjd } else if (strcmp(Jvalue, "disable") == 0) { 404163842Spjd if ((~sblock.fs_flags & FS_GJOURNAL) == 405163842Spjd FS_GJOURNAL) { 406163842Spjd warnx("%s remains unchanged as disabled", 407163842Spjd name); 408163842Spjd } else { 409163842Spjd sblock.fs_flags &= ~FS_GJOURNAL; 410163842Spjd warnx("%s cleared", name); 411163842Spjd } 412163842Spjd } 413163842Spjd } 414248623Smckusick if (kflag) { 415248623Smckusick name = "space to hold for metadata blocks"; 416248623Smckusick if (sblock.fs_metaspace == kvalue) 417248623Smckusick warnx("%s remains unchanged as %d", name, kvalue); 418248623Smckusick else { 419248623Smckusick kvalue = blknum(&sblock, kvalue); 420248623Smckusick if (kvalue > sblock.fs_fpg / 2) { 421248623Smckusick kvalue = blknum(&sblock, sblock.fs_fpg / 2); 422248623Smckusick warnx("%s cannot exceed half the file system " 423248623Smckusick "space", name); 424248623Smckusick } 425248623Smckusick warnx("%s changes from %jd to %d", 426248623Smckusick name, sblock.fs_metaspace, kvalue); 427248623Smckusick sblock.fs_metaspace = kvalue; 428248623Smckusick } 429248623Smckusick } 430105120Srwatson if (lflag) { 431105120Srwatson name = "multilabel"; 432105120Srwatson if (strcmp(lvalue, "enable") == 0) { 433105120Srwatson if (sblock.fs_flags & FS_MULTILABEL) { 434105120Srwatson warnx("%s remains unchanged as enabled", name); 435105120Srwatson } else { 436105120Srwatson sblock.fs_flags |= FS_MULTILABEL; 437105120Srwatson warnx("%s set", name); 438105120Srwatson } 439105120Srwatson } else if (strcmp(lvalue, "disable") == 0) { 440105120Srwatson if ((~sblock.fs_flags & FS_MULTILABEL) == 441105120Srwatson FS_MULTILABEL) { 442105120Srwatson warnx("%s remains unchanged as disabled", 443105120Srwatson name); 444105120Srwatson } else { 445105120Srwatson sblock.fs_flags &= ~FS_MULTILABEL; 446105206Srwatson warnx("%s cleared", name); 447105120Srwatson } 448105120Srwatson } 449105120Srwatson } 45069829Scharnier if (mflag) { 45169829Scharnier name = "minimum percentage of free space"; 452127455Sbde if (sblock.fs_minfree == mvalue) 45369829Scharnier warnx("%s remains unchanged as %d%%", name, mvalue); 45469829Scharnier else { 45569829Scharnier warnx("%s changes from %d%% to %d%%", 45669829Scharnier name, sblock.fs_minfree, mvalue); 45769829Scharnier sblock.fs_minfree = mvalue; 45869829Scharnier if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE) 45969829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 46069829Scharnier if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME) 46169829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 46269829Scharnier } 46369829Scharnier } 464200796Strasz if (Nflag) { 465200796Strasz name = "NFSv4 ACLs"; 466200796Strasz if (strcmp(Nvalue, "enable") == 0) { 467200796Strasz if (sblock.fs_flags & FS_NFS4ACLS) { 468200796Strasz warnx("%s remains unchanged as enabled", name); 469200796Strasz } else if (sblock.fs_flags & FS_ACLS) { 470200796Strasz warnx("%s and POSIX.1e ACLs are mutually " 471200796Strasz "exclusive", name); 472200796Strasz } else { 473200796Strasz sblock.fs_flags |= FS_NFS4ACLS; 474200796Strasz warnx("%s set", name); 475200796Strasz } 476200796Strasz } else if (strcmp(Nvalue, "disable") == 0) { 477200796Strasz if ((~sblock.fs_flags & FS_NFS4ACLS) == 478200796Strasz FS_NFS4ACLS) { 479200796Strasz warnx("%s remains unchanged as disabled", 480200796Strasz name); 481200796Strasz } else { 482200796Strasz sblock.fs_flags &= ~FS_NFS4ACLS; 483200796Strasz warnx("%s cleared", name); 484200796Strasz } 485200796Strasz } 486200796Strasz } 48769829Scharnier if (nflag) { 48869829Scharnier name = "soft updates"; 48969829Scharnier if (strcmp(nvalue, "enable") == 0) { 490127455Sbde if (sblock.fs_flags & FS_DOSOFTDEP) 49169829Scharnier warnx("%s remains unchanged as enabled", name); 492127455Sbde else if (sblock.fs_clean == 0) { 49375498Smckusick warnx("%s cannot be enabled until fsck is run", 49475498Smckusick name); 49569829Scharnier } else { 49669829Scharnier sblock.fs_flags |= FS_DOSOFTDEP; 49769829Scharnier warnx("%s set", name); 49869829Scharnier } 49969829Scharnier } else if (strcmp(nvalue, "disable") == 0) { 500127455Sbde if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) 50169829Scharnier warnx("%s remains unchanged as disabled", name); 502127455Sbde else { 50369829Scharnier sblock.fs_flags &= ~FS_DOSOFTDEP; 50469829Scharnier warnx("%s cleared", name); 50569829Scharnier } 50669829Scharnier } 50769829Scharnier } 50869829Scharnier if (oflag) { 50969829Scharnier name = "optimization preference"; 51069829Scharnier chg[FS_OPTSPACE] = "space"; 51169829Scharnier chg[FS_OPTTIME] = "time"; 512127455Sbde if (sblock.fs_optim == ovalue) 51369829Scharnier warnx("%s remains unchanged as %s", name, chg[ovalue]); 51469829Scharnier else { 51569829Scharnier warnx("%s changes from %s to %s", 51669829Scharnier name, chg[sblock.fs_optim], chg[ovalue]); 51769829Scharnier sblock.fs_optim = ovalue; 51869829Scharnier if (sblock.fs_minfree >= MINFREE && 519127455Sbde ovalue == FS_OPTSPACE) 52069829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 521127455Sbde if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME) 52269829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 52369829Scharnier } 52469829Scharnier } 52575377Smckusick if (sflag) { 52675377Smckusick name = "expected number of files per directory"; 527203769Smckusick if (sblock.fs_avgfpdir == (unsigned)svalue) { 52875377Smckusick warnx("%s remains unchanged as %d", name, svalue); 52975377Smckusick } 53075377Smckusick else { 53175377Smckusick warnx("%s changes from %d to %d", 53275377Smckusick name, sblock.fs_avgfpdir, svalue); 53375377Smckusick sblock.fs_avgfpdir = svalue; 53475377Smckusick } 53575377Smckusick } 536216798Skib if (tflag) { 537216798Skib name = "issue TRIM to the disk"; 538216798Skib if (strcmp(tvalue, "enable") == 0) { 539216798Skib if (sblock.fs_flags & FS_TRIM) 540216798Skib warnx("%s remains unchanged as enabled", name); 541216798Skib else { 542216798Skib sblock.fs_flags |= FS_TRIM; 543216798Skib warnx("%s set", name); 544216798Skib } 545216798Skib } else if (strcmp(tvalue, "disable") == 0) { 546216798Skib if ((~sblock.fs_flags & FS_TRIM) == FS_TRIM) 547216798Skib warnx("%s remains unchanged as disabled", name); 548216798Skib else { 549216798Skib sblock.fs_flags &= ~FS_TRIM; 550216798Skib warnx("%s cleared", name); 551216798Skib } 552216798Skib } 553216798Skib } 55469829Scharnier 555109963Sjmallett if (sbwrite(&disk, Aflag) == -1) 556109963Sjmallett goto err; 557109963Sjmallett ufs_disk_close(&disk); 55842873Sluoqi if (active) { 55942873Sluoqi bzero(&args, sizeof(args)); 560109963Sjmallett if (mount("ufs", on, 56142873Sluoqi stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) 56242873Sluoqi err(9, "%s: reload", special); 563102231Strhodes warnx("file system reloaded"); 56442873Sluoqi } 5651558Srgrimes exit(0); 566109963Sjmalletterr: 567109963Sjmallett if (disk.d_error != NULL) 568109963Sjmallett errx(11, "%s: %s", special, disk.d_error); 569109963Sjmallett else 570109963Sjmallett err(12, "%s", special); 5711558Srgrimes} 5721558Srgrimes 573242265Straszstatic void 574207141Sjeffsbdirty(void) 575207141Sjeff{ 576207141Sjeff disk.d_fs.fs_flags |= FS_UNCLEAN | FS_NEEDSFSCK; 577207141Sjeff disk.d_fs.fs_clean = 0; 578207141Sjeff} 579207141Sjeff 580207141Sjeffstatic ufs2_daddr_t 581207141Sjeffjournal_balloc(void) 582207141Sjeff{ 583207141Sjeff ufs2_daddr_t blk; 584207141Sjeff struct cg *cgp; 585207141Sjeff int valid; 586207141Sjeff static int contig = 1; 587207141Sjeff 588207141Sjeff cgp = &disk.d_cg; 589207141Sjeff for (;;) { 590207141Sjeff blk = cgballoc(&disk); 591207141Sjeff if (blk > 0) 592207141Sjeff break; 593207141Sjeff /* 594207141Sjeff * If we failed to allocate a block from this cg, move to 595207141Sjeff * the next. 596207141Sjeff */ 597207141Sjeff if (cgwrite(&disk) < 0) { 598207141Sjeff warn("Failed to write updated cg"); 599207141Sjeff return (-1); 600207141Sjeff } 601207141Sjeff while ((valid = cgread(&disk)) == 1) { 602207141Sjeff /* 603207141Sjeff * Try to minimize fragmentation by requiring a minimum 604207141Sjeff * number of blocks present. 605207141Sjeff */ 606208241Sjeff if (cgp->cg_cs.cs_nbfree > 256 * 1024) 607207141Sjeff break; 608207141Sjeff if (contig == 0 && cgp->cg_cs.cs_nbfree) 609207141Sjeff break; 610207141Sjeff } 611207141Sjeff if (valid) 612207141Sjeff continue; 613207141Sjeff /* 614207141Sjeff * Try once through looking only for large contiguous regions 615207141Sjeff * and again taking any space we can find. 616207141Sjeff */ 617207141Sjeff if (contig) { 618207141Sjeff contig = 0; 619207141Sjeff disk.d_ccg = 0; 620207141Sjeff warnx("Journal file fragmented."); 621207141Sjeff continue; 622207141Sjeff } 623207141Sjeff warnx("Failed to find sufficient free blocks for the journal"); 624207141Sjeff return -1; 625207141Sjeff } 626207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), clrbuf, 627207141Sjeff sblock.fs_bsize) <= 0) { 628207141Sjeff warn("Failed to initialize new block"); 629207141Sjeff return -1; 630207141Sjeff } 631207141Sjeff return (blk); 632207141Sjeff} 633207141Sjeff 634207141Sjeff/* 635207141Sjeff * Search a directory block for the SUJ_FILE. 636207141Sjeff */ 637207141Sjeffstatic ino_t 638207141Sjeffdir_search(ufs2_daddr_t blk, int bytes) 639207141Sjeff{ 640207141Sjeff char block[MAXBSIZE]; 641207141Sjeff struct direct *dp; 642207141Sjeff int off; 643207141Sjeff 644207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, bytes) <= 0) { 645207141Sjeff warn("Failed to read dir block"); 646207141Sjeff return (-1); 647207141Sjeff } 648207141Sjeff for (off = 0; off < bytes; off += dp->d_reclen) { 649207141Sjeff dp = (struct direct *)&block[off]; 650207141Sjeff if (dp->d_reclen == 0) 651207141Sjeff break; 652207141Sjeff if (dp->d_ino == 0) 653207141Sjeff continue; 654207141Sjeff if (dp->d_namlen != strlen(SUJ_FILE)) 655207141Sjeff continue; 656207141Sjeff if (bcmp(dp->d_name, SUJ_FILE, dp->d_namlen) != 0) 657207141Sjeff continue; 658207141Sjeff return (dp->d_ino); 659207141Sjeff } 660207141Sjeff 661207141Sjeff return (0); 662207141Sjeff} 663207141Sjeff 664207141Sjeff/* 665207141Sjeff * Search in the ROOTINO for the SUJ_FILE. If it exists we can not enable 666207141Sjeff * journaling. 667207141Sjeff */ 668207141Sjeffstatic ino_t 669207141Sjeffjournal_findfile(void) 670207141Sjeff{ 671207141Sjeff struct ufs1_dinode *dp1; 672207141Sjeff struct ufs2_dinode *dp2; 673207141Sjeff ino_t ino; 674207141Sjeff int mode; 675207141Sjeff void *ip; 676207141Sjeff int i; 677207141Sjeff 678207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 679207141Sjeff warn("Failed to get root inode"); 680207141Sjeff return (-1); 681207141Sjeff } 682207141Sjeff dp2 = ip; 683207141Sjeff dp1 = ip; 684207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 685207141Sjeff if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { 686207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 687207141Sjeff return (-1); 688207141Sjeff } 689207141Sjeff for (i = 0; i < NDADDR; i++) { 690207141Sjeff if (dp1->di_db[i] == 0) 691207141Sjeff break; 692207141Sjeff if ((ino = dir_search(dp1->di_db[i], 693207141Sjeff sblksize(&sblock, (off_t)dp1->di_size, i))) != 0) 694207141Sjeff return (ino); 695207141Sjeff } 696207141Sjeff } else { 697247399Spho if ((off_t)dp2->di_size >= lblktosize(&sblock, NDADDR)) { 698207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 699207141Sjeff return (-1); 700207141Sjeff } 701207141Sjeff for (i = 0; i < NDADDR; i++) { 702207141Sjeff if (dp2->di_db[i] == 0) 703207141Sjeff break; 704207141Sjeff if ((ino = dir_search(dp2->di_db[i], 705207141Sjeff sblksize(&sblock, (off_t)dp2->di_size, i))) != 0) 706207141Sjeff return (ino); 707207141Sjeff } 708207141Sjeff } 709207141Sjeff 710207141Sjeff return (0); 711207141Sjeff} 712207141Sjeff 713218603Skibstatic void 714250718Sdelphijdir_clear_block(const char *block, off_t off) 715218603Skib{ 716218603Skib struct direct *dp; 717218603Skib 718218603Skib for (; off < sblock.fs_bsize; off += DIRBLKSIZ) { 719218603Skib dp = (struct direct *)&block[off]; 720218603Skib dp->d_ino = 0; 721218603Skib dp->d_reclen = DIRBLKSIZ; 722218603Skib dp->d_type = DT_UNKNOWN; 723218603Skib } 724218603Skib} 725218603Skib 726207141Sjeff/* 727207141Sjeff * Insert the journal at inode 'ino' into directory blk 'blk' at the first 728207141Sjeff * free offset of 'off'. DIRBLKSIZ blocks after off are initialized as 729207141Sjeff * empty. 730207141Sjeff */ 731207141Sjeffstatic int 732207141Sjeffdir_insert(ufs2_daddr_t blk, off_t off, ino_t ino) 733207141Sjeff{ 734207141Sjeff struct direct *dp; 735207141Sjeff char block[MAXBSIZE]; 736207141Sjeff 737207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 738207141Sjeff warn("Failed to read dir block"); 739207141Sjeff return (-1); 740207141Sjeff } 741207141Sjeff bzero(&block[off], sblock.fs_bsize - off); 742207141Sjeff dp = (struct direct *)&block[off]; 743207141Sjeff dp->d_ino = ino; 744207141Sjeff dp->d_reclen = DIRBLKSIZ; 745207141Sjeff dp->d_type = DT_REG; 746207141Sjeff dp->d_namlen = strlen(SUJ_FILE); 747207141Sjeff bcopy(SUJ_FILE, &dp->d_name, strlen(SUJ_FILE)); 748218603Skib dir_clear_block(block, off + DIRBLKSIZ); 749207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 750207141Sjeff warn("Failed to write dir block"); 751207141Sjeff return (-1); 752207141Sjeff } 753207141Sjeff return (0); 754207141Sjeff} 755207141Sjeff 756207141Sjeff/* 757207141Sjeff * Extend a directory block in 'blk' by copying it to a full size block 758207141Sjeff * and inserting the new journal inode into .sujournal. 759207141Sjeff */ 760207141Sjeffstatic int 761207141Sjeffdir_extend(ufs2_daddr_t blk, ufs2_daddr_t nblk, off_t size, ino_t ino) 762207141Sjeff{ 763207141Sjeff char block[MAXBSIZE]; 764207141Sjeff 765218603Skib if (bread(&disk, fsbtodb(&sblock, blk), block, 766218603Skib roundup(size, sblock.fs_fsize)) <= 0) { 767207141Sjeff warn("Failed to read dir block"); 768207141Sjeff return (-1); 769207141Sjeff } 770218603Skib dir_clear_block(block, size); 771218603Skib if (bwrite(&disk, fsbtodb(&sblock, nblk), block, sblock.fs_bsize) 772218603Skib <= 0) { 773207141Sjeff warn("Failed to write dir block"); 774207141Sjeff return (-1); 775207141Sjeff } 776207141Sjeff 777218603Skib return (dir_insert(nblk, size, ino)); 778207141Sjeff} 779207141Sjeff 780207141Sjeff/* 781207141Sjeff * Insert the journal file into the ROOTINO directory. We always extend the 782207141Sjeff * last frag 783207141Sjeff */ 784207141Sjeffstatic int 785207141Sjeffjournal_insertfile(ino_t ino) 786207141Sjeff{ 787207141Sjeff struct ufs1_dinode *dp1; 788207141Sjeff struct ufs2_dinode *dp2; 789207141Sjeff void *ip; 790207141Sjeff ufs2_daddr_t nblk; 791207141Sjeff ufs2_daddr_t blk; 792207141Sjeff ufs_lbn_t lbn; 793207141Sjeff int size; 794207141Sjeff int mode; 795207141Sjeff int off; 796207141Sjeff 797207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 798207141Sjeff warn("Failed to get root inode"); 799207141Sjeff sbdirty(); 800207141Sjeff return (-1); 801207141Sjeff } 802207141Sjeff dp2 = ip; 803207141Sjeff dp1 = ip; 804207141Sjeff blk = 0; 805207141Sjeff size = 0; 806207141Sjeff nblk = journal_balloc(); 807207141Sjeff if (nblk <= 0) 808207141Sjeff return (-1); 809207141Sjeff /* 810207141Sjeff * For simplicity sake we aways extend the ROOTINO into a new 811207141Sjeff * directory block rather than searching for space and inserting 812207141Sjeff * into an existing block. However, if the rootino has frags 813207141Sjeff * have to free them and extend the block. 814207141Sjeff */ 815207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 816207141Sjeff lbn = lblkno(&sblock, dp1->di_size); 817207141Sjeff off = blkoff(&sblock, dp1->di_size); 818207141Sjeff blk = dp1->di_db[lbn]; 819207141Sjeff size = sblksize(&sblock, (off_t)dp1->di_size, lbn); 820207141Sjeff } else { 821207141Sjeff lbn = lblkno(&sblock, dp2->di_size); 822207141Sjeff off = blkoff(&sblock, dp2->di_size); 823207141Sjeff blk = dp2->di_db[lbn]; 824207141Sjeff size = sblksize(&sblock, (off_t)dp2->di_size, lbn); 825207141Sjeff } 826207141Sjeff if (off != 0) { 827207141Sjeff if (dir_extend(blk, nblk, off, ino) == -1) 828207141Sjeff return (-1); 829207141Sjeff } else { 830207141Sjeff blk = 0; 831207141Sjeff if (dir_insert(nblk, 0, ino) == -1) 832207141Sjeff return (-1); 833207141Sjeff } 834207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 835207141Sjeff dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 836207141Sjeff dp1->di_db[lbn] = nblk; 837207141Sjeff dp1->di_size = lblktosize(&sblock, lbn+1); 838207141Sjeff } else { 839207141Sjeff dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 840207141Sjeff dp2->di_db[lbn] = nblk; 841207141Sjeff dp2->di_size = lblktosize(&sblock, lbn+1); 842207141Sjeff } 843207141Sjeff if (putino(&disk) < 0) { 844207141Sjeff warn("Failed to write root inode"); 845207141Sjeff return (-1); 846207141Sjeff } 847207141Sjeff if (cgwrite(&disk) < 0) { 848207141Sjeff warn("Failed to write updated cg"); 849207141Sjeff sbdirty(); 850207141Sjeff return (-1); 851207141Sjeff } 852207141Sjeff if (blk) { 853207141Sjeff if (cgbfree(&disk, blk, size) < 0) { 854207141Sjeff warn("Failed to write cg"); 855207141Sjeff return (-1); 856207141Sjeff } 857207141Sjeff } 858207141Sjeff 859207141Sjeff return (0); 860207141Sjeff} 861207141Sjeff 862207141Sjeffstatic int 863207141Sjeffindir_fill(ufs2_daddr_t blk, int level, int *resid) 864207141Sjeff{ 865207141Sjeff char indirbuf[MAXBSIZE]; 866207141Sjeff ufs1_daddr_t *bap1; 867207141Sjeff ufs2_daddr_t *bap2; 868207141Sjeff ufs2_daddr_t nblk; 869207141Sjeff int ncnt; 870207141Sjeff int cnt; 871207141Sjeff int i; 872207141Sjeff 873207141Sjeff bzero(indirbuf, sizeof(indirbuf)); 874207141Sjeff bap1 = (ufs1_daddr_t *)indirbuf; 875207141Sjeff bap2 = (void *)bap1; 876207141Sjeff cnt = 0; 877207141Sjeff for (i = 0; i < NINDIR(&sblock) && *resid != 0; i++) { 878207141Sjeff nblk = journal_balloc(); 879207141Sjeff if (nblk <= 0) 880207141Sjeff return (-1); 881207141Sjeff cnt++; 882207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 883207141Sjeff *bap1++ = nblk; 884207141Sjeff else 885207141Sjeff *bap2++ = nblk; 886207141Sjeff if (level != 0) { 887207141Sjeff ncnt = indir_fill(nblk, level - 1, resid); 888207141Sjeff if (ncnt <= 0) 889207141Sjeff return (-1); 890207141Sjeff cnt += ncnt; 891207141Sjeff } else 892207141Sjeff (*resid)--; 893207141Sjeff } 894207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), indirbuf, 895207141Sjeff sblock.fs_bsize) <= 0) { 896207141Sjeff warn("Failed to write indirect"); 897207141Sjeff return (-1); 898207141Sjeff } 899207141Sjeff return (cnt); 900207141Sjeff} 901207141Sjeff 902207141Sjeff/* 903207141Sjeff * Clear the flag bits so the journal can be removed. 904207141Sjeff */ 905242265Straszstatic void 906207141Sjeffjournal_clear(void) 907207141Sjeff{ 908207141Sjeff struct ufs1_dinode *dp1; 909207141Sjeff struct ufs2_dinode *dp2; 910207141Sjeff ino_t ino; 911207141Sjeff int mode; 912207141Sjeff void *ip; 913207141Sjeff 914207141Sjeff ino = journal_findfile(); 915207141Sjeff if (ino == (ino_t)-1 || ino == 0) { 916207141Sjeff warnx("Journal file does not exist"); 917207141Sjeff return; 918207141Sjeff } 919241013Smdf printf("Clearing journal flags from inode %ju\n", (uintmax_t)ino); 920207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 921207141Sjeff warn("Failed to get journal inode"); 922207141Sjeff return; 923207141Sjeff } 924207141Sjeff dp2 = ip; 925207141Sjeff dp1 = ip; 926207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 927207141Sjeff dp1->di_flags = 0; 928207141Sjeff else 929207141Sjeff dp2->di_flags = 0; 930207141Sjeff if (putino(&disk) < 0) { 931207141Sjeff warn("Failed to write journal inode"); 932207141Sjeff return; 933207141Sjeff } 934207141Sjeff} 935207141Sjeff 936242265Straszstatic int 937207141Sjeffjournal_alloc(int64_t size) 938207141Sjeff{ 939207141Sjeff struct ufs1_dinode *dp1; 940207141Sjeff struct ufs2_dinode *dp2; 941207141Sjeff ufs2_daddr_t blk; 942207141Sjeff void *ip; 943207141Sjeff struct cg *cgp; 944207141Sjeff int resid; 945207141Sjeff ino_t ino; 946207141Sjeff int blks; 947207141Sjeff int mode; 948226266Smckusick time_t utime; 949207141Sjeff int i; 950207141Sjeff 951207141Sjeff cgp = &disk.d_cg; 952207141Sjeff ino = 0; 953207141Sjeff 954207141Sjeff /* 955207141Sjeff * If the journal file exists we can't allocate it. 956207141Sjeff */ 957207141Sjeff ino = journal_findfile(); 958207141Sjeff if (ino == (ino_t)-1) 959207141Sjeff return (-1); 960207141Sjeff if (ino > 0) { 961207141Sjeff warnx("Journal file %s already exists, please remove.", 962207141Sjeff SUJ_FILE); 963207141Sjeff return (-1); 964207141Sjeff } 965207141Sjeff /* 966207141Sjeff * If the user didn't supply a size pick one based on the filesystem 967207141Sjeff * size constrained with hardcoded MIN and MAX values. We opt for 968207141Sjeff * 1/1024th of the filesystem up to MAX but not exceeding one CG and 969207141Sjeff * not less than the MIN. 970207141Sjeff */ 971207141Sjeff if (size == 0) { 972207141Sjeff size = (sblock.fs_size * sblock.fs_bsize) / 1024; 973207141Sjeff size = MIN(SUJ_MAX, size); 974207141Sjeff if (size / sblock.fs_fsize > sblock.fs_fpg) 975207141Sjeff size = sblock.fs_fpg * sblock.fs_fsize; 976207141Sjeff size = MAX(SUJ_MIN, size); 977208241Sjeff /* fsck does not support fragments in journal files. */ 978208241Sjeff size = roundup(size, sblock.fs_bsize); 979207141Sjeff } 980207141Sjeff resid = blocks = size / sblock.fs_bsize; 981207141Sjeff if (sblock.fs_cstotal.cs_nbfree < blocks) { 982207141Sjeff warn("Insufficient free space for %jd byte journal", size); 983207141Sjeff return (-1); 984207141Sjeff } 985207141Sjeff /* 986207141Sjeff * Find a cg with enough blocks to satisfy the journal 987207141Sjeff * size. Presently the journal does not span cgs. 988207141Sjeff */ 989207141Sjeff while (cgread(&disk) == 1) { 990207141Sjeff if (cgp->cg_cs.cs_nifree == 0) 991207141Sjeff continue; 992207141Sjeff ino = cgialloc(&disk); 993207141Sjeff if (ino <= 0) 994207141Sjeff break; 995241013Smdf printf("Using inode %ju in cg %d for %jd byte journal\n", 996241013Smdf (uintmax_t)ino, cgp->cg_cgx, size); 997207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 998207141Sjeff warn("Failed to get allocated inode"); 999207141Sjeff sbdirty(); 1000207141Sjeff goto out; 1001207141Sjeff } 1002207141Sjeff /* 1003207141Sjeff * We leave fields unrelated to the number of allocated 1004207141Sjeff * blocks and size uninitialized. This causes legacy 1005207141Sjeff * fsck implementations to clear the inode. 1006207141Sjeff */ 1007207141Sjeff dp2 = ip; 1008207141Sjeff dp1 = ip; 1009226266Smckusick time(&utime); 1010207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1011207141Sjeff bzero(dp1, sizeof(*dp1)); 1012207141Sjeff dp1->di_size = size; 1013207141Sjeff dp1->di_mode = IFREG | IREAD; 1014207141Sjeff dp1->di_nlink = 1; 1015207141Sjeff dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 1016226266Smckusick dp1->di_atime = utime; 1017226266Smckusick dp1->di_mtime = utime; 1018226266Smckusick dp1->di_ctime = utime; 1019207141Sjeff } else { 1020207141Sjeff bzero(dp2, sizeof(*dp2)); 1021207141Sjeff dp2->di_size = size; 1022207141Sjeff dp2->di_mode = IFREG | IREAD; 1023207141Sjeff dp2->di_nlink = 1; 1024207141Sjeff dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 1025226266Smckusick dp2->di_atime = utime; 1026226266Smckusick dp2->di_mtime = utime; 1027226266Smckusick dp2->di_ctime = utime; 1028226266Smckusick dp2->di_birthtime = utime; 1029207141Sjeff } 1030207141Sjeff for (i = 0; i < NDADDR && resid; i++, resid--) { 1031207141Sjeff blk = journal_balloc(); 1032207141Sjeff if (blk <= 0) 1033207141Sjeff goto out; 1034207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1035207141Sjeff dp1->di_db[i] = blk; 1036207141Sjeff dp1->di_blocks++; 1037207141Sjeff } else { 1038207141Sjeff dp2->di_db[i] = blk; 1039207141Sjeff dp2->di_blocks++; 1040207141Sjeff } 1041207141Sjeff } 1042207141Sjeff for (i = 0; i < NIADDR && resid; i++) { 1043207141Sjeff blk = journal_balloc(); 1044207141Sjeff if (blk <= 0) 1045207141Sjeff goto out; 1046207141Sjeff blks = indir_fill(blk, i, &resid) + 1; 1047207141Sjeff if (blks <= 0) { 1048207141Sjeff sbdirty(); 1049207141Sjeff goto out; 1050207141Sjeff } 1051207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1052207141Sjeff dp1->di_ib[i] = blk; 1053207141Sjeff dp1->di_blocks += blks; 1054207141Sjeff } else { 1055207141Sjeff dp2->di_ib[i] = blk; 1056207141Sjeff dp2->di_blocks += blks; 1057207141Sjeff } 1058207141Sjeff } 1059207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 1060207141Sjeff dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize; 1061207141Sjeff else 1062207141Sjeff dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize; 1063207141Sjeff if (putino(&disk) < 0) { 1064207141Sjeff warn("Failed to write inode"); 1065207141Sjeff sbdirty(); 1066207141Sjeff return (-1); 1067207141Sjeff } 1068207141Sjeff if (cgwrite(&disk) < 0) { 1069207141Sjeff warn("Failed to write updated cg"); 1070207141Sjeff sbdirty(); 1071207141Sjeff return (-1); 1072207141Sjeff } 1073207141Sjeff if (journal_insertfile(ino) < 0) { 1074207141Sjeff sbdirty(); 1075207141Sjeff return (-1); 1076207141Sjeff } 1077207141Sjeff sblock.fs_sujfree = 0; 1078207141Sjeff return (0); 1079207141Sjeff } 1080207141Sjeff warnx("Insufficient free space for the journal."); 1081207141Sjeffout: 1082207141Sjeff return (-1); 1083207141Sjeff} 1084207141Sjeff 1085242265Straszstatic void 1086109597Sjmallettusage(void) 10871558Srgrimes{ 1088216798Skib fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n", 1089111287Sru"usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]", 1090248623Smckusick" [-J enable | disable] [-j enable | disable] [-k metaspace]", 1091207462Sedwin" [-L volname] [-l enable | disable] [-m minfree]", 1092207462Sedwin" [-N enable | disable] [-n enable | disable]", 1093216798Skib" [-o space | time] [-p] [-s avgfpdir] [-t enable | disable]", 1094216798Skib" special | filesystem"); 10951558Srgrimes exit(2); 10961558Srgrimes} 10971558Srgrimes 1098242265Straszstatic void 1099109597Sjmallettprintfs(void) 11001558Srgrimes{ 1101200796Strasz warnx("POSIX.1e ACLs: (-a) %s", 1102105162Srwatson (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled"); 1103200796Strasz warnx("NFSv4 ACLs: (-N) %s", 1104200796Strasz (sblock.fs_flags & FS_NFS4ACLS)? "enabled" : "disabled"); 1105105162Srwatson warnx("MAC multilabel: (-l) %s", 1106105162Srwatson (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled"); 1107109468Sjmallett warnx("soft updates: (-n) %s", 110834266Sjulian (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); 1109207141Sjeff warnx("soft update journaling: (-j) %s", 1110207141Sjeff (sblock.fs_flags & FS_SUJ)? "enabled" : "disabled"); 1111163842Spjd warnx("gjournal: (-J) %s", 1112163842Spjd (sblock.fs_flags & FS_GJOURNAL)? "enabled" : "disabled"); 1113216798Skib warnx("trim: (-t) %s", 1114216798Skib (sblock.fs_flags & FS_TRIM)? "enabled" : "disabled"); 11159315Sjoerg warnx("maximum blocks per file in a cylinder group: (-e) %d", 11169315Sjoerg sblock.fs_maxbpg); 111775377Smckusick warnx("average file size: (-f) %d", 111875377Smckusick sblock.fs_avgfilesize); 111975377Smckusick warnx("average number of files in a directory: (-s) %d", 112075377Smckusick sblock.fs_avgfpdir); 11219315Sjoerg warnx("minimum percentage of free space: (-m) %d%%", 11229315Sjoerg sblock.fs_minfree); 1123248623Smckusick warnx("space to hold for metadata blocks: (-k) %jd", 1124248623Smckusick sblock.fs_metaspace); 11259315Sjoerg warnx("optimization preference: (-o) %s", 11269315Sjoerg sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); 11279315Sjoerg if (sblock.fs_minfree >= MINFREE && 11289315Sjoerg sblock.fs_optim == FS_OPTSPACE) 11299315Sjoerg warnx(OPTWARN, "time", ">=", MINFREE); 11309315Sjoerg if (sblock.fs_minfree < MINFREE && 11319315Sjoerg sblock.fs_optim == FS_OPTTIME) 11329315Sjoerg warnx(OPTWARN, "space", "<", MINFREE); 1133110174Sgordon warnx("volume label: (-L) %s", 1134110174Sgordon sblock.fs_volname); 11359315Sjoerg} 1136