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