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