mkfs.c revision 92763
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1989, 1993 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 3537664Scharnier#if 0 3623682Speterstatic char sccsid[] = "@(#)mkfs.c 8.11 (Berkeley) 5/3/95"; 3737664Scharnier#endif 3837664Scharnierstatic const char rcsid[] = 3950476Speter "$FreeBSD: head/sbin/newfs/mkfs.c 92763 2002-03-20 07:16:15Z phk $"; 401558Srgrimes#endif /* not lint */ 411558Srgrimes 4237664Scharnier#include <err.h> 4337664Scharnier#include <signal.h> 4492709Siedowse#include <stdlib.h> 4537664Scharnier#include <string.h> 4637664Scharnier#include <stdio.h> 471558Srgrimes#include <unistd.h> 481558Srgrimes#include <sys/param.h> 491558Srgrimes#include <sys/time.h> 5037664Scharnier#include <sys/types.h> 511558Srgrimes#include <sys/wait.h> 521558Srgrimes#include <sys/resource.h> 5343804Sdillon#include <sys/stat.h> 541558Srgrimes#include <ufs/ufs/dinode.h> 551558Srgrimes#include <ufs/ufs/dir.h> 561558Srgrimes#include <ufs/ffs/fs.h> 571558Srgrimes#include <sys/disklabel.h> 583550Sphk#include <sys/file.h> 593550Sphk#include <sys/mman.h> 6013637Sjoerg#include <sys/ioctl.h> 6192717Sphk#include "newfs.h" 621558Srgrimes 631558Srgrimes/* 641558Srgrimes * make file system for cylinder-group style file systems 651558Srgrimes */ 661558Srgrimes 671558Srgrimes/* 681558Srgrimes * We limit the size of the inode map to be no more than a 691558Srgrimes * third of the cylinder group space, since we must leave at 701558Srgrimes * least an equal amount of space for the block map. 711558Srgrimes * 721558Srgrimes * N.B.: MAXIPG must be a multiple of INOPB(fs). 731558Srgrimes */ 741558Srgrimes#define MAXIPG(fs) roundup((fs)->fs_bsize * NBBY / 3, INOPB(fs)) 751558Srgrimes 761558Srgrimes#define UMASK 0755 771558Srgrimes#define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) 781558Srgrimes#define POWEROF2(num) (((num) & ((num) - 1)) == 0) 791558Srgrimes 8092717Sphkstatic union { 811558Srgrimes struct fs fs; 821558Srgrimes char pad[SBSIZE]; 831558Srgrimes} fsun; 841558Srgrimes#define sblock fsun.fs 8592717Sphkstatic struct csum *fscs; 861558Srgrimes 8792717Sphkstatic union { 881558Srgrimes struct cg cg; 891558Srgrimes char pad[MAXBSIZE]; 901558Srgrimes} cgun; 911558Srgrimes#define acg cgun.cg 921558Srgrimes 9392717Sphkstatic struct dinode zino[MAXBSIZE / sizeof(struct dinode)]; 941558Srgrimes 9592717Sphkstatic int fsi, fso; 9692717Sphkstatic int randinit; 9792717Sphkstatic daddr_t alloc(int size, int mode); 9892763Sphkstatic long calcipg(long lcpg, long bpcg, off_t *usedbp); 9992717Sphkstatic int charsperline(void); 10092717Sphkstatic void clrblock (struct fs *, unsigned char *, int); 10192717Sphkstatic void fsinit (time_t); 10292712Siedowsestatic int ilog2(int); 10392717Sphkstatic void initcg (int, time_t); 10492717Sphkstatic int isblock (struct fs *, unsigned char *, int); 10592717Sphkstatic void iput (struct dinode *, ino_t); 10692717Sphkstatic int makedir (struct direct *, int); 10792717Sphkstatic void rdfs (daddr_t, int, char *); 10892717Sphkstatic void setblock (struct fs *, unsigned char *, int); 10992717Sphkstatic void wtfs (daddr_t, int, char *); 11092717Sphkstatic void wtfsflush (void); 1111558Srgrimes 11237664Scharniervoid 11392711Siedowsemkfs(struct partition *pp, char *fsys, int fi, int fo) 1141558Srgrimes{ 11592483Sphk long i, mincpc, mincpg, inospercg; 11692763Sphk long cylno, j, lwarn = 0; 1171558Srgrimes long used, mincpgcnt, bpcg; 11823682Speter off_t usedb; 1191558Srgrimes long mapcramped, inodecramped; 1201558Srgrimes time_t utime; 1211558Srgrimes quad_t sizepb; 12213769Sjoerg int width; 12313769Sjoerg char tmpbuf[100]; /* XXX this will break in about 2,500 years */ 1241558Srgrimes 12592722Sphk if (Rflag) 12692722Sphk utime = 1000000000; 12792722Sphk else 12892722Sphk time(&utime); 12992722Sphk if (!Rflag && !randinit) { 13024215Sache randinit = 1; 13126625Sache srandomdev(); 13224215Sache } 1331558Srgrimes fsi = fi; 1341558Srgrimes fso = fo; 13592763Sphk sblock.fs_inodefmt = FS_44INODEFMT; 13692763Sphk sblock.fs_maxsymlinklen = MAXSYMLINKLEN; 13775124Sbde if (Uflag) 13875078Sobrien sblock.fs_flags |= FS_DOSOFTDEP; 1391558Srgrimes /* 1401558Srgrimes * Validate the given file system size. 1411558Srgrimes * Verify that its last block can actually be accessed. 1421558Srgrimes */ 1431558Srgrimes if (fssize <= 0) 1441558Srgrimes printf("preposterous size %d\n", fssize), exit(13); 14520061Ssos wtfs(fssize - (realsectorsize / DEV_BSIZE), realsectorsize, 14692532Sbde (char *)&sblock); 1471558Srgrimes /* 1481558Srgrimes * collect and verify the sector and track info 1491558Srgrimes */ 15092763Sphk sblock.fs_nsect = secpercyl; 15192763Sphk sblock.fs_ntrak = 1; 1521558Srgrimes if (sblock.fs_nsect <= 0) 1531558Srgrimes printf("preposterous nsect %d\n", sblock.fs_nsect), exit(15); 1541558Srgrimes /* 15575377Smckusick * collect and verify the filesystem density info 15675377Smckusick */ 15775377Smckusick sblock.fs_avgfilesize = avgfilesize; 15875377Smckusick sblock.fs_avgfpdir = avgfilesperdir; 15975377Smckusick if (sblock.fs_avgfilesize <= 0) 16075377Smckusick printf("illegal expected average file size %d\n", 16175377Smckusick sblock.fs_avgfilesize), exit(14); 16275377Smckusick if (sblock.fs_avgfpdir <= 0) 16375377Smckusick printf("illegal expected number of files per directory %d\n", 16475377Smckusick sblock.fs_avgfpdir), exit(15); 16575377Smckusick /* 1661558Srgrimes * collect and verify the block and fragment sizes 1671558Srgrimes */ 1681558Srgrimes sblock.fs_bsize = bsize; 1691558Srgrimes sblock.fs_fsize = fsize; 1701558Srgrimes if (!POWEROF2(sblock.fs_bsize)) { 1711558Srgrimes printf("block size must be a power of 2, not %d\n", 1721558Srgrimes sblock.fs_bsize); 1731558Srgrimes exit(16); 1741558Srgrimes } 1751558Srgrimes if (!POWEROF2(sblock.fs_fsize)) { 1761558Srgrimes printf("fragment size must be a power of 2, not %d\n", 1771558Srgrimes sblock.fs_fsize); 1781558Srgrimes exit(17); 1791558Srgrimes } 1801558Srgrimes if (sblock.fs_fsize < sectorsize) { 1811558Srgrimes printf("fragment size %d is too small, minimum is %d\n", 1821558Srgrimes sblock.fs_fsize, sectorsize); 1831558Srgrimes exit(18); 1841558Srgrimes } 1851558Srgrimes if (sblock.fs_bsize < MINBSIZE) { 1861558Srgrimes printf("block size %d is too small, minimum is %d\n", 1871558Srgrimes sblock.fs_bsize, MINBSIZE); 1881558Srgrimes exit(19); 1891558Srgrimes } 1901558Srgrimes if (sblock.fs_bsize < sblock.fs_fsize) { 19192532Sbde printf( 19292532Sbde "block size (%d) cannot be smaller than fragment size (%d)\n", 19392532Sbde sblock.fs_bsize, sblock.fs_fsize); 1941558Srgrimes exit(20); 1951558Srgrimes } 1961558Srgrimes sblock.fs_bmask = ~(sblock.fs_bsize - 1); 1971558Srgrimes sblock.fs_fmask = ~(sblock.fs_fsize - 1); 1981558Srgrimes sblock.fs_qbmask = ~sblock.fs_bmask; 1991558Srgrimes sblock.fs_qfmask = ~sblock.fs_fmask; 20092712Siedowse sblock.fs_bshift = ilog2(sblock.fs_bsize); 20192712Siedowse sblock.fs_fshift = ilog2(sblock.fs_fsize); 2021558Srgrimes sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 20392712Siedowse sblock.fs_fragshift = ilog2(sblock.fs_frag); 2041558Srgrimes if (sblock.fs_frag > MAXFRAG) { 20592532Sbde printf( 20692532Sbde "fragment size %d is too small, minimum with block size %d is %d\n", 20792532Sbde sblock.fs_fsize, sblock.fs_bsize, 2081558Srgrimes sblock.fs_bsize / MAXFRAG); 2091558Srgrimes exit(21); 2101558Srgrimes } 21192763Sphk sblock.fs_nrpos = 1; 2121558Srgrimes sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); 2131558Srgrimes sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); 2141558Srgrimes sblock.fs_nspf = sblock.fs_fsize / sectorsize; 21592712Siedowse sblock.fs_fsbtodb = ilog2(NSPF(&sblock)); 2161558Srgrimes sblock.fs_sblkno = 2171558Srgrimes roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); 2181558Srgrimes sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 2191558Srgrimes roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); 2201558Srgrimes sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 22185860Sphk sblock.fs_cgoffset = 22285860Sphk roundup(howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); 22392763Sphk sblock.fs_cgmask = 0xffffffff; 2241558Srgrimes sblock.fs_maxfilesize = sblock.fs_bsize * NDADDR - 1; 2251558Srgrimes for (sizepb = sblock.fs_bsize, i = 0; i < NIADDR; i++) { 2261558Srgrimes sizepb *= NINDIR(&sblock); 2271558Srgrimes sblock.fs_maxfilesize += sizepb; 2281558Srgrimes } 2291558Srgrimes /* 2301558Srgrimes * Validate specified/determined secpercyl 2311558Srgrimes * and calculate minimum cylinders per group. 2321558Srgrimes */ 2331558Srgrimes sblock.fs_spc = secpercyl; 2341558Srgrimes for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 2351558Srgrimes sblock.fs_cpc > 1 && (i & 1) == 0; 2361558Srgrimes sblock.fs_cpc >>= 1, i >>= 1) 2371558Srgrimes /* void */; 2381558Srgrimes mincpc = sblock.fs_cpc; 2391558Srgrimes bpcg = sblock.fs_spc * sectorsize; 2401558Srgrimes inospercg = roundup(bpcg / sizeof(struct dinode), INOPB(&sblock)); 2411558Srgrimes if (inospercg > MAXIPG(&sblock)) 2421558Srgrimes inospercg = MAXIPG(&sblock); 2431558Srgrimes used = (sblock.fs_iblkno + inospercg / INOPF(&sblock)) * NSPF(&sblock); 2441558Srgrimes mincpgcnt = howmany(sblock.fs_cgoffset * (~sblock.fs_cgmask) + used, 2451558Srgrimes sblock.fs_spc); 2461558Srgrimes mincpg = roundup(mincpgcnt, mincpc); 2471558Srgrimes /* 2481558Srgrimes * Ensure that cylinder group with mincpg has enough space 2491558Srgrimes * for block maps. 2501558Srgrimes */ 2511558Srgrimes sblock.fs_cpg = mincpg; 2521558Srgrimes sblock.fs_ipg = inospercg; 2531558Srgrimes if (maxcontig > 1) 2541558Srgrimes sblock.fs_contigsumsize = MIN(maxcontig, FS_MAXCONTIG); 2551558Srgrimes mapcramped = 0; 2561558Srgrimes while (CGSIZE(&sblock) > sblock.fs_bsize) { 2571558Srgrimes mapcramped = 1; 2581558Srgrimes if (sblock.fs_bsize < MAXBSIZE) { 2591558Srgrimes sblock.fs_bsize <<= 1; 26085860Sphk if ((i & 1) == 0) 2611558Srgrimes i >>= 1; 26285860Sphk else { 2631558Srgrimes sblock.fs_cpc <<= 1; 2641558Srgrimes mincpc <<= 1; 2651558Srgrimes mincpg = roundup(mincpgcnt, mincpc); 2661558Srgrimes sblock.fs_cpg = mincpg; 2671558Srgrimes } 2681558Srgrimes sblock.fs_frag <<= 1; 2691558Srgrimes sblock.fs_fragshift += 1; 2701558Srgrimes if (sblock.fs_frag <= MAXFRAG) 2711558Srgrimes continue; 2721558Srgrimes } 2731558Srgrimes if (sblock.fs_fsize == sblock.fs_bsize) { 2741558Srgrimes printf("There is no block size that"); 2751558Srgrimes printf(" can support this disk\n"); 2761558Srgrimes exit(22); 2771558Srgrimes } 2781558Srgrimes sblock.fs_frag >>= 1; 2791558Srgrimes sblock.fs_fragshift -= 1; 2801558Srgrimes sblock.fs_fsize <<= 1; 2811558Srgrimes sblock.fs_nspf <<= 1; 2821558Srgrimes } 2831558Srgrimes /* 2841558Srgrimes * Ensure that cylinder group with mincpg has enough space for inodes. 2851558Srgrimes */ 2861558Srgrimes inodecramped = 0; 28723682Speter inospercg = calcipg(mincpg, bpcg, &usedb); 2881558Srgrimes sblock.fs_ipg = inospercg; 2891558Srgrimes while (inospercg > MAXIPG(&sblock)) { 2901558Srgrimes inodecramped = 1; 2911558Srgrimes if (mincpc == 1 || sblock.fs_frag == 1 || 2921558Srgrimes sblock.fs_bsize == MINBSIZE) 2931558Srgrimes break; 2941558Srgrimes printf("With a block size of %d %s %d\n", sblock.fs_bsize, 29585860Sphk "minimum bytes per inode is", 29685860Sphk (int)((mincpg * (off_t)bpcg - usedb) / 29785860Sphk MAXIPG(&sblock) + 1)); 2981558Srgrimes sblock.fs_bsize >>= 1; 2991558Srgrimes sblock.fs_frag >>= 1; 3001558Srgrimes sblock.fs_fragshift -= 1; 3011558Srgrimes mincpc >>= 1; 3021558Srgrimes sblock.fs_cpg = roundup(mincpgcnt, mincpc); 3031558Srgrimes if (CGSIZE(&sblock) > sblock.fs_bsize) { 3041558Srgrimes sblock.fs_bsize <<= 1; 3051558Srgrimes break; 3061558Srgrimes } 3071558Srgrimes mincpg = sblock.fs_cpg; 30823682Speter inospercg = calcipg(mincpg, bpcg, &usedb); 3091558Srgrimes sblock.fs_ipg = inospercg; 3101558Srgrimes } 3111558Srgrimes if (inodecramped) { 3121558Srgrimes if (inospercg > MAXIPG(&sblock)) { 3131558Srgrimes printf("Minimum bytes per inode is %d\n", 31485860Sphk (int)((mincpg * (off_t)bpcg - usedb) / 31585860Sphk MAXIPG(&sblock) + 1)); 3161558Srgrimes } else if (!mapcramped) { 3171558Srgrimes printf("With %d bytes per inode, ", density); 31837239Sbde printf("minimum cylinders per group is %ld\n", mincpg); 3191558Srgrimes } 3201558Srgrimes } 3211558Srgrimes if (mapcramped) { 3221558Srgrimes printf("With %d sectors per cylinder, ", sblock.fs_spc); 32337239Sbde printf("minimum cylinders per group is %ld\n", mincpg); 3241558Srgrimes } 3251558Srgrimes if (inodecramped || mapcramped) { 3261558Srgrimes if (sblock.fs_bsize != bsize) 3271558Srgrimes printf("%s to be changed from %d to %d\n", 3281558Srgrimes "This requires the block size", 3291558Srgrimes bsize, sblock.fs_bsize); 3301558Srgrimes if (sblock.fs_fsize != fsize) 3311558Srgrimes printf("\t%s to be changed from %d to %d\n", 33285860Sphk "and the fragment size", fsize, sblock.fs_fsize); 3331558Srgrimes exit(23); 3341558Srgrimes } 3358871Srgrimes /* 3361558Srgrimes * Calculate the number of cylinders per group 3371558Srgrimes */ 3381558Srgrimes sblock.fs_cpg = cpg; 3391558Srgrimes if (sblock.fs_cpg % mincpc != 0) { 34037239Sbde printf("%s groups must have a multiple of %ld cylinders\n", 34185860Sphk cpgflg ? "Cylinder" : "Warning: cylinder", mincpc); 3421558Srgrimes sblock.fs_cpg = roundup(sblock.fs_cpg, mincpc); 3431558Srgrimes if (!cpgflg) 3441558Srgrimes cpg = sblock.fs_cpg; 3451558Srgrimes } 3461558Srgrimes /* 3471558Srgrimes * Must ensure there is enough space for inodes. 3481558Srgrimes */ 34923682Speter sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 3501558Srgrimes while (sblock.fs_ipg > MAXIPG(&sblock)) { 3511558Srgrimes inodecramped = 1; 3521558Srgrimes sblock.fs_cpg -= mincpc; 35323682Speter sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 3541558Srgrimes } 3551558Srgrimes /* 3561558Srgrimes * Must ensure there is enough space to hold block map. 3571558Srgrimes */ 3581558Srgrimes while (CGSIZE(&sblock) > sblock.fs_bsize) { 3591558Srgrimes mapcramped = 1; 3601558Srgrimes sblock.fs_cpg -= mincpc; 36123682Speter sblock.fs_ipg = calcipg(sblock.fs_cpg, bpcg, &usedb); 3621558Srgrimes } 3631558Srgrimes sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 3641558Srgrimes if ((sblock.fs_cpg * sblock.fs_spc) % NSPB(&sblock) != 0) { 36537239Sbde printf("panic (fs_cpg * fs_spc) %% NSPF != 0"); 3661558Srgrimes exit(24); 3671558Srgrimes } 3681558Srgrimes if (sblock.fs_cpg < mincpg) { 36937239Sbde printf("cylinder groups must have at least %ld cylinders\n", 3701558Srgrimes mincpg); 3711558Srgrimes exit(25); 3721558Srgrimes } else if (sblock.fs_cpg != cpg) { 3731558Srgrimes if (!cpgflg) 3741558Srgrimes printf("Warning: "); 3751558Srgrimes else if (!mapcramped && !inodecramped) 3761558Srgrimes exit(26); 3771558Srgrimes if (mapcramped && inodecramped) 3781558Srgrimes printf("Block size and bytes per inode restrict"); 3791558Srgrimes else if (mapcramped) 3801558Srgrimes printf("Block size restricts"); 3811558Srgrimes else 3821558Srgrimes printf("Bytes per inode restrict"); 3831558Srgrimes printf(" cylinders per group to %d.\n", sblock.fs_cpg); 3841558Srgrimes if (cpgflg) 3851558Srgrimes exit(27); 3861558Srgrimes } 3871558Srgrimes sblock.fs_cgsize = fragroundup(&sblock, CGSIZE(&sblock)); 3881558Srgrimes /* 3891558Srgrimes * Now have size for file system and nsect and ntrak. 3901558Srgrimes * Determine number of cylinders and blocks in the file system. 3911558Srgrimes */ 3921558Srgrimes sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 3931558Srgrimes sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 3941558Srgrimes if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 3951558Srgrimes sblock.fs_ncyl++; 39692763Sphk lwarn = 1; 3971558Srgrimes } 3981558Srgrimes if (sblock.fs_ncyl < 1) { 3991558Srgrimes printf("file systems must have at least one cylinder\n"); 4001558Srgrimes exit(28); 4011558Srgrimes } 4021558Srgrimes /* 4031558Srgrimes * Determine feasability/values of rotational layout tables. 4041558Srgrimes * 4051558Srgrimes * The size of the rotational layout tables is limited by the 4061558Srgrimes * size of the superblock, SBSIZE. The amount of space available 4071558Srgrimes * for tables is calculated as (SBSIZE - sizeof (struct fs)). 4081558Srgrimes * The size of these tables is inversely proportional to the block 4091558Srgrimes * size of the file system. The size increases if sectors per track 4101558Srgrimes * are not powers of two, because more cylinders must be described 4111558Srgrimes * by the tables before the rotational pattern repeats (fs_cpc). 4121558Srgrimes */ 41392763Sphk sblock.fs_interleave = 1; 41492763Sphk sblock.fs_trackskew = 0; 41592763Sphk sblock.fs_npsect = secpercyl; 4161558Srgrimes sblock.fs_postblformat = FS_DYNAMICPOSTBLFMT; 4171558Srgrimes sblock.fs_sbsize = fragroundup(&sblock, sizeof(struct fs)); 41832623Sbde if (sblock.fs_sbsize > SBSIZE) 41932623Sbde sblock.fs_sbsize = SBSIZE; 42092763Sphk sblock.fs_cpc = 0; 4211558Srgrimes /* 4221558Srgrimes * Compute/validate number of cylinder groups. 4231558Srgrimes */ 4241558Srgrimes sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 4251558Srgrimes if (sblock.fs_ncyl % sblock.fs_cpg) 4261558Srgrimes sblock.fs_ncg++; 4271558Srgrimes sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 4281558Srgrimes i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); 4291558Srgrimes if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { 43037239Sbde printf("inode blocks/cyl group (%ld) >= data blocks (%ld)\n", 4311558Srgrimes cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, 43237239Sbde (long)(sblock.fs_fpg / sblock.fs_frag)); 4331558Srgrimes printf("number of cylinders per cylinder group (%d) %s.\n", 4341558Srgrimes sblock.fs_cpg, "must be increased"); 4351558Srgrimes exit(29); 4361558Srgrimes } 4371558Srgrimes j = sblock.fs_ncg - 1; 4381558Srgrimes if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && 4391558Srgrimes cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 4401558Srgrimes if (j == 0) { 4411558Srgrimes printf("Filesystem must have at least %d sectors\n", 4421558Srgrimes NSPF(&sblock) * 4431558Srgrimes (cgdmin(&sblock, 0) + 3 * sblock.fs_frag)); 4441558Srgrimes exit(30); 4451558Srgrimes } 44692532Sbde printf( 44792532Sbde"Warning: inode blocks/cyl group (%ld) >= data blocks (%ld) in last\n", 4481558Srgrimes (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, 4491558Srgrimes i / sblock.fs_frag); 45092532Sbde printf( 45192532Sbde" cylinder group. This implies %ld sector(s) cannot be allocated.\n", 45292532Sbde i * NSPF(&sblock)); 4531558Srgrimes sblock.fs_ncg--; 4541558Srgrimes sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; 4551558Srgrimes sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / 4561558Srgrimes NSPF(&sblock); 45792763Sphk lwarn = 0; 4581558Srgrimes } 45992763Sphk if (lwarn) { 4601558Srgrimes printf("Warning: %d sector(s) in last cylinder unallocated\n", 4611558Srgrimes sblock.fs_spc - 46285860Sphk (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) * 46385860Sphk sblock.fs_spc)); 4641558Srgrimes } 4651558Srgrimes /* 4661558Srgrimes * fill in remaining fields of the super block 4671558Srgrimes */ 4681558Srgrimes sblock.fs_csaddr = cgdmin(&sblock, 0); 4691558Srgrimes sblock.fs_cssize = 4701558Srgrimes fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 47171073Siedowse /* 47271073Siedowse * The superblock fields 'fs_csmask' and 'fs_csshift' are no 47371073Siedowse * longer used. However, we still initialise them so that the 47471073Siedowse * filesystem remains compatible with old kernels. 47571073Siedowse */ 4761558Srgrimes i = sblock.fs_bsize / sizeof(struct csum); 4771558Srgrimes sblock.fs_csmask = ~(i - 1); 47892712Siedowse sblock.fs_csshift = ilog2(i); 4791558Srgrimes fscs = (struct csum *)calloc(1, sblock.fs_cssize); 48037664Scharnier if (fscs == NULL) 48137664Scharnier errx(31, "calloc failed"); 4821558Srgrimes sblock.fs_magic = FS_MAGIC; 48392763Sphk sblock.fs_rotdelay = 0; 4841558Srgrimes sblock.fs_minfree = minfree; 4851558Srgrimes sblock.fs_maxcontig = maxcontig; 4861558Srgrimes sblock.fs_maxbpg = maxbpg; 48792763Sphk sblock.fs_rps = 60; 4881558Srgrimes sblock.fs_optim = opt; 4891558Srgrimes sblock.fs_cgrotor = 0; 4901558Srgrimes sblock.fs_cstotal.cs_ndir = 0; 4911558Srgrimes sblock.fs_cstotal.cs_nbfree = 0; 4921558Srgrimes sblock.fs_cstotal.cs_nifree = 0; 4931558Srgrimes sblock.fs_cstotal.cs_nffree = 0; 4941558Srgrimes sblock.fs_fmod = 0; 4951558Srgrimes sblock.fs_ronly = 0; 4962294Sdg sblock.fs_clean = 1; 49724149Sguido sblock.fs_id[0] = (long)utime; 49824215Sache sblock.fs_id[1] = random(); 49924149Sguido 5001558Srgrimes /* 5011558Srgrimes * Dump out summary information about file system. 5021558Srgrimes */ 50377420Sphk printf("%s:\t%d sectors in %d %s of %d tracks, %d sectors\n", 50477420Sphk fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 50577420Sphk "cylinders", sblock.fs_ntrak, sblock.fs_nsect); 5061558Srgrimes#define B2MBFACTOR (1 / (1024.0 * 1024.0)) 50785860Sphk printf("\t%.1fMB in %d cyl groups (%d c/g, %.2fMB/g, %d i/g)%s\n", 50877420Sphk (float)sblock.fs_size * sblock.fs_fsize * B2MBFACTOR, 50977420Sphk sblock.fs_ncg, sblock.fs_cpg, 51077420Sphk (float)sblock.fs_fpg * sblock.fs_fsize * B2MBFACTOR, 51177420Sphk sblock.fs_ipg, 51277420Sphk sblock.fs_flags & FS_DOSOFTDEP ? " SOFTUPDATES" : ""); 5131558Srgrimes#undef B2MBFACTOR 5141558Srgrimes /* 5151558Srgrimes * Now build the cylinders group blocks and 5161558Srgrimes * then print out indices of cylinder groups. 5171558Srgrimes */ 51877420Sphk printf("super-block backups (for fsck -b #) at:\n"); 51913769Sjoerg i = 0; 52013769Sjoerg width = charsperline(); 5211558Srgrimes for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 5221558Srgrimes initcg(cylno, utime); 52375904Skris j = snprintf(tmpbuf, sizeof(tmpbuf), " %ld%s", 52450134Sbillf fsbtodb(&sblock, cgsblock(&sblock, cylno)), 52585860Sphk cylno < (sblock.fs_ncg-1) ? "," : ""); 52681980Sbrian if (j < 0) 52781980Sbrian tmpbuf[j = 0] = '\0'; 52837239Sbde if (i + j >= width) { 5291558Srgrimes printf("\n"); 53013769Sjoerg i = 0; 53113769Sjoerg } 53213769Sjoerg i += j; 53313769Sjoerg printf("%s", tmpbuf); 5348218Sdg fflush(stdout); 5351558Srgrimes } 53677420Sphk printf("\n"); 53777420Sphk if (Nflag) 5381558Srgrimes exit(0); 5391558Srgrimes /* 5401558Srgrimes * Now construct the initial file system, 5411558Srgrimes * then write out the super-block. 5421558Srgrimes */ 5431558Srgrimes fsinit(utime); 5441558Srgrimes sblock.fs_time = utime; 5451558Srgrimes wtfs((int)SBOFF / sectorsize, sbsize, (char *)&sblock); 5461558Srgrimes for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 5471558Srgrimes wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 5481558Srgrimes sblock.fs_cssize - i < sblock.fs_bsize ? 54985860Sphk sblock.fs_cssize - i : sblock.fs_bsize, 5501558Srgrimes ((char *)fscs) + i); 5518871Srgrimes /* 5521558Srgrimes * Write out the duplicate super blocks 5531558Srgrimes */ 5541558Srgrimes for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 5551558Srgrimes wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 5561558Srgrimes sbsize, (char *)&sblock); 55767478Sjwd wtfsflush(); 5581558Srgrimes /* 5591558Srgrimes * Update information about this partion in pack 5601558Srgrimes * label, to that it may be updated on disk. 5611558Srgrimes */ 5621558Srgrimes pp->p_fstype = FS_BSDFFS; 5631558Srgrimes pp->p_fsize = sblock.fs_fsize; 5641558Srgrimes pp->p_frag = sblock.fs_frag; 5651558Srgrimes pp->p_cpg = sblock.fs_cpg; 5661558Srgrimes} 5671558Srgrimes 5681558Srgrimes/* 5691558Srgrimes * Initialize a cylinder group. 5701558Srgrimes */ 57137664Scharniervoid 57292711Siedowseinitcg(int cylno, time_t utime) 5731558Srgrimes{ 5741558Srgrimes daddr_t cbase, d, dlower, dupper, dmax, blkno; 57592483Sphk struct csum *cs; 57692710Siedowse long i, j; 5771558Srgrimes 5781558Srgrimes /* 5791558Srgrimes * Determine block bounds for cylinder group. 5801558Srgrimes * Allow space for super block summary information in first 5811558Srgrimes * cylinder group. 5821558Srgrimes */ 5831558Srgrimes cbase = cgbase(&sblock, cylno); 5841558Srgrimes dmax = cbase + sblock.fs_fpg; 5851558Srgrimes if (dmax > sblock.fs_size) 5861558Srgrimes dmax = sblock.fs_size; 5871558Srgrimes dlower = cgsblock(&sblock, cylno) - cbase; 5881558Srgrimes dupper = cgdmin(&sblock, cylno) - cbase; 5891558Srgrimes if (cylno == 0) 5901558Srgrimes dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 5911558Srgrimes cs = fscs + cylno; 59223682Speter memset(&acg, 0, sblock.fs_cgsize); 5931558Srgrimes acg.cg_time = utime; 5941558Srgrimes acg.cg_magic = CG_MAGIC; 5951558Srgrimes acg.cg_cgx = cylno; 5961558Srgrimes if (cylno == sblock.fs_ncg - 1) 5971558Srgrimes acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 5981558Srgrimes else 5991558Srgrimes acg.cg_ncyl = sblock.fs_cpg; 6001558Srgrimes acg.cg_niblk = sblock.fs_ipg; 6011558Srgrimes acg.cg_ndblk = dmax - cbase; 6021558Srgrimes if (sblock.fs_contigsumsize > 0) 6031558Srgrimes acg.cg_nclusterblks = acg.cg_ndblk / sblock.fs_frag; 60423682Speter acg.cg_btotoff = &acg.cg_space[0] - (u_char *)(&acg.cg_firstfield); 60538579Sdfr acg.cg_boff = acg.cg_btotoff + sblock.fs_cpg * sizeof(int32_t); 6068871Srgrimes acg.cg_iusedoff = acg.cg_boff + 60792763Sphk sblock.fs_cpg * sizeof(u_int16_t); 6081558Srgrimes acg.cg_freeoff = acg.cg_iusedoff + howmany(sblock.fs_ipg, NBBY); 6091558Srgrimes if (sblock.fs_contigsumsize <= 0) { 6101558Srgrimes acg.cg_nextfreeoff = acg.cg_freeoff + 61192532Sbde howmany(sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), 61292532Sbde NBBY); 6131558Srgrimes } else { 6141558Srgrimes acg.cg_clustersumoff = acg.cg_freeoff + howmany 6151558Srgrimes (sblock.fs_cpg * sblock.fs_spc / NSPF(&sblock), NBBY) - 61638579Sdfr sizeof(u_int32_t); 6171558Srgrimes acg.cg_clustersumoff = 61838579Sdfr roundup(acg.cg_clustersumoff, sizeof(u_int32_t)); 6191558Srgrimes acg.cg_clusteroff = acg.cg_clustersumoff + 62038579Sdfr (sblock.fs_contigsumsize + 1) * sizeof(u_int32_t); 6211558Srgrimes acg.cg_nextfreeoff = acg.cg_clusteroff + howmany 6221558Srgrimes (sblock.fs_cpg * sblock.fs_spc / NSPB(&sblock), NBBY); 6231558Srgrimes } 62492532Sbde if (acg.cg_nextfreeoff - (long)(&acg.cg_firstfield) > 62592532Sbde sblock.fs_cgsize) { 6261558Srgrimes printf("Panic: cylinder group too big\n"); 6271558Srgrimes exit(37); 6281558Srgrimes } 6291558Srgrimes acg.cg_cs.cs_nifree += sblock.fs_ipg; 6301558Srgrimes if (cylno == 0) 6311558Srgrimes for (i = 0; i < ROOTINO; i++) { 6321558Srgrimes setbit(cg_inosused(&acg), i); 6331558Srgrimes acg.cg_cs.cs_nifree--; 6341558Srgrimes } 63524149Sguido for (i = 0; i < sblock.fs_ipg / INOPF(&sblock); i += sblock.fs_frag) { 63624149Sguido for (j = 0; j < sblock.fs_bsize / sizeof(struct dinode); j++) 63724215Sache zino[j].di_gen = random(); 6381558Srgrimes wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno) + i), 6391558Srgrimes sblock.fs_bsize, (char *)zino); 64024149Sguido } 6411558Srgrimes if (cylno > 0) { 6421558Srgrimes /* 6431558Srgrimes * In cylno 0, beginning space is reserved 6441558Srgrimes * for boot and super blocks. 6451558Srgrimes */ 6461558Srgrimes for (d = 0; d < dlower; d += sblock.fs_frag) { 6471558Srgrimes blkno = d / sblock.fs_frag; 6481558Srgrimes setblock(&sblock, cg_blksfree(&acg), blkno); 6491558Srgrimes if (sblock.fs_contigsumsize > 0) 6501558Srgrimes setbit(cg_clustersfree(&acg), blkno); 6511558Srgrimes acg.cg_cs.cs_nbfree++; 6521558Srgrimes cg_blktot(&acg)[cbtocylno(&sblock, d)]++; 6531558Srgrimes cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) 6541558Srgrimes [cbtorpos(&sblock, d)]++; 6551558Srgrimes } 6561558Srgrimes sblock.fs_dsize += dlower; 6571558Srgrimes } 6581558Srgrimes sblock.fs_dsize += acg.cg_ndblk - dupper; 65937664Scharnier if ((i = dupper % sblock.fs_frag)) { 6601558Srgrimes acg.cg_frsum[sblock.fs_frag - i]++; 6611558Srgrimes for (d = dupper + sblock.fs_frag - i; dupper < d; dupper++) { 6621558Srgrimes setbit(cg_blksfree(&acg), dupper); 6631558Srgrimes acg.cg_cs.cs_nffree++; 6641558Srgrimes } 6651558Srgrimes } 66685860Sphk for (d = dupper; d + sblock.fs_frag <= dmax - cbase;) { 6671558Srgrimes blkno = d / sblock.fs_frag; 6681558Srgrimes setblock(&sblock, cg_blksfree(&acg), blkno); 6691558Srgrimes if (sblock.fs_contigsumsize > 0) 6701558Srgrimes setbit(cg_clustersfree(&acg), blkno); 6711558Srgrimes acg.cg_cs.cs_nbfree++; 6721558Srgrimes cg_blktot(&acg)[cbtocylno(&sblock, d)]++; 6731558Srgrimes cg_blks(&sblock, &acg, cbtocylno(&sblock, d)) 6741558Srgrimes [cbtorpos(&sblock, d)]++; 6751558Srgrimes d += sblock.fs_frag; 6761558Srgrimes } 6771558Srgrimes if (d < dmax - cbase) { 6781558Srgrimes acg.cg_frsum[dmax - cbase - d]++; 6791558Srgrimes for (; d < dmax - cbase; d++) { 6801558Srgrimes setbit(cg_blksfree(&acg), d); 6811558Srgrimes acg.cg_cs.cs_nffree++; 6821558Srgrimes } 6831558Srgrimes } 6841558Srgrimes if (sblock.fs_contigsumsize > 0) { 68523682Speter int32_t *sump = cg_clustersum(&acg); 6861558Srgrimes u_char *mapp = cg_clustersfree(&acg); 6871558Srgrimes int map = *mapp++; 6881558Srgrimes int bit = 1; 6891558Srgrimes int run = 0; 6901558Srgrimes 6911558Srgrimes for (i = 0; i < acg.cg_nclusterblks; i++) { 69285860Sphk if ((map & bit) != 0) 6931558Srgrimes run++; 69485860Sphk else if (run != 0) { 6951558Srgrimes if (run > sblock.fs_contigsumsize) 6961558Srgrimes run = sblock.fs_contigsumsize; 6971558Srgrimes sump[run]++; 6981558Srgrimes run = 0; 6991558Srgrimes } 70085860Sphk if ((i & (NBBY - 1)) != NBBY - 1) 7011558Srgrimes bit <<= 1; 70285860Sphk else { 7031558Srgrimes map = *mapp++; 7041558Srgrimes bit = 1; 7051558Srgrimes } 7061558Srgrimes } 7071558Srgrimes if (run != 0) { 7081558Srgrimes if (run > sblock.fs_contigsumsize) 7091558Srgrimes run = sblock.fs_contigsumsize; 7101558Srgrimes sump[run]++; 7111558Srgrimes } 7121558Srgrimes } 7131558Srgrimes sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 7141558Srgrimes sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 7151558Srgrimes sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 7161558Srgrimes sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 7171558Srgrimes *cs = acg.cg_cs; 7181558Srgrimes wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 7191558Srgrimes sblock.fs_bsize, (char *)&acg); 7201558Srgrimes} 7211558Srgrimes 7221558Srgrimes/* 7231558Srgrimes * initialize the file system 7241558Srgrimes */ 7251558Srgrimesstruct dinode node; 7261558Srgrimes 7271558Srgrimes#ifdef LOSTDIR 7281558Srgrimes#define PREDEFDIR 3 7291558Srgrimes#else 7301558Srgrimes#define PREDEFDIR 2 7311558Srgrimes#endif 7321558Srgrimes 7331558Srgrimesstruct direct root_dir[] = { 7341558Srgrimes { ROOTINO, sizeof(struct direct), DT_DIR, 1, "." }, 7351558Srgrimes { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 7361558Srgrimes#ifdef LOSTDIR 7371558Srgrimes { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found" }, 7381558Srgrimes#endif 7391558Srgrimes}; 7401558Srgrimesstruct odirect { 7411558Srgrimes u_long d_ino; 7421558Srgrimes u_short d_reclen; 7431558Srgrimes u_short d_namlen; 7441558Srgrimes u_char d_name[MAXNAMLEN + 1]; 7451558Srgrimes} oroot_dir[] = { 7461558Srgrimes { ROOTINO, sizeof(struct direct), 1, "." }, 7471558Srgrimes { ROOTINO, sizeof(struct direct), 2, ".." }, 7481558Srgrimes#ifdef LOSTDIR 7491558Srgrimes { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 7501558Srgrimes#endif 7511558Srgrimes}; 7521558Srgrimes#ifdef LOSTDIR 7531558Srgrimesstruct direct lost_found_dir[] = { 7541558Srgrimes { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." }, 7551558Srgrimes { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." }, 7561558Srgrimes { 0, DIRBLKSIZ, 0, 0, 0 }, 7571558Srgrimes}; 7581558Srgrimesstruct odirect olost_found_dir[] = { 7591558Srgrimes { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 7601558Srgrimes { ROOTINO, sizeof(struct direct), 2, ".." }, 7611558Srgrimes { 0, DIRBLKSIZ, 0, 0 }, 7621558Srgrimes}; 7631558Srgrimes#endif 7641558Srgrimeschar buf[MAXBSIZE]; 7651558Srgrimes 76637664Scharniervoid 76792711Siedowsefsinit(time_t utime) 7681558Srgrimes{ 76937664Scharnier#ifdef LOSTDIR 7701558Srgrimes int i; 77137664Scharnier#endif 7721558Srgrimes 7731558Srgrimes /* 7741558Srgrimes * initialize the node 7751558Srgrimes */ 77623682Speter node.di_atime = utime; 77723682Speter node.di_mtime = utime; 77823682Speter node.di_ctime = utime; 7791558Srgrimes#ifdef LOSTDIR 7801558Srgrimes /* 7811558Srgrimes * create the lost+found directory 7821558Srgrimes */ 78392763Sphk (void)makedir(lost_found_dir, 2); 78492763Sphk for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 78592763Sphk memmove(&buf[i], &lost_found_dir[2], 78692763Sphk DIRSIZ(0, &lost_found_dir[2])); 7871558Srgrimes node.di_mode = IFDIR | UMASK; 7881558Srgrimes node.di_nlink = 2; 7891558Srgrimes node.di_size = sblock.fs_bsize; 7901558Srgrimes node.di_db[0] = alloc(node.di_size, node.di_mode); 7911558Srgrimes node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 7921558Srgrimes wtfs(fsbtodb(&sblock, node.di_db[0]), node.di_size, buf); 7931558Srgrimes iput(&node, LOSTFOUNDINO); 7941558Srgrimes#endif 7951558Srgrimes /* 7961558Srgrimes * create the root directory 7971558Srgrimes */ 79877420Sphk node.di_mode = IFDIR | UMASK; 7991558Srgrimes node.di_nlink = PREDEFDIR; 80092763Sphk node.di_size = makedir(root_dir, PREDEFDIR); 8011558Srgrimes node.di_db[0] = alloc(sblock.fs_fsize, node.di_mode); 8021558Srgrimes node.di_blocks = btodb(fragroundup(&sblock, node.di_size)); 8031558Srgrimes wtfs(fsbtodb(&sblock, node.di_db[0]), sblock.fs_fsize, buf); 8041558Srgrimes iput(&node, ROOTINO); 8051558Srgrimes} 8061558Srgrimes 8071558Srgrimes/* 8081558Srgrimes * construct a set of directory entries in "buf". 8091558Srgrimes * return size of directory. 8101558Srgrimes */ 81137664Scharnierint 81292711Siedowsemakedir(struct direct *protodir, int entries) 8131558Srgrimes{ 8141558Srgrimes char *cp; 8151558Srgrimes int i, spcleft; 8161558Srgrimes 8171558Srgrimes spcleft = DIRBLKSIZ; 8181558Srgrimes for (cp = buf, i = 0; i < entries - 1; i++) { 8191558Srgrimes protodir[i].d_reclen = DIRSIZ(0, &protodir[i]); 82023682Speter memmove(cp, &protodir[i], protodir[i].d_reclen); 8211558Srgrimes cp += protodir[i].d_reclen; 8221558Srgrimes spcleft -= protodir[i].d_reclen; 8231558Srgrimes } 8241558Srgrimes protodir[i].d_reclen = spcleft; 82523682Speter memmove(cp, &protodir[i], DIRSIZ(0, &protodir[i])); 8261558Srgrimes return (DIRBLKSIZ); 8271558Srgrimes} 8281558Srgrimes 8291558Srgrimes/* 8301558Srgrimes * allocate a block or frag 8311558Srgrimes */ 8321558Srgrimesdaddr_t 83392711Siedowsealloc(int size, int mode) 8341558Srgrimes{ 8351558Srgrimes int i, frag; 8361558Srgrimes daddr_t d, blkno; 8371558Srgrimes 8381558Srgrimes rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 8391558Srgrimes (char *)&acg); 8401558Srgrimes if (acg.cg_magic != CG_MAGIC) { 8411558Srgrimes printf("cg 0: bad magic number\n"); 8421558Srgrimes return (0); 8431558Srgrimes } 8441558Srgrimes if (acg.cg_cs.cs_nbfree == 0) { 8451558Srgrimes printf("first cylinder group ran out of space\n"); 8461558Srgrimes return (0); 8471558Srgrimes } 8481558Srgrimes for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 8491558Srgrimes if (isblock(&sblock, cg_blksfree(&acg), d / sblock.fs_frag)) 8501558Srgrimes goto goth; 8511558Srgrimes printf("internal error: can't find block in cyl 0\n"); 8521558Srgrimes return (0); 8531558Srgrimesgoth: 8541558Srgrimes blkno = fragstoblks(&sblock, d); 8551558Srgrimes clrblock(&sblock, cg_blksfree(&acg), blkno); 85623682Speter if (sblock.fs_contigsumsize > 0) 85723682Speter clrbit(cg_clustersfree(&acg), blkno); 8581558Srgrimes acg.cg_cs.cs_nbfree--; 8591558Srgrimes sblock.fs_cstotal.cs_nbfree--; 8601558Srgrimes fscs[0].cs_nbfree--; 8611558Srgrimes if (mode & IFDIR) { 8621558Srgrimes acg.cg_cs.cs_ndir++; 8631558Srgrimes sblock.fs_cstotal.cs_ndir++; 8641558Srgrimes fscs[0].cs_ndir++; 8651558Srgrimes } 8661558Srgrimes cg_blktot(&acg)[cbtocylno(&sblock, d)]--; 8671558Srgrimes cg_blks(&sblock, &acg, cbtocylno(&sblock, d))[cbtorpos(&sblock, d)]--; 8681558Srgrimes if (size != sblock.fs_bsize) { 8691558Srgrimes frag = howmany(size, sblock.fs_fsize); 8701558Srgrimes fscs[0].cs_nffree += sblock.fs_frag - frag; 8711558Srgrimes sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 8721558Srgrimes acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 8731558Srgrimes acg.cg_frsum[sblock.fs_frag - frag]++; 8741558Srgrimes for (i = frag; i < sblock.fs_frag; i++) 8751558Srgrimes setbit(cg_blksfree(&acg), d + i); 8761558Srgrimes } 8771558Srgrimes wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 8781558Srgrimes (char *)&acg); 8791558Srgrimes return (d); 8801558Srgrimes} 8811558Srgrimes 8821558Srgrimes/* 88323682Speter * Calculate number of inodes per group. 88423682Speter */ 88523682Speterlong 88692763Sphkcalcipg(long lcpg, long bpcg, off_t *usedbp) 88723682Speter{ 88823682Speter int i; 88923682Speter long ipg, new_ipg, ncg, ncyl; 89023682Speter off_t usedb; 89123682Speter 89223682Speter /* 89323682Speter * Prepare to scale by fssize / (number of sectors in cylinder groups). 89423682Speter * Note that fssize is still in sectors, not filesystem blocks. 89523682Speter */ 89636498Sbde ncyl = howmany(fssize, (u_int)secpercyl); 89792763Sphk ncg = howmany(ncyl, lcpg); 89823682Speter /* 89923682Speter * Iterate a few times to allow for ipg depending on itself. 90023682Speter */ 90123682Speter ipg = 0; 90223682Speter for (i = 0; i < 10; i++) { 90385860Sphk usedb = (sblock.fs_iblkno + ipg / INOPF(&sblock)) * 90485860Sphk NSPF(&sblock) * (off_t)sectorsize; 90592763Sphk new_ipg = (lcpg * (quad_t)bpcg - usedb) / density * 90692763Sphk fssize / ncg / secpercyl / lcpg; 90723682Speter new_ipg = roundup(new_ipg, INOPB(&sblock)); 90823682Speter if (new_ipg == ipg) 90923682Speter break; 91023682Speter ipg = new_ipg; 91123682Speter } 91223682Speter *usedbp = usedb; 91323682Speter return (ipg); 91423682Speter} 91523682Speter 91623682Speter/* 9171558Srgrimes * Allocate an inode on the disk 9181558Srgrimes */ 91937664Scharniervoid 92092711Siedowseiput(struct dinode *ip, ino_t ino) 9211558Srgrimes{ 92292763Sphk struct dinode lbuf[MAXINOPB]; 9231558Srgrimes daddr_t d; 9241558Srgrimes int c; 9251558Srgrimes 92624215Sache ip->di_gen = random(); 9271558Srgrimes c = ino_to_cg(&sblock, ino); 9281558Srgrimes rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 9291558Srgrimes (char *)&acg); 9301558Srgrimes if (acg.cg_magic != CG_MAGIC) { 9311558Srgrimes printf("cg 0: bad magic number\n"); 9321558Srgrimes exit(31); 9331558Srgrimes } 9341558Srgrimes acg.cg_cs.cs_nifree--; 9351558Srgrimes setbit(cg_inosused(&acg), ino); 9361558Srgrimes wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 9371558Srgrimes (char *)&acg); 9381558Srgrimes sblock.fs_cstotal.cs_nifree--; 9391558Srgrimes fscs[0].cs_nifree--; 9401558Srgrimes if (ino >= sblock.fs_ipg * sblock.fs_ncg) { 9411558Srgrimes printf("fsinit: inode value out of range (%d).\n", ino); 9421558Srgrimes exit(32); 9431558Srgrimes } 9441558Srgrimes d = fsbtodb(&sblock, ino_to_fsba(&sblock, ino)); 94592763Sphk rdfs(d, sblock.fs_bsize, (char *)lbuf); 94692763Sphk lbuf[ino_to_fsbo(&sblock, ino)] = *ip; 94792763Sphk wtfs(d, sblock.fs_bsize, (char *)lbuf); 9481558Srgrimes} 9491558Srgrimes 9501558Srgrimes/* 9511558Srgrimes * read a block from the file system 9521558Srgrimes */ 95337664Scharniervoid 95492711Siedowserdfs(daddr_t bno, int size, char *bf) 9551558Srgrimes{ 9561558Srgrimes int n; 9571558Srgrimes 95867478Sjwd wtfsflush(); 9591558Srgrimes if (lseek(fsi, (off_t)bno * sectorsize, 0) < 0) { 96037239Sbde printf("seek error: %ld\n", (long)bno); 96137664Scharnier err(33, "rdfs"); 9621558Srgrimes } 9631558Srgrimes n = read(fsi, bf, size); 9641558Srgrimes if (n != size) { 96537239Sbde printf("read error: %ld\n", (long)bno); 96637664Scharnier err(34, "rdfs"); 9671558Srgrimes } 9681558Srgrimes} 9691558Srgrimes 97067239Speter#define WCSIZE (128 * 1024) 97167239Speterdaddr_t wc_sect; /* units of sectorsize */ 97267239Speterint wc_end; /* bytes */ 97367239Speterstatic char wc[WCSIZE]; /* bytes */ 97467239Speter 9751558Srgrimes/* 97667478Sjwd * Flush dirty write behind buffer. 97767478Sjwd */ 97867478Sjwdvoid 97967478Sjwdwtfsflush() 98067478Sjwd{ 98167478Sjwd int n; 98267478Sjwd if (wc_end) { 98367478Sjwd if (lseek(fso, (off_t)wc_sect * sectorsize, SEEK_SET) < 0) { 98467478Sjwd printf("seek error: %ld\n", (long)wc_sect); 98567478Sjwd err(35, "wtfs - writecombine"); 98667478Sjwd } 98767478Sjwd n = write(fso, wc, wc_end); 98867478Sjwd if (n != wc_end) { 98967478Sjwd printf("write error: %ld\n", (long)wc_sect); 99067478Sjwd err(36, "wtfs - writecombine"); 99167478Sjwd } 99267478Sjwd wc_end = 0; 99367478Sjwd } 99467478Sjwd} 99567478Sjwd 99667478Sjwd/* 9971558Srgrimes * write a block to the file system 9981558Srgrimes */ 99937664Scharniervoid 100092711Siedowsewtfs(daddr_t bno, int size, char *bf) 10011558Srgrimes{ 100292711Siedowse int done, n; 10031558Srgrimes 10041558Srgrimes if (Nflag) 10051558Srgrimes return; 100667239Speter done = 0; 100767239Speter if (wc_end == 0 && size <= WCSIZE) { 100867239Speter wc_sect = bno; 100967239Speter bcopy(bf, wc, size); 101067239Speter wc_end = size; 101167239Speter if (wc_end < WCSIZE) 101267239Speter return; 101367239Speter done = 1; 101467239Speter } 101567479Sjwd if ((off_t)wc_sect * sectorsize + wc_end == (off_t)bno * sectorsize && 101667239Speter wc_end + size <= WCSIZE) { 101767239Speter bcopy(bf, wc + wc_end, size); 101867239Speter wc_end += size; 101967239Speter if (wc_end < WCSIZE) 102067239Speter return; 102167239Speter done = 1; 102267239Speter } 102367478Sjwd wtfsflush(); 102467239Speter if (done) 102567239Speter return; 10261558Srgrimes if (lseek(fso, (off_t)bno * sectorsize, SEEK_SET) < 0) { 102737239Sbde printf("seek error: %ld\n", (long)bno); 102837664Scharnier err(35, "wtfs"); 10291558Srgrimes } 10301558Srgrimes n = write(fso, bf, size); 10311558Srgrimes if (n != size) { 103237239Sbde printf("write error: %ld\n", (long)bno); 103337664Scharnier err(36, "wtfs"); 10341558Srgrimes } 10351558Srgrimes} 10361558Srgrimes 10371558Srgrimes/* 10381558Srgrimes * check if a block is available 10391558Srgrimes */ 104037664Scharnierint 104192711Siedowseisblock(struct fs *fs, unsigned char *cp, int h) 10421558Srgrimes{ 10431558Srgrimes unsigned char mask; 10441558Srgrimes 10451558Srgrimes switch (fs->fs_frag) { 10461558Srgrimes case 8: 10471558Srgrimes return (cp[h] == 0xff); 10481558Srgrimes case 4: 10491558Srgrimes mask = 0x0f << ((h & 0x1) << 2); 10501558Srgrimes return ((cp[h >> 1] & mask) == mask); 10511558Srgrimes case 2: 10521558Srgrimes mask = 0x03 << ((h & 0x3) << 1); 10531558Srgrimes return ((cp[h >> 2] & mask) == mask); 10541558Srgrimes case 1: 10551558Srgrimes mask = 0x01 << (h & 0x7); 10561558Srgrimes return ((cp[h >> 3] & mask) == mask); 10571558Srgrimes default: 10581558Srgrimes fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 10591558Srgrimes return (0); 10601558Srgrimes } 10611558Srgrimes} 10621558Srgrimes 10631558Srgrimes/* 10641558Srgrimes * take a block out of the map 10651558Srgrimes */ 106637664Scharniervoid 106792711Siedowseclrblock(struct fs *fs, unsigned char *cp, int h) 10681558Srgrimes{ 10691558Srgrimes switch ((fs)->fs_frag) { 10701558Srgrimes case 8: 10711558Srgrimes cp[h] = 0; 10721558Srgrimes return; 10731558Srgrimes case 4: 10741558Srgrimes cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 10751558Srgrimes return; 10761558Srgrimes case 2: 10771558Srgrimes cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 10781558Srgrimes return; 10791558Srgrimes case 1: 10801558Srgrimes cp[h >> 3] &= ~(0x01 << (h & 0x7)); 10811558Srgrimes return; 10821558Srgrimes default: 10831558Srgrimes fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 10841558Srgrimes return; 10851558Srgrimes } 10861558Srgrimes} 10871558Srgrimes 10881558Srgrimes/* 10891558Srgrimes * put a block into the map 10901558Srgrimes */ 109137664Scharniervoid 109292711Siedowsesetblock(struct fs *fs, unsigned char *cp, int h) 10931558Srgrimes{ 10941558Srgrimes switch (fs->fs_frag) { 10951558Srgrimes case 8: 10961558Srgrimes cp[h] = 0xff; 10971558Srgrimes return; 10981558Srgrimes case 4: 10991558Srgrimes cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 11001558Srgrimes return; 11011558Srgrimes case 2: 11021558Srgrimes cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 11031558Srgrimes return; 11041558Srgrimes case 1: 11051558Srgrimes cp[h >> 3] |= (0x01 << (h & 0x7)); 11061558Srgrimes return; 11071558Srgrimes default: 11081558Srgrimes fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 11091558Srgrimes return; 11101558Srgrimes } 11111558Srgrimes} 111213637Sjoerg 111313637Sjoerg/* 111413769Sjoerg * Determine the number of characters in a 111513637Sjoerg * single line. 111613637Sjoerg */ 111713637Sjoerg 111813637Sjoergstatic int 111992717Sphkcharsperline(void) 112013637Sjoerg{ 112113769Sjoerg int columns; 112213637Sjoerg char *cp; 112313637Sjoerg struct winsize ws; 112413637Sjoerg 112513637Sjoerg columns = 0; 112613637Sjoerg if (ioctl(0, TIOCGWINSZ, &ws) != -1) 112713637Sjoerg columns = ws.ws_col; 112813637Sjoerg if (columns == 0 && (cp = getenv("COLUMNS"))) 112913637Sjoerg columns = atoi(cp); 113013637Sjoerg if (columns == 0) 113113637Sjoerg columns = 80; /* last resort */ 113285860Sphk return (columns); 113313637Sjoerg} 113492712Siedowse 113592712Siedowsestatic int 113692712Siedowseilog2(int val) 113792712Siedowse{ 113892763Sphk u_int n; 113992712Siedowse 114092712Siedowse for (n = 0; n < sizeof(n) * NBBY; n++) 114192712Siedowse if (1 << n == val) 114292712Siedowse return (n); 114392712Siedowse errx(1, "ilog2: %d is not a power of 2\n", val); 114492712Siedowse} 1145