tunefs.c revision 218603
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 218603 2011-02-12 13:12:45Z kib $"); 431558Srgrimes 441558Srgrimes/* 45102231Strhodes * tunefs: change layout parameters to an existing file system. 461558Srgrimes */ 471558Srgrimes#include <sys/param.h> 4842873Sluoqi#include <sys/mount.h> 4996478Sphk#include <sys/disklabel.h> 501558Srgrimes#include <sys/stat.h> 511558Srgrimes 5298542Smckusick#include <ufs/ufs/ufsmount.h> 5398542Smckusick#include <ufs/ufs/dinode.h> 541558Srgrimes#include <ufs/ffs/fs.h> 55207141Sjeff#include <ufs/ufs/dir.h> 561558Srgrimes 57110174Sgordon#include <ctype.h> 581558Srgrimes#include <err.h> 591558Srgrimes#include <fcntl.h> 601558Srgrimes#include <fstab.h> 61109597Sjmallett#include <libufs.h> 6238040Scharnier#include <paths.h> 631558Srgrimes#include <stdio.h> 641558Srgrimes#include <stdlib.h> 65207141Sjeff#include <stdint.h> 6658047Ssheldonh#include <string.h> 671558Srgrimes#include <unistd.h> 681558Srgrimes 691558Srgrimes/* the optimization warning string template */ 701558Srgrimes#define OPTWARN "should optimize for %s with minfree %s %d%%" 711558Srgrimes 72109597Sjmallettstruct uufsd disk; 73109597Sjmallett#define sblock disk.d_fs 741558Srgrimes 7592883Simpvoid usage(void); 7692883Simpvoid printfs(void); 77207141Sjeffint journal_alloc(int64_t size); 78207141Sjeffvoid journal_clear(void); 79207141Sjeffvoid sbdirty(void); 801558Srgrimes 811558Srgrimesint 82109597Sjmallettmain(int argc, char *argv[]) 831558Srgrimes{ 84207141Sjeff char *avalue, *jvalue, *Jvalue, *Lvalue, *lvalue, *Nvalue, *nvalue; 85216798Skib char *tvalue; 86109963Sjmallett const char *special, *on; 8779750Sdd const char *name; 88127455Sbde int active; 89207141Sjeff int Aflag, aflag, eflag, evalue, fflag, fvalue, jflag, Jflag, Lflag; 90207141Sjeff int lflag, mflag, mvalue, Nflag, nflag, oflag, ovalue, pflag, sflag; 91216798Skib int tflag; 92207141Sjeff int svalue, Sflag, Svalue; 93127441Sbde int ch, found_arg, i; 9479750Sdd const char *chg[2]; 9542873Sluoqi struct ufs_args args; 9642873Sluoqi struct statfs stfs; 971558Srgrimes 98127441Sbde if (argc < 3) 99127441Sbde usage(); 100207141Sjeff Aflag = aflag = eflag = fflag = jflag = Jflag = Lflag = lflag = 0; 101216798Skib mflag = Nflag = nflag = oflag = pflag = sflag = tflag = 0; 102207141Sjeff avalue = jvalue = Jvalue = Lvalue = lvalue = Nvalue = nvalue = NULL; 103207141Sjeff evalue = fvalue = mvalue = ovalue = svalue = Svalue = 0; 104127455Sbde active = 0; 105127441Sbde found_arg = 0; /* At least one arg is required. */ 106216798Skib while ((ch = getopt(argc, argv, "Aa:e:f:j:J:L:l:m:N:n:o:ps:S:t:")) 107216798Skib != -1) 108127441Sbde switch (ch) { 109127441Sbde 110127441Sbde case 'A': 111127441Sbde found_arg = 1; 112127441Sbde Aflag++; 113127441Sbde break; 114127441Sbde 115127441Sbde case 'a': 116127441Sbde found_arg = 1; 117200796Strasz name = "POSIX.1e ACLs"; 118127441Sbde avalue = optarg; 119127441Sbde if (strcmp(avalue, "enable") && 120127441Sbde strcmp(avalue, "disable")) { 121127441Sbde errx(10, "bad %s (options are %s)", 122127441Sbde name, "`enable' or `disable'"); 123127441Sbde } 124127441Sbde aflag = 1; 125127441Sbde break; 126127441Sbde 127127441Sbde case 'e': 128127441Sbde found_arg = 1; 129127441Sbde name = "maximum blocks per file in a cylinder group"; 130127441Sbde evalue = atoi(optarg); 131127441Sbde if (evalue < 1) 132127441Sbde errx(10, "%s must be >= 1 (was %s)", 133127441Sbde name, optarg); 134127441Sbde eflag = 1; 135127441Sbde break; 136127441Sbde 137127441Sbde case 'f': 138127441Sbde found_arg = 1; 139127441Sbde name = "average file size"; 140127441Sbde fvalue = atoi(optarg); 141127441Sbde if (fvalue < 1) 142127441Sbde errx(10, "%s must be >= 1 (was %s)", 143127441Sbde name, optarg); 144127441Sbde fflag = 1; 145127441Sbde break; 146127441Sbde 147207141Sjeff case 'j': 148207141Sjeff found_arg = 1; 149207141Sjeff name = "softdep journaled file system"; 150207141Sjeff jvalue = optarg; 151207141Sjeff if (strcmp(jvalue, "enable") && 152207141Sjeff strcmp(jvalue, "disable")) { 153207141Sjeff errx(10, "bad %s (options are %s)", 154207141Sjeff name, "`enable' or `disable'"); 155207141Sjeff } 156207141Sjeff jflag = 1; 157207141Sjeff break; 158207141Sjeff 159163842Spjd case 'J': 160163842Spjd found_arg = 1; 161163842Spjd name = "gjournaled file system"; 162163842Spjd Jvalue = optarg; 163163842Spjd if (strcmp(Jvalue, "enable") && 164163842Spjd strcmp(Jvalue, "disable")) { 165163842Spjd errx(10, "bad %s (options are %s)", 166163842Spjd name, "`enable' or `disable'"); 167163842Spjd } 168163842Spjd Jflag = 1; 169163842Spjd break; 170163842Spjd 171163842Spjd 172127441Sbde case 'L': 173127441Sbde found_arg = 1; 174127441Sbde name = "volume label"; 175127441Sbde Lvalue = optarg; 176127441Sbde i = -1; 177127441Sbde while (isalnum(Lvalue[++i])); 178127441Sbde if (Lvalue[i] != '\0') { 179127441Sbde errx(10, 180127441Sbde "bad %s. Valid characters are alphanumerics.", 181127441Sbde name); 182127441Sbde } 183127441Sbde if (strlen(Lvalue) >= MAXVOLLEN) { 184127441Sbde errx(10, "bad %s. Length is longer than %d.", 185127441Sbde name, MAXVOLLEN - 1); 186127441Sbde } 187127441Sbde Lflag = 1; 188127441Sbde break; 189127441Sbde 190127441Sbde case 'l': 191127441Sbde found_arg = 1; 192127441Sbde name = "multilabel MAC file system"; 193127441Sbde lvalue = optarg; 194127441Sbde if (strcmp(lvalue, "enable") && 195127441Sbde strcmp(lvalue, "disable")) { 196127441Sbde errx(10, "bad %s (options are %s)", 197127441Sbde name, "`enable' or `disable'"); 198127441Sbde } 199127441Sbde lflag = 1; 200127441Sbde break; 201127441Sbde 202127441Sbde case 'm': 203127441Sbde found_arg = 1; 204127441Sbde name = "minimum percentage of free space"; 205127441Sbde mvalue = atoi(optarg); 206127441Sbde if (mvalue < 0 || mvalue > 99) 207127441Sbde errx(10, "bad %s (%s)", name, optarg); 208127441Sbde mflag = 1; 209127441Sbde break; 210127441Sbde 211200796Strasz case 'N': 212200796Strasz found_arg = 1; 213200796Strasz name = "NFSv4 ACLs"; 214200796Strasz Nvalue = optarg; 215200796Strasz if (strcmp(Nvalue, "enable") && 216200796Strasz strcmp(Nvalue, "disable")) { 217200796Strasz errx(10, "bad %s (options are %s)", 218200796Strasz name, "`enable' or `disable'"); 219200796Strasz } 220200796Strasz Nflag = 1; 221200796Strasz break; 222200796Strasz 223127441Sbde case 'n': 224127441Sbde found_arg = 1; 225127441Sbde name = "soft updates"; 226127441Sbde nvalue = optarg; 227127455Sbde if (strcmp(nvalue, "enable") != 0 && 228127455Sbde strcmp(nvalue, "disable") != 0) { 229127441Sbde errx(10, "bad %s (options are %s)", 230127441Sbde name, "`enable' or `disable'"); 231127441Sbde } 232127441Sbde nflag = 1; 233127441Sbde break; 234127441Sbde 235127441Sbde case 'o': 236127441Sbde found_arg = 1; 237127441Sbde name = "optimization preference"; 238127455Sbde if (strcmp(optarg, "space") == 0) 239127441Sbde ovalue = FS_OPTSPACE; 240127455Sbde else if (strcmp(optarg, "time") == 0) 241127441Sbde ovalue = FS_OPTTIME; 242127441Sbde else 243127441Sbde errx(10, 244127441Sbde "bad %s (options are `space' or `time')", 245127441Sbde name); 246127441Sbde oflag = 1; 247127441Sbde break; 248127441Sbde 249127441Sbde case 'p': 250127441Sbde found_arg = 1; 251127441Sbde pflag = 1; 252127441Sbde break; 253127441Sbde 254127441Sbde case 's': 255127441Sbde found_arg = 1; 256127441Sbde name = "expected number of files per directory"; 257127441Sbde svalue = atoi(optarg); 258127441Sbde if (svalue < 1) 259127441Sbde errx(10, "%s must be >= 1 (was %s)", 260127441Sbde name, optarg); 261127441Sbde sflag = 1; 262127441Sbde break; 263127441Sbde 264207141Sjeff case 'S': 265207141Sjeff found_arg = 1; 266207141Sjeff name = "Softdep Journal Size"; 267207141Sjeff Svalue = atoi(optarg); 268207141Sjeff if (Svalue < SUJ_MIN) 269207141Sjeff errx(10, "%s must be >= %d (was %s)", 270207141Sjeff name, SUJ_MIN, optarg); 271207141Sjeff Sflag = 1; 272207141Sjeff break; 273207141Sjeff 274216798Skib case 't': 275216798Skib found_arg = 1; 276216798Skib name = "trim"; 277216798Skib tvalue = optarg; 278216798Skib if (strcmp(tvalue, "enable") != 0 && 279216798Skib strcmp(tvalue, "disable") != 0) { 280216798Skib errx(10, "bad %s (options are %s)", 281216798Skib name, "`enable' or `disable'"); 282216798Skib } 283216798Skib tflag = 1; 284216798Skib break; 285216798Skib 286127441Sbde default: 287127441Sbde usage(); 288105120Srwatson } 28969314Scharnier argc -= optind; 29069314Scharnier argv += optind; 29169314Scharnier if (found_arg == 0 || argc != 1) 292127441Sbde usage(); 29369314Scharnier 294109963Sjmallett on = special = argv[0]; 295109963Sjmallett if (ufs_disk_fillout(&disk, special) == -1) 296109963Sjmallett goto err; 297109963Sjmallett if (disk.d_name != special) { 298207421Sjeff if (statfs(special, &stfs) != 0) 299207421Sjeff warn("Can't stat %s", special); 300207421Sjeff if (strcmp(special, stfs.f_mntonname) == 0) 30169829Scharnier active = 1; 30269829Scharnier } 30369829Scharnier 30469829Scharnier if (pflag) { 30569829Scharnier printfs(); 30669829Scharnier exit(0); 30769829Scharnier } 308110174Sgordon if (Lflag) { 309110174Sgordon name = "volume label"; 310110174Sgordon strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN); 311110174Sgordon } 312105120Srwatson if (aflag) { 313200796Strasz name = "POSIX.1e ACLs"; 314105120Srwatson if (strcmp(avalue, "enable") == 0) { 315105120Srwatson if (sblock.fs_flags & FS_ACLS) { 316105120Srwatson warnx("%s remains unchanged as enabled", name); 317200796Strasz } else if (sblock.fs_flags & FS_NFS4ACLS) { 318200796Strasz warnx("%s and NFSv4 ACLs are mutually " 319200796Strasz "exclusive", name); 320105120Srwatson } else { 321105120Srwatson sblock.fs_flags |= FS_ACLS; 322105120Srwatson warnx("%s set", name); 323105120Srwatson } 324105120Srwatson } else if (strcmp(avalue, "disable") == 0) { 325105120Srwatson if ((~sblock.fs_flags & FS_ACLS) == 326105120Srwatson FS_ACLS) { 327105120Srwatson warnx("%s remains unchanged as disabled", 328105120Srwatson name); 329105120Srwatson } else { 330105120Srwatson sblock.fs_flags &= ~FS_ACLS; 331105206Srwatson warnx("%s cleared", name); 332105120Srwatson } 333105120Srwatson } 334105120Srwatson } 33569829Scharnier if (eflag) { 33669829Scharnier name = "maximum blocks per file in a cylinder group"; 337127455Sbde if (sblock.fs_maxbpg == evalue) 33869829Scharnier warnx("%s remains unchanged as %d", name, evalue); 33969829Scharnier else { 34069829Scharnier warnx("%s changes from %d to %d", 341127455Sbde name, sblock.fs_maxbpg, evalue); 34269829Scharnier sblock.fs_maxbpg = evalue; 34369829Scharnier } 34469829Scharnier } 34575377Smckusick if (fflag) { 34675377Smckusick name = "average file size"; 347203769Smckusick if (sblock.fs_avgfilesize == (unsigned)fvalue) { 34875377Smckusick warnx("%s remains unchanged as %d", name, fvalue); 34975377Smckusick } 35075377Smckusick else { 35175377Smckusick warnx("%s changes from %d to %d", 35275377Smckusick name, sblock.fs_avgfilesize, fvalue); 35375377Smckusick sblock.fs_avgfilesize = fvalue; 35475377Smckusick } 35575377Smckusick } 356207141Sjeff if (jflag) { 357207141Sjeff name = "soft updates journaling"; 358207141Sjeff if (strcmp(jvalue, "enable") == 0) { 359207141Sjeff if ((sblock.fs_flags & (FS_DOSOFTDEP | FS_SUJ)) == 360207141Sjeff (FS_DOSOFTDEP | FS_SUJ)) { 361207141Sjeff warnx("%s remains unchanged as enabled", name); 362207141Sjeff } else if (sblock.fs_clean == 0) { 363207141Sjeff warnx("%s cannot be enabled until fsck is run", 364207141Sjeff name); 365207141Sjeff } else if (journal_alloc(Svalue) != 0) { 366207141Sjeff warnx("%s can not be enabled", name); 367207141Sjeff } else { 368207141Sjeff sblock.fs_flags |= FS_DOSOFTDEP | FS_SUJ; 369207141Sjeff warnx("%s set", name); 370207141Sjeff } 371207141Sjeff } else if (strcmp(jvalue, "disable") == 0) { 372207141Sjeff if ((~sblock.fs_flags & FS_SUJ) == FS_SUJ) { 373207141Sjeff warnx("%s remains unchanged as disabled", name); 374207141Sjeff } else { 375207141Sjeff journal_clear(); 376208241Sjeff sblock.fs_flags &= ~FS_SUJ; 377207141Sjeff sblock.fs_sujfree = 0; 378208241Sjeff warnx("%s cleared but soft updates still set.", 379208241Sjeff name); 380208241Sjeff 381208241Sjeff warnx("remove .sujournal to reclaim space"); 382207141Sjeff } 383207141Sjeff } 384207141Sjeff } 385163842Spjd if (Jflag) { 386163842Spjd name = "gjournal"; 387163842Spjd if (strcmp(Jvalue, "enable") == 0) { 388163842Spjd if (sblock.fs_flags & FS_GJOURNAL) { 389163842Spjd warnx("%s remains unchanged as enabled", name); 390163842Spjd } else { 391163842Spjd sblock.fs_flags |= FS_GJOURNAL; 392163842Spjd warnx("%s set", name); 393163842Spjd } 394163842Spjd } else if (strcmp(Jvalue, "disable") == 0) { 395163842Spjd if ((~sblock.fs_flags & FS_GJOURNAL) == 396163842Spjd FS_GJOURNAL) { 397163842Spjd warnx("%s remains unchanged as disabled", 398163842Spjd name); 399163842Spjd } else { 400163842Spjd sblock.fs_flags &= ~FS_GJOURNAL; 401163842Spjd warnx("%s cleared", name); 402163842Spjd } 403163842Spjd } 404163842Spjd } 405105120Srwatson if (lflag) { 406105120Srwatson name = "multilabel"; 407105120Srwatson if (strcmp(lvalue, "enable") == 0) { 408105120Srwatson if (sblock.fs_flags & FS_MULTILABEL) { 409105120Srwatson warnx("%s remains unchanged as enabled", name); 410105120Srwatson } else { 411105120Srwatson sblock.fs_flags |= FS_MULTILABEL; 412105120Srwatson warnx("%s set", name); 413105120Srwatson } 414105120Srwatson } else if (strcmp(lvalue, "disable") == 0) { 415105120Srwatson if ((~sblock.fs_flags & FS_MULTILABEL) == 416105120Srwatson FS_MULTILABEL) { 417105120Srwatson warnx("%s remains unchanged as disabled", 418105120Srwatson name); 419105120Srwatson } else { 420105120Srwatson sblock.fs_flags &= ~FS_MULTILABEL; 421105206Srwatson warnx("%s cleared", name); 422105120Srwatson } 423105120Srwatson } 424105120Srwatson } 42569829Scharnier if (mflag) { 42669829Scharnier name = "minimum percentage of free space"; 427127455Sbde if (sblock.fs_minfree == mvalue) 42869829Scharnier warnx("%s remains unchanged as %d%%", name, mvalue); 42969829Scharnier else { 43069829Scharnier warnx("%s changes from %d%% to %d%%", 43169829Scharnier name, sblock.fs_minfree, mvalue); 43269829Scharnier sblock.fs_minfree = mvalue; 43369829Scharnier if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE) 43469829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 43569829Scharnier if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME) 43669829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 43769829Scharnier } 43869829Scharnier } 439200796Strasz if (Nflag) { 440200796Strasz name = "NFSv4 ACLs"; 441200796Strasz if (strcmp(Nvalue, "enable") == 0) { 442200796Strasz if (sblock.fs_flags & FS_NFS4ACLS) { 443200796Strasz warnx("%s remains unchanged as enabled", name); 444200796Strasz } else if (sblock.fs_flags & FS_ACLS) { 445200796Strasz warnx("%s and POSIX.1e ACLs are mutually " 446200796Strasz "exclusive", name); 447200796Strasz } else { 448200796Strasz sblock.fs_flags |= FS_NFS4ACLS; 449200796Strasz warnx("%s set", name); 450200796Strasz } 451200796Strasz } else if (strcmp(Nvalue, "disable") == 0) { 452200796Strasz if ((~sblock.fs_flags & FS_NFS4ACLS) == 453200796Strasz FS_NFS4ACLS) { 454200796Strasz warnx("%s remains unchanged as disabled", 455200796Strasz name); 456200796Strasz } else { 457200796Strasz sblock.fs_flags &= ~FS_NFS4ACLS; 458200796Strasz warnx("%s cleared", name); 459200796Strasz } 460200796Strasz } 461200796Strasz } 46269829Scharnier if (nflag) { 46369829Scharnier name = "soft updates"; 46469829Scharnier if (strcmp(nvalue, "enable") == 0) { 465127455Sbde if (sblock.fs_flags & FS_DOSOFTDEP) 46669829Scharnier warnx("%s remains unchanged as enabled", name); 467127455Sbde else if (sblock.fs_clean == 0) { 46875498Smckusick warnx("%s cannot be enabled until fsck is run", 46975498Smckusick name); 47069829Scharnier } else { 47169829Scharnier sblock.fs_flags |= FS_DOSOFTDEP; 47269829Scharnier warnx("%s set", name); 47369829Scharnier } 47469829Scharnier } else if (strcmp(nvalue, "disable") == 0) { 475127455Sbde if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) 47669829Scharnier warnx("%s remains unchanged as disabled", name); 477127455Sbde else { 47869829Scharnier sblock.fs_flags &= ~FS_DOSOFTDEP; 47969829Scharnier warnx("%s cleared", name); 48069829Scharnier } 48169829Scharnier } 48269829Scharnier } 48369829Scharnier if (oflag) { 48469829Scharnier name = "optimization preference"; 48569829Scharnier chg[FS_OPTSPACE] = "space"; 48669829Scharnier chg[FS_OPTTIME] = "time"; 487127455Sbde if (sblock.fs_optim == ovalue) 48869829Scharnier warnx("%s remains unchanged as %s", name, chg[ovalue]); 48969829Scharnier else { 49069829Scharnier warnx("%s changes from %s to %s", 49169829Scharnier name, chg[sblock.fs_optim], chg[ovalue]); 49269829Scharnier sblock.fs_optim = ovalue; 49369829Scharnier if (sblock.fs_minfree >= MINFREE && 494127455Sbde ovalue == FS_OPTSPACE) 49569829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 496127455Sbde if (sblock.fs_minfree < MINFREE && ovalue == FS_OPTTIME) 49769829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 49869829Scharnier } 49969829Scharnier } 50075377Smckusick if (sflag) { 50175377Smckusick name = "expected number of files per directory"; 502203769Smckusick if (sblock.fs_avgfpdir == (unsigned)svalue) { 50375377Smckusick warnx("%s remains unchanged as %d", name, svalue); 50475377Smckusick } 50575377Smckusick else { 50675377Smckusick warnx("%s changes from %d to %d", 50775377Smckusick name, sblock.fs_avgfpdir, svalue); 50875377Smckusick sblock.fs_avgfpdir = svalue; 50975377Smckusick } 51075377Smckusick } 511216798Skib if (tflag) { 512216798Skib name = "issue TRIM to the disk"; 513216798Skib if (strcmp(tvalue, "enable") == 0) { 514216798Skib if (sblock.fs_flags & FS_TRIM) 515216798Skib warnx("%s remains unchanged as enabled", name); 516216798Skib else { 517216798Skib sblock.fs_flags |= FS_TRIM; 518216798Skib warnx("%s set", name); 519216798Skib } 520216798Skib } else if (strcmp(tvalue, "disable") == 0) { 521216798Skib if ((~sblock.fs_flags & FS_TRIM) == FS_TRIM) 522216798Skib warnx("%s remains unchanged as disabled", name); 523216798Skib else { 524216798Skib sblock.fs_flags &= ~FS_TRIM; 525216798Skib warnx("%s cleared", name); 526216798Skib } 527216798Skib } 528216798Skib } 52969829Scharnier 530109963Sjmallett if (sbwrite(&disk, Aflag) == -1) 531109963Sjmallett goto err; 532109963Sjmallett ufs_disk_close(&disk); 53342873Sluoqi if (active) { 53442873Sluoqi bzero(&args, sizeof(args)); 535109963Sjmallett if (mount("ufs", on, 53642873Sluoqi stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) 53742873Sluoqi err(9, "%s: reload", special); 538102231Strhodes warnx("file system reloaded"); 53942873Sluoqi } 5401558Srgrimes exit(0); 541109963Sjmalletterr: 542109963Sjmallett if (disk.d_error != NULL) 543109963Sjmallett errx(11, "%s: %s", special, disk.d_error); 544109963Sjmallett else 545109963Sjmallett err(12, "%s", special); 5461558Srgrimes} 5471558Srgrimes 5481558Srgrimesvoid 549207141Sjeffsbdirty(void) 550207141Sjeff{ 551207141Sjeff disk.d_fs.fs_flags |= FS_UNCLEAN | FS_NEEDSFSCK; 552207141Sjeff disk.d_fs.fs_clean = 0; 553207141Sjeff} 554207141Sjeff 555207141Sjeffint blocks; 556207141Sjeffstatic char clrbuf[MAXBSIZE]; 557207141Sjeff 558207141Sjeffstatic ufs2_daddr_t 559207141Sjeffjournal_balloc(void) 560207141Sjeff{ 561207141Sjeff ufs2_daddr_t blk; 562207141Sjeff struct cg *cgp; 563207141Sjeff int valid; 564207141Sjeff static int contig = 1; 565207141Sjeff 566207141Sjeff cgp = &disk.d_cg; 567207141Sjeff for (;;) { 568207141Sjeff blk = cgballoc(&disk); 569207141Sjeff if (blk > 0) 570207141Sjeff break; 571207141Sjeff /* 572207141Sjeff * If we failed to allocate a block from this cg, move to 573207141Sjeff * the next. 574207141Sjeff */ 575207141Sjeff if (cgwrite(&disk) < 0) { 576207141Sjeff warn("Failed to write updated cg"); 577207141Sjeff return (-1); 578207141Sjeff } 579207141Sjeff while ((valid = cgread(&disk)) == 1) { 580207141Sjeff /* 581207141Sjeff * Try to minimize fragmentation by requiring a minimum 582207141Sjeff * number of blocks present. 583207141Sjeff */ 584208241Sjeff if (cgp->cg_cs.cs_nbfree > 256 * 1024) 585207141Sjeff break; 586207141Sjeff if (contig == 0 && cgp->cg_cs.cs_nbfree) 587207141Sjeff break; 588207141Sjeff } 589207141Sjeff if (valid) 590207141Sjeff continue; 591207141Sjeff /* 592207141Sjeff * Try once through looking only for large contiguous regions 593207141Sjeff * and again taking any space we can find. 594207141Sjeff */ 595207141Sjeff if (contig) { 596207141Sjeff contig = 0; 597207141Sjeff disk.d_ccg = 0; 598207141Sjeff warnx("Journal file fragmented."); 599207141Sjeff continue; 600207141Sjeff } 601207141Sjeff warnx("Failed to find sufficient free blocks for the journal"); 602207141Sjeff return -1; 603207141Sjeff } 604207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), clrbuf, 605207141Sjeff sblock.fs_bsize) <= 0) { 606207141Sjeff warn("Failed to initialize new block"); 607207141Sjeff return -1; 608207141Sjeff } 609207141Sjeff return (blk); 610207141Sjeff} 611207141Sjeff 612207141Sjeff/* 613207141Sjeff * Search a directory block for the SUJ_FILE. 614207141Sjeff */ 615207141Sjeffstatic ino_t 616207141Sjeffdir_search(ufs2_daddr_t blk, int bytes) 617207141Sjeff{ 618207141Sjeff char block[MAXBSIZE]; 619207141Sjeff struct direct *dp; 620207141Sjeff int off; 621207141Sjeff 622207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, bytes) <= 0) { 623207141Sjeff warn("Failed to read dir block"); 624207141Sjeff return (-1); 625207141Sjeff } 626207141Sjeff for (off = 0; off < bytes; off += dp->d_reclen) { 627207141Sjeff dp = (struct direct *)&block[off]; 628207141Sjeff if (dp->d_reclen == 0) 629207141Sjeff break; 630207141Sjeff if (dp->d_ino == 0) 631207141Sjeff continue; 632207141Sjeff if (dp->d_namlen != strlen(SUJ_FILE)) 633207141Sjeff continue; 634207141Sjeff if (bcmp(dp->d_name, SUJ_FILE, dp->d_namlen) != 0) 635207141Sjeff continue; 636207141Sjeff return (dp->d_ino); 637207141Sjeff } 638207141Sjeff 639207141Sjeff return (0); 640207141Sjeff} 641207141Sjeff 642207141Sjeff/* 643207141Sjeff * Search in the ROOTINO for the SUJ_FILE. If it exists we can not enable 644207141Sjeff * journaling. 645207141Sjeff */ 646207141Sjeffstatic ino_t 647207141Sjeffjournal_findfile(void) 648207141Sjeff{ 649207141Sjeff struct ufs1_dinode *dp1; 650207141Sjeff struct ufs2_dinode *dp2; 651207141Sjeff ino_t ino; 652207141Sjeff int mode; 653207141Sjeff void *ip; 654207141Sjeff int i; 655207141Sjeff 656207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 657207141Sjeff warn("Failed to get root inode"); 658207141Sjeff return (-1); 659207141Sjeff } 660207141Sjeff dp2 = ip; 661207141Sjeff dp1 = ip; 662207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 663207141Sjeff if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { 664207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 665207141Sjeff return (-1); 666207141Sjeff } 667207141Sjeff for (i = 0; i < NDADDR; i++) { 668207141Sjeff if (dp1->di_db[i] == 0) 669207141Sjeff break; 670207141Sjeff if ((ino = dir_search(dp1->di_db[i], 671207141Sjeff sblksize(&sblock, (off_t)dp1->di_size, i))) != 0) 672207141Sjeff return (ino); 673207141Sjeff } 674207141Sjeff } else { 675207141Sjeff if ((off_t)dp1->di_size >= lblktosize(&sblock, NDADDR)) { 676207141Sjeff warnx("ROOTINO extends beyond direct blocks."); 677207141Sjeff return (-1); 678207141Sjeff } 679207141Sjeff for (i = 0; i < NDADDR; i++) { 680207141Sjeff if (dp2->di_db[i] == 0) 681207141Sjeff break; 682207141Sjeff if ((ino = dir_search(dp2->di_db[i], 683207141Sjeff sblksize(&sblock, (off_t)dp2->di_size, i))) != 0) 684207141Sjeff return (ino); 685207141Sjeff } 686207141Sjeff } 687207141Sjeff 688207141Sjeff return (0); 689207141Sjeff} 690207141Sjeff 691218603Skibstatic void 692218603Skibdir_clear_block(char *block, off_t off) 693218603Skib{ 694218603Skib struct direct *dp; 695218603Skib 696218603Skib for (; off < sblock.fs_bsize; off += DIRBLKSIZ) { 697218603Skib dp = (struct direct *)&block[off]; 698218603Skib dp->d_ino = 0; 699218603Skib dp->d_reclen = DIRBLKSIZ; 700218603Skib dp->d_type = DT_UNKNOWN; 701218603Skib } 702218603Skib} 703218603Skib 704207141Sjeff/* 705207141Sjeff * Insert the journal at inode 'ino' into directory blk 'blk' at the first 706207141Sjeff * free offset of 'off'. DIRBLKSIZ blocks after off are initialized as 707207141Sjeff * empty. 708207141Sjeff */ 709207141Sjeffstatic int 710207141Sjeffdir_insert(ufs2_daddr_t blk, off_t off, ino_t ino) 711207141Sjeff{ 712207141Sjeff struct direct *dp; 713207141Sjeff char block[MAXBSIZE]; 714207141Sjeff 715207141Sjeff if (bread(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 716207141Sjeff warn("Failed to read dir block"); 717207141Sjeff return (-1); 718207141Sjeff } 719207141Sjeff bzero(&block[off], sblock.fs_bsize - off); 720207141Sjeff dp = (struct direct *)&block[off]; 721207141Sjeff dp->d_ino = ino; 722207141Sjeff dp->d_reclen = DIRBLKSIZ; 723207141Sjeff dp->d_type = DT_REG; 724207141Sjeff dp->d_namlen = strlen(SUJ_FILE); 725207141Sjeff bcopy(SUJ_FILE, &dp->d_name, strlen(SUJ_FILE)); 726218603Skib dir_clear_block(block, off + DIRBLKSIZ); 727207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), block, sblock.fs_bsize) <= 0) { 728207141Sjeff warn("Failed to write dir block"); 729207141Sjeff return (-1); 730207141Sjeff } 731207141Sjeff return (0); 732207141Sjeff} 733207141Sjeff 734207141Sjeff/* 735207141Sjeff * Extend a directory block in 'blk' by copying it to a full size block 736207141Sjeff * and inserting the new journal inode into .sujournal. 737207141Sjeff */ 738207141Sjeffstatic int 739207141Sjeffdir_extend(ufs2_daddr_t blk, ufs2_daddr_t nblk, off_t size, ino_t ino) 740207141Sjeff{ 741207141Sjeff char block[MAXBSIZE]; 742207141Sjeff 743218603Skib if (bread(&disk, fsbtodb(&sblock, blk), block, 744218603Skib roundup(size, sblock.fs_fsize)) <= 0) { 745207141Sjeff warn("Failed to read dir block"); 746207141Sjeff return (-1); 747207141Sjeff } 748218603Skib dir_clear_block(block, size); 749218603Skib if (bwrite(&disk, fsbtodb(&sblock, nblk), block, sblock.fs_bsize) 750218603Skib <= 0) { 751207141Sjeff warn("Failed to write dir block"); 752207141Sjeff return (-1); 753207141Sjeff } 754207141Sjeff 755218603Skib return (dir_insert(nblk, size, ino)); 756207141Sjeff} 757207141Sjeff 758207141Sjeff/* 759207141Sjeff * Insert the journal file into the ROOTINO directory. We always extend the 760207141Sjeff * last frag 761207141Sjeff */ 762207141Sjeffstatic int 763207141Sjeffjournal_insertfile(ino_t ino) 764207141Sjeff{ 765207141Sjeff struct ufs1_dinode *dp1; 766207141Sjeff struct ufs2_dinode *dp2; 767207141Sjeff void *ip; 768207141Sjeff ufs2_daddr_t nblk; 769207141Sjeff ufs2_daddr_t blk; 770207141Sjeff ufs_lbn_t lbn; 771207141Sjeff int size; 772207141Sjeff int mode; 773207141Sjeff int off; 774207141Sjeff 775207141Sjeff if (getino(&disk, &ip, ROOTINO, &mode) != 0) { 776207141Sjeff warn("Failed to get root inode"); 777207141Sjeff sbdirty(); 778207141Sjeff return (-1); 779207141Sjeff } 780207141Sjeff dp2 = ip; 781207141Sjeff dp1 = ip; 782207141Sjeff blk = 0; 783207141Sjeff size = 0; 784207141Sjeff nblk = journal_balloc(); 785207141Sjeff if (nblk <= 0) 786207141Sjeff return (-1); 787207141Sjeff /* 788207141Sjeff * For simplicity sake we aways extend the ROOTINO into a new 789207141Sjeff * directory block rather than searching for space and inserting 790207141Sjeff * into an existing block. However, if the rootino has frags 791207141Sjeff * have to free them and extend the block. 792207141Sjeff */ 793207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 794207141Sjeff lbn = lblkno(&sblock, dp1->di_size); 795207141Sjeff off = blkoff(&sblock, dp1->di_size); 796207141Sjeff blk = dp1->di_db[lbn]; 797207141Sjeff size = sblksize(&sblock, (off_t)dp1->di_size, lbn); 798207141Sjeff } else { 799207141Sjeff lbn = lblkno(&sblock, dp2->di_size); 800207141Sjeff off = blkoff(&sblock, dp2->di_size); 801207141Sjeff blk = dp2->di_db[lbn]; 802207141Sjeff size = sblksize(&sblock, (off_t)dp2->di_size, lbn); 803207141Sjeff } 804207141Sjeff if (off != 0) { 805207141Sjeff if (dir_extend(blk, nblk, off, ino) == -1) 806207141Sjeff return (-1); 807207141Sjeff } else { 808207141Sjeff blk = 0; 809207141Sjeff if (dir_insert(nblk, 0, ino) == -1) 810207141Sjeff return (-1); 811207141Sjeff } 812207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 813207141Sjeff dp1->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 814207141Sjeff dp1->di_db[lbn] = nblk; 815207141Sjeff dp1->di_size = lblktosize(&sblock, lbn+1); 816207141Sjeff } else { 817207141Sjeff dp2->di_blocks += (sblock.fs_bsize - size) / DEV_BSIZE; 818207141Sjeff dp2->di_db[lbn] = nblk; 819207141Sjeff dp2->di_size = lblktosize(&sblock, lbn+1); 820207141Sjeff } 821207141Sjeff if (putino(&disk) < 0) { 822207141Sjeff warn("Failed to write root inode"); 823207141Sjeff return (-1); 824207141Sjeff } 825207141Sjeff if (cgwrite(&disk) < 0) { 826207141Sjeff warn("Failed to write updated cg"); 827207141Sjeff sbdirty(); 828207141Sjeff return (-1); 829207141Sjeff } 830207141Sjeff if (blk) { 831207141Sjeff if (cgbfree(&disk, blk, size) < 0) { 832207141Sjeff warn("Failed to write cg"); 833207141Sjeff return (-1); 834207141Sjeff } 835207141Sjeff } 836207141Sjeff 837207141Sjeff return (0); 838207141Sjeff} 839207141Sjeff 840207141Sjeffstatic int 841207141Sjeffindir_fill(ufs2_daddr_t blk, int level, int *resid) 842207141Sjeff{ 843207141Sjeff char indirbuf[MAXBSIZE]; 844207141Sjeff ufs1_daddr_t *bap1; 845207141Sjeff ufs2_daddr_t *bap2; 846207141Sjeff ufs2_daddr_t nblk; 847207141Sjeff int ncnt; 848207141Sjeff int cnt; 849207141Sjeff int i; 850207141Sjeff 851207141Sjeff bzero(indirbuf, sizeof(indirbuf)); 852207141Sjeff bap1 = (ufs1_daddr_t *)indirbuf; 853207141Sjeff bap2 = (void *)bap1; 854207141Sjeff cnt = 0; 855207141Sjeff for (i = 0; i < NINDIR(&sblock) && *resid != 0; i++) { 856207141Sjeff nblk = journal_balloc(); 857207141Sjeff if (nblk <= 0) 858207141Sjeff return (-1); 859207141Sjeff cnt++; 860207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 861207141Sjeff *bap1++ = nblk; 862207141Sjeff else 863207141Sjeff *bap2++ = nblk; 864207141Sjeff if (level != 0) { 865207141Sjeff ncnt = indir_fill(nblk, level - 1, resid); 866207141Sjeff if (ncnt <= 0) 867207141Sjeff return (-1); 868207141Sjeff cnt += ncnt; 869207141Sjeff } else 870207141Sjeff (*resid)--; 871207141Sjeff } 872207141Sjeff if (bwrite(&disk, fsbtodb(&sblock, blk), indirbuf, 873207141Sjeff sblock.fs_bsize) <= 0) { 874207141Sjeff warn("Failed to write indirect"); 875207141Sjeff return (-1); 876207141Sjeff } 877207141Sjeff return (cnt); 878207141Sjeff} 879207141Sjeff 880207141Sjeff/* 881207141Sjeff * Clear the flag bits so the journal can be removed. 882207141Sjeff */ 883207141Sjeffvoid 884207141Sjeffjournal_clear(void) 885207141Sjeff{ 886207141Sjeff struct ufs1_dinode *dp1; 887207141Sjeff struct ufs2_dinode *dp2; 888207141Sjeff ino_t ino; 889207141Sjeff int mode; 890207141Sjeff void *ip; 891207141Sjeff 892207141Sjeff ino = journal_findfile(); 893207141Sjeff if (ino == (ino_t)-1 || ino == 0) { 894207141Sjeff warnx("Journal file does not exist"); 895207141Sjeff return; 896207141Sjeff } 897207141Sjeff printf("Clearing journal flags from inode %d\n", ino); 898207141Sjeff if (getino(&disk, &ip, ino, &mode) != 0) { 899207141Sjeff warn("Failed to get journal inode"); 900207141Sjeff return; 901207141Sjeff } 902207141Sjeff dp2 = ip; 903207141Sjeff dp1 = ip; 904207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 905207141Sjeff dp1->di_flags = 0; 906207141Sjeff else 907207141Sjeff dp2->di_flags = 0; 908207141Sjeff if (putino(&disk) < 0) { 909207141Sjeff warn("Failed to write journal inode"); 910207141Sjeff return; 911207141Sjeff } 912207141Sjeff} 913207141Sjeff 914207141Sjeffint 915207141Sjeffjournal_alloc(int64_t size) 916207141Sjeff{ 917207141Sjeff struct ufs1_dinode *dp1; 918207141Sjeff struct ufs2_dinode *dp2; 919207141Sjeff ufs2_daddr_t blk; 920207141Sjeff void *ip; 921207141Sjeff struct cg *cgp; 922207141Sjeff int resid; 923207141Sjeff ino_t ino; 924207141Sjeff int blks; 925207141Sjeff int mode; 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; 972207141Sjeff printf("Using inode %d in cg %d for %jd byte journal\n", 973207141Sjeff 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; 986207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 987207141Sjeff bzero(dp1, sizeof(*dp1)); 988207141Sjeff dp1->di_size = size; 989207141Sjeff dp1->di_mode = IFREG | IREAD; 990207141Sjeff dp1->di_nlink = 1; 991207141Sjeff dp1->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 992207141Sjeff } else { 993207141Sjeff bzero(dp2, sizeof(*dp2)); 994207141Sjeff dp2->di_size = size; 995207141Sjeff dp2->di_mode = IFREG | IREAD; 996207141Sjeff dp2->di_nlink = 1; 997207141Sjeff dp2->di_flags = SF_IMMUTABLE | SF_NOUNLINK | UF_NODUMP; 998207141Sjeff } 999207141Sjeff for (i = 0; i < NDADDR && resid; i++, resid--) { 1000207141Sjeff blk = journal_balloc(); 1001207141Sjeff if (blk <= 0) 1002207141Sjeff goto out; 1003207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1004207141Sjeff dp1->di_db[i] = blk; 1005207141Sjeff dp1->di_blocks++; 1006207141Sjeff } else { 1007207141Sjeff dp2->di_db[i] = blk; 1008207141Sjeff dp2->di_blocks++; 1009207141Sjeff } 1010207141Sjeff } 1011207141Sjeff for (i = 0; i < NIADDR && resid; i++) { 1012207141Sjeff blk = journal_balloc(); 1013207141Sjeff if (blk <= 0) 1014207141Sjeff goto out; 1015207141Sjeff blks = indir_fill(blk, i, &resid) + 1; 1016207141Sjeff if (blks <= 0) { 1017207141Sjeff sbdirty(); 1018207141Sjeff goto out; 1019207141Sjeff } 1020207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) { 1021207141Sjeff dp1->di_ib[i] = blk; 1022207141Sjeff dp1->di_blocks += blks; 1023207141Sjeff } else { 1024207141Sjeff dp2->di_ib[i] = blk; 1025207141Sjeff dp2->di_blocks += blks; 1026207141Sjeff } 1027207141Sjeff } 1028207141Sjeff if (sblock.fs_magic == FS_UFS1_MAGIC) 1029207141Sjeff dp1->di_blocks *= sblock.fs_bsize / disk.d_bsize; 1030207141Sjeff else 1031207141Sjeff dp2->di_blocks *= sblock.fs_bsize / disk.d_bsize; 1032207141Sjeff if (putino(&disk) < 0) { 1033207141Sjeff warn("Failed to write inode"); 1034207141Sjeff sbdirty(); 1035207141Sjeff return (-1); 1036207141Sjeff } 1037207141Sjeff if (cgwrite(&disk) < 0) { 1038207141Sjeff warn("Failed to write updated cg"); 1039207141Sjeff sbdirty(); 1040207141Sjeff return (-1); 1041207141Sjeff } 1042207141Sjeff if (journal_insertfile(ino) < 0) { 1043207141Sjeff sbdirty(); 1044207141Sjeff return (-1); 1045207141Sjeff } 1046207141Sjeff sblock.fs_sujfree = 0; 1047207141Sjeff return (0); 1048207141Sjeff } 1049207141Sjeff warnx("Insufficient free space for the journal."); 1050207141Sjeffout: 1051207141Sjeff return (-1); 1052207141Sjeff} 1053207141Sjeff 1054207141Sjeffvoid 1055109597Sjmallettusage(void) 10561558Srgrimes{ 1057216798Skib fprintf(stderr, "%s\n%s\n%s\n%s\n%s\n%s\n", 1058111287Sru"usage: tunefs [-A] [-a enable | disable] [-e maxbpg] [-f avgfilesize]", 1059207462Sedwin" [-J enable | disable] [-j enable | disable]", 1060207462Sedwin" [-L volname] [-l enable | disable] [-m minfree]", 1061207462Sedwin" [-N enable | disable] [-n enable | disable]", 1062216798Skib" [-o space | time] [-p] [-s avgfpdir] [-t enable | disable]", 1063216798Skib" special | filesystem"); 10641558Srgrimes exit(2); 10651558Srgrimes} 10661558Srgrimes 10671558Srgrimesvoid 1068109597Sjmallettprintfs(void) 10691558Srgrimes{ 1070200796Strasz warnx("POSIX.1e ACLs: (-a) %s", 1071105162Srwatson (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled"); 1072200796Strasz warnx("NFSv4 ACLs: (-N) %s", 1073200796Strasz (sblock.fs_flags & FS_NFS4ACLS)? "enabled" : "disabled"); 1074105162Srwatson warnx("MAC multilabel: (-l) %s", 1075105162Srwatson (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled"); 1076109468Sjmallett warnx("soft updates: (-n) %s", 107734266Sjulian (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); 1078207141Sjeff warnx("soft update journaling: (-j) %s", 1079207141Sjeff (sblock.fs_flags & FS_SUJ)? "enabled" : "disabled"); 1080163842Spjd warnx("gjournal: (-J) %s", 1081163842Spjd (sblock.fs_flags & FS_GJOURNAL)? "enabled" : "disabled"); 1082216798Skib warnx("trim: (-t) %s", 1083216798Skib (sblock.fs_flags & FS_TRIM)? "enabled" : "disabled"); 10849315Sjoerg warnx("maximum blocks per file in a cylinder group: (-e) %d", 10859315Sjoerg sblock.fs_maxbpg); 108675377Smckusick warnx("average file size: (-f) %d", 108775377Smckusick sblock.fs_avgfilesize); 108875377Smckusick warnx("average number of files in a directory: (-s) %d", 108975377Smckusick sblock.fs_avgfpdir); 10909315Sjoerg warnx("minimum percentage of free space: (-m) %d%%", 10919315Sjoerg sblock.fs_minfree); 10929315Sjoerg warnx("optimization preference: (-o) %s", 10939315Sjoerg sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); 10949315Sjoerg if (sblock.fs_minfree >= MINFREE && 10959315Sjoerg sblock.fs_optim == FS_OPTSPACE) 10969315Sjoerg warnx(OPTWARN, "time", ">=", MINFREE); 10979315Sjoerg if (sblock.fs_minfree < MINFREE && 10989315Sjoerg sblock.fs_optim == FS_OPTTIME) 10999315Sjoerg warnx(OPTWARN, "space", "<", MINFREE); 1100110174Sgordon warnx("volume label: (-L) %s", 1101110174Sgordon sblock.fs_volname); 11029315Sjoerg} 1103