1 /* $NetBSD: newfs.c,v 1.23 2006/09/05 19:44:44 riz Exp $ */
4 * Copyright (c) 1989, 1992, 1993
5 * The Regents of the University of California. All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 * may be used to endorse or promote products derived from this software
17 * without specific prior written permission.
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32 #include <sys/cdefs.h>
34 __COPYRIGHT("@(#) Copyright (c) 1989, 1992, 1993\
35 The Regents of the University of California. All rights reserved.");
40 static char sccsid
[] = "@(#)newfs.c 8.5 (Berkeley) 5/24/95";
42 __RCSID("$NetBSD: newfs.c,v 1.23 2006/09/05 19:44:44 riz Exp $");
47 * newfs: friendly front end to mkfs
49 #include <sys/param.h>
50 #include <sys/ucred.h>
52 #include <sys/ioctl.h>
54 #include <sys/mount.h>
55 #include <sys/sysctl.h>
59 #include <ufs/ufs/dir.h>
60 #include <ufs/ufs/dinode.h>
61 #include <ufs/lfs/lfs.h>
77 #define COMPAT /* allow non-labeled disks */
80 const char lmsg
[] = "%s: can't read disk label; disk type must be specified";
82 const char lmsg
[] = "%s: can't read disk label";
85 int Nflag
= 0; /* run without writing file system */
86 int fssize
; /* file system size */
87 int sectorsize
; /* bytes/sector */
88 int fsize
= 0; /* fragment size */
89 int bsize
= 0; /* block size */
90 int ibsize
= 0; /* inode block size */
91 int interleave
= 0; /* segment interleave */
92 int minfree
= MINFREE
; /* free space threshold */
93 int minfreeseg
= 0; /* segments not counted in bfree total */
94 int resvseg
= 0; /* free segments reserved for the cleaner */
95 u_int32_t roll_id
= 0; /* roll-forward id */
96 u_long memleft
; /* virtual memory available */
97 caddr_t membase
; /* start address of memory based filesystem */
101 int preen
= 0; /* Coexistence with fsck_lfs */
103 char device
[MAXPATHLEN
];
104 char *progname
, *special
;
106 static int64_t strsuftoi64(const char *, const char *, int64_t, int64_t, int *);
107 static void usage(void);
109 /* CHUNKSIZE should be larger than MAXPHYS */
110 #define CHUNKSIZE (1024 * 1024)
113 auto_segsize(int fd
, off_t len
, int version
)
116 time_t start
, finish
;
122 /* First, get sequential access bandwidth */
125 for (off
= 0; finish
- start
< 10; off
+= CHUNKSIZE
) {
126 if (pread(fd
, buf
, CHUNKSIZE
, off
) < 0)
130 /* Bandwidth = bytes / sec */
131 /* printf("%ld bytes in %ld seconds\n", (long)off, (long)(finish - start)); */
132 bw
= off
/ (finish
- start
);
134 /* Second, seek time */
136 finish
= start
; /* structure copy */
137 for (seeks
= 0; finish
- start
< 10; ) {
138 off
= (((double)rand()) * (btodb(len
))) / ((off_t
)RAND_MAX
+ 1);
139 if (pread(fd
, buf
, dbtob(1), dbtob(off
)) < 0)
144 /* printf("%ld seeks in %ld seconds\n", (long)seeks, (long)(finish - start)); */
145 /* Seek time in units/sec */
146 seeks
/= (finish
- start
);
150 printf("bw = %ld B/s, seek time %ld ms (%ld seeks/s)\n",
151 (long)bw
, 1000/seeks
, seeks
);
152 final
= dbtob(btodb(4 * bw
/ seeks
));
154 for (i
= 0; final
; final
>>= 1, i
++)
158 printf("using initial segment size %ld\n", (long)final
);
163 main(int argc
, char **argv
)
166 struct disk_geom geo
;
167 struct dkwedge_info dkw
;
169 int debug
, force
, fsi
, fso
, segsize
, maxpartitions
;
172 const char *opstring
;
176 version
= DFL_VERSION
; /* what version of lfs to make */
178 if ((progname
= strrchr(*argv
, '/')) != NULL
)
183 maxpartitions
= getmaxpartitions();
184 if (maxpartitions
> 26)
185 fatal("insane maxpartitions value %d", maxpartitions
);
187 opstring
= "AB:b:DFf:I:i:LM:m:NO:R:r:S:s:v:";
189 debug
= force
= segsize
= start
= 0;
190 while ((ch
= getopt(argc
, argv
, opstring
)) != -1)
192 case 'A': /* Adaptively configure segment size */
195 case 'B': /* LFS segment size */
196 segsize
= strsuftoi64("segment size", optarg
, LFS_MINSEGSIZE
, INT64_MAX
, NULL
);
205 interleave
= strsuftoi64("interleave", optarg
, 0, INT64_MAX
, NULL
);
207 case 'L': /* Compatibility only */
210 minfreeseg
= strsuftoi64("minfreeseg", optarg
, 0, INT64_MAX
, NULL
);
216 start
= strsuftoi64("start", optarg
, 0, INT64_MAX
, NULL
);
219 resvseg
= strsuftoi64("resvseg", optarg
, 0, INT64_MAX
, NULL
);
222 secsize
= strsuftoi64("sector size", optarg
, 1, INT64_MAX
, NULL
);
223 if (secsize
<= 0 || (secsize
& (secsize
- 1)))
224 fatal("%s: bad sector size", optarg
);
232 bsize
= strsuftoi64("block size", optarg
, LFS_MINBLOCKSIZE
, INT64_MAX
, NULL
);
235 fsize
= strsuftoi64("fragment size", optarg
, LFS_MINBLOCKSIZE
, INT64_MAX
, NULL
);
238 ibsize
= strsuftoi64("inode block size", optarg
, LFS_MINBLOCKSIZE
, INT64_MAX
, NULL
);
241 minfree
= strsuftoi64("free space %", optarg
, 0, 99, NULL
);
244 roll_id
= strsuftoi64("roll-forward id", optarg
, 1, UINT_MAX
, NULL
);
247 fssize
= strsuftoi64("file system size", optarg
, 0, INT64_MAX
, &byte_sized
);
250 version
= strsuftoi64("file system version", optarg
, 1, LFS_VERSION
, NULL
);
259 if (argc
!= 2 && argc
!= 1)
263 * If the -N flag isn't specified, open the output file. If no path
264 * prefix, try /dev/r%s and then /dev/%s.
267 if (strchr(special
, '/') == NULL
) {
268 (void)snprintf(device
, sizeof(device
), "%sr%s", _PATH_DEV
,
270 if (stat(device
, &st
) == -1)
271 (void)snprintf(device
, sizeof(device
), "%s%s",
277 (debug
? O_CREAT
: 0) | O_RDWR
, DEFFILEMODE
);
279 fatal("%s: %s", special
, strerror(errno
));
283 /* Open the input file. */
284 fsi
= open(special
, O_RDONLY
);
286 fatal("%s: %s", special
, strerror(errno
));
287 if (fstat(fsi
, &st
) < 0)
288 fatal("%s: %s", special
, strerror(errno
));
291 if (!S_ISCHR(st
.st_mode
)) {
292 if (!S_ISREG(st
.st_mode
)) {
293 fatal("%s: neither a character special device "
294 "nor a regular file", special
);
296 (void)strcpy(dkw
.dkw_ptype
, DKW_PTYPE_LFS
);
299 dkw
.dkw_size
= st
.st_size
/ secsize
;
302 if (disktype
== NULL
)
305 if (getdiskinfo(special
, fsi
, disktype
, &geo
, &dkw
) == -1)
306 errx(1, lmsg
, special
);
308 if (dkw
.dkw_size
== 0)
309 fatal("%s: is zero sized", argv
[0]);
310 if (!force
&& strcmp(dkw
.dkw_ptype
, DKW_PTYPE_LFS
) != 0)
311 fatal("%s: is not `%s', but `%s'", argv
[0],
312 DKW_PTYPE_LFS
, dkw
.dkw_ptype
);
316 secsize
= geo
.dg_secsize
;
318 /* From here on out fssize is in sectors */
323 /* If force, make the partition look like an LFS */
325 (void)strcpy(dkw
.dkw_ptype
, DKW_PTYPE_LFS
);
327 dkw
.dkw_size
= fssize
;
330 if (fssize
!= 0 && fssize
< dkw
.dkw_size
)
331 dkw
.dkw_size
= fssize
;
333 /* Try autoconfiguring segment size, if asked to */
335 if (!S_ISCHR(st
.st_mode
)) {
336 warnx("%s is not a character special device, ignoring -A", special
);
339 segsize
= auto_segsize(fsi
, dbtob(dkw
.dkw_size
),
343 /* If we're making a LFS, we break out here */
344 r
= make_lfs(fso
, secsize
, &dkw
, minfree
, bsize
, fsize
, segsize
,
345 minfreeseg
, resvseg
, version
, start
, ibsize
, interleave
, roll_id
);
352 strsuftoi64(const char *desc
, const char *arg
, int64_t min
, int64_t max
, int *num_suffix
)
359 r1
= strtoll(arg
, &ep
, 10);
360 if (ep
[0] != '\0' && ep
[1] != '\0')
361 errx(1, "%s `%s' is not a valid number.", desc
, arg
);
365 if (num_suffix
!= NULL
)
378 if (num_suffix
!= NULL
)
382 errx(1, "`%s' is not a valid suffix for %s.", ep
, desc
);
384 result
= r1
<< shift
;
385 if (errno
== ERANGE
|| result
>> shift
!= r1
)
386 errx(1, "%s `%s' is too large to convert.", desc
, arg
);
388 errx(1, "%s `%s' (%" PRId64
") is less than the minimum (%" PRId64
").",
389 desc
, arg
, result
, min
);
391 errx(1, "%s `%s' (%" PRId64
") is greater than the maximum (%" PRId64
").",
392 desc
, arg
, result
, max
);
399 fprintf(stderr
, "usage: newfs_lfs [ -fsoptions ] special-device\n");
400 fprintf(stderr
, "where fsoptions are:\n");
401 fprintf(stderr
, "\t-A (autoconfigure segment size)\n");
402 fprintf(stderr
, "\t-B segment size in bytes\n");
403 fprintf(stderr
, "\t-D (debug)\n");
404 fprintf(stderr
, "\t-M count of segments not counted in bfree\n");
406 "\t-N (do not create file system, just print out parameters)\n");
407 fprintf(stderr
, "\t-O first segment offset in sectors\n");
408 fprintf(stderr
, "\t-R count of segments reserved for the cleaner\n");
409 fprintf(stderr
, "\t-b block size in bytes\n");
410 fprintf(stderr
, "\t-f frag size in bytes\n");
411 fprintf(stderr
, "\t-m minimum free space %%\n");
412 fprintf(stderr
, "\t-s file system size in sectors\n");
413 fprintf(stderr
, "\t-v version\n");