tunefs.c revision 69314
117683Spst/* 239291Sfenner * Copyright (c) 1983, 1993 317683Spst * The Regents of the University of California. All rights reserved. 417683Spst * 517683Spst * Redistribution and use in source and binary forms, with or without 617683Spst * modification, are permitted provided that the following conditions 717683Spst * are met: 817683Spst * 1. Redistributions of source code must retain the above copyright 917683Spst * notice, this list of conditions and the following disclaimer. 1017683Spst * 2. Redistributions in binary form must reproduce the above copyright 1117683Spst * notice, this list of conditions and the following disclaimer in the 1217683Spst * documentation and/or other materials provided with the distribution. 1317683Spst * 3. All advertising materials mentioning features or use of this software 1417683Spst * must display the following acknowledgement: 1517683Spst * This product includes software developed by the University of 1617683Spst * California, Berkeley and its contributors. 1717683Spst * 4. Neither the name of the University nor the names of its contributors 1817683Spst * may be used to endorse or promote products derived from this software 1917683Spst * without specific prior written permission. 2017683Spst * 2117683Spst * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22127664Sbms * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23214518Srpaulo * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2417683Spst * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2517683Spst * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2675107Sfenner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2775107Sfenner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2875107Sfenner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2975107Sfenner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3017683Spst * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3117683Spst * SUCH DAMAGE. 3217683Spst */ 3317683Spst 3417683Spst#ifndef lint 3517683Spststatic const char copyright[] = 3617683Spst"@(#) Copyright (c) 1983, 1993\n\ 3717683Spst The Regents of the University of California. All rights reserved.\n"; 3817683Spst#endif /* not lint */ 3917683Spst 4017683Spst#ifndef lint 4117683Spst#if 0 4217683Spststatic char sccsid[] = "@(#)tunefs.c 8.2 (Berkeley) 4/19/94"; 4317683Spst#endif 4417683Spststatic const char rcsid[] = 4517683Spst "$FreeBSD: head/sbin/tunefs/tunefs.c 69314 2000-11-28 18:17:15Z charnier $"; 4617683Spst#endif /* not lint */ 4717683Spst 4817683Spst/* 4917683Spst * tunefs: change layout parameters to an existing file system. 5017683Spst */ 5117683Spst#include <sys/param.h> 5217683Spst#include <sys/mount.h> 5317683Spst#include <sys/stat.h> 5417683Spst 5517683Spst#include <ufs/ffs/fs.h> 5617683Spst#include <ufs/ufs/ufsmount.h> 5717683Spst 5817683Spst#include <err.h> 5917683Spst#include <fcntl.h> 6017683Spst#include <fstab.h> 61127664Sbms#include <paths.h> 62127664Sbms#include <stdio.h> 6317683Spst#include <stdlib.h> 6417683Spst#include <string.h> 6517683Spst#include <unistd.h> 66146768Ssam 67146768Ssam/* the optimization warning string template */ 6817683Spst#define OPTWARN "should optimize for %s with minfree %s %d%%" 6917683Spst 7017683Spstunion { 71127664Sbms struct fs sb; 72127664Sbms char pad[MAXBSIZE]; 73127664Sbms} sbun; 74127664Sbms#define sblock sbun.sb 75127664Sbms 76127664Sbmsint fi; 77127664Sbmslong dev_bsize = 1; 78127664Sbms 79127664Sbmsvoid bwrite __P((daddr_t, char *, int)); 80127664Sbmsint bread __P((daddr_t, char *, int)); 81127664Sbmsvoid getsb __P((struct fs *, char *)); 82127664Sbmsvoid putsb __P((struct fs *, char *, int)); 8317683Spstvoid usage __P((void)); 8417683Spstvoid printfs __P((void)); 8517683Spst 8617683Spstint 8717683Spstmain(argc, argv) 8817683Spst int argc; 89127664Sbms char *argv[]; 9017683Spst{ 9117683Spst char *special, *name, *action; 9217683Spst struct stat st; 9317683Spst int i; 9475107Sfenner int Aflag = 0, active = 0; 9575107Sfenner struct fstab *fs; 9617683Spst char *chg[2], device[MAXPATHLEN]; 9717683Spst struct ufs_args args; 9817683Spst struct statfs stfs; 9917683Spst int found_arg, ch; 100146768Ssam 101146768Ssam if (argc < 3) 102146768Ssam usage(); 103240725Skevlo special = argv[argc - 1]; 104146768Ssam fs = getfsfile(special); 105146768Ssam if (fs) { 106146768Ssam if (statfs(special, &stfs) == 0 && 107146768Ssam strcmp(special, stfs.f_mntonname) == 0) { 108146768Ssam active = 1; 109146768Ssam } 11017683Spst special = fs->fs_spec; 11117683Spst } 11217683Spstagain: 113127664Sbms if (stat(special, &st) < 0) { 114127664Sbms if (*special != '/') { 115127664Sbms if (*special == 'r') 116127664Sbms special++; 117127664Sbms (void)sprintf(device, "%s/%s", _PATH_DEV, special); 118127664Sbms special = device; 119127664Sbms goto again; 120127664Sbms } 121127664Sbms err(1, "%s", special); 122127664Sbms } 123127664Sbms if ((st.st_mode & S_IFMT) != S_IFBLK && 12417683Spst (st.st_mode & S_IFMT) != S_IFCHR) 12517683Spst errx(10, "%s: not a block or character device", special); 12617683Spst getsb(&sblock, special); 12717683Spst 128127664Sbms found_arg = 0; /* at least one arg is required */ 129127664Sbms while ((ch = getopt(argc, argv, "Aa:d:e:m:n:o:p")) != -1) 13017683Spst switch (ch) { 13117683Spst case 'A': 13217683Spst found_arg = 1; 13317683Spst Aflag++; 13417683Spst break; 13517683Spst case 'a': 13617683Spst found_arg = 1; 13717683Spst name = "maximum contiguous block count"; 138127664Sbms i = atoi(optarg); 139146768Ssam if (i < 1) 140146768Ssam errx(10, "%s must be >= 1 (was %s)", name, optarg); 141146768Ssam if (sblock.fs_maxcontig == i) { 142146768Ssam warnx("%s remains unchanged as %d", name, i); 143146768Ssam break; 144146768Ssam } 145146768Ssam warnx("%s changes from %d to %d", name, sblock.fs_maxcontig, i); 146146768Ssam sblock.fs_maxcontig = i; 147146768Ssam break; 148146768Ssam case 'd': 149146768Ssam found_arg = 1; 150146768Ssam name = "rotational delay between contiguous blocks"; 151146768Ssam i = atoi(optarg); 152146768Ssam if (sblock.fs_rotdelay == i) { 153146768Ssam warnx("%s remains unchanged as %dms", name, i); 154146768Ssam break; 155146768Ssam } 156146768Ssam warnx("%s changes from %dms to %dms", 157127664Sbms name, sblock.fs_rotdelay, i); 15817683Spst sblock.fs_rotdelay = i; 15917683Spst break; 16017683Spst case 'e': 16117683Spst found_arg = 1; 16217683Spst name = "maximum blocks per file in a cylinder group"; 16375107Sfenner i = atoi(optarg); 16417683Spst if (i < 1) 16575107Sfenner errx(10, "%s must be >= 1 (was %s)", name, optarg); 16675107Sfenner if (sblock.fs_maxbpg == i) { 16717683Spst warnx("%s remains unchanged as %d", name, i); 16817683Spst break; 16917683Spst } 17098530Sfenner warnx("%s changes from %d to %d", name, sblock.fs_maxbpg, i); 17198530Sfenner sblock.fs_maxbpg = i; 17298530Sfenner break; 17398530Sfenner case 'm': 17498530Sfenner found_arg = 1; 17598530Sfenner name = "minimum percentage of free space"; 17698530Sfenner i = atoi(optarg); 17798530Sfenner if (i < 0 || i > 99) 17898530Sfenner errx(10, "bad %s (%s)", name, optarg); 17998530Sfenner if (sblock.fs_minfree == i) { 18098530Sfenner warnx("%s remains unchanged as %d%%", name, i); 18198530Sfenner break; 18298530Sfenner } 18317683Spst warnx("%s changes from %d%% to %d%%", 18417683Spst name, sblock.fs_minfree, i); 18517683Spst sblock.fs_minfree = i; 18617683Spst if (i >= MINFREE && sblock.fs_optim == FS_OPTSPACE) 18798530Sfenner warnx(OPTWARN, "time", ">=", MINFREE); 18898530Sfenner if (i < MINFREE && sblock.fs_optim == FS_OPTTIME) 18998530Sfenner warnx(OPTWARN, "space", "<", MINFREE); 19098530Sfenner break; 19198530Sfenner case 'n': 19217683Spst found_arg = 1; 19317683Spst name = "soft updates"; 19417683Spst if (strcmp(optarg, "enable") == 0) { 19517683Spst sblock.fs_flags |= FS_DOSOFTDEP; 19617683Spst action = "set"; 197190225Srpaulo } else if (strcmp(optarg, "disable") == 0) { 198190225Srpaulo sblock.fs_flags &= ~FS_DOSOFTDEP; 19917683Spst action = "cleared"; 20017683Spst } else { 20117683Spst errx(10, "bad %s (options are %s)", 20217683Spst name, "`enable' or `disable'"); 20317683Spst } 20475107Sfenner warnx("%s %s", name, action); 20575107Sfenner break; 20675107Sfenner case 'o': 20717683Spst found_arg = 1; 20817683Spst name = "optimization preference"; 20917683Spst chg[FS_OPTSPACE] = "space"; 210190225Srpaulo chg[FS_OPTTIME] = "time"; 21175107Sfenner if (strcmp(optarg, chg[FS_OPTSPACE]) == 0) 21217683Spst i = FS_OPTSPACE; 21317683Spst else if (strcmp(optarg, chg[FS_OPTTIME]) == 0) 21417683Spst i = FS_OPTTIME; 21575107Sfenner else 21617683Spst errx(10, "bad %s (options are `space' or `time')", 217190225Srpaulo name); 21817683Spst if (sblock.fs_optim == i) { 219190225Srpaulo warnx("%s remains unchanged as %s", name, chg[i]); 22075107Sfenner break; 22117683Spst } 22217683Spst warnx("%s changes from %s to %s", 22375107Sfenner name, chg[sblock.fs_optim], chg[i]); 22417683Spst sblock.fs_optim = i; 225190225Srpaulo if (sblock.fs_minfree >= MINFREE && i == FS_OPTSPACE) 22675107Sfenner warnx(OPTWARN, "time", ">=", MINFREE); 22717683Spst if (sblock.fs_minfree < MINFREE && i == FS_OPTTIME) 22817683Spst warnx(OPTWARN, "space", "<", MINFREE); 229214518Srpaulo break; 230214518Srpaulo case 'p': 231190225Srpaulo printfs(); 232190225Srpaulo exit(0); 23317683Spst default: 23417683Spst usage(); 23517683Spst } 23617683Spst argc -= optind; 237190225Srpaulo argv += optind; 238190225Srpaulo 239190225Srpaulo if (found_arg == 0 || argc != 1) 240190225Srpaulo usage(); 241190225Srpaulo 242190225Srpaulo putsb(&sblock, special, Aflag); 243190225Srpaulo if (active) { 244190225Srpaulo bzero(&args, sizeof(args)); 245190225Srpaulo if (mount("ufs", fs->fs_file, 246190225Srpaulo stfs.f_flags | MNT_UPDATE | MNT_RELOAD, &args) < 0) 247190225Srpaulo err(9, "%s: reload", special); 248190225Srpaulo warnx("file system reloaded"); 249190225Srpaulo } 25017683Spst exit(0); 25117683Spst} 25275107Sfenner 253146768Ssamvoid 254146768Ssamusage() 255146768Ssam{ 256146768Ssam fprintf(stderr, "%s\n%s\n%s\n", 257146768Ssam"usage: tunefs [-A] [-a maxcontig] [-d rotdelay] [-e maxbpg] [-m minfree]", 258146768Ssam" [-p] [-n enable | disable] [-o optimize_preference]", 259146768Ssam" special | filesystem"); 260146768Ssam exit(2); 261146768Ssam} 262146768Ssam 263146768Ssamvoid 264146768Ssamgetsb(fs, file) 265146768Ssam register struct fs *fs; 266146768Ssam char *file; 267146768Ssam{ 268146768Ssam 269146768Ssam fi = open(file, O_RDONLY); 270146768Ssam if (fi < 0) 271146768Ssam err(3, "cannot open %s", file); 272146768Ssam if (bread((daddr_t)SBOFF, (char *)fs, SBSIZE)) 273146768Ssam err(4, "%s: bad super block", file); 274146768Ssam if (fs->fs_magic != FS_MAGIC) 275146768Ssam err(5, "%s: bad magic number", file); 276146768Ssam dev_bsize = fs->fs_fsize / fsbtodb(fs, 1); 277146768Ssam} 278146768Ssam 279146768Ssamvoid 280146768Ssamputsb(fs, file, all) 281146768Ssam register struct fs *fs; 282190225Srpaulo char *file; 283190225Srpaulo int all; 284190225Srpaulo{ 28517683Spst int i; 28617683Spst 28775107Sfenner /* 288190225Srpaulo * Re-open the device read-write. Use the read-only file 28939291Sfenner * descriptor as an interlock to prevent the device from 29075107Sfenner * being mounted while we are switching mode. 291190225Srpaulo */ 292127664Sbms i = fi; 293127664Sbms fi = open(file, O_RDWR); 294190225Srpaulo close(i); 295127664Sbms if (fi < 0) 296127664Sbms err(3, "cannot open %s", file); 297190225Srpaulo bwrite((daddr_t)SBOFF / dev_bsize, (char *)fs, SBSIZE); 29817683Spst if (all) 299127664Sbms for (i = 0; i < fs->fs_ncg; i++) 30017683Spst bwrite(fsbtodb(fs, cgsblock(fs, i)), 301190225Srpaulo (char *)fs, SBSIZE); 30275107Sfenner close(fi); 30317683Spst} 30417683Spst 305190225Srpaulovoid 306190225Srpauloprintfs() 307190225Srpaulo{ 308190225Srpaulo warnx("soft updates: (-n) %s", 309190225Srpaulo (sblock.fs_flags & FS_DOSOFTDEP)? "enabled" : "disabled"); 310190225Srpaulo warnx("maximum contiguous block count: (-a) %d", 311190225Srpaulo sblock.fs_maxcontig); 312190225Srpaulo warnx("rotational delay between contiguous blocks: (-d) %d ms", 313190225Srpaulo sblock.fs_rotdelay); 31475107Sfenner warnx("maximum blocks per file in a cylinder group: (-e) %d", 31575107Sfenner sblock.fs_maxbpg); 31675107Sfenner warnx("minimum percentage of free space: (-m) %d%%", 31775107Sfenner sblock.fs_minfree); 31875107Sfenner warnx("optimization preference: (-o) %s", 31975107Sfenner sblock.fs_optim == FS_OPTSPACE ? "space" : "time"); 32075107Sfenner if (sblock.fs_minfree >= MINFREE && 321190225Srpaulo sblock.fs_optim == FS_OPTSPACE) 32275107Sfenner warnx(OPTWARN, "time", ">=", MINFREE); 323190225Srpaulo if (sblock.fs_minfree < MINFREE && 32475107Sfenner sblock.fs_optim == FS_OPTTIME) 32575107Sfenner warnx(OPTWARN, "space", "<", MINFREE); 32675107Sfenner} 32775107Sfenner 32875107Sfennervoid 32975107Sfennerbwrite(blk, buf, size) 33075107Sfenner daddr_t blk; 33175107Sfenner char *buf; 33275107Sfenner int size; 33375107Sfenner{ 33475107Sfenner 33575107Sfenner if (lseek(fi, (off_t)blk * dev_bsize, SEEK_SET) < 0) 33675107Sfenner err(6, "FS SEEK"); 33775107Sfenner if (write(fi, buf, size) != size) 33875107Sfenner err(7, "FS WRITE"); 33975107Sfenner} 34075107Sfenner 34175107Sfennerint 34275107Sfennerbread(bno, buf, cnt) 34375107Sfenner daddr_t bno; 344190225Srpaulo char *buf; 345190225Srpaulo int cnt; 34675107Sfenner{ 34717683Spst int i; 34875107Sfenner 34975107Sfenner if (lseek(fi, (off_t)bno * dev_bsize, SEEK_SET) < 0) 35075107Sfenner return(1); 35175107Sfenner if ((i = read(fi, buf, cnt)) != cnt) { 35275107Sfenner for(i=0; i<sblock.fs_bsize; i++) 353190225Srpaulo buf[i] = 0; 35475107Sfenner return (1); 35575107Sfenner } 35675107Sfenner return (0); 357190225Srpaulo} 35875107Sfenner