tunefs.c revision 110174
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 * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 3538040Scharnierstatic const char copyright[] = 361558Srgrimes"@(#) Copyright (c) 1983, 1993\n\ 371558Srgrimes The Regents of the University of California. All rights reserved.\n"; 381558Srgrimes#endif /* not lint */ 391558Srgrimes 401558Srgrimes#ifndef lint 4138040Scharnier#if 0 421558Srgrimesstatic char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94"; 4338040Scharnier#endif 4438040Scharnierstatic const char rcsid[] = 4550476Speter "$FreeBSD: head/sbin/tunefs/tunefs.c 110174 2003-02-01 04:17:10Z gordon $"; 461558Srgrimes#endif /* not lint */ 471558Srgrimes 481558Srgrimes/* 49102231Strhodes * tunefs: change layout parameters to an existing file system. 501558Srgrimes */ 511558Srgrimes#include <sys/param.h> 5242873Sluoqi#include <sys/mount.h> 5396478Sphk#include <sys/disklabel.h> 541558Srgrimes#include <sys/stat.h> 551558Srgrimes 5698542Smckusick#include <ufs/ufs/ufsmount.h> 5798542Smckusick#include <ufs/ufs/dinode.h> 581558Srgrimes#include <ufs/ffs/fs.h> 591558Srgrimes 60110174Sgordon#include <ctype.h> 611558Srgrimes#include <err.h> 621558Srgrimes#include <fcntl.h> 631558Srgrimes#include <fstab.h> 64109597Sjmallett#include <libufs.h> 6538040Scharnier#include <paths.h> 661558Srgrimes#include <stdio.h> 671558Srgrimes#include <stdlib.h> 6858047Ssheldonh#include <string.h> 691558Srgrimes#include <unistd.h> 701558Srgrimes 711558Srgrimes/* the optimization warning string template */ 721558Srgrimes#define OPTWARN "should optimize for %s with minfree %s %d%%" 731558Srgrimes 74109597Sjmallettstruct uufsd disk; 75109597Sjmallett#define sblock disk.d_fs 761558Srgrimes 7792883Simpvoid usage(void); 7892883Simpvoid printfs(void); 791558Srgrimes 801558Srgrimesint 81109597Sjmallettmain(int argc, char *argv[]) 821558Srgrimes{ 83109963Sjmallett const char *special, *on; 8479750Sdd const char *name; 85110174Sgordon int Aflag = 0, Lflag = 0, active = 0, aflag = 0; 86105120Srwatson int eflag = 0, fflag = 0, lflag = 0, mflag = 0; 8775377Smckusick int nflag = 0, oflag = 0, pflag = 0, sflag = 0; 88103005Sphk int evalue = 0, fvalue = 0; 8975377Smckusick int mvalue = 0, ovalue = 0, svalue = 0; 90110174Sgordon char *Lvalue = NULL, *avalue = NULL, *lvalue = NULL, *nvalue = NULL; 9179750Sdd const char *chg[2]; 9242873Sluoqi struct ufs_args args; 9342873Sluoqi struct statfs stfs; 94110174Sgordon int found_arg, ch, i; 951558Srgrimes 9669314Scharnier if (argc < 3) 9769314Scharnier usage(); 9869314Scharnier found_arg = 0; /* at least one arg is required */ 99110174Sgordon while ((ch = getopt(argc, argv, "AL:a:e:f:l:m:n:o:ps:")) != -1) 10069314Scharnier switch (ch) { 101105156Srwatson case 'A': 102105156Srwatson found_arg = 1; 103105156Srwatson Aflag++; 104105156Srwatson break; 105110174Sgordon case 'L': 106110174Sgordon found_arg = 1; 107110174Sgordon name = "volume label"; 108110174Sgordon Lvalue = optarg; 109110174Sgordon i = -1; 110110174Sgordon while (isalnum(Lvalue[++i])); 111110174Sgordon if (Lvalue[i] != '\0') { 112110174Sgordon errx(10, "bad %s. Valid characters are alphanumerics.", 113110174Sgordon name); 114110174Sgordon } 115110174Sgordon if (strlen(Lvalue) >= MAXVOLLEN) { 116110174Sgordon errx(10, "bad %s. Length is longer than %d.", 117110174Sgordon name, MAXVOLLEN - 1); 118110174Sgordon } 119110174Sgordon Lflag = 1; 120110174Sgordon break; 121105120Srwatson case 'a': 122105120Srwatson found_arg = 1; 123105120Srwatson name = "ACLs"; 124105120Srwatson avalue = optarg; 125105120Srwatson if (strcmp(avalue, "enable") && strcmp(avalue, "disable")) { 126105120Srwatson errx(10, "bad %s (options are %s)", name, 127105120Srwatson "`enable' or `disable'"); 128105120Srwatson } 129105120Srwatson aflag = 1; 130105120Srwatson break; 13169314Scharnier case 'e': 13269314Scharnier found_arg = 1; 13369314Scharnier name = "maximum blocks per file in a cylinder group"; 13469829Scharnier evalue = atoi(optarg); 13569829Scharnier if (evalue < 1) 13669314Scharnier errx(10, "%s must be >= 1 (was %s)", name, optarg); 13769829Scharnier eflag = 1; 13869314Scharnier break; 13975377Smckusick case 'f': 14075377Smckusick found_arg = 1; 14175377Smckusick name = "average file size"; 14275377Smckusick fvalue = atoi(optarg); 14375377Smckusick if (fvalue < 1) 14475377Smckusick errx(10, "%s must be >= 1 (was %s)", name, optarg); 14575377Smckusick fflag = 1; 14675377Smckusick break; 147105120Srwatson case 'l': 148105120Srwatson found_arg = 1; 149105120Srwatson name = "multilabel MAC file system"; 150105120Srwatson lvalue = optarg; 151105120Srwatson if (strcmp(lvalue, "enable") && strcmp(lvalue, "disable")) { 152105120Srwatson errx(10, "bad %s (options are %s)", name, 153105120Srwatson "`enable' or `disable'"); 154105120Srwatson } 155105120Srwatson lflag = 1; 156105120Srwatson break; 15769314Scharnier case 'm': 15869314Scharnier found_arg = 1; 15969314Scharnier name = "minimum percentage of free space"; 16069829Scharnier mvalue = atoi(optarg); 16169829Scharnier if (mvalue < 0 || mvalue > 99) 16269314Scharnier errx(10, "bad %s (%s)", name, optarg); 16369829Scharnier mflag = 1; 16469314Scharnier break; 16569314Scharnier case 'n': 16669314Scharnier found_arg = 1; 16769314Scharnier name = "soft updates"; 16869829Scharnier nvalue = optarg; 16969829Scharnier if (strcmp(nvalue, "enable") && strcmp(nvalue, "disable")) { 17069314Scharnier errx(10, "bad %s (options are %s)", 17169314Scharnier name, "`enable' or `disable'"); 17269314Scharnier } 17369829Scharnier nflag = 1; 17469314Scharnier break; 17569314Scharnier case 'o': 17669314Scharnier found_arg = 1; 17769314Scharnier name = "optimization preference"; 17869314Scharnier chg[FS_OPTSPACE] = "space"; 17969314Scharnier chg[FS_OPTTIME] = "time"; 18069314Scharnier if (strcmp(optarg, chg[FS_OPTSPACE]) == 0) 18169829Scharnier ovalue = FS_OPTSPACE; 18269314Scharnier else if (strcmp(optarg, chg[FS_OPTTIME]) == 0) 18369829Scharnier ovalue = FS_OPTTIME; 18469314Scharnier else 18569314Scharnier errx(10, "bad %s (options are `space' or `time')", 1861558Srgrimes name); 18769829Scharnier oflag = 1; 18869314Scharnier break; 18969314Scharnier case 'p': 19071790Sben found_arg = 1; 19169829Scharnier pflag = 1; 19269829Scharnier break; 19375377Smckusick case 's': 19475377Smckusick found_arg = 1; 19575377Smckusick name = "expected number of files per directory"; 19675377Smckusick svalue = atoi(optarg); 19775377Smckusick if (svalue < 1) 19875377Smckusick errx(10, "%s must be >= 1 (was %s)", name, optarg); 19975377Smckusick sflag = 1; 20075377Smckusick break; 20169314Scharnier default: 20269314Scharnier usage(); 20369314Scharnier } 20469314Scharnier argc -= optind; 20569314Scharnier argv += optind; 2061558Srgrimes 20769314Scharnier if (found_arg == 0 || argc != 1) 20869314Scharnier usage(); 20969314Scharnier 210109963Sjmallett on = special = argv[0]; 211109963Sjmallett if (ufs_disk_fillout(&disk, special) == -1) 212109963Sjmallett goto err; 213109963Sjmallett if (disk.d_name != special) { 214109963Sjmallett special = disk.d_name; 21569829Scharnier if (statfs(special, &stfs) == 0 && 216109963Sjmallett strcmp(special, stfs.f_mntonname) == 0) 21769829Scharnier active = 1; 21869829Scharnier } 21969829Scharnier 22069829Scharnier if (pflag) { 22169829Scharnier printfs(); 22269829Scharnier exit(0); 22369829Scharnier } 224110174Sgordon if (Lflag) { 225110174Sgordon name = "volume label"; 226110174Sgordon strlcpy(sblock.fs_volname, Lvalue, MAXVOLLEN); 227110174Sgordon } 228105120Srwatson if (aflag) { 229105120Srwatson name = "ACLs"; 230105120Srwatson if (strcmp(avalue, "enable") == 0) { 231105120Srwatson if (sblock.fs_flags & FS_ACLS) { 232105120Srwatson warnx("%s remains unchanged as enabled", name); 233105120Srwatson } else { 234105120Srwatson sblock.fs_flags |= FS_ACLS; 235105120Srwatson warnx("%s set", name); 236105120Srwatson } 237105120Srwatson } else if (strcmp(avalue, "disable") == 0) { 238105120Srwatson if ((~sblock.fs_flags & FS_ACLS) == 239105120Srwatson FS_ACLS) { 240105120Srwatson warnx("%s remains unchanged as disabled", 241105120Srwatson name); 242105120Srwatson } else { 243105120Srwatson sblock.fs_flags &= ~FS_ACLS; 244105206Srwatson warnx("%s cleared", name); 245105120Srwatson } 246105120Srwatson } 247105120Srwatson } 24869829Scharnier if (eflag) { 24969829Scharnier name = "maximum blocks per file in a cylinder group"; 25069829Scharnier if (sblock.fs_maxbpg == evalue) { 25169829Scharnier warnx("%s remains unchanged as %d", name, evalue); 25269829Scharnier } 25369829Scharnier else { 25469829Scharnier warnx("%s changes from %d to %d", 25569829Scharnier name, sblock.fs_maxbpg, evalue); 25669829Scharnier sblock.fs_maxbpg = evalue; 25769829Scharnier } 25869829Scharnier } 25975377Smckusick if (fflag) { 26075377Smckusick name = "average file size"; 26175377Smckusick if (sblock.fs_avgfilesize == fvalue) { 26275377Smckusick warnx("%s remains unchanged as %d", name, fvalue); 26375377Smckusick } 26475377Smckusick else { 26575377Smckusick warnx("%s changes from %d to %d", 26675377Smckusick name, sblock.fs_avgfilesize, fvalue); 26775377Smckusick sblock.fs_avgfilesize = fvalue; 26875377Smckusick } 26975377Smckusick } 270105120Srwatson if (lflag) { 271105120Srwatson name = "multilabel"; 272105120Srwatson if (strcmp(lvalue, "enable") == 0) { 273105120Srwatson if (sblock.fs_flags & FS_MULTILABEL) { 274105120Srwatson warnx("%s remains unchanged as enabled", name); 275105120Srwatson } else { 276105120Srwatson sblock.fs_flags |= FS_MULTILABEL; 277105120Srwatson warnx("%s set", name); 278105120Srwatson } 279105120Srwatson } else if (strcmp(lvalue, "disable") == 0) { 280105120Srwatson if ((~sblock.fs_flags & FS_MULTILABEL) == 281105120Srwatson FS_MULTILABEL) { 282105120Srwatson warnx("%s remains unchanged as disabled", 283105120Srwatson name); 284105120Srwatson } else { 285105120Srwatson sblock.fs_flags &= ~FS_MULTILABEL; 286105206Srwatson warnx("%s cleared", name); 287105120Srwatson } 288105120Srwatson } 289105120Srwatson } 29069829Scharnier if (mflag) { 29169829Scharnier name = "minimum percentage of free space"; 29269829Scharnier if (sblock.fs_minfree == mvalue) { 29369829Scharnier warnx("%s remains unchanged as %d%%", name, mvalue); 29469829Scharnier } 29569829Scharnier else { 29669829Scharnier warnx("%s changes from %d%% to %d%%", 29769829Scharnier name, sblock.fs_minfree, mvalue); 29869829Scharnier sblock.fs_minfree = mvalue; 29969829Scharnier if (mvalue >= MINFREE && sblock.fs_optim == FS_OPTSPACE) 30069829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 30169829Scharnier if (mvalue < MINFREE && sblock.fs_optim == FS_OPTTIME) 30269829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 30369829Scharnier } 30469829Scharnier } 30569829Scharnier if (nflag) { 30669829Scharnier name = "soft updates"; 30769829Scharnier if (strcmp(nvalue, "enable") == 0) { 30875498Smckusick if (sblock.fs_flags & FS_DOSOFTDEP) { 30969829Scharnier warnx("%s remains unchanged as enabled", name); 31075498Smckusick } else if (sblock.fs_clean == 0) { 31175498Smckusick warnx("%s cannot be enabled until fsck is run", 31275498Smckusick name); 31369829Scharnier } else { 31469829Scharnier sblock.fs_flags |= FS_DOSOFTDEP; 31569829Scharnier warnx("%s set", name); 31669829Scharnier } 31769829Scharnier } else if (strcmp(nvalue, "disable") == 0) { 31869829Scharnier if ((~sblock.fs_flags & FS_DOSOFTDEP) == FS_DOSOFTDEP) { 31969829Scharnier warnx("%s remains unchanged as disabled", name); 32069829Scharnier } else { 32169829Scharnier sblock.fs_flags &= ~FS_DOSOFTDEP; 32269829Scharnier warnx("%s cleared", name); 32369829Scharnier } 32469829Scharnier } 32569829Scharnier } 32669829Scharnier if (oflag) { 32769829Scharnier name = "optimization preference"; 32869829Scharnier chg[FS_OPTSPACE] = "space"; 32969829Scharnier chg[FS_OPTTIME] = "time"; 33069829Scharnier if (sblock.fs_optim == ovalue) { 33169829Scharnier warnx("%s remains unchanged as %s", name, chg[ovalue]); 33269829Scharnier } 33369829Scharnier else { 33469829Scharnier warnx("%s changes from %s to %s", 33569829Scharnier name, chg[sblock.fs_optim], chg[ovalue]); 33669829Scharnier sblock.fs_optim = ovalue; 33769829Scharnier if (sblock.fs_minfree >= MINFREE && 33869829Scharnier ovalue == FS_OPTSPACE) 33969829Scharnier warnx(OPTWARN, "time", ">=", MINFREE); 34069829Scharnier if (sblock.fs_minfree < MINFREE && 34169829Scharnier ovalue == FS_OPTTIME) 34269829Scharnier warnx(OPTWARN, "space", "<", MINFREE); 34369829Scharnier } 34469829Scharnier } 34575377Smckusick if (sflag) { 34675377Smckusick name = "expected number of files per directory"; 34775377Smckusick if (sblock.fs_avgfpdir == svalue) { 34875377Smckusick warnx("%s remains unchanged as %d", name, svalue); 34975377Smckusick } 35075377Smckusick else { 35175377Smckusick warnx("%s changes from %d to %d", 35275377Smckusick name, sblock.fs_avgfpdir, svalue); 35375377Smckusick sblock.fs_avgfpdir = svalue; 35475377Smckusick } 35575377Smckusick } 35669829Scharnier 357109963Sjmallett if (sbwrite(&disk, Aflag) == -1) 358109963Sjmallett goto err; 359109963Sjmallett ufs_disk_close(&disk); 36042873Sluoqi if (active) { 36142873Sluoqi bzero(&args, sizeof(args)); 362109963Sjmallett if (mount("ufs", on, 36342873Sluoqi stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) 36442873Sluoqi err(9, "%s: reload", special); 365102231Strhodes warnx("file system reloaded"); 36642873Sluoqi } 3671558Srgrimes exit(0); 368109963Sjmalletterr: 369109963Sjmallett if (disk.d_error != NULL) 370109963Sjmallett errx(11, "%s: %s", special, disk.d_error); 371109963Sjmallett else 372109963Sjmallett err(12, "%s", special); 3731558Srgrimes} 3741558Srgrimes 3751558Srgrimesvoid 376109597Sjmallettusage(void) 3771558Srgrimes{ 378110174Sgordon fprintf(stderr, "%s\n%s\n%s\n%s\n", 379110174Sgordon"usage: tunefs [-A] [-L volname] [-a enable | disable] [-e maxbpg]", 380110174Sgordon" [-f avgfilesize] [-l enable | disable] [-m minfree]", 381110174Sgordon" [-n enable | disable] [-o space | time] [-p]", 382110174Sgordon" [-s avgfpdir] special | filesystem"); 3831558Srgrimes exit(2); 3841558Srgrimes} 3851558Srgrimes 3861558Srgrimesvoid 387109597Sjmallettprintfs(void) 3881558Srgrimes{ 389105162Srwatson warnx("ACLs: (-a) %s", 390105162Srwatson (sblock.fs_flags & FS_ACLS)? "enabled" : "disabled"); 391105162Srwatson warnx("MAC multilabel: (-l) %s", 392105162Srwatson (sblock.fs_flags & FS_MULTILABEL)? "enabled" : "disabled"); 393109468Sjmallett warnx("soft updates: (-n) %s", 39434266Sjulian (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); 3959315Sjoerg warnx("maximum blocks per file in a cylinder group: (-e) %d", 3969315Sjoerg sblock.fs_maxbpg); 39775377Smckusick warnx("average file size: (-f) %d", 39875377Smckusick sblock.fs_avgfilesize); 39975377Smckusick warnx("average number of files in a directory: (-s) %d", 40075377Smckusick sblock.fs_avgfpdir); 4019315Sjoerg warnx("minimum percentage of free space: (-m) %d%%", 4029315Sjoerg sblock.fs_minfree); 4039315Sjoerg warnx("optimization preference: (-o) %s", 4049315Sjoerg sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); 4059315Sjoerg if (sblock.fs_minfree >= MINFREE && 4069315Sjoerg sblock.fs_optim == FS_OPTSPACE) 4079315Sjoerg warnx(OPTWARN, "time", ">=", MINFREE); 4089315Sjoerg if (sblock.fs_minfree < MINFREE && 4099315Sjoerg sblock.fs_optim == FS_OPTTIME) 4109315Sjoerg warnx(OPTWARN, "space", "<", MINFREE); 411110174Sgordon warnx("volume label: (-L) %s", 412110174Sgordon sblock.fs_volname); 4139315Sjoerg} 414