xref: /dragonfly/sbin/newfs/newfs.c (revision 2c3b1d1bc3a233e4bf80218452e719882a1bb011)
1 /*
2  * Copyright (c) 1983, 1989, 1993, 1994
3  *        The Regents of the University of California.  All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the University nor the names of its contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  *
29  * @(#) Copyright (c) 1983, 1989, 1993, 1994 The Regents of the University of California.  All rights reserved.
30  * @(#)newfs.c      8.13 (Berkeley) 5/1/95
31  * $FreeBSD: src/sbin/newfs/newfs.c,v 1.30.2.9 2003/05/13 12:03:55 joerg Exp $
32  */
33 
34 /*
35  * newfs: friendly front end to mkfs
36  */
37 #include <sys/param.h>
38 #include <sys/stat.h>
39 #include <sys/diskslice.h>
40 #include <sys/mount.h>
41 #include <sys/sysctl.h>
42 
43 #include <vfs/ufs/dir.h>
44 #include <vfs/ufs/dinode.h>
45 #include <vfs/ufs/fs.h>
46 #include <vfs/ufs/ufsmount.h>
47 
48 #include <ctype.h>
49 #include <err.h>
50 #include <errno.h>
51 #include <fcntl.h>
52 #include <mntopts.h>
53 #include <inttypes.h>
54 #include <paths.h>
55 #include <stdio.h>
56 #include <stdlib.h>
57 #include <string.h>
58 #include <syslog.h>
59 #include <unistd.h>
60 #include <disktab.h>
61 
62 #ifdef MFS
63 #include <sys/types.h>
64 #include <sys/mman.h>
65 #endif
66 
67 #include <stdarg.h>
68 
69 #include "defs.h"
70 
71 struct mntopt mopts[] = {
72           MOPT_STDOPTS,
73           MOPT_ASYNC,
74           MOPT_NULL,
75 };
76 
77 void      fatal(const char *fmt, ...) __dead2 __printflike(1, 2);
78 
79 #define   COMPAT                        /* allow non-labeled disks */
80 
81 /*
82  * The following two constants set the default block and fragment sizes.
83  * Both constants must be a power of 2 and meet the following constraints:
84  *        MINBSIZE <= DESBLKSIZE <= MAXBSIZE
85  *        sectorsize <= DESFRAGSIZE <= DESBLKSIZE
86  *        DESBLKSIZE / DESFRAGSIZE <= 8
87  */
88 #define   DFL_FRAGSIZE        2048
89 #define   DFL_BLKSIZE         16384
90 
91 /*
92  * Cylinder groups may have up to many cylinders. The actual
93  * number used depends upon how much information can be stored
94  * on a single cylinder. The default is to use as many as possible
95  * cylinders per group.
96  */
97 #define   DESCPG              65536     /* desired fs_cpg ("infinity") */
98 
99 /*
100  * Once upon a time...
101  *    ROTDELAY gives the minimum number of milliseconds to initiate
102  *    another disk transfer on the same cylinder. It is used in
103  *    determining the rotationally optimal layout for disk blocks
104  *    within a file; the default of fs_rotdelay is 4ms.
105  *
106  * ...but now we make this 0 to disable the rotdelay delay because
107  * modern drives with read/write-behind achieve higher performance
108  * without the delay.
109  */
110 #define ROTDELAY    0
111 
112 /*
113  * MAXBLKPG determines the maximum number of data blocks which are
114  * placed in a single cylinder group. The default is one indirect
115  * block worth of data blocks.
116  */
117 #define MAXBLKPG(bsize)       ((bsize) / sizeof(daddr_t))
118 
119 /*
120  * Each file system has a number of inodes statically allocated.
121  * We allocate one inode slot per NFPI fragments, expecting this
122  * to be far more than we will ever need.
123  */
124 #define   NFPI                4
125 
126 /*
127  * Once upon a time...
128  *    For each cylinder we keep track of the availability of blocks at different
129  *    rotational positions, so that we can lay out the data to be picked
130  *    up with minimum rotational latency.  NRPOS is the default number of
131  *    rotational positions that we distinguish.  With NRPOS of 8 the resolution
132  *    of our summary information is 2ms for a typical 3600 rpm drive.
133  *
134  * ...but now we make this 1 (which essentially disables the rotational
135  * position table because modern drives with read-ahead and write-behind do
136  * better without the rotational position table.
137  */
138 #define   NRPOS               1         /* number distinct rotational positions */
139 
140 /*
141  * About the same time as the above, we knew what went where on the disks.
142  * no longer so, so kill the code which finds the different platters too...
143  * We do this by saying one head, with a lot of sectors on it.
144  * The number of sectors are used to determine the size of a cyl-group.
145  * Kirk suggested one or two meg per "cylinder" so we say two.
146  */
147 #define NTRACKS               1         /* number of heads */
148 #define NSECTORS    4096      /* number of sectors */
149 
150 int       mfs;                          /* run as the memory based filesystem */
151 char      *mfs_mtpt;                    /* mount point for mfs                  */
152 struct stat mfs_mtstat;                 /* stat prior to mount                  */
153 int       Lflag;                        /* add a volume label */
154 int       Nflag;                        /* run without writing file system */
155 int       Oflag;                        /* format as an 4.3BSD file system */
156 int       Cflag;                        /* copy underlying filesystem (mfs only) */
157 int       Uflag;                        /* enable soft updates for file system */
158 int       Eflag;                        /* erase contents using TRIM */
159 uint64_t slice_offset;                  /* Pysical device slice offset */
160 u_long    fssize;                       /* file system size */
161 int       ntracks = NTRACKS;  /* # tracks/cylinder */
162 int       nsectors = NSECTORS;          /* # sectors/track */
163 int       nphyssectors;                 /* # sectors/track including spares */
164 int       secpercyl;                    /* sectors per cylinder */
165 int       trackspares = -1;   /* spare sectors per track */
166 int       cylspares = -1;               /* spare sectors per cylinder */
167 int       sectorsize;                   /* bytes/sector */
168 int       realsectorsize;               /* bytes/sector in hardware */
169 int       rpm;                          /* revolutions/minute of drive */
170 int       interleave;                   /* hardware sector interleave */
171 int       trackskew = -1;               /* sector 0 skew, per track */
172 int       headswitch;                   /* head switch time, usec */
173 int       trackseek;                    /* track-to-track seek, usec */
174 int       fsize = 0;                    /* fragment size */
175 int       bsize = 0;                    /* block size */
176 int       cpg = DESCPG;                 /* cylinders/cylinder group */
177 int       cpgflg;                       /* cylinders/cylinder group flag was given */
178 int       minfree = MINFREE;  /* free space threshold */
179 int       opt = DEFAULTOPT;   /* optimization preference (space or time) */
180 int       density;            /* number of bytes per inode */
181 int       maxcontig = 0;                /* max contiguous blocks to allocate */
182 int       rotdelay = ROTDELAY;          /* rotational delay between blocks */
183 int       maxbpg;                       /* maximum blocks per file in a cyl group */
184 int       nrpos = NRPOS;                /* # of distinguished rotational positions */
185 int       avgfilesize = AVFILESIZ;/* expected average file size */
186 int       avgfilesperdir = AFPDIR;/* expected number of files per directory */
187 int       bbsize = BBSIZE;    /* boot block size */
188 int       sbsize = SBSIZE;    /* superblock size */
189 int       mntflags = MNT_ASYNC;         /* flags to be passed to mount */
190 int       t_or_u_flag = 0;    /* user has specified -t or -u */
191 caddr_t   membase;            /* start address of memory based filesystem */
192 char      *filename;
193 u_char    *volumelabel = NULL;          /* volume label for filesystem */
194 #ifdef COMPAT
195 char      *disktype;
196 int       unlabeled;
197 #endif
198 
199 char      mfsdevname[256];
200 char      *progname;
201 
202 static void usage(void);
203 static void mfsintr(int signo);
204 
205 int
main(int argc,char ** argv)206 main(int argc, char **argv)
207 {
208           int ch, i;
209           struct disktab geom;                    /* disk geometry data */
210           struct stat st;
211           struct statfs *mp;
212           int fsi = -1, fso = -1, len, n, vflag;
213           char *s1, *s2, *special;
214           const char *opstring;
215 #ifdef MFS
216           struct vfsconf vfc;
217           int error;
218 #endif
219 
220           bzero(&geom, sizeof(geom));
221           vflag = 0;
222           if ((progname = strrchr(*argv, '/')))
223                     ++progname;
224           else
225                     progname = *argv;
226 
227           if (strstr(progname, "mfs")) {
228                     mfs = 1;
229                     Nflag++;
230           }
231 
232           opstring = mfs ?
233               "L:NCF:T:Ua:b:c:d:e:f:g:h:i:m:o:s:v" :
234               "L:NEOS:T:Ua:b:c:d:e:f:g:h:i:k:l:m:n:o:p:r:s:t:u:vx:";
235           while ((ch = getopt(argc, argv, opstring)) != -1) {
236                     switch (ch) {
237                     case 'E':
238                               Eflag = 1;
239                               break;
240                     case 'L':
241                               volumelabel = optarg;
242                               i = -1;
243                               while (isalnum(volumelabel[++i]))
244                                         ;
245                               if (volumelabel[i] != '\0')
246                                         errx(1, "bad volume label. Valid characters are alphanumerics.");
247                               if (strlen(volumelabel) >= MAXVOLLEN)
248                                         errx(1, "bad volume label. Length is longer than %d.",
249                                             MAXVOLLEN);
250                               Lflag = 1;
251                               break;
252                     case 'N':
253                               Nflag = 1;
254                               break;
255                     case 'O':
256                               Oflag = 1;
257                               break;
258                     case 'C':
259                               Cflag = 1;          /* MFS only */
260                               break;
261                     case 'S':
262                               if ((sectorsize = atoi(optarg)) <= 0)
263                                         fatal("%s: bad sector size", optarg);
264                               break;
265 #ifdef COMPAT
266                     case 'T':
267                               disktype = optarg;
268                               break;
269 #endif
270                     case 'F':
271                               filename = optarg;
272                               break;
273                     case 'U':
274                               Uflag = 1;
275                               break;
276                     case 'a':
277                               if ((maxcontig = atoi(optarg)) <= 0)
278                                         fatal("%s: bad maximum contiguous blocks",
279                                             optarg);
280                               break;
281                     case 'b':
282                               if ((bsize = atoi(optarg)) < MINBSIZE)
283                                         fatal("%s: bad block size", optarg);
284                               break;
285                     case 'c':
286                               if ((cpg = atoi(optarg)) <= 0)
287                                         fatal("%s: bad cylinders/group", optarg);
288                               cpgflg++;
289                               break;
290                     case 'd':
291                               if ((rotdelay = atoi(optarg)) < 0)
292                                         fatal("%s: bad rotational delay", optarg);
293                               break;
294                     case 'e':
295                               if ((maxbpg = atoi(optarg)) <= 0)
296                     fatal("%s: bad blocks per file in a cylinder group",
297                                             optarg);
298                               break;
299                     case 'f':
300                               if ((fsize = atoi(optarg)) <= 0)
301                                         fatal("%s: bad fragment size", optarg);
302                               break;
303                     case 'g':
304                               if ((avgfilesize = atoi(optarg)) <= 0)
305                                         fatal("%s: bad average file size", optarg);
306                               break;
307                     case 'h':
308                               if ((avgfilesperdir = atoi(optarg)) <= 0)
309                                         fatal("%s: bad average files per dir", optarg);
310                               break;
311                     case 'i':
312                               if ((density = atoi(optarg)) <= 0)
313                                         fatal("%s: bad bytes per inode", optarg);
314                               break;
315                     case 'k':
316                               if ((trackskew = atoi(optarg)) < 0)
317                                         fatal("%s: bad track skew", optarg);
318                               break;
319                     case 'l':
320                               if ((interleave = atoi(optarg)) <= 0)
321                                         fatal("%s: bad interleave", optarg);
322                               break;
323                     case 'm':
324                               if ((minfree = atoi(optarg)) < 0 || minfree > 99)
325                                         fatal("%s: bad free space %%", optarg);
326                               break;
327                     case 'n':
328                               if ((nrpos = atoi(optarg)) < 0)
329                                         fatal("%s: bad rotational layout count",
330                                             optarg);
331                               if (nrpos == 0)
332                                         nrpos = 1;
333                               break;
334                     case 'o':
335                               if (mfs)
336                                         getmntopts(optarg, mopts, &mntflags, 0);
337                               else {
338                                         if (strcmp(optarg, "space") == 0)
339                                                   opt = FS_OPTSPACE;
340                                         else if (strcmp(optarg, "time") == 0)
341                                                   opt = FS_OPTTIME;
342                                         else
343           fatal("%s: unknown optimization preference: use `space' or `time'", optarg);
344                               }
345                               break;
346                     case 'p':
347                               if ((trackspares = atoi(optarg)) < 0)
348                                         fatal("%s: bad spare sectors per track",
349                                             optarg);
350                               break;
351                     case 'r':
352                               if ((rpm = atoi(optarg)) <= 0)
353                                         fatal("%s: bad revolutions/minute", optarg);
354                               break;
355                     case 's':
356                               /*
357                                * Unsigned long but limit to long.  On 32 bit a
358                                * tad under 2G, on 64 bit the upper bound is more
359                                * swap space then operand size.
360                                *
361                                * NOTE: fssize is converted from 512 byte sectors
362                                * to filesystem block-sized sectors by mkfs XXX.
363                                */
364                               fssize = strtoul(optarg, NULL, 10);
365                               if (fssize == 0 || fssize > LONG_MAX)
366                                         fatal("%s: bad file system size", optarg);
367                               break;
368                     case 't':
369                               t_or_u_flag++;
370                               if ((ntracks = atoi(optarg)) < 0)
371                                         fatal("%s: bad total tracks", optarg);
372                               break;
373                     case 'u':
374                               t_or_u_flag++;
375                               if ((nsectors = atoi(optarg)) < 0)
376                                         fatal("%s: bad sectors/track", optarg);
377                               break;
378                     case 'v':
379                               vflag = 1;
380                               break;
381                     case 'x':
382                               if ((cylspares = atoi(optarg)) < 0)
383                                         fatal("%s: bad spare sectors per cylinder",
384                                             optarg);
385                               break;
386                     case '?':
387                     default:
388                               usage();
389                     }
390           }
391           argc -= optind;
392           argv += optind;
393 
394           if (argc != 2 && (mfs || argc != 1))
395                     usage();
396 
397           special = argv[0];
398           /* Copy the NetBSD way of faking up a disk label */
399         if (mfs && !strcmp(special, "swap")) {
400                 /*
401                  * it's an MFS, mounted on "swap."  fake up a label.
402                  * XXX XXX XXX
403                  */
404                 fso = -1;       /* XXX; normally done below. */
405 
406                     geom.d_media_blksize = 512;
407                     geom.d_nheads = 16;
408                     geom.d_secpertrack = 64;
409                     /* geom.d_ncylinders not used */
410                     geom.d_secpercyl = 1024;
411                     geom.d_media_blocks = 16384;
412                 geom.d_rpm = 3600;
413                 geom.d_interleave = 1;
414 
415                 goto havelabel;
416         }
417 
418           /*
419            * If we can't stat the device and the path is relative, try
420            * prepending /dev.
421            */
422           if (stat(special, &st) < 0 && special[0] && special[0] != '/')
423                     asprintf(&special, "/dev/%s", special);
424 
425           if (Eflag) {
426                     char sysctl_name[64];
427                     int trim_enabled = 0;
428                     size_t olen = sizeof(trim_enabled);
429                     char *dev_name = strdup(special);
430 
431                     dev_name = strtok(dev_name + strlen("/dev/da"),"s");
432                     sprintf(sysctl_name, "kern.cam.da.%s.trim_enabled",
433                         dev_name);
434 
435                     if (sysctlbyname(sysctl_name, &trim_enabled, &olen, NULL, 0) < 0) {
436                               printf("Device:%s does not support the TRIM command\n",
437                                   special);
438                               usage();
439                     }
440                     if(!trim_enabled) {
441                               printf("Erase device option selected, but sysctl (%s) "
442                                   "is not enabled\n",sysctl_name);
443                               usage();
444 
445                     }
446           }
447           if (Nflag) {
448                     fso = -1;
449           } else {
450                     fso = open(special, O_WRONLY);
451                     if (fso < 0)
452                               fatal("%s: %s", special, strerror(errno));
453 
454                     /* Bail if target special is mounted */
455                     n = getmntinfo(&mp, MNT_NOWAIT);
456                     if (n == 0)
457                               fatal("%s: getmntinfo: %s", special, strerror(errno));
458 
459                     len = sizeof(_PATH_DEV) - 1;
460                     s1 = special;
461                     if (strncmp(_PATH_DEV, s1, len) == 0)
462                               s1 += len;
463 
464                     while (--n >= 0) {
465                               s2 = mp->f_mntfromname;
466                               if (strncmp(_PATH_DEV, s2, len) == 0) {
467                                         s2 += len - 1;
468                                         *s2 = 'r';
469                               }
470                               if (strcmp(s1, s2) == 0 || strcmp(s1, &s2[1]) == 0)
471                                         fatal("%s is mounted on %s",
472                                             special, mp->f_mntonname);
473                               ++mp;
474                     }
475           }
476           if (mfs && disktype != NULL) {
477                     struct disktab *dt;
478 
479                     if ((dt = getdisktabbyname(disktype)) == NULL)
480                               fatal("%s: unknown disk type", disktype);
481                     geom = *dt;
482           } else {
483                     struct partinfo pinfo;
484 
485                     if (special[0] == 0)
486                               fatal("null special file name");
487                     fsi = open(special, O_RDONLY);
488                     if (fsi < 0)
489                               fatal("%s: %s", special, strerror(errno));
490                     if (fstat(fsi, &st) < 0)
491                               fatal("%s: %s", special, strerror(errno));
492                     if ((st.st_mode & S_IFMT) != S_IFCHR && !mfs && !vflag)
493                               printf("%s: %s: not a character-special device\n",
494                                   progname, special);
495 #ifdef COMPAT
496                     if (!mfs && disktype == NULL)
497                               disktype = argv[1];
498 #endif
499                     if (ioctl(fsi, DIOCGPART, &pinfo) < 0) {
500                               if (!vflag) {
501                                         fatal("%s: unable to retrieve geometry "
502                                               "information", argv[0]);
503                               }
504                               /*
505                                * fake up geometry data
506                                */
507                               geom.d_media_blksize = 512;
508                               geom.d_nheads = 16;
509                               geom.d_secpertrack = 64;
510                               geom.d_secpercyl = 1024;
511                               geom.d_media_blocks = st.st_size /
512                                                         geom.d_media_blksize;
513                               geom.d_media_size = geom.d_media_blocks *
514                                                       geom.d_media_blksize;
515                               /* geom.d_ncylinders not used */
516                     } else {
517                               /*
518                                * extract geometry from pinfo
519                                */
520                               geom.d_media_blksize = pinfo.media_blksize;
521                               geom.d_nheads = pinfo.d_nheads;
522                               geom.d_secpertrack = pinfo.d_secpertrack;
523                               geom.d_secpercyl = pinfo.d_secpercyl;
524                               /* geom.d_ncylinders not used */
525                               geom.d_media_blocks = pinfo.media_blocks;
526                               geom.d_media_size = pinfo.media_size;
527                               slice_offset = pinfo.media_offset;
528                     }
529                     if (geom.d_media_blocks == 0 || geom.d_media_size == 0) {
530                               fatal("%s: is unavailable", argv[0]);
531                     }
532                     printf("%s: media size %6.2fMB\n",
533                             argv[0], geom.d_media_size / 1024.0 / 1024.0);
534                     if (geom.d_media_size / 512 >= 0x80000000ULL)
535                               fatal("%s: media size is too large for newfs to handle",
536                                     argv[0]);
537           }
538 havelabel:
539           if (fssize == 0)
540                     fssize = geom.d_media_blocks;
541           if ((u_long)fssize > geom.d_media_blocks && !mfs) {
542                  fatal("%s: maximum file system size is %" PRIu64 " blocks",
543                          argv[0], geom.d_media_blocks);
544           }
545           if (rpm == 0) {
546                     rpm = geom.d_rpm;
547                     if (rpm <= 0)
548                               rpm = 3600;
549           }
550           if (ntracks == 0) {
551                     ntracks = geom.d_nheads;
552                     if (ntracks <= 0)
553                               fatal("%s: no default #tracks", argv[0]);
554           }
555           if (nsectors == 0) {
556                     nsectors = geom.d_secpertrack;
557                     if (nsectors <= 0)
558                               fatal("%s: no default #sectors/track", argv[0]);
559           }
560           if (sectorsize == 0) {
561                     sectorsize = geom.d_media_blksize;
562                     if (sectorsize <= 0)
563                               fatal("%s: no default sector size", argv[0]);
564           }
565           if (trackskew == -1) {
566                     trackskew = geom.d_trackskew;
567                     if (trackskew < 0)
568                               trackskew = 0;
569           }
570           if (interleave == 0) {
571                     interleave = geom.d_interleave;
572                     if (interleave <= 0)
573                               interleave = 1;
574           }
575           if (fsize == 0)
576                     fsize = MAX(DFL_FRAGSIZE, geom.d_media_blksize);
577           if (bsize == 0)
578                     bsize = MIN(DFL_BLKSIZE, 8 * fsize);
579           /*
580            * Maxcontig sets the default for the maximum number of blocks
581            * that may be allocated sequentially. With filesystem clustering
582            * it is possible to allocate contiguous blocks up to the maximum
583            * transfer size permitted by the controller or buffering.
584            */
585           if (maxcontig == 0)
586                     maxcontig = MAX(1, MAXPHYS / bsize - 1);
587           if (density == 0)
588                     density = NFPI * fsize;
589           if (minfree < MINFREE && opt != FS_OPTSPACE) {
590                     fprintf(stderr, "Warning: changing optimization to space ");
591                     fprintf(stderr, "because minfree is less than %d%%\n", MINFREE);
592                     opt = FS_OPTSPACE;
593           }
594           if (trackspares == -1)
595                     trackspares = 0;
596           nphyssectors = nsectors + trackspares;
597           if (cylspares == -1)
598                     cylspares = 0;
599           secpercyl = nsectors * ntracks - cylspares;
600           /*
601            * Only complain if -t or -u have been specified; the default
602            * case (4096 sectors per cylinder) is intended to disagree
603            * with the disklabel.
604            */
605           if (t_or_u_flag && (uint32_t)secpercyl != geom.d_secpercyl)
606                     fprintf(stderr, "%s (%d) %s (%u)\n",
607                               "Warning: calculated sectors per cylinder", secpercyl,
608                               "disagrees with disk label", geom.d_secpercyl);
609           if (maxbpg == 0)
610                     maxbpg = MAXBLKPG(bsize);
611           headswitch = geom.d_headswitch;
612           trackseek = geom.d_trkseek;
613           realsectorsize = sectorsize;
614           if (sectorsize != DEV_BSIZE) {                    /* XXX */
615                     int secperblk = sectorsize / DEV_BSIZE;
616 
617                     sectorsize = DEV_BSIZE;
618                     nsectors *= secperblk;
619                     nphyssectors *= secperblk;
620                     secpercyl *= secperblk;
621                     fssize *= secperblk;
622           }
623           if (mfs) {
624                     mfs_mtpt = argv[1];
625                     if (
626                         stat(mfs_mtpt, &mfs_mtstat) < 0 ||
627                         !S_ISDIR(mfs_mtstat.st_mode)
628                     ) {
629                               fatal("mount point not dir: %s", mfs_mtpt);
630                     }
631           }
632           mkfs(special, fsi, fso, (Cflag && mfs) ? argv[1] : NULL);
633 
634           /*
635            * NOTE: Newfs no longer accesses or attempts to update the
636            * filesystem disklabel.
637            *
638            * NOTE: fssize is converted from 512 byte sectors
639            * to filesystem block-sized sectors by mkfs XXX.
640            */
641           if (!Nflag)
642                     close(fso);
643           close(fsi);
644 #ifdef MFS
645           if (mfs) {
646                     struct mfs_args args;
647 
648                     bzero(&args, sizeof(args));
649 
650                     snprintf(mfsdevname, sizeof(mfsdevname), "/dev/mfs%d",
651                               getpid());
652                     args.fspec = mfsdevname;
653                     args.export.ex_root = -2;
654                     if (mntflags & MNT_RDONLY)
655                               args.export.ex_flags = MNT_EXRDONLY;
656                     else
657                               args.export.ex_flags = 0;
658                     args.base = membase;
659                     args.size = fssize * fsize;
660 
661                     error = getvfsbyname("mfs", &vfc);
662                     if (error && vfsisloadable("mfs")) {
663                               if (vfsload("mfs"))
664                                         fatal("vfsload(mfs)");
665                               endvfsent();        /* flush cache */
666                               error = getvfsbyname("mfs", &vfc);
667                     }
668                     if (error)
669                               fatal("mfs filesystem not available");
670 
671 #if 0
672                     int udev;
673                     udev = (253 << 8) | (getpid() & 255) |
674                               ((getpid() & ~0xFF) << 8);
675                     if (mknod(mfsdevname, S_IFCHR | 0700, udev) < 0)
676                               printf("Warning: unable to create %s\n", mfsdevname);
677 #endif
678                     signal(SIGINT, mfsintr);
679                     if (mount(vfc.vfc_name, argv[1], mntflags, &args) < 0)
680                               fatal("%s: %s", argv[1], strerror(errno));
681                     signal(SIGINT, SIG_DFL);
682                     mfsintr(SIGINT);
683           }
684 #endif
685           exit(0);
686 }
687 
688 #ifdef MFS
689 
690 static void
mfsintr(__unused int signo)691 mfsintr(__unused int signo)
692 {
693           if (filename)
694                     munmap(membase, fssize * fsize);
695 #if 0
696           remove(mfsdevname);
697 #endif
698 }
699 
700 #endif
701 
702 /*VARARGS*/
703 void
fatal(const char * fmt,...)704 fatal(const char *fmt, ...)
705 {
706           va_list ap;
707 
708           va_start(ap, fmt);
709           if (fcntl(STDERR_FILENO, F_GETFL) < 0) {
710                     openlog(progname, LOG_CONS, LOG_DAEMON);
711                     vsyslog(LOG_ERR, fmt, ap);
712                     closelog();
713           } else {
714                     vwarnx(fmt, ap);
715           }
716           va_end(ap);
717           exit(1);
718           /*NOTREACHED*/
719 }
720 
721 void
usage(void)722 usage(void)
723 {
724           if (mfs) {
725                     fprintf(stderr,
726                         "usage: %s [ -fsoptions ] special-device mount-point\n",
727                               progname);
728           } else
729                     fprintf(stderr,
730                         "usage: %s [ -fsoptions ] special-device%s\n",
731                         progname,
732 #ifdef COMPAT
733                         " [device-type]");
734 #else
735                         "");
736 #endif
737           fprintf(stderr, "where fsoptions are:\n");
738           fprintf(stderr, "\t-C (mfs) Copy the underlying filesystem to the MFS mount\n");
739           fprintf(stderr, "\t-E erase file system contents using TRIM\n");
740           fprintf(stderr, "\t-L volume name\n");
741           fprintf(stderr,
742               "\t-N do not create file system, just print out parameters\n");
743           fprintf(stderr, "\t-O create a 4.3BSD format filesystem\n");
744           fprintf(stderr, "\t-S sector size\n");
745 #ifdef COMPAT
746           fprintf(stderr, "\t-T disktype\n");
747 #endif
748           fprintf(stderr, "\t-U enable soft updates\n");
749           fprintf(stderr, "\t-a maximum contiguous blocks\n");
750           fprintf(stderr, "\t-b block size\n");
751           fprintf(stderr, "\t-c cylinders/group\n");
752           fprintf(stderr, "\t-d rotational delay between contiguous blocks\n");
753           fprintf(stderr, "\t-e maximum blocks per file in a cylinder group\n");
754           fprintf(stderr, "\t-f frag size\n");
755           fprintf(stderr, "\t-g average file size\n");
756           fprintf(stderr, "\t-h average files per directory\n");
757           fprintf(stderr, "\t-i number of bytes per inode\n");
758           fprintf(stderr, "\t-k sector 0 skew, per track\n");
759           fprintf(stderr, "\t-l hardware sector interleave\n");
760           fprintf(stderr, "\t-m minimum free space %%\n");
761           fprintf(stderr, "\t-n number of distinguished rotational positions\n");
762           fprintf(stderr, "\t-o optimization preference (`space' or `time')\n");
763           fprintf(stderr, "\t-p spare sectors per track\n");
764           fprintf(stderr, "\t-s file system size (sectors)\n");
765           fprintf(stderr, "\t-r revolutions/minute\n");
766           fprintf(stderr, "\t-t tracks/cylinder\n");
767           fprintf(stderr, "\t-u sectors/track\n");
768           fprintf(stderr,
769         "\t-v do not attempt to determine partition name from device name\n");
770           fprintf(stderr, "\t-x spare sectors per cylinder\n");
771           exit(1);
772 }
773