TRIM support
[dragonfly.git] / sbin / newfs / mkfs.c
1 /*
2  * Copyright (c) 1980, 1989, 1993
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. All advertising materials mentioning features or use of this software
14  *    must display the following acknowledgement:
15  *      This product includes software developed by the University of
16  *      California, Berkeley and its contributors.
17  * 4. Neither the name of the University nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  *
33  * @(#)mkfs.c   8.11 (Berkeley) 5/3/95
34  * $FreeBSD: src/sbin/newfs/mkfs.c,v 1.29.2.6 2001/09/21 19:15:21 dillon Exp $
35  * $DragonFly: src/sbin/newfs/mkfs.c,v 1.14 2007/05/20 19:29:21 dillon Exp $
36  */
37
38 #include "defs.h"
39
40 #include <stdlib.h>
41 #include <sys/ioctl_compat.h>
42
43 /*
44  * make file system for cylinder-group style file systems
45  */
46
47 /*
48  * We limit the size of the inode map to be no more than a
49  * third of the cylinder group space, since we must leave at
50  * least an equal amount of space for the block map.
51  *
52  * N.B.: MAXIPG must be a multiple of INOPB(fs).
53  */
54 #define MAXIPG(fs)      roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs))
55
56 #define UMASK           0755
57 #define MAXINOPB        (MAXBSIZE / sizeof(struct ufs1_dinode))
58 #define POWEROF2(num)   (((num) & ((num) - 1)) == 0)
59
60 #ifdef STANDALONE
61 #error "mkfs.c: STANDALONE compilation no longer supported"
62 #endif
63
64 /*
65  * variables set up by front end.
66  */
67 extern int      mfs;            /* run as the memory based filesystem */
68 extern char     *mfs_mtpt;      /* mount point for mfs          */ 
69 extern struct stat mfs_mtstat;  /* stat prior to mount          */
70 extern int      Lflag;          /* add a volume label */
71 extern int      Nflag;          /* run mkfs without writing file system */
72 extern int      Oflag;          /* format as an 4.3BSD file system */
73 extern int      Uflag;          /* enable soft updates for file system */
74 extern int      Eflag;          /* erase contents using TRIM */
75 extern uint64_t slice_offset;   /* Pysical device slice offset */
76 extern u_long   fssize;         /* file system size */
77 extern int      ntracks;        /* # tracks/cylinder */
78 extern int      nsectors;       /* # sectors/track */
79 extern int      nphyssectors;   /* # sectors/track including spares */
80 extern int      secpercyl;      /* sectors per cylinder */
81 extern int      sectorsize;     /* bytes/sector */
82 extern int      realsectorsize; /* bytes/sector in hardware*/
83 extern int      rpm;            /* revolutions/minute of drive */
84 extern int      interleave;     /* hardware sector interleave */
85 extern int      trackskew;      /* sector 0 skew, per track */
86 extern int      fsize;          /* fragment size */
87 extern int      bsize;          /* block size */
88 extern int      cpg;            /* cylinders/cylinder group */
89 extern int      cpgflg;         /* cylinders/cylinder group flag was given */
90 extern int      minfree;        /* free space threshold */
91 extern int      opt;            /* optimization preference (space or time) */
92 extern int      density;        /* number of bytes per inode */
93 extern int      maxcontig;      /* max contiguous blocks to allocate */
94 extern int      rotdelay;       /* rotational delay between blocks */
95 extern int      maxbpg;         /* maximum blocks per file in a cyl group */
96 extern int      nrpos;          /* # of distinguished rotational positions */
97 extern int      bbsize;         /* boot block size */
98 extern int      sbsize;         /* superblock size */
99 extern int      avgfilesize;    /* expected average file size */
100 extern int      avgfilesperdir; /* expected number of files per directory */
101 extern caddr_t  membase;        /* start address of memory based filesystem */
102 extern char *   filename;
103 extern u_char   *volumelabel;   /* volume label for filesystem */
104 extern struct disktab geom;
105
106 extern void fatal(const char *fmt, ...);
107
108 union {
109         struct fs fs;
110         char pad[SBSIZE];
111 } fsun;
112 #define sblock  fsun.fs
113 struct  csum *fscs;
114
115 union {
116         struct cg cg;
117         char pad[MAXBSIZE];
118 } cgun;
119 #define acg     cgun.cg
120
121 struct ufs1_dinode zino[MAXBSIZE / sizeof(struct ufs1_dinode)];
122
123 int     fsi, fso;
124 static fsnode_t copyroot;
125 static fsnode_t copyhlinks;
126 #ifdef FSIRAND
127 int     randinit;
128 #endif
129 daddr_t alloc(int, int);
130 long    calcipg(long, long, off_t *);
131 static int charsperline(void);
132 void clrblock(struct fs *, unsigned char *, int);
133 void fsinit(time_t);
134 void initcg(int, time_t);
135 int isblock(struct fs *, unsigned char *, int);
136 void iput(struct ufs1_dinode *, ino_t);
137 int makedir(struct direct *, int);
138 void parentready(int);
139 void rdfs(daddr_t, int, char *);
140 void setblock(struct fs *, unsigned char *, int);
141 void started(int);
142 void erfs(off_t, off_t);
143 void wtfs(daddr_t, int, char *);
144 void wtfsflush(void);
145
146 int mfs_ppid = 0;
147 int parentready_signalled;
148
149 void
150 mkfs(char *fsys, int fi, int fo, const char *mfscopy)
151 {
152         long i, mincpc, mincpg, inospercg;
153         long cylno, rpos, blk, j, emitwarn = 0;
154         long used, mincpgcnt, bpcg;
155         off_t usedb;
156         long mapcramped, inodecramped;
157         long postblsize, rotblsize, totalsbsize;
158         int status, fd;
159         time_t utime;
160         quad_t sizepb;
161         int width;
162         char tmpbuf[100];       /* XXX this will break in about 2,500 years */
163
164         time(&utime);
165 #ifdef FSIRAND
166         if (!randinit) {
167                 randinit = 1;
168                 srandomdev();
169         }
170 #endif
171         if (mfs) {
172                 int omask;
173                 pid_t child;
174
175                 mfs_ppid = getpid();
176                 signal(SIGUSR1, parentready);
177                 if ((child = fork()) != 0) {
178                         /*
179                          * Parent
180                          */
181                         if (child == -1)
182                                 err(10, "mfs");
183                         if (mfscopy)
184                             copyroot = FSCopy(&copyhlinks, mfscopy);
185                         signal(SIGUSR1, started);
186                         kill(child, SIGUSR1);
187                         while (waitpid(child, &status, 0) != child)
188                                 ;
189                         exit(WEXITSTATUS(status));
190                         /* NOTREACHED */
191                 }
192
193                 /*
194                  * Child
195                  */
196                 omask = sigblock(sigmask(SIGUSR1));
197                 while (parentready_signalled == 0)
198                         sigpause(omask);
199                 sigsetmask(omask);
200                 if (filename != NULL) {
201                         unsigned char buf[BUFSIZ];
202                         unsigned long l, l1;
203                         ssize_t w;
204
205                         fd = open(filename, O_RDWR|O_TRUNC|O_CREAT, 0644);
206                         if(fd < 0)
207                                 err(12, "%s", filename);
208                         l1 = fssize * sectorsize;
209                         if (l1 > BUFSIZ)
210                                 l1 = BUFSIZ;
211                         for (l = 0; l < fssize * (u_long)sectorsize; l += l1) {
212                                 w = write(fd, buf, l1);
213                                 if (w < 0 || (u_long)w != l1)
214                                         err(12, "%s", filename);
215                         }
216                         membase = mmap(NULL, fssize * sectorsize,
217                                        PROT_READ|PROT_WRITE,
218                                        MAP_SHARED, fd, 0);
219                         if (membase == MAP_FAILED)
220                                 err(12, "mmap");
221                         close(fd);
222                 } else {
223                         membase = mmap(NULL, fssize * sectorsize,
224                                        PROT_READ|PROT_WRITE,
225                                        MAP_SHARED|MAP_ANON, -1, 0);
226                         if (membase == MAP_FAILED)
227                                 errx(13, "mmap (anonymous memory) failed");
228                 }
229         }
230         fsi = fi;
231         fso = fo;
232         if (Oflag) {
233                 sblock.fs_inodefmt = FS_42INODEFMT;
234                 sblock.fs_maxsymlinklen = 0;
235         } else {
236                 sblock.fs_inodefmt = FS_44INODEFMT;
237                 sblock.fs_maxsymlinklen = MAXSYMLINKLEN;
238         }
239         if (Uflag)
240                 sblock.fs_flags |= FS_DOSOFTDEP;
241         if (Lflag)
242                 strlcpy(sblock.fs_volname, volumelabel, MAXVOLLEN);
243
244         /*
245          * Validate the given file system size.
246          * Verify that its last block can actually be accessed.
247          */
248         if (fssize == 0)
249                 printf("preposterous size %lu\n", fssize), exit(13);
250         wtfs(fssize - (realsectorsize / DEV_BSIZE), realsectorsize,
251                  (char *)&sblock);
252         /*
253          * collect and verify the sector and track info
254          */
255         sblock.fs_nsect = nsectors;
256         sblock.fs_ntrak = ntracks;
257         if (sblock.fs_ntrak <= 0)
258                 printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(14);
259         if (sblock.fs_nsect <= 0)
260                 printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15);
261         /*
262          * collect and verify the filesystem density info
263          */
264         sblock.fs_avgfilesize = avgfilesize;
265         sblock.fs_avgfpdir = avgfilesperdir;
266         if (sblock.fs_avgfilesize <= 0)
267                 printf("illegal expected average file size %d\n",
268                     sblock.fs_avgfilesize), exit(14);
269         if (sblock.fs_avgfpdir <= 0)
270                 printf("illegal expected number of files per directory %d\n",
271                     sblock.fs_avgfpdir), exit(15);
272         /*
273          * collect and verify the block and fragment sizes
274          */
275         sblock.fs_bsize = bsize;
276         sblock.fs_fsize = fsize;
277         if (!POWEROF2(sblock.fs_bsize)) {
278                 printf("block size must be a power of 2, not %d\n",
279                     sblock.fs_bsize);
280                 exit(16);
281         }
282         if (!POWEROF2(sblock.fs_fsize)) {
283                 printf("fragment size must be a power of 2, not %d\n",
284                     sblock.fs_fsize);
285                 exit(17);
286         }
287         if (sblock.fs_fsize < sectorsize) {
288                 printf("fragment size %d is too small, minimum is %d\n",
289                     sblock.fs_fsize, sectorsize);
290                 exit(18);
291         }
292         if (sblock.fs_bsize < MINBSIZE) {
293                 printf("block size %d is too small, minimum is %d\n",
294                     sblock.fs_bsize, MINBSIZE);
295                 exit(19);
296         }
297         if (sblock.fs_bsize < sblock.fs_fsize) {
298                 printf("block size (%d) cannot be smaller than fragment size (%d)\n",
299                     sblock.fs_bsize, sblock.fs_fsize);
300                 exit(20);
301         }
302         sblock.fs_bmask = ~(sblock.fs_bsize - 1);
303         sblock.fs_fmask = ~(sblock.fs_fsize - 1);
304         sblock.fs_qbmask = ~sblock.fs_bmask;
305         sblock.fs_qfmask = ~sblock.fs_fmask;
306         for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1)
307                 sblock.fs_bshift++;
308         for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1)
309                 sblock.fs_fshift++;
310         sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize);
311         for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1)
312                 sblock.fs_fragshift++;
313         if (sblock.fs_frag > MAXFRAG) {
314                 printf("fragment size %d is too small, minimum with block size %d is %d\n",
315                     sblock.fs_fsize, sblock.fs_bsize,
316                     sblock.fs_bsize / MAXFRAG);
317                 exit(21);
318         }
319         sblock.fs_nrpos = nrpos;
320         sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t);
321         sblock.fs_inopb = sblock.fs_bsize / sizeof(struct ufs1_dinode);
322         sblock.fs_nspf = sblock.fs_fsize / sectorsize;
323         for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1)
324                 sblock.fs_fsbtodb++;
325         sblock.fs_sblkno =
326             roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag);
327         sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno +
328             roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag));
329         sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag;
330         sblock.fs_cgoffset = roundup(
331             howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag);
332         for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1)
333                 sblock.fs_cgmask <<= 1;
334         if (!POWEROF2(sblock.fs_ntrak))
335                 sblock.fs_cgmask <<= 1;
336         sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1;
337         for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) {
338                 sizepb *= NINDIR(&sblock);
339                 sblock.fs_maxfilesize += sizepb;
340         }
341         /*
342          * Validate specified/determined secpercyl
343          * and calculate minimum cylinders per group.
344          */
345         sblock.fs_spc = secpercyl;
346         for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc;
347              sblock.fs_cpc > 1 && (i & 1) == 0;
348              sblock.fs_cpc >>= 1, i >>= 1)
349                 /* void */;
350         mincpc = sblock.fs_cpc;
351         bpcg = sblock.fs_spc * sectorsize;
352         inospercg = roundup(bpcg / sizeof(struct ufs1_dinode), INOPB(&sblock));
353         if (inospercg > MAXIPG(&sblock))
354                 inospercg = MAXIPG(&sblock);
355         used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock);
356         mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used,
357             sblock.fs_spc);
358         mincpg = roundup(mincpgcnt, mincpc);
359         /*
360          * Ensure that cylinder group with mincpg has enough space
361          * for block maps.
362          */
363         sblock.fs_cpg = mincpg;
364         sblock.fs_ipg = inospercg;
365         if (maxcontig > 1)
366                 sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG);
367         mapcramped = 0;
368         while (CGSIZE(&sblock) > (uint32_t)sblock.fs_bsize) {
369                 mapcramped = 1;
370                 if (sblock.fs_bsize < MAXBSIZE) {
371                         sblock.fs_bsize <<= 1;
372                         if ((i & 1) == 0) {
373                                 i >>= 1;
374                         } else {
375                                 sblock.fs_cpc <<= 1;
376                                 mincpc <<= 1;
377                                 mincpg = roundup(mincpgcnt, mincpc);
378                                 sblock.fs_cpg = mincpg;
379                         }
380                         sblock.fs_frag <<= 1;
381                         sblock.fs_fragshift += 1;
382                         if (sblock.fs_frag <= MAXFRAG)
383                                 continue;
384                 }
385                 if (sblock.fs_fsize == sblock.fs_bsize) {
386                         printf("There is no block size that");
387                         printf(" can support this disk\n");
388                         exit(22);
389                 }
390                 sblock.fs_frag >>= 1;
391                 sblock.fs_fragshift -= 1;
392                 sblock.fs_fsize <<= 1;
393                 sblock.fs_nspf <<= 1;
394         }
395         /*
396          * Ensure that cylinder group with mincpg has enough space for inodes.
397          */
398         inodecramped = 0;
399         inospercg = calcipg(mincpg, bpcg, &usedb);
400         sblock.fs_ipg = inospercg;
401         while (inospercg > MAXIPG(&sblock)) {
402                 inodecramped = 1;
403                 if (mincpc == 1 || sblock.fs_frag == 1 ||
404                     sblock.fs_bsize == MINBSIZE)
405                         break;
406                 printf("With a block size of %d %s %d\n", sblock.fs_bsize,
407                        "minimum bytes per inode is",
408                        (int)((mincpg * (off_t)bpcg - usedb)
409                              / MAXIPG(&sblock) + 1));
410                 sblock.fs_bsize >>= 1;
411                 sblock.fs_frag >>= 1;
412                 sblock.fs_fragshift -= 1;
413                 mincpc >>= 1;
414                 sblock.fs_cpg = roundup(mincpgcnt, mincpc);
415                 if (CGSIZE(&sblock) > (uint32_t)sblock.fs_bsize) {
416                         sblock.fs_bsize <<= 1;
417                         break;
418                 }
419                 mincpg = sblock.fs_cpg;
420                 inospercg = calcipg(mincpg, bpcg, &usedb);
421                 sblock.fs_ipg = inospercg;
422         }
423         if (inodecramped) {
424                 if (inospercg > MAXIPG(&sblock)) {
425                         printf("Minimum bytes per inode is %d\n",
426                                (int)((mincpg * (off_t)bpcg - usedb)
427                                      / MAXIPG(&sblock) + 1));
428                 } else if (!mapcramped) {
429                         printf("With %d bytes per inode, ", density);
430                         printf("minimum cylinders per group is %ld\n", mincpg);
431                 }
432         }
433         if (mapcramped) {
434                 printf("With %d sectors per cylinder, ", sblock.fs_spc);
435                 printf("minimum cylinders per group is %ld\n", mincpg);
436         }
437         if (inodecramped || mapcramped) {
438                 if (sblock.fs_bsize != bsize)
439                         printf("%s to be changed from %d to %d\n",
440                             "This requires the block size",
441                             bsize, sblock.fs_bsize);
442                 if (sblock.fs_fsize != fsize)
443                         printf("\t%s to be changed from %d to %d\n",
444                             "and the fragment size",
445                             fsize, sblock.fs_fsize);
446                 exit(23);
447         }
448         /*
449          * Calculate the number of cylinders per group
450          */
451         sblock.fs_cpg = cpg;
452         if (sblock.fs_cpg % mincpc != 0) {
453                 printf("%s groups must have a multiple of %ld cylinders\n",
454                         cpgflg ? "Cylinder" : "Warning: cylinder", mincpc);
455                 sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc);
456                 if (!cpgflg)
457                         cpg = sblock.fs_cpg;
458         }
459         /*
460          * Must ensure there is enough space for inodes.
461          */
462         sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
463         while (sblock.fs_ipg > MAXIPG(&sblock)) {
464                 inodecramped = 1;
465                 sblock.fs_cpg -= mincpc;
466                 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
467         }
468         /*
469          * Must ensure there is enough space to hold block map.
470          */
471         while (CGSIZE(&sblock) > (uint32_t)sblock.fs_bsize) {
472                 mapcramped = 1;
473                 sblock.fs_cpg -= mincpc;
474                 sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb);
475         }
476         sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock);
477         if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) {
478                 printf("panic (fs_cpg * fs_spc) %% NSPF != 0");
479                 exit(24);
480         }
481         if (sblock.fs_cpg < mincpg) {
482                 printf("cylinder groups must have at least %ld cylinders\n",
483                         mincpg);
484                 exit(25);
485         } else if (sblock.fs_cpg != cpg) {
486                 if (!cpgflg && !mfs)
487                         printf("Warning: ");
488                 else if (!mapcramped && !inodecramped)
489                         exit(26);
490                 if (!mfs) {
491                     if (mapcramped && inodecramped)
492                         printf("Block size and bytes per inode restrict");
493                     else if (mapcramped)
494                         printf("Block size restricts");
495                     else
496                         printf("Bytes per inode restrict");
497                     printf(" cylinders per group to %d.\n", sblock.fs_cpg);
498                 }
499                 if (cpgflg)
500                         exit(27);
501         }
502         sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock));
503         /*
504          * Now have size for file system and nsect and ntrak.
505          * Determine number of cylinders and blocks in the file system.
506          */
507         sblock.fs_size = fssize = dbtofsb(&sblock, fssize);
508         sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc;
509         if ((long)fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) {
510                 sblock.fs_ncyl++;
511                 emitwarn = 1;
512         }
513         if (sblock.fs_ncyl < 1) {
514                 printf("file systems must have at least one cylinder\n");
515                 exit(28);
516         }
517         /*
518          * Determine feasability/values of rotational layout tables.
519          *
520          * The size of the rotational layout tables is limited by the
521          * size of the superblock, SBSIZE. The amount of space available
522          * for tables is calculated as (SBSIZE - sizeof (struct fs)).
523          * The size of these tables is inversely proportional to the block
524          * size of the file system. The size increases if sectors per track
525          * are not powers of two, because more cylinders must be described
526          * by the tables before the rotational pattern repeats (fs_cpc).
527          */
528         sblock.fs_interleave = interleave;
529         sblock.fs_trackskew = trackskew;
530         sblock.fs_npsect = nphyssectors;
531         sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT;
532         sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs));
533         if (sblock.fs_sbsize > SBSIZE)
534                 sblock.fs_sbsize = SBSIZE;
535         if (sblock.fs_ntrak == 1) {
536                 sblock.fs_cpc = 0;
537                 goto next;
538         }
539         postblsize = sblock.fs_nrpos * sblock.fs_cpc * sizeof(int16_t);
540         rotblsize = sblock.fs_cpc * sblock.fs_spc / NSPB(&sblock);
541         totalsbsize = sizeof(struct fs) + rotblsize;
542         if (sblock.fs_nrpos == 8 && sblock.fs_cpc <= 16) {
543                 /* use old static table space */
544                 sblock.fs_postbloff = (char *)(&sblock.fs_opostbl[0][0]) -
545                     (char *)(&sblock.fs_firstfield);
546                 sblock.fs_rotbloff = &sblock.fs_space[0] -
547                     (u_char *)(&sblock.fs_firstfield);
548         } else {
549                 /* use dynamic table space */
550                 sblock.fs_postbloff = &sblock.fs_space[0] -
551                     (u_char *)(&sblock.fs_firstfield);
552                 sblock.fs_rotbloff = sblock.fs_postbloff + postblsize;
553                 totalsbsize += postblsize;
554         }
555         if (totalsbsize > SBSIZE ||
556             sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) {
557                 printf("%s %s %d %s %d.%s",
558                     "Warning: insufficient space in super block for\n",
559                     "rotational layout tables with nsect", sblock.fs_nsect,
560                     "and ntrak", sblock.fs_ntrak,
561                     "\nFile system performance may be impaired.\n");
562                 sblock.fs_cpc = 0;
563                 goto next;
564         }
565         sblock.fs_sbsize = fragroundup(&sblock, totalsbsize);
566         if (sblock.fs_sbsize > SBSIZE)
567                 sblock.fs_sbsize = SBSIZE;
568         /*
569          * calculate the available blocks for each rotational position
570          */
571         for (cylno = 0; cylno < sblock.fs_cpc; cylno++)
572                 for (rpos = 0; rpos < sblock.fs_nrpos; rpos++)
573                         fs_postbl(&sblock, cylno)[rpos] = -1;
574         for (i = (rotblsize - 1) * sblock.fs_frag;
575              i >= 0; i -= sblock.fs_frag) {
576                 cylno = cbtocylno(&sblock, i);
577                 rpos = cbtorpos(&sblock, i);
578                 blk = fragstoblks(&sblock, i);
579                 if (fs_postbl(&sblock, cylno)[rpos] == -1)
580                         fs_rotbl(&sblock)[blk] = 0;
581                 else
582                         fs_rotbl(&sblock)[blk] =
583                             fs_postbl(&sblock, cylno)[rpos] - blk;
584                 fs_postbl(&sblock, cylno)[rpos] = blk;
585         }
586 next:
587         /*
588          * Compute/validate number of cylinder groups.
589          */
590         sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg;
591         if (sblock.fs_ncyl % sblock.fs_cpg)
592                 sblock.fs_ncg++;
593         sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock);
594         i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1);
595         if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) {
596                 printf("inode blocks/cyl group (%ld) >= data blocks (%ld)\n",
597                     cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag,
598                     (long)(sblock.fs_fpg / sblock.fs_frag));
599                 printf("number of cylinders per cylinder group (%d) %s.\n",
600                     sblock.fs_cpg, "must be increased");
601                 exit(29);
602         }
603         j = sblock.fs_ncg - 1;
604         if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg &&
605             cgdmin(&sblock, j) - cgbase(&sblock, j) > i) {
606                 if (j == 0) {
607                         printf("Filesystem must have at least %d sectors\n",
608                             NSPF(&sblock) *
609                             (cgdmin(&sblock, 0) + 3 * sblock.fs_frag));
610                         exit(30);
611                 }
612                 printf(
613 "Warning: inode blocks/cyl group (%ld) >= data blocks (%ld) in last\n",
614                     (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag,
615                     i / sblock.fs_frag);
616                 printf(
617 "    cylinder group. This implies %ld sector(s) cannot be allocated.\n",
618                     i * NSPF(&sblock));
619                 sblock.fs_ncg--;
620                 sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg;
621                 sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc /
622                     NSPF(&sblock);
623                 emitwarn = 0;
624         }
625         if (emitwarn && !mfs) {
626                 printf("Warning: %lu sector(s) in last cylinder unallocated\n",
627                     sblock.fs_spc -
628                     (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1)
629                     * sblock.fs_spc));
630         }
631         /*
632          * fill in remaining fields of the super block
633          */
634         sblock.fs_csaddr = cgdmin(&sblock, 0);
635         sblock.fs_cssize =
636             fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum));
637         /*
638          * The superblock fields 'fs_csmask' and 'fs_csshift' are no
639          * longer used. However, we still initialise them so that the
640          * filesystem remains compatible with old kernels.
641          */
642         i = sblock.fs_bsize / sizeof(struct csum);
643         sblock.fs_csmask = ~(i - 1);
644         for (sblock.fs_csshift = 0; i > 1; i >>= 1)
645                 sblock.fs_csshift++;
646         fscs = (struct csum *)calloc(1, sblock.fs_cssize);
647         if (fscs == NULL)
648                 errx(31, "calloc failed");
649         sblock.fs_magic = FS_MAGIC;
650         sblock.fs_rotdelay = rotdelay;
651         sblock.fs_minfree = minfree;
652         sblock.fs_maxcontig = maxcontig;
653         sblock.fs_maxbpg = maxbpg;
654         sblock.fs_rps = rpm / 60;
655         sblock.fs_optim = opt;
656         sblock.fs_cgrotor = 0;
657         sblock.fs_cstotal.cs_ndir = 0;
658         sblock.fs_cstotal.cs_nbfree = 0;
659         sblock.fs_cstotal.cs_nifree = 0;
660         sblock.fs_cstotal.cs_nffree = 0;
661         sblock.fs_fmod = 0;
662         sblock.fs_ronly = 0;
663         sblock.fs_clean = 1;
664 #ifdef FSIRAND
665         sblock.fs_id[0] = (long)utime;
666         sblock.fs_id[1] = random();
667 #endif
668
669         /*
670          * Dump out summary information about file system.
671          */
672         if (!mfs) {
673                 printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n",
674                     fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl,
675                     "cylinders", sblock.fs_ntrak, sblock.fs_nsect);
676 #define B2MBFACTOR (1 / (1024.0 * 1024.0))
677                 printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)%s\n",
678                     (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR,
679                     sblock.fs_ncg, sblock.fs_cpg,
680                     (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR,
681                     sblock.fs_ipg,
682                         sblock.fs_flags & FS_DOSOFTDEP ? " SOFTUPDATES" : "");
683 #undef B2MBFACTOR
684         }
685         
686         if (Eflag && !Nflag) {
687                 printf("Erasing sectors [%ld --- %ld]\n",
688                     (SBOFF+ slice_offset)/sectorsize,
689                     fsbtodb(&sblock,sblock.fs_size) -
690                     ((SBOFF + slice_offset)/ sectorsize) - 1);
691                 erfs(SBOFF+ slice_offset, (fsbtodb(&sblock,sblock.fs_size) -
692                     ((SBOFF + slice_offset)/ sectorsize) - 1) *
693                     (unsigned long long)sectorsize);
694         }
695         /*
696          * Now build the cylinders group blocks and
697          * then print out indices of cylinder groups.
698          */
699         if (!mfs)
700                 printf("super-block backups (for fsck -b #) at:\n");
701         i = 0;
702         width = charsperline();
703         for (cylno = 0; cylno < sblock.fs_ncg; cylno++) {
704                 initcg(cylno, utime);
705                 if (mfs)
706                         continue;
707                 j = snprintf(tmpbuf, sizeof(tmpbuf), " %ld%s",
708                     fsbtodb(&sblock, cgsblock(&sblock, cylno)),
709                     cylno < (sblock.fs_ncg-1) ? "," : "" );
710                 if (i + j >= width) {
711                         printf("\n");
712                         i = 0;
713                 }
714                 i += j;
715                 printf("%s", tmpbuf);
716                 fflush(stdout);
717         }
718         if (!mfs)
719                 printf("\n");
720         if (Nflag && !mfs)
721                 exit(0);
722         /*
723          * Now construct the initial file system,
724          * then write out the super-block.
725          */
726         fsinit(utime);
727         sblock.fs_time = utime;
728         wtfs((int)SBOFF / sectorsize, sbsize, (char *)&sblock);
729         for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize)
730                 wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)),
731                         sblock.fs_cssize - i < sblock.fs_bsize ?
732                             sblock.fs_cssize - i : sblock.fs_bsize,
733                         ((char *)fscs) + i);
734         /*
735          * Write out the duplicate super blocks
736          */
737         for (cylno = 0; cylno < sblock.fs_ncg; cylno++)
738                 wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)),
739                     sbsize, (char *)&sblock);
740         wtfsflush();
741
742         /*
743          * NOTE: we no longer update information in the disklabel
744          */
745
746         /*
747          * Notify parent process of success.
748          * Dissociate from session and tty.
749          *
750          * NOTE: We are the child and may receive a SIGINT due
751          *       to losing the tty session? XXX
752          */
753         if (mfs) {
754                 /* YYY */
755                 kill(mfs_ppid, SIGUSR1);
756                 setsid();
757                 close(0);
758                 close(1);
759                 close(2);
760                 chdir("/");
761                 /* returns to mount_mfs (newfs) and issues the mount */
762         }
763 }
764
765 /*
766  * Initialize a cylinder group.
767  */
768 void
769 initcg(int cylno, time_t utime)
770 {
771         daddr_t cbase, d, dlower, dupper, dmax, blkno;
772         long i;
773         unsigned long k;
774         struct csum *cs;
775 #ifdef FSIRAND
776         uint32_t j;
777 #endif
778
779         /*
780          * Determine block bounds for cylinder group.
781          * Allow space for super block summary information in first
782          * cylinder group.
783          */
784         cbase = cgbase(&sblock, cylno);
785         dmax = cbase + sblock.fs_fpg;
786         if (dmax > sblock.fs_size)
787                 dmax = sblock.fs_size;
788         dlower = cgsblock(&sblock, cylno) - cbase;
789         dupper = cgdmin(&sblock, cylno) - cbase;
790         if (cylno == 0)
791                 dupper += howmany(sblock.fs_cssize, sblock.fs_fsize);
792         cs = fscs + cylno;
793         memset(&acg, 0, sblock.fs_cgsize);
794         acg.cg_time = utime;
795         acg.cg_magic = CG_MAGIC;
796         acg.cg_cgx = cylno;
797         if (cylno == sblock.fs_ncg - 1)
798                 acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg;
799         else
800                 acg.cg_ncyl = sblock.fs_cpg;
801         acg.cg_niblk = sblock.fs_ipg;
802         acg.cg_ndblk = dmax - cbase;
803         if (sblock.fs_contigsumsize > 0)
804                 acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag;
805         acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield);
806         acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t);
807         acg.cg_iusedoff = acg.cg_boff +
808                 sblock.fs_cpg * sblock.fs_nrpos * sizeof(u_int16_t);
809         acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY);
810         if (sblock.fs_contigsumsize <= 0) {
811                 acg.cg_nextfreeoff = acg.cg_freeoff +
812                    howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY);
813         } else {
814                 acg.cg_clustersumoff = acg.cg_freeoff + howmany
815                     (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) -
816                     sizeof(u_int32_t);
817                 acg.cg_clustersumoff =
818                     roundup(acg.cg_clustersumoff, sizeof(u_int32_t));
819                 acg.cg_clusteroff = acg.cg_clustersumoff +
820                     (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t);
821                 acg.cg_nextfreeoff = acg.cg_clusteroff + howmany
822                     (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY);
823         }
824         if (acg.cg_nextfreeoff - (long)(&acg.cg_firstfield) > sblock.fs_cgsize) {
825                 printf("Panic: cylinder group too big\n");
826                 exit(37);
827         }
828         acg.cg_cs.cs_nifree += sblock.fs_ipg;
829         if (cylno == 0) {
830                 for (k = 0; k < ROOTINO; k++) {
831                         setbit(cg_inosused(&acg), k);
832                         acg.cg_cs.cs_nifree--;
833                 }
834         }
835         for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) {
836 #ifdef FSIRAND
837                 for (j = 0;
838                      j < sblock.fs_bsize / sizeof(struct ufs1_dinode);
839                      j++) {
840                         zino[j].di_gen = random();
841                 }
842 #endif
843                 wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i),
844                     sblock.fs_bsize, (char *)zino);
845         }
846         if (cylno > 0) {
847                 /*
848                  * In cylno 0, beginning space is reserved
849                  * for boot and super blocks.
850                  */
851                 for (d = 0; d < dlower; d += sblock.fs_frag) {
852                         blkno = d / sblock.fs_frag;
853                         setblock(&sblock, cg_blksfree(&acg), blkno);
854                         if (sblock.fs_contigsumsize > 0)
855                                 setbit(cg_clustersfree(&acg), blkno);
856                         acg.cg_cs.cs_nbfree++;
857                         cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
858                         cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
859                             [cbtorpos(&sblock, d)]++;
860                 }
861                 sblock.fs_dsize += dlower;
862         }
863         sblock.fs_dsize += acg.cg_ndblk - dupper;
864         if ((i = dupper % sblock.fs_frag)) {
865                 acg.cg_frsum[sblock.fs_frag - i]++;
866                 for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) {
867                         setbit(cg_blksfree(&acg), dupper);
868                         acg.cg_cs.cs_nffree++;
869                 }
870         }
871         for (d = dupper; d + sblock.fs_frag <= dmax - cbase; ) {
872                 blkno = d / sblock.fs_frag;
873                 setblock(&sblock, cg_blksfree(&acg), blkno);
874                 if (sblock.fs_contigsumsize > 0)
875                         setbit(cg_clustersfree(&acg), blkno);
876                 acg.cg_cs.cs_nbfree++;
877                 cg_blktot(&acg)[cbtocylno(&sblock, d)]++;
878                 cg_blks(&sblock, &acg, cbtocylno(&sblock, d))
879                     [cbtorpos(&sblock, d)]++;
880                 d += sblock.fs_frag;
881         }
882         if (d < dmax - cbase) {
883                 acg.cg_frsum[dmax - cbase - d]++;
884                 for (; d < dmax - cbase; d++) {
885                         setbit(cg_blksfree(&acg), d);
886                         acg.cg_cs.cs_nffree++;
887                 }
888         }
889         if (sblock.fs_contigsumsize > 0) {
890                 int32_t *sump = cg_clustersum(&acg);
891                 u_char *mapp = cg_clustersfree(&acg);
892                 int map = *mapp++;
893                 int bit = 1;
894                 int run = 0;
895
896                 for (i = 0; i < acg.cg_nclusterblks; i++) {
897                         if ((map & bit) != 0) {
898                                 run++;
899                         } else if (run != 0) {
900                                 if (run > sblock.fs_contigsumsize)
901                                         run = sblock.fs_contigsumsize;
902                                 sump[run]++;
903                                 run = 0;
904                         }
905                         if ((i & (NBBY - 1)) != (NBBY - 1)) {
906                                 bit <<= 1;
907                         } else {
908                                 map = *mapp++;
909                                 bit = 1;
910                         }
911                 }
912                 if (run != 0) {
913                         if (run > sblock.fs_contigsumsize)
914                                 run = sblock.fs_contigsumsize;
915                         sump[run]++;
916                 }
917         }
918         sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir;
919         sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree;
920         sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree;
921         sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree;
922         *cs = acg.cg_cs;
923         wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)),
924                 sblock.fs_bsize, (char *)&acg);
925 }
926
927 /*
928  * initialize the file system
929  */
930 struct ufs1_dinode node;
931
932 #ifdef LOSTDIR
933 #define PREDEFDIR 3
934 #else
935 #define PREDEFDIR 2
936 #endif
937
938 struct direct root_dir[] = {
939         { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." },
940         { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." },
941 #ifdef LOSTDIR
942         { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" },
943 #endif
944 };
945 struct odirect {
946         u_long  d_ino;
947         u_short d_reclen;
948         u_short d_namlen;
949         u_char  d_name[MAXNAMLEN + 1];
950 } oroot_dir[] = {
951         { ROOTINO, sizeof(struct direct), 1, "." },
952         { ROOTINO, sizeof(struct direct), 2, ".." },
953 #ifdef LOSTDIR
954         { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" },
955 #endif
956 };
957 #ifdef LOSTDIR
958 struct direct lost_found_dir[] = {
959         { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." },
960         { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." },
961         { 0, DIRBLKSIZ, 0, 0, 0 },
962 };
963 struct odirect olost_found_dir[] = {
964         { LOSTFOUNDINO, sizeof(struct direct), 1, "." },
965         { ROOTINO, sizeof(struct direct), 2, ".." },
966         { 0, DIRBLKSIZ, 0, 0 },
967 };
968 #endif
969 char buf[MAXBSIZE];
970
971 void
972 fsinit(time_t utime)
973 {
974 #ifdef LOSTDIR
975         int i;
976 #endif
977
978         /*
979          * initialize the node
980          */
981         node.di_atime = utime;
982         node.di_mtime = utime;
983         node.di_ctime = utime;
984 #ifdef LOSTDIR
985         /*
986          * create the lost+found directory
987          */
988         if (Oflag) {
989                 makedir((struct direct *)olost_found_dir, 2);
990                 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ)
991                         memmove(&buf[i], &olost_found_dir[2],
992                             DIRSIZ(0, &olost_found_dir[2]));
993         } else {
994                 makedir(lost_found_dir, 2);
995                 for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ)
996                         memmove(&buf[i], &lost_found_dir[2],
997                             DIRSIZ(0, &lost_found_dir[2]));
998         }
999         node.di_mode = IFDIR | UMASK;
1000         node.di_nlink = 2;
1001         node.di_size = sblock.fs_bsize;
1002         node.di_db[0] = alloc(node.di_size, node.di_mode);
1003         node.di_blocks = btodb(fragroundup(&sblock, node.di_size));
1004         wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf);
1005         iput(&node, LOSTFOUNDINO);
1006 #endif
1007         /*
1008          * create the root directory
1009          */
1010         if (mfs)
1011                 node.di_mode = IFDIR | 01777;
1012         else
1013                 node.di_mode = IFDIR | UMASK;
1014         node.di_nlink = PREDEFDIR;
1015         if (Oflag)
1016                 node.di_size = makedir((struct direct *)oroot_dir, PREDEFDIR);
1017         else
1018                 node.di_size = makedir(root_dir, PREDEFDIR);
1019         node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode);
1020         node.di_blocks = btodb(fragroundup(&sblock, node.di_size));
1021         wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf);
1022         iput(&node, ROOTINO);
1023 }
1024
1025 /*
1026  * construct a set of directory entries in "buf".
1027  * return size of directory.
1028  */
1029 int
1030 makedir(struct direct *protodir, int entries)
1031 {
1032         char *cp;
1033         int i, spcleft;
1034
1035         spcleft = DIRBLKSIZ;
1036         for (cp = buf, i = 0; i < entries - 1; i++) {
1037                 protodir[i].d_reclen = DIRSIZ(0, &protodir[i]);
1038                 memmove(cp, &protodir[i], protodir[i].d_reclen);
1039                 cp += protodir[i].d_reclen;
1040                 spcleft -= protodir[i].d_reclen;
1041         }
1042         protodir[i].d_reclen = spcleft;
1043         memmove(cp, &protodir[i], DIRSIZ(0, &protodir[i]));
1044         return (DIRBLKSIZ);
1045 }
1046
1047 /*
1048  * allocate a block or frag
1049  */
1050 daddr_t
1051 alloc(int size, int mode)
1052 {
1053         int i, frag;
1054         daddr_t d, blkno;
1055
1056         rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
1057             (char *)&acg);
1058         if (acg.cg_magic != CG_MAGIC) {
1059                 printf("cg 0: bad magic number\n");
1060                 return (0);
1061         }
1062         if (acg.cg_cs.cs_nbfree == 0) {
1063                 printf("first cylinder group ran out of space\n");
1064                 return (0);
1065         }
1066         for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag)
1067                 if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag))
1068                         goto goth;
1069         printf("internal error: can't find block in cyl 0\n");
1070         return (0);
1071 goth:
1072         blkno = fragstoblks(&sblock, d);
1073         clrblock(&sblock, cg_blksfree(&acg), blkno);
1074         if (sblock.fs_contigsumsize > 0)
1075                 clrbit(cg_clustersfree(&acg), blkno);
1076         acg.cg_cs.cs_nbfree--;
1077         sblock.fs_cstotal.cs_nbfree--;
1078         fscs[0].cs_nbfree--;
1079         if (mode & IFDIR) {
1080                 acg.cg_cs.cs_ndir++;
1081                 sblock.fs_cstotal.cs_ndir++;
1082                 fscs[0].cs_ndir++;
1083         }
1084         cg_blktot(&acg)[cbtocylno(&sblock, d)]--;
1085         cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--;
1086         if (size != sblock.fs_bsize) {
1087                 frag = howmany(size, sblock.fs_fsize);
1088                 fscs[0].cs_nffree += sblock.fs_frag - frag;
1089                 sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag;
1090                 acg.cg_cs.cs_nffree += sblock.fs_frag - frag;
1091                 acg.cg_frsum[sblock.fs_frag - frag]++;
1092                 for (i = frag; i < sblock.fs_frag; i++)
1093                         setbit(cg_blksfree(&acg), d + i);
1094         }
1095         wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
1096             (char *)&acg);
1097         return (d);
1098 }
1099
1100 /*
1101  * Calculate number of inodes per group.
1102  */
1103 long
1104 calcipg(long cylspg, long bpcg, off_t *usedbp)
1105 {
1106         int i;
1107         long ipg, new_ipg, ncg, ncyl;
1108         off_t usedb;
1109
1110         /*
1111          * Prepare to scale by fssize / (number of sectors in cylinder groups).
1112          * Note that fssize is still in sectors, not filesystem blocks.
1113          */
1114         ncyl = howmany(fssize, (u_int)secpercyl);
1115         ncg = howmany(ncyl, cylspg);
1116         /*
1117          * Iterate a few times to allow for ipg depending on itself.
1118          */
1119         ipg = 0;
1120         for (i = 0; i < 10; i++) {
1121                 usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock))
1122                         * NSPF(&sblock) * (off_t)sectorsize;
1123                 new_ipg = (cylspg * (quad_t)bpcg - usedb) / density * fssize
1124                           / ncg / secpercyl / cylspg;
1125                 new_ipg = roundup(new_ipg, INOPB(&sblock));
1126                 if (new_ipg == ipg)
1127                         break;
1128                 ipg = new_ipg;
1129         }
1130         *usedbp = usedb;
1131         return (ipg);
1132 }
1133
1134 /*
1135  * Allocate an inode on the disk
1136  */
1137 void
1138 iput(struct ufs1_dinode *ip, ino_t ino)
1139 {
1140         struct ufs1_dinode inobuf[MAXINOPB];
1141         daddr_t d;
1142         int c;
1143
1144 #ifdef FSIRAND
1145         ip->di_gen = random();
1146 #endif
1147         c = ino_to_cg(&sblock, ino);
1148         rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
1149             (char *)&acg);
1150         if (acg.cg_magic != CG_MAGIC) {
1151                 printf("cg 0: bad magic number\n");
1152                 exit(31);
1153         }
1154         acg.cg_cs.cs_nifree--;
1155         setbit(cg_inosused(&acg), ino);
1156         wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize,
1157             (char *)&acg);
1158         sblock.fs_cstotal.cs_nifree--;
1159         fscs[0].cs_nifree--;
1160         if (ino >= (uint32_t)sblock.fs_ipg * (uint32_t)sblock.fs_ncg) {
1161                 printf("fsinit: inode value out of range (%ju).\n",
1162                     (uintmax_t)ino);
1163                 exit(32);
1164         }
1165         d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino));
1166         rdfs(d, sblock.fs_bsize, (char *)inobuf);
1167         inobuf[ino_to_fsbo(&sblock, ino)] = *ip;
1168         wtfs(d, sblock.fs_bsize, (char *)inobuf);
1169 }
1170
1171 /*
1172  * Parent notifies child that it can proceed with the newfs and mount
1173  * operation (occurs after parent has copied the underlying filesystem
1174  * if the -C option was specified (for MFS), or immediately after the
1175  * parent forked the child otherwise).
1176  */
1177 void
1178 parentready(__unused int signo)
1179 {
1180         parentready_signalled = 1;
1181 }
1182
1183 /*
1184  * Notify parent process that the filesystem has created itself successfully.
1185  *
1186  * We have to wait until the mount has actually completed!
1187  */
1188 void
1189 started(__unused int signo)
1190 {
1191         int retry = 100;        /* 10 seconds, 100ms */
1192
1193         while (mfs_ppid && retry) {
1194                 struct stat st;
1195
1196                 if (
1197                     stat(mfs_mtpt, &st) < 0 ||
1198                     st.st_dev != mfs_mtstat.st_dev
1199                 ) {
1200                         break;
1201                 }
1202                 usleep(100*1000);
1203                 --retry;
1204         }
1205         if (retry == 0) {
1206                 fatal("mfs mount failed waiting for mount to go active");
1207         } else if (copyroot) {
1208                 FSPaste(mfs_mtpt, copyroot, copyhlinks);
1209         }
1210         exit(0);
1211 }
1212
1213 /*
1214  * read a block from the file system
1215  */
1216 void
1217 rdfs(daddr_t bno, int size, char *bf)
1218 {
1219         int n;
1220
1221         wtfsflush();
1222         if (mfs) {
1223                 memmove(bf, membase + bno * sectorsize, size);
1224                 return;
1225         }
1226         if (lseek(fsi, (off_t)bno * sectorsize, 0) < 0) {
1227                 printf("seek error: %ld\n", (long)bno);
1228                 err(33, "rdfs");
1229         }
1230         n = read(fsi, bf, size);
1231         if (n != size) {
1232                 printf("read error: %ld\n", (long)bno);
1233                 err(34, "rdfs");
1234         }
1235 }
1236
1237 #define WCSIZE (128 * 1024)
1238 daddr_t wc_sect;                /* units of sectorsize */
1239 int wc_end;                     /* bytes */
1240 static char wc[WCSIZE];         /* bytes */
1241
1242 /*
1243  * Flush dirty write behind buffer.
1244  */
1245 void
1246 wtfsflush(void)
1247 {
1248         int n;
1249         if (wc_end) {
1250                 if (lseek(fso, (off_t)wc_sect * sectorsize, SEEK_SET) < 0) {
1251                         printf("seek error: %ld\n", (long)wc_sect);
1252                         err(35, "wtfs - writecombine");
1253                 }
1254                 n = write(fso, wc, wc_end);
1255                 if (n != wc_end) {
1256                         printf("write error: %ld\n", (long)wc_sect);
1257                         err(36, "wtfs - writecombine");
1258                 }
1259                 wc_end = 0;
1260         }
1261 }
1262
1263 /*
1264  * Issue ioctl to erase range of sectors using TRIM
1265  */
1266 void
1267 erfs(off_t byte_start, off_t size)
1268 {
1269         off_t ioarg[2];
1270         ioarg[0] = byte_start;
1271         ioarg[1] = size;
1272         if (ioctl(fsi, IOCTLTRIM, ioarg) < 0) {
1273                 err(37, "Device trim failed\n");
1274         }
1275 }
1276
1277 /*
1278  * write a block to the file system
1279  */
1280 void
1281 wtfs(daddr_t bno, int size, char *bf)
1282 {
1283         int n;
1284         int done;
1285
1286         if (mfs) {
1287                 memmove(membase + bno * sectorsize, bf, size);
1288                 return;
1289         }
1290         if (Nflag)
1291                 return;
1292         done = 0;
1293         if (wc_end == 0 && size <= WCSIZE) {
1294                 wc_sect = bno;
1295                 bcopy(bf, wc, size);
1296                 wc_end = size;
1297                 if (wc_end < WCSIZE)
1298                         return;
1299                 done = 1;
1300         }
1301         if ((off_t)wc_sect * sectorsize + wc_end == (off_t)bno * sectorsize &&
1302             wc_end + size <= WCSIZE) {
1303                 bcopy(bf, wc + wc_end, size);
1304                 wc_end += size;
1305                 if (wc_end < WCSIZE)
1306                         return;
1307                 done = 1;
1308         }
1309         wtfsflush();
1310         if (done)
1311                 return;
1312         if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) {
1313                 printf("seek error: %ld\n", (long)bno);
1314                 err(35, "wtfs");
1315         }
1316         n = write(fso, bf, size);
1317         if (n != size) {
1318                 printf("write error: fso %d blk %ld %d/%d\n", 
1319                         fso, (long)bno, n, size);
1320                 err(36, "wtfs");
1321         }
1322 }
1323
1324 /*
1325  * check if a block is available
1326  */
1327 int
1328 isblock(struct fs *fs, unsigned char *cp, int h)
1329 {
1330         unsigned char mask;
1331
1332         switch (fs->fs_frag) {
1333         case 8:
1334                 return (cp[h] == 0xff);
1335         case 4:
1336                 mask = 0x0f << ((h & 0x1) << 2);
1337                 return ((cp[h >> 1] & mask) == mask);
1338         case 2:
1339                 mask = 0x03 << ((h & 0x3) << 1);
1340                 return ((cp[h >> 2] & mask) == mask);
1341         case 1:
1342                 mask = 0x01 << (h & 0x7);
1343                 return ((cp[h >> 3] & mask) == mask);
1344         default:
1345                 fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag);
1346                 return (0);
1347         }
1348 }
1349
1350 /*
1351  * take a block out of the map
1352  */
1353 void
1354 clrblock(struct fs *fs, unsigned char *cp, int h)
1355 {
1356         switch ((fs)->fs_frag) {
1357         case 8:
1358                 cp[h] = 0;
1359                 return;
1360         case 4:
1361                 cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2));
1362                 return;
1363         case 2:
1364                 cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1));
1365                 return;
1366         case 1:
1367                 cp[h >> 3] &= ~(0x01 << (h & 0x7));
1368                 return;
1369         default:
1370                 fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag);
1371                 return;
1372         }
1373 }
1374
1375 /*
1376  * put a block into the map
1377  */
1378 void
1379 setblock(struct fs *fs, unsigned char *cp, int h)
1380 {
1381         switch (fs->fs_frag) {
1382         case 8:
1383                 cp[h] = 0xff;
1384                 return;
1385         case 4:
1386                 cp[h >> 1] |= (0x0f << ((h & 0x1) << 2));
1387                 return;
1388         case 2:
1389                 cp[h >> 2] |= (0x03 << ((h & 0x3) << 1));
1390                 return;
1391         case 1:
1392                 cp[h >> 3] |= (0x01 << (h & 0x7));
1393                 return;
1394         default:
1395                 fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag);
1396                 return;
1397         }
1398 }
1399
1400 /*
1401  * Determine the number of characters in a
1402  * single line.
1403  */
1404
1405 static int
1406 charsperline(void)
1407 {
1408         int columns;
1409         char *cp;
1410         struct winsize ws;
1411
1412         columns = 0;
1413         if (ioctl(0, TIOCGWINSZ, &ws) != -1)
1414                 columns = ws.ws_col;
1415         if (columns == 0 && (cp = getenv("COLUMNS")))
1416                 columns = atoi(cp);
1417         if (columns == 0)
1418                 columns = 80;   /* last resort */
1419         return columns;
1420 }