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
39 #pragma ident "%Z%%M% %I% %E% SMI"
42 * tunefs: change layout parameters to an existing file system.
49 #include <sys/param.h>
50 #include <sys/types.h>
52 #include <sys/mntent.h>
54 #define bcopy(f, t, n) memcpy(t, f, n)
55 #define bzero(s, n) memset(s, 0, n)
56 #define bcmp(s, d, n) memcmp(s, d, n)
58 #define index(s, r) strchr(s, r)
59 #define rindex(s, r) strrchr(s, r)
61 #include <sys/sysmacros.h>
63 #include <sys/fs/ufs_fs.h>
64 #include <sys/vnode.h>
65 #include <sys/fs/ufs_inode.h>
68 #include <sys/mnttab.h>
69 #include <sys/vfstab.h>
70 #include <sys/ustat.h>
71 #include <sys/filio.h>
72 #include <sys/fs/ufs_filio.h>
74 extern offset_t
llseek();
80 #define sblock sbun.sb
83 struct ustat ustatarea
;
88 static void getsb(struct fs
*, char *);
89 static void bwrite(diskaddr_t
, char *, int);
91 static int bread(diskaddr_t
, char *, int);
92 static int isnumber(char *);
94 extern char *getfullrawname(), *getfullblkname();
97 searchvfstab(char **specialp
)
100 struct vfstab vfsbuf
;
103 blockspecial
= getfullblkname(*specialp
);
104 if (blockspecial
== NULL
)
105 blockspecial
= *specialp
;
107 if ((vfstab
= fopen(VFSTAB
, "r")) == NULL
) {
108 fprintf(stderr
, "%s: ", VFSTAB
);
111 while (getvfsent(vfstab
, &vfsbuf
) == NULL
)
112 if (strcmp(vfsbuf
.vfs_fstype
, MNTTYPE_UFS
) == 0)
113 if ((strcmp(vfsbuf
.vfs_mountp
, *specialp
) == 0) ||
114 (strcmp(vfsbuf
.vfs_special
, *specialp
) == 0) ||
115 (strcmp(vfsbuf
.vfs_special
, blockspecial
) == 0) ||
116 (strcmp(vfsbuf
.vfs_fsckdev
, *specialp
) == 0)) {
117 *specialp
= strdup(vfsbuf
.vfs_special
);
124 searchmnttab(char **specialp
, char **mountpointp
)
127 struct mnttab mntbuf
;
130 blockspecial
= getfullblkname(*specialp
);
131 if (blockspecial
== NULL
)
132 blockspecial
= *specialp
;
134 if ((mnttab
= fopen(MNTTAB
, "r")) == NULL
)
136 while (getmntent(mnttab
, &mntbuf
) == NULL
)
137 if (strcmp(mntbuf
.mnt_fstype
, MNTTYPE_UFS
) == 0)
138 if ((strcmp(mntbuf
.mnt_mountp
, *specialp
) == 0) ||
139 (strcmp(mntbuf
.mnt_special
, blockspecial
) == 0) ||
140 (strcmp(mntbuf
.mnt_special
, *specialp
) == 0)) {
141 *specialp
= strdup(mntbuf
.mnt_special
);
142 *mountpointp
= strdup(mntbuf
.mnt_mountp
);
149 main(int argc
, char *argv
[])
151 char *special
, *name
, *mountpoint
= NULL
;
157 struct fiotune fiotune
;
162 special
= argv
[argc
- 1];
165 * For performance, don't search mnttab unless necessary
168 if (stat64(special
, &st
) >= 0) {
170 * If mounted directory, search mnttab for special
172 if ((st
.st_mode
& S_IFMT
) == S_IFDIR
) {
173 if (st
.st_ino
== UFSROOTINO
)
174 searchmnttab(&special
, &mountpoint
);
176 * If mounted device, search mnttab for mountpoint
178 } else if ((st
.st_mode
& S_IFMT
) == S_IFBLK
||
179 (st
.st_mode
& S_IFMT
) == S_IFCHR
) {
180 if (ustat(st
.st_rdev
, &ustatarea
) >= 0)
181 searchmnttab(&special
, &mountpoint
);
185 * Doesn't appear to be mounted; take ``unmounted'' path
187 if (mountpoint
== NULL
)
188 searchvfstab(&special
);
190 if ((special
= getfullrawname(special
)) == NULL
) {
191 fprintf(stderr
, "tunefs: malloc failed\n");
195 if (*special
== '\0') {
196 fprintf(stderr
, "tunefs: Could not find raw device for %s\n",
201 if (stat64(special
, &st
) < 0) {
202 fprintf(stderr
, "tunefs: "); perror(special
);
207 * If a mountpoint has been found then we will ioctl() the file
208 * system instead of writing to the file system's device
210 /* ustat() ok because max number of UFS inodes can fit in ino_t */
211 if (ustat(st
.st_rdev
, &ustatarea
) >= 0) {
212 if (mountpoint
== NULL
) {
213 printf("%s is mounted, can't tunefs\n", special
);
219 if ((st
.st_mode
& S_IFMT
) != S_IFBLK
&&
220 (st
.st_mode
& S_IFMT
) != S_IFCHR
)
221 fatal("%s: not a block or character device", special
);
222 getsb(&sblock
, special
);
223 while ((opt
= getopt(argc
, argv
, "o:m:e:d:a:AV")) != EOF
) {
231 name
= "maximum contiguous block count";
232 if (!isnumber(optarg
))
233 fatal("%s: %s must be >= 1", *argv
, name
);
236 fatal("%s: %s must be >= 1", *argv
, name
);
237 fprintf(stdout
, "%s changes from %d to %d\n",
238 name
, sblock
.fs_maxcontig
, i
);
239 sblock
.fs_maxcontig
= i
;
243 sblock
.fs_rotdelay
= 0;
248 "maximum blocks per file in a cylinder group";
249 if (!isnumber(optarg
))
250 fatal("%s: %s must be >= 1", *argv
, name
);
253 fatal("%s: %s must be >= 1", *argv
, name
);
254 fprintf(stdout
, "%s changes from %d to %d\n",
255 name
, sblock
.fs_maxbpg
, i
);
256 sblock
.fs_maxbpg
= i
;
260 name
= "minimum percentage of free space";
261 if (!isnumber(optarg
))
262 fatal("%s: bad %s", *argv
, name
);
265 fatal("%s: bad %s", *argv
, name
);
267 "%s changes from %d%% to %d%%\n",
268 name
, sblock
.fs_minfree
, i
);
269 sblock
.fs_minfree
= i
;
273 name
= "optimization preference";
274 chg
[FS_OPTSPACE
] = "space";
275 chg
[FS_OPTTIME
] = "time";
276 if (strcmp(optarg
, chg
[FS_OPTSPACE
]) == 0)
278 else if (strcmp(optarg
, chg
[FS_OPTTIME
]) == 0)
281 fatal("%s: bad %s (options are `space' or `time')",
283 if (sblock
.fs_optim
== i
) {
285 "%s remains unchanged as %s\n",
290 "%s changes from %s to %s\n",
291 name
, chg
[sblock
.fs_optim
], chg
[i
]);
300 (void) fprintf(stdout
, "tunefs -F ufs ");
301 for (opt_count
= 1; opt_count
< argc
;
303 opt_text
= argv
[opt_count
];
305 (void) fprintf(stdout
, " %s ",
308 (void) fprintf(stdout
, "\n");
316 if ((argc
- optind
) != 1)
319 mountfd
= open(mountpoint
, O_RDONLY
);
323 "tunefs: can't tune %s\n", mountpoint
);
326 fiotune
.maxcontig
= sblock
.fs_maxcontig
;
327 fiotune
.rotdelay
= sblock
.fs_rotdelay
;
328 fiotune
.maxbpg
= sblock
.fs_maxbpg
;
329 fiotune
.minfree
= sblock
.fs_minfree
;
330 fiotune
.optim
= sblock
.fs_optim
;
331 if (ioctl(mountfd
, _FIOTUNE
, &fiotune
) == -1) {
334 "tunefs: can't tune %s\n", mountpoint
);
339 bwrite((diskaddr_t
)SBLOCK
, (char *)&sblock
, SBSIZE
);
342 for (i
= 0; i
< sblock
.fs_ncg
; i
++)
343 bwrite(fsbtodb(&sblock
, cgsblock(&sblock
, i
)),
344 (char *)&sblock
, SBSIZE
);
354 fprintf(stderr
, "ufs usage: tunefs tuneup-options special-device\n");
355 fprintf(stderr
, "where tuneup-options are:\n");
356 fprintf(stderr
, "\t-a maximum contiguous blocks\n");
357 fprintf(stderr
, "\t-d rotational delay between contiguous blocks\n");
358 fprintf(stderr
, "\t-e maximum blocks per file in a cylinder group\n");
359 fprintf(stderr
, "\t-m minimum percentage of free space\n");
360 fprintf(stderr
, "\t-o optimization preference (`space' or `time')\n");
365 getsb(struct fs
*fs
, char *file
)
368 fi
= open64(file
, O_RDWR
);
370 fprintf(stderr
, "Cannot open ");
374 if (bread((diskaddr_t
)SBLOCK
, (char *)fs
, SBSIZE
)) {
375 fprintf(stderr
, "Bad super block ");
379 if ((fs
->fs_magic
!= FS_MAGIC
) && (fs
->fs_magic
!= MTB_UFS_MAGIC
)) {
380 fprintf(stderr
, "%s: bad magic number\n", file
);
383 if (fs
->fs_magic
== FS_MAGIC
&&
384 (fs
->fs_version
!= UFS_EFISTYLE4NONEFI_VERSION_2
&&
385 fs
->fs_version
!= UFS_VERSION_MIN
)) {
386 fprintf(stderr
, "%s: unrecognized ufs version: %d\n", file
,
390 if (fs
->fs_magic
== MTB_UFS_MAGIC
&&
391 (fs
->fs_version
> MTB_UFS_VERSION_1
||
392 fs
->fs_version
< MTB_UFS_VERSION_MIN
)) {
393 fprintf(stderr
, "%s: unrecognized ufs version: %d\n", file
,
400 bwrite(diskaddr_t blk
, char *buf
, int size
)
402 if (llseek(fi
, (offset_t
)blk
* DEV_BSIZE
, 0) < 0) {
406 if (write(fi
, buf
, size
) != size
) {
413 bread(diskaddr_t bno
, char *buf
, int cnt
)
417 if (llseek(fi
, (offset_t
)bno
* DEV_BSIZE
, 0) < 0) {
418 fprintf(stderr
, "bread: ");
422 if ((i
= read(fi
, buf
, cnt
)) != cnt
) {
424 for (i
= 0; i
< sblock
.fs_bsize
; i
++)
433 fatal(char *fmt
, char *arg1
, char *arg2
)
435 fprintf(stderr
, "tunefs: ");
436 fprintf(stderr
, fmt
, arg1
, arg2
);
448 if (c
< '0' || c
> '9')