4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
26 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
27 /* All Rights Reserved */
30 * University Copyright- Copyright (c) 1982, 1986, 1988
31 * The Regents of the University of California
34 * University Acknowledgment- Portions of this document are derived from
35 * software developed by the University of California, Berkeley, and its
40 * tunefs: change layout parameters to an existing file system.
47 #include <sys/param.h>
48 #include <sys/types.h>
50 #include <sys/mntent.h>
52 #define bcopy(f, t, n) memcpy(t, f, n)
53 #define bzero(s, n) memset(s, 0, n)
54 #define bcmp(s, d, n) memcmp(s, d, n)
56 #define index(s, r) strchr(s, r)
57 #define rindex(s, r) strrchr(s, r)
59 #include <sys/sysmacros.h>
61 #include <sys/fs/ufs_fs.h>
62 #include <sys/vnode.h>
63 #include <sys/fs/ufs_inode.h>
66 #include <sys/mnttab.h>
67 #include <sys/vfstab.h>
68 #include <sys/ustat.h>
69 #include <sys/filio.h>
70 #include <sys/fs/ufs_filio.h>
72 extern offset_t
llseek();
78 #define sblock sbun.sb
81 struct ustat ustatarea
;
86 static void getsb(struct fs
*, char *);
87 static void bwrite(diskaddr_t
, char *, int);
89 static int bread(diskaddr_t
, char *, int);
90 static int isnumber(char *);
92 extern char *getfullrawname(), *getfullblkname();
95 searchvfstab(char **specialp
)
101 blockspecial
= getfullblkname(*specialp
);
102 if (blockspecial
== NULL
)
103 blockspecial
= *specialp
;
105 if ((vfstab
= fopen(VFSTAB
, "r")) == NULL
) {
106 fprintf(stderr
, "%s: ", VFSTAB
);
109 while (getvfsent(vfstab
, &vfsbuf
) == 0)
110 if (strcmp(vfsbuf
.vfs_fstype
, MNTTYPE_UFS
) == 0)
111 if ((strcmp(vfsbuf
.vfs_mountp
, *specialp
) == 0) ||
112 (strcmp(vfsbuf
.vfs_special
, *specialp
) == 0) ||
113 (strcmp(vfsbuf
.vfs_special
, blockspecial
) == 0) ||
114 (strcmp(vfsbuf
.vfs_fsckdev
, *specialp
) == 0)) {
115 *specialp
= strdup(vfsbuf
.vfs_special
);
122 searchmnttab(char **specialp
, char **mountpointp
)
125 struct mnttab mntbuf
;
128 blockspecial
= getfullblkname(*specialp
);
129 if (blockspecial
== NULL
)
130 blockspecial
= *specialp
;
132 if ((mnttab
= fopen(MNTTAB
, "r")) == NULL
)
134 while (getmntent(mnttab
, &mntbuf
) == 0)
135 if (strcmp(mntbuf
.mnt_fstype
, MNTTYPE_UFS
) == 0)
136 if ((strcmp(mntbuf
.mnt_mountp
, *specialp
) == 0) ||
137 (strcmp(mntbuf
.mnt_special
, blockspecial
) == 0) ||
138 (strcmp(mntbuf
.mnt_special
, *specialp
) == 0)) {
139 *specialp
= strdup(mntbuf
.mnt_special
);
140 *mountpointp
= strdup(mntbuf
.mnt_mountp
);
147 main(int argc
, char *argv
[])
149 char *special
, *name
, *mountpoint
= NULL
;
155 struct fiotune fiotune
;
160 special
= argv
[argc
- 1];
163 * For performance, don't search mnttab unless necessary
166 if (stat64(special
, &st
) >= 0) {
168 * If mounted directory, search mnttab for special
170 if ((st
.st_mode
& S_IFMT
) == S_IFDIR
) {
171 if (st
.st_ino
== UFSROOTINO
)
172 searchmnttab(&special
, &mountpoint
);
174 * If mounted device, search mnttab for mountpoint
176 } else if ((st
.st_mode
& S_IFMT
) == S_IFBLK
||
177 (st
.st_mode
& S_IFMT
) == S_IFCHR
) {
178 if (ustat(st
.st_rdev
, &ustatarea
) >= 0)
179 searchmnttab(&special
, &mountpoint
);
183 * Doesn't appear to be mounted; take ``unmounted'' path
185 if (mountpoint
== NULL
)
186 searchvfstab(&special
);
188 if ((special
= getfullrawname(special
)) == NULL
) {
189 fprintf(stderr
, "tunefs: malloc failed\n");
193 if (*special
== '\0') {
194 fprintf(stderr
, "tunefs: Could not find raw device for %s\n",
199 if (stat64(special
, &st
) < 0) {
200 fprintf(stderr
, "tunefs: "); perror(special
);
205 * If a mountpoint has been found then we will ioctl() the file
206 * system instead of writing to the file system's device
208 /* ustat() ok because max number of UFS inodes can fit in ino_t */
209 if (ustat(st
.st_rdev
, &ustatarea
) >= 0) {
210 if (mountpoint
== NULL
) {
211 printf("%s is mounted, can't tunefs\n", special
);
217 if ((st
.st_mode
& S_IFMT
) != S_IFBLK
&&
218 (st
.st_mode
& S_IFMT
) != S_IFCHR
)
219 fatal("%s: not a block or character device", special
);
220 getsb(&sblock
, special
);
221 while ((opt
= getopt(argc
, argv
, "o:m:e:d:a:AV")) != EOF
) {
229 name
= "maximum contiguous block count";
230 if (!isnumber(optarg
))
231 fatal("%s: %s must be >= 1", *argv
, name
);
234 fatal("%s: %s must be >= 1", *argv
, name
);
235 fprintf(stdout
, "%s changes from %d to %d\n",
236 name
, sblock
.fs_maxcontig
, i
);
237 sblock
.fs_maxcontig
= i
;
241 sblock
.fs_rotdelay
= 0;
246 "maximum blocks per file in a cylinder group";
247 if (!isnumber(optarg
))
248 fatal("%s: %s must be >= 1", *argv
, name
);
251 fatal("%s: %s must be >= 1", *argv
, name
);
252 fprintf(stdout
, "%s changes from %d to %d\n",
253 name
, sblock
.fs_maxbpg
, i
);
254 sblock
.fs_maxbpg
= i
;
258 name
= "minimum percentage of free space";
259 if (!isnumber(optarg
))
260 fatal("%s: bad %s", *argv
, name
);
263 fatal("%s: bad %s", *argv
, name
);
265 "%s changes from %d%% to %d%%\n",
266 name
, sblock
.fs_minfree
, i
);
267 sblock
.fs_minfree
= i
;
271 name
= "optimization preference";
272 chg
[FS_OPTSPACE
] = "space";
273 chg
[FS_OPTTIME
] = "time";
274 if (strcmp(optarg
, chg
[FS_OPTSPACE
]) == 0)
276 else if (strcmp(optarg
, chg
[FS_OPTTIME
]) == 0)
279 fatal("%s: bad %s (options are `space' or `time')",
281 if (sblock
.fs_optim
== i
) {
283 "%s remains unchanged as %s\n",
288 "%s changes from %s to %s\n",
289 name
, chg
[sblock
.fs_optim
], chg
[i
]);
298 (void) fprintf(stdout
, "tunefs -F ufs ");
299 for (opt_count
= 1; opt_count
< argc
;
301 opt_text
= argv
[opt_count
];
303 (void) fprintf(stdout
, " %s ",
306 (void) fprintf(stdout
, "\n");
314 if ((argc
- optind
) != 1)
317 mountfd
= open(mountpoint
, O_RDONLY
);
321 "tunefs: can't tune %s\n", mountpoint
);
324 fiotune
.maxcontig
= sblock
.fs_maxcontig
;
325 fiotune
.rotdelay
= sblock
.fs_rotdelay
;
326 fiotune
.maxbpg
= sblock
.fs_maxbpg
;
327 fiotune
.minfree
= sblock
.fs_minfree
;
328 fiotune
.optim
= sblock
.fs_optim
;
329 if (ioctl(mountfd
, _FIOTUNE
, &fiotune
) == -1) {
332 "tunefs: can't tune %s\n", mountpoint
);
337 bwrite((diskaddr_t
)SBLOCK
, (char *)&sblock
, SBSIZE
);
340 for (i
= 0; i
< sblock
.fs_ncg
; i
++)
341 bwrite(fsbtodb(&sblock
, cgsblock(&sblock
, i
)),
342 (char *)&sblock
, SBSIZE
);
352 fprintf(stderr
, "ufs usage: tunefs tuneup-options special-device\n");
353 fprintf(stderr
, "where tuneup-options are:\n");
354 fprintf(stderr
, "\t-a maximum contiguous blocks\n");
355 fprintf(stderr
, "\t-d rotational delay between contiguous blocks\n");
356 fprintf(stderr
, "\t-e maximum blocks per file in a cylinder group\n");
357 fprintf(stderr
, "\t-m minimum percentage of free space\n");
358 fprintf(stderr
, "\t-o optimization preference (`space' or `time')\n");
363 getsb(struct fs
*fs
, char *file
)
366 fi
= open64(file
, O_RDWR
);
368 fprintf(stderr
, "Cannot open ");
372 if (bread((diskaddr_t
)SBLOCK
, (char *)fs
, SBSIZE
)) {
373 fprintf(stderr
, "Bad super block ");
377 if ((fs
->fs_magic
!= FS_MAGIC
) && (fs
->fs_magic
!= MTB_UFS_MAGIC
)) {
378 fprintf(stderr
, "%s: bad magic number\n", file
);
381 if (fs
->fs_magic
== FS_MAGIC
&&
382 (fs
->fs_version
!= UFS_EFISTYLE4NONEFI_VERSION_2
&&
383 fs
->fs_version
!= UFS_VERSION_MIN
)) {
384 fprintf(stderr
, "%s: unrecognized ufs version: %d\n", file
,
388 if (fs
->fs_magic
== MTB_UFS_MAGIC
&&
389 (fs
->fs_version
> MTB_UFS_VERSION_1
||
390 fs
->fs_version
< MTB_UFS_VERSION_MIN
)) {
391 fprintf(stderr
, "%s: unrecognized ufs version: %d\n", file
,
398 bwrite(diskaddr_t blk
, char *buf
, int size
)
400 if (llseek(fi
, (offset_t
)blk
* DEV_BSIZE
, 0) < 0) {
404 if (write(fi
, buf
, size
) != size
) {
411 bread(diskaddr_t bno
, char *buf
, int cnt
)
415 if (llseek(fi
, (offset_t
)bno
* DEV_BSIZE
, 0) < 0) {
416 fprintf(stderr
, "bread: ");
420 if ((i
= read(fi
, buf
, cnt
)) != cnt
) {
422 for (i
= 0; i
< sblock
.fs_bsize
; i
++)
431 fatal(char *fmt
, char *arg1
, char *arg2
)
433 fprintf(stderr
, "tunefs: ");
434 fprintf(stderr
, fmt
, arg1
, arg2
);
446 if (c
< '0' || c
> '9')