121137Sdist /* 221137Sdist * Copyright (c) 1980 Regents of the University of California. 321137Sdist * All rights reserved. The Berkeley software License Agreement 421137Sdist * specifies the terms and conditions for redistribution. 521137Sdist */ 621137Sdist 713604Ssam #ifndef lint 8*30691Skarels static char sccsid[] = "@(#)mkfs.c 6.3 (Berkeley) 03/29/87"; 921137Sdist #endif not lint 104234Smckusick 114234Smckusick /* 124234Smckusick * make file system for cylinder-group style file systems 134234Smckusick */ 144234Smckusick 154234Smckusick #ifndef STANDALONE 164234Smckusick #include <stdio.h> 174234Smckusick #include <a.out.h> 184234Smckusick #endif 194234Smckusick 206495Smckusick #include <sys/param.h> 216495Smckusick #include <sys/inode.h> 226495Smckusick #include <sys/fs.h> 2313604Ssam #include <sys/dir.h> 2430381Smckusick #include <sys/disklabel.h> 254234Smckusick 2630381Smckusick /* 2730381Smckusick * MAXBLKPG determines the maximum number of data blocks which are 2830381Smckusick * placed in a single cylinder group. This is currently a function 2930381Smckusick * of the block and fragment size of the file system. 3030381Smckusick */ 3130381Smckusick #define MAXBLKPG(fs) ((fs)->fs_fsize / sizeof(daddr_t)) 3230381Smckusick 335336Smckusic #define UMASK 0755 345346Smckusic #define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) 355336Smckusic #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 364234Smckusick 3730381Smckusick /* 3830381Smckusick * variables set up by front end. 3930381Smckusick */ 4030386Smckusick extern int Nflag; /* run mkfs without writing file system */ 4130386Smckusick extern int fssize; /* file system size */ 4230386Smckusick extern int ntracks; /* # tracks/cylinder */ 4330386Smckusick extern int nsectors; /* # sectors/track */ 4430386Smckusick extern int nphyssectors; /* # sectors/track including spares */ 4530386Smckusick extern int secpercyl; /* sectors per cylinder */ 4630386Smckusick extern int sectorsize; /* bytes/sector */ 4730386Smckusick extern int rpm; /* revolutions/minute of drive */ 4830386Smckusick extern int interleave; /* hardware sector interleave */ 4930386Smckusick extern int trackskew; /* sector 0 skew, per track */ 5030386Smckusick extern int headswitch; /* head switch time, usec */ 5130386Smckusick extern int trackseek; /* track-to-track seek, usec */ 5230386Smckusick extern int fsize; /* fragment size */ 5330386Smckusick extern int bsize; /* block size */ 5430386Smckusick extern int cpg; /* cylinders/cylinder group */ 5530386Smckusick extern int minfree; /* free space threshold */ 5630386Smckusick extern int opt; /* optimization preference (space or time) */ 5730386Smckusick extern int density; /* number of bytes per inode */ 5830386Smckusick extern int maxcontig; /* max contiguous blocks to allocate */ 5930386Smckusick extern int rotdelay; /* rotational delay between blocks */ 60*30691Skarels extern int bbsize; /* boot block size */ 61*30691Skarels extern int sbsize; /* superblock size */ 6230381Smckusick 634234Smckusick union { 644234Smckusick struct fs fs; 655324Smckusic char pad[MAXBSIZE]; 664234Smckusick } fsun; 674234Smckusick #define sblock fsun.fs 684234Smckusick struct csum *fscs; 694234Smckusick 704234Smckusick union { 714234Smckusick struct cg cg; 725324Smckusic char pad[MAXBSIZE]; 734234Smckusick } cgun; 744234Smckusick #define acg cgun.cg 754234Smckusick 765336Smckusic struct dinode zino[MAXIPG]; 775336Smckusic 7830381Smckusick int fsi, fso; 795336Smckusic time_t utime; 804234Smckusick daddr_t alloc(); 814234Smckusick 8230381Smckusick mkfs(pp, fsys, fi, fo) 8330381Smckusick struct partition *pp; 8430381Smckusick char *fsys; 8530381Smckusick int fi, fo; 864234Smckusick { 8730381Smckusick long cylno, rpos, blk, i, j, warn = 0; 884234Smckusick 895336Smckusic #ifndef STANDALONE 904234Smckusick time(&utime); 915336Smckusic #endif 9230381Smckusick fsi = fi; 9330381Smckusick fso = fo; 9412252Smckusick /* 9512252Smckusick * Validate the given file system size. 9612252Smckusick * Verify that its last block can actually be accessed. 9712252Smckusick */ 985336Smckusic if (fssize <= 0) 995336Smckusic printf("preposterous size %d\n", fssize), exit(1); 10030381Smckusick wtfs(fssize - 1, sectorsize, (char *)&sblock); 1015336Smckusic /* 1025336Smckusic * collect and verify the sector and track info 1035336Smckusic */ 10430381Smckusick sblock.fs_nsect = nsectors; 10530381Smckusick sblock.fs_ntrak = ntracks; 1065336Smckusic if (sblock.fs_ntrak <= 0) 1075336Smckusic printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 1085336Smckusic if (sblock.fs_nsect <= 0) 1095336Smckusic printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 11030381Smckusick sblock.fs_spc = secpercyl; 1115336Smckusic /* 1125336Smckusic * collect and verify the block and fragment sizes 1135336Smckusic */ 11430381Smckusick sblock.fs_bsize = bsize; 11530381Smckusick sblock.fs_fsize = fsize; 1165336Smckusic if (!POWEROF2(sblock.fs_bsize)) { 1175336Smckusic printf("block size must be a power of 2, not %d\n", 1185336Smckusic sblock.fs_bsize); 1194234Smckusick exit(1); 1204234Smckusick } 1215336Smckusic if (!POWEROF2(sblock.fs_fsize)) { 1225336Smckusic printf("fragment size must be a power of 2, not %d\n", 1235336Smckusic sblock.fs_fsize); 1244234Smckusick exit(1); 1254234Smckusick } 12630381Smckusick if (sblock.fs_fsize < sectorsize) { 1275324Smckusic printf("fragment size %d is too small, minimum is %d\n", 12830381Smckusick sblock.fs_fsize, sectorsize); 1295324Smckusic exit(1); 1305324Smckusic } 1315324Smckusic if (sblock.fs_bsize < MINBSIZE) { 1325324Smckusic printf("block size %d is too small, minimum is %d\n", 1335324Smckusic sblock.fs_bsize, MINBSIZE); 1345324Smckusic exit(1); 1355324Smckusic } 1365336Smckusic if (sblock.fs_bsize < sblock.fs_fsize) { 1375336Smckusic printf("block size (%d) cannot be smaller than fragment size (%d)\n", 1385336Smckusic sblock.fs_bsize, sblock.fs_fsize); 1394234Smckusick exit(1); 1404234Smckusick } 1415955Smckusic sblock.fs_bmask = ~(sblock.fs_bsize - 1); 1425955Smckusic sblock.fs_fmask = ~(sblock.fs_fsize - 1); 1435955Smckusic for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 1445955Smckusic sblock.fs_bshift++; 1455955Smckusic for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 1465955Smckusic sblock.fs_fshift++; 1475955Smckusic sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 14810076Smckusick for (sblock.fs_fragshift = 0, i = sblock.fs_frag; i > 1; i >>= 1) 14910076Smckusick sblock.fs_fragshift++; 1505336Smckusic if (sblock.fs_frag > MAXFRAG) { 1515336Smckusic printf("fragment size %d is too small, minimum with block size %d is %d\n", 1525336Smckusic sblock.fs_fsize, sblock.fs_bsize, 1535336Smckusic sblock.fs_bsize / MAXFRAG); 1545336Smckusic exit(1); 1554234Smckusick } 15610076Smckusick sblock.fs_nindir = sblock.fs_bsize / sizeof(daddr_t); 15710076Smckusick sblock.fs_inopb = sblock.fs_bsize / sizeof(struct dinode); 15830381Smckusick sblock.fs_nspf = sblock.fs_fsize / sectorsize; 15930381Smckusick for (sblock.fs_fsbtodb = 0, i = NSPF(&sblock); i > 1; i >>= 1) 16010076Smckusick sblock.fs_fsbtodb++; 1616532Smckusick sblock.fs_sblkno = 162*30691Skarels roundup(howmany(bbsize + sbsize, sblock.fs_fsize), sblock.fs_frag); 1636532Smckusick sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 164*30691Skarels roundup(howmany(sbsize, sblock.fs_fsize), sblock.fs_frag)); 1655362Smckusic sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 1666532Smckusick sblock.fs_cgoffset = roundup( 16730381Smckusick howmany(sblock.fs_nsect, NSPF(&sblock)), sblock.fs_frag); 1686532Smckusick for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) 1696532Smckusick sblock.fs_cgmask <<= 1; 1706532Smckusick if (!POWEROF2(sblock.fs_ntrak)) 1716532Smckusick sblock.fs_cgmask <<= 1; 1725399Smckusic for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 1735399Smckusic sblock.fs_cpc > 1 && (i & 1) == 0; 1745399Smckusic sblock.fs_cpc >>= 1, i >>= 1) 1755399Smckusic /* void */; 1765605Smckusic if (sblock.fs_cpc > MAXCPG) { 1775605Smckusic printf("maximum block size with nsect %d and ntrak %d is %d\n", 1785605Smckusic sblock.fs_nsect, sblock.fs_ntrak, 1795605Smckusic sblock.fs_bsize / (sblock.fs_cpc / MAXCPG)); 1805605Smckusic exit(1); 1815605Smckusic } 1825336Smckusic /* 1835336Smckusic * collect and verify the number of cylinders per group 1844234Smckusick */ 18530381Smckusick sblock.fs_cpg = cpg; 18630381Smckusick if (sblock.fs_cpg % sblock.fs_cpc != 0) { 18730381Smckusick sblock.fs_cpg -= sblock.fs_cpg % sblock.fs_cpc; 18830381Smckusick printf("%s groups must have a multiple of %d cylinders\n", 18930381Smckusick "Warning: cylinder", sblock.fs_cpc); 19030381Smckusick } 19130381Smckusick sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 19230381Smckusick while (sblock.fs_fpg / sblock.fs_frag > MAXBPG(&sblock) && 19330381Smckusick sblock.fs_cpg > sblock.fs_cpc) { 19430381Smckusick sblock.fs_cpg -= sblock.fs_cpc; 1955336Smckusic sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1964234Smckusick } 1975336Smckusic if (sblock.fs_cpg < 1) { 1985336Smckusic printf("cylinder groups must have at least 1 cylinder\n"); 1995336Smckusic exit(1); 20030381Smckusick } else if (sblock.fs_cpg > MAXCPG) { 2015336Smckusic printf("cylinder groups are limited to %d cylinders\n", MAXCPG); 2025336Smckusic exit(1); 20330381Smckusick } else if (sblock.fs_cpg < cpg) { 20430381Smckusick printf("%s: block size restricts cylinders per group to %d\n", 20530381Smckusick "Warning", sblock.fs_cpg); 2065336Smckusic } 2074234Smckusick /* 2085336Smckusic * Now have size for file system and nsect and ntrak. 2095336Smckusic * Determine number of cylinders and blocks in the file system. 2105336Smckusic */ 2115336Smckusic sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 2125336Smckusic sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 2135362Smckusic if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 2145362Smckusic sblock.fs_ncyl++; 2156532Smckusick warn = 1; 2165362Smckusic } 2175362Smckusic if (sblock.fs_ncyl < 1) { 2185362Smckusic printf("file systems must have at least one cylinder\n"); 2195336Smckusic exit(1); 2205336Smckusic } 2215336Smckusic /* 2225362Smckusic * determine feasability/values of rotational layout tables 2235362Smckusic */ 2245362Smckusic if (sblock.fs_ntrak == 1) { 2255362Smckusic sblock.fs_cpc = 0; 2265362Smckusic goto next; 2275362Smckusic } 2285362Smckusic if (sblock.fs_spc * sblock.fs_cpc > MAXBPC * NSPB(&sblock) || 2295362Smckusic sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { 2305362Smckusic printf("%s %s %d %s %d.%s", 2315362Smckusic "Warning: insufficient space in super block for\n", 2325362Smckusic "rotational layout tables with nsect", sblock.fs_nsect, 2335362Smckusic "and ntrak", sblock.fs_ntrak, 23418552Sbloom "\nFile system performance may be impaired.\n"); 2355362Smckusic sblock.fs_cpc = 0; 2365362Smckusic goto next; 2375362Smckusic } 2385362Smckusic /* 2395362Smckusic * calculate the available blocks for each rotational position 2405362Smckusic */ 24130386Smckusick sblock.fs_interleave = interleave; 24230386Smckusick sblock.fs_trackskew = trackskew; 24330386Smckusick sblock.fs_npsect = nphyssectors; 2445362Smckusic for (cylno = 0; cylno < MAXCPG; cylno++) 2455362Smckusic for (rpos = 0; rpos < NRPOS; rpos++) 2465362Smckusic sblock.fs_postbl[cylno][rpos] = -1; 2475362Smckusic blk = sblock.fs_spc * sblock.fs_cpc / NSPF(&sblock); 2485362Smckusic for (i = 0; i < blk; i += sblock.fs_frag) 2495362Smckusic /* void */; 2505362Smckusic for (i -= sblock.fs_frag; i >= 0; i -= sblock.fs_frag) { 2515362Smckusic cylno = cbtocylno(&sblock, i); 2525362Smckusic rpos = cbtorpos(&sblock, i); 2535362Smckusic blk = i / sblock.fs_frag; 2545362Smckusic if (sblock.fs_postbl[cylno][rpos] == -1) 2555362Smckusic sblock.fs_rotbl[blk] = 0; 2565362Smckusic else 2575362Smckusic sblock.fs_rotbl[blk] = 2585362Smckusic sblock.fs_postbl[cylno][rpos] - blk; 2595362Smckusic sblock.fs_postbl[cylno][rpos] = blk; 2605362Smckusic } 2615362Smckusic next: 2625362Smckusic /* 2635336Smckusic * Validate specified/determined cpg. 2645336Smckusic */ 2655336Smckusic if (sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) { 2665336Smckusic printf("too many sectors per cylinder (%d sectors)\n", 2675336Smckusic sblock.fs_spc); 2685336Smckusic while(sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) { 2695336Smckusic sblock.fs_bsize <<= 1; 2705336Smckusic if (sblock.fs_frag < MAXFRAG) 2715336Smckusic sblock.fs_frag <<= 1; 2725336Smckusic else 2735336Smckusic sblock.fs_fsize <<= 1; 2745336Smckusic } 2755336Smckusic printf("nsect %d, and ntrak %d, requires block size of %d,\n", 2765336Smckusic sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_bsize); 2775336Smckusic printf("\tand fragment size of %d\n", sblock.fs_fsize); 2785336Smckusic exit(1); 2795336Smckusic } 2805336Smckusic if (sblock.fs_fpg > MAXBPG(&sblock) * sblock.fs_frag) { 2815336Smckusic printf("cylinder group too large (%d cylinders); ", 2825336Smckusic sblock.fs_cpg); 2835362Smckusic printf("max: %d cylinders per group\n", 2845336Smckusic MAXBPG(&sblock) * sblock.fs_frag / 2855336Smckusic (sblock.fs_fpg / sblock.fs_cpg)); 2865336Smckusic exit(1); 2875336Smckusic } 2885955Smckusic sblock.fs_cgsize = fragroundup(&sblock, 2895955Smckusic sizeof(struct cg) + howmany(sblock.fs_fpg, NBBY)); 2905336Smckusic /* 2914234Smckusick * Compute/validate number of cylinder groups. 2924234Smckusick */ 2934234Smckusick sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 2944234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) 2954234Smckusick sblock.fs_ncg++; 2965336Smckusic if ((sblock.fs_spc * sblock.fs_cpg) % NSPF(&sblock)) { 2974234Smckusick printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 2984234Smckusick sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 2994234Smckusick printf("as this would would have cyl groups whose size\n"); 3005324Smckusic printf("is not a multiple of %d; choke!\n", sblock.fs_fsize); 3014234Smckusick exit(1); 3024234Smckusick } 3034234Smckusick /* 3044234Smckusick * Compute number of inode blocks per cylinder group. 30530381Smckusick * Start with one inode per density bytes; adjust as necessary. 3064234Smckusick */ 3075362Smckusic i = sblock.fs_iblkno + MAXIPG / INOPF(&sblock); 30830381Smckusick density = (fssize - sblock.fs_ncg * i) * sblock.fs_fsize / density / 30912437Smckusick INOPB(&sblock); 31030381Smckusick if (density <= 0) 31130381Smckusick density = 1; 31230381Smckusick sblock.fs_ipg = ((density / sblock.fs_ncg) + 1) * INOPB(&sblock); 3134234Smckusick if (sblock.fs_ipg > MAXIPG) 3144234Smckusick sblock.fs_ipg = MAXIPG; 3155362Smckusic sblock.fs_dblkno = sblock.fs_iblkno + sblock.fs_ipg / INOPF(&sblock); 3166532Smckusick i = MIN(~sblock.fs_cgmask, sblock.fs_ncg - 1); 3176532Smckusick if (cgdmin(&sblock, i) - cgbase(&sblock, i) >= sblock.fs_fpg) { 3184234Smckusick printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 3196532Smckusick cgdmin(&sblock, i) - cgbase(&sblock, i) / sblock.fs_frag, 3205324Smckusic sblock.fs_fpg / sblock.fs_frag); 3216532Smckusick printf("number of cylinders per cylinder group must be increased\n"); 3225324Smckusic exit(1); 3235324Smckusic } 3246532Smckusick j = sblock.fs_ncg - 1; 3256532Smckusick if ((i = fssize - j * sblock.fs_fpg) < sblock.fs_fpg && 3266532Smckusick cgdmin(&sblock, j) - cgbase(&sblock, j) > i) { 3276532Smckusick printf("Warning: inode blocks/cyl group (%d) >= data blocks (%d) in last\n", 3286532Smckusick (cgdmin(&sblock, j) - cgbase(&sblock, j)) / sblock.fs_frag, 3296532Smckusick i / sblock.fs_frag); 3306532Smckusick printf(" cylinder group. This implies %d sector(s) cannot be allocated.\n", 3316532Smckusick i * NSPF(&sblock)); 3326532Smckusick sblock.fs_ncg--; 3336532Smckusick sblock.fs_ncyl -= sblock.fs_ncyl % sblock.fs_cpg; 3346532Smckusick sblock.fs_size = fssize = sblock.fs_ncyl * sblock.fs_spc / 3356532Smckusick NSPF(&sblock); 3366532Smckusick warn = 0; 3376532Smckusick } 3386532Smckusick if (warn) { 3396532Smckusick printf("Warning: %d sector(s) in last cylinder unallocated\n", 3406532Smckusick sblock.fs_spc - 3416532Smckusick (fssize * NSPF(&sblock) - (sblock.fs_ncyl - 1) 3426532Smckusick * sblock.fs_spc)); 3436532Smckusick } 3445336Smckusic /* 3455336Smckusic * fill in remaining fields of the super block 3465336Smckusic */ 3475383Smckusic sblock.fs_csaddr = cgdmin(&sblock, 0); 3486532Smckusick sblock.fs_cssize = 3496532Smckusick fragroundup(&sblock, sblock.fs_ncg * sizeof(struct csum)); 35010076Smckusick i = sblock.fs_bsize / sizeof(struct csum); 35110076Smckusick sblock.fs_csmask = ~(i - 1); 35210076Smckusick for (sblock.fs_csshift = 0; i > 1; i >>= 1) 35310076Smckusick sblock.fs_csshift++; 35410076Smckusick i = sizeof(struct fs) + 35510076Smckusick howmany(sblock.fs_spc * sblock.fs_cpc, NSPB(&sblock)); 35610076Smckusick sblock.fs_sbsize = fragroundup(&sblock, i); 3576532Smckusick fscs = (struct csum *)calloc(1, sblock.fs_cssize); 3585362Smckusic sblock.fs_magic = FS_MAGIC; 35930381Smckusick sblock.fs_rotdelay = rotdelay; 36030381Smckusick sblock.fs_minfree = minfree; 36130381Smckusick sblock.fs_maxcontig = maxcontig; 36230386Smckusick sblock.fs_headswitch = headswitch; 36330386Smckusick sblock.fs_trkseek = trackseek; 3648259Smckusick sblock.fs_maxbpg = MAXBLKPG(&sblock); 36530381Smckusick sblock.fs_rps = rpm / 60; 36630381Smckusick sblock.fs_optim = opt; 3675336Smckusic sblock.fs_cgrotor = 0; 3685336Smckusic sblock.fs_cstotal.cs_ndir = 0; 3695336Smckusic sblock.fs_cstotal.cs_nbfree = 0; 3705336Smckusic sblock.fs_cstotal.cs_nifree = 0; 3715336Smckusic sblock.fs_cstotal.cs_nffree = 0; 3724234Smckusick sblock.fs_fmod = 0; 3734234Smckusick sblock.fs_ronly = 0; 3744234Smckusick /* 3755336Smckusic * Dump out summary information about file system. 3764234Smckusick */ 3774234Smckusick printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 3785336Smckusic fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 3795324Smckusic sblock.fs_ntrak, sblock.fs_nsect); 3804234Smckusick printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 3815324Smckusic (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg, 3825324Smckusic sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6, 3835324Smckusic sblock.fs_ipg); 3844234Smckusick /* 3854234Smckusick * Now build the cylinders group blocks and 3865336Smckusic * then print out indices of cylinder groups. 3874234Smckusick */ 3886532Smckusick printf("super-block backups (for fsck -b#) at:"); 3896532Smckusick for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 3905362Smckusic initcg(cylno); 3916532Smckusick if (cylno % 10 == 0) 3926532Smckusick printf("\n"); 3936532Smckusick printf(" %d,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); 3946532Smckusick } 39511525Ssam printf("\n"); 39616944Smckusick if (Nflag) 39716944Smckusick exit(0); 3984234Smckusick /* 3995336Smckusic * Now construct the initial file system, 4004234Smckusick * then write out the super-block. 4014234Smckusick */ 4025336Smckusic fsinit(); 4034234Smckusick sblock.fs_time = utime; 404*30691Skarels wtfs(SBOFF / sectorsize, sbsize, (char *)&sblock); 4055324Smckusic for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 4065955Smckusic wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 4076532Smckusick sblock.fs_cssize - i < sblock.fs_bsize ? 4086532Smckusick sblock.fs_cssize - i : sblock.fs_bsize, 4096532Smckusick ((char *)fscs) + i); 4105336Smckusic /* 4115336Smckusic * Write out the duplicate super blocks 4125336Smckusic */ 4138295Smckusick for (cylno = 0; cylno < sblock.fs_ncg; cylno++) 4146532Smckusick wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 415*30691Skarels sbsize, (char *)&sblock); 41630381Smckusick /* 41730381Smckusick * Update information about this partion in pack 41830381Smckusick * label, to that it may be updated on disk. 41930381Smckusick */ 42030381Smckusick pp->p_fstype = FS_BSDFFS; 42130381Smckusick pp->p_fsize = sblock.fs_fsize; 42230381Smckusick pp->p_frag = sblock.fs_frag; 42330381Smckusick pp->p_cpg = sblock.fs_cpg; 4244234Smckusick } 4254234Smckusick 4264234Smckusick /* 4274234Smckusick * Initialize a cylinder group. 4284234Smckusick */ 4295362Smckusic initcg(cylno) 4305362Smckusic int cylno; 4314234Smckusick { 4326532Smckusick daddr_t cbase, d, dlower, dupper, dmax; 4334234Smckusick long i, j, s; 4344234Smckusick register struct csum *cs; 4354234Smckusick 4364234Smckusick /* 4374234Smckusick * Determine block bounds for cylinder group. 4384234Smckusick * Allow space for super block summary information in first 4394234Smckusick * cylinder group. 4404234Smckusick */ 4415383Smckusic cbase = cgbase(&sblock, cylno); 4424234Smckusick dmax = cbase + sblock.fs_fpg; 4434234Smckusick if (dmax > sblock.fs_size) 4444234Smckusick dmax = sblock.fs_size; 4456532Smckusick dlower = cgsblock(&sblock, cylno) - cbase; 4466532Smckusick dupper = cgdmin(&sblock, cylno) - cbase; 4475362Smckusic cs = fscs + cylno; 4484234Smckusick acg.cg_time = utime; 4494234Smckusick acg.cg_magic = CG_MAGIC; 4505362Smckusic acg.cg_cgx = cylno; 4518139Smckusick if (cylno == sblock.fs_ncg - 1) 4528139Smckusick acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 4538139Smckusick else 4548139Smckusick acg.cg_ncyl = sblock.fs_cpg; 4554234Smckusick acg.cg_niblk = sblock.fs_ipg; 4564234Smckusick acg.cg_ndblk = dmax - cbase; 4574788Smckusic acg.cg_cs.cs_ndir = 0; 4584788Smckusic acg.cg_cs.cs_nffree = 0; 4594788Smckusic acg.cg_cs.cs_nbfree = 0; 4604788Smckusic acg.cg_cs.cs_nifree = 0; 4616532Smckusick acg.cg_rotor = 0; 4626532Smckusick acg.cg_frotor = 0; 4634257Smckusic acg.cg_irotor = 0; 4645324Smckusic for (i = 0; i < sblock.fs_frag; i++) { 4654465Smckusic acg.cg_frsum[i] = 0; 4664465Smckusic } 4674465Smckusic for (i = 0; i < sblock.fs_ipg; ) { 4685324Smckusic for (j = INOPB(&sblock); j > 0; j--) { 4694234Smckusick clrbit(acg.cg_iused, i); 4704234Smckusick i++; 4714234Smckusick } 4725324Smckusic acg.cg_cs.cs_nifree += INOPB(&sblock); 4734234Smckusick } 4745362Smckusic if (cylno == 0) 4755336Smckusic for (i = 0; i < ROOTINO; i++) { 4765336Smckusic setbit(acg.cg_iused, i); 4775336Smckusic acg.cg_cs.cs_nifree--; 4785336Smckusic } 4794234Smckusick while (i < MAXIPG) { 4804234Smckusick clrbit(acg.cg_iused, i); 4814234Smckusick i++; 4824234Smckusick } 48316944Smckusick wtfs(fsbtodb(&sblock, cgimin(&sblock, cylno)), 48416944Smckusick sblock.fs_ipg * sizeof (struct dinode), (char *)zino); 4855370Smckusic for (i = 0; i < MAXCPG; i++) { 4865370Smckusic acg.cg_btot[i] = 0; 4874234Smckusick for (j = 0; j < NRPOS; j++) 4884234Smckusick acg.cg_b[i][j] = 0; 4895370Smckusic } 4905362Smckusic if (cylno == 0) { 4916532Smckusick /* 4926532Smckusick * reserve space for summary info and Boot block 4936532Smckusick */ 4946532Smckusick dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 4956532Smckusick for (d = 0; d < dlower; d += sblock.fs_frag) 4966532Smckusick clrblock(&sblock, acg.cg_free, d/sblock.fs_frag); 4976532Smckusick } else { 4986532Smckusick for (d = 0; d < dlower; d += sblock.fs_frag) { 4996532Smckusick setblock(&sblock, acg.cg_free, d/sblock.fs_frag); 5006532Smckusick acg.cg_cs.cs_nbfree++; 5016532Smckusick acg.cg_btot[cbtocylno(&sblock, d)]++; 5026532Smckusick acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++; 5036532Smckusick } 5046532Smckusick sblock.fs_dsize += dlower; 5054234Smckusick } 5066532Smckusick sblock.fs_dsize += acg.cg_ndblk - dupper; 5076532Smckusick for (; d < dupper; d += sblock.fs_frag) 5085324Smckusic clrblock(&sblock, acg.cg_free, d/sblock.fs_frag); 5096532Smckusick if (d > dupper) { 5106532Smckusick acg.cg_frsum[d - dupper]++; 5116532Smckusick for (i = d - 1; i >= dupper; i--) { 5126532Smckusick setbit(acg.cg_free, i); 5136532Smckusick acg.cg_cs.cs_nffree++; 5146532Smckusick } 5156532Smckusick } 5166532Smckusick while ((d + sblock.fs_frag) <= dmax - cbase) { 5175324Smckusic setblock(&sblock, acg.cg_free, d/sblock.fs_frag); 5184788Smckusic acg.cg_cs.cs_nbfree++; 5195370Smckusic acg.cg_btot[cbtocylno(&sblock, d)]++; 5205362Smckusic acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++; 5215324Smckusic d += sblock.fs_frag; 5224234Smckusick } 5236532Smckusick if (d < dmax - cbase) { 5245362Smckusic acg.cg_frsum[dmax - cbase - d]++; 5254251Smckusic for (; d < dmax - cbase; d++) { 5264251Smckusic setbit(acg.cg_free, d); 5274788Smckusic acg.cg_cs.cs_nffree++; 5284251Smckusic } 5298139Smckusick for (; d % sblock.fs_frag != 0; d++) 5308139Smckusick clrbit(acg.cg_free, d); 5316532Smckusick } 5328139Smckusick for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++) 5338139Smckusick clrblock(&sblock, acg.cg_free, d); 5344788Smckusic sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 5354788Smckusic sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 5364788Smckusic sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 5374788Smckusic sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 5384788Smckusic *cs = acg.cg_cs; 5395383Smckusic wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 5405324Smckusic sblock.fs_bsize, (char *)&acg); 5414234Smckusick } 5424234Smckusick 5435336Smckusic /* 5445336Smckusic * initialize the file system 5455336Smckusic */ 5465336Smckusic struct inode node; 54730381Smckusick 54830381Smckusick #ifdef LOSTDIR 5495336Smckusic #define PREDEFDIR 3 55030381Smckusick #else 55130381Smckusick #define PREDEFDIR 2 55230381Smckusick #endif 55330381Smckusick 5545934Smckusic struct direct root_dir[] = { 5555934Smckusic { ROOTINO, sizeof(struct direct), 1, "." }, 5565934Smckusic { ROOTINO, sizeof(struct direct), 2, ".." }, 55730381Smckusick #ifdef LOSTDIR 5585934Smckusic { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 55930381Smckusick #endif 5605336Smckusic }; 56130381Smckusick #ifdef LOSTDIR 5625934Smckusic struct direct lost_found_dir[] = { 5635934Smckusic { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 5645934Smckusic { ROOTINO, sizeof(struct direct), 2, ".." }, 5655934Smckusic { 0, DIRBLKSIZ, 0, 0 }, 5665336Smckusic }; 56730381Smckusick #endif 5685934Smckusic char buf[MAXBSIZE]; 5695336Smckusic 5705336Smckusic fsinit() 5714234Smckusick { 5725934Smckusic int i; 5735934Smckusic 5744234Smckusick /* 5755336Smckusic * initialize the node 5764234Smckusick */ 5775336Smckusic node.i_atime = utime; 5785336Smckusic node.i_mtime = utime; 5795336Smckusic node.i_ctime = utime; 58030381Smckusick #ifdef LOSTDIR 5814234Smckusick /* 5825336Smckusic * create the lost+found directory 5834234Smckusick */ 5845934Smckusic (void)makedir(lost_found_dir, 2); 5855934Smckusic for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 5865934Smckusic bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2])); 5875336Smckusic node.i_number = LOSTFOUNDINO; 5885336Smckusic node.i_mode = IFDIR | UMASK; 5895336Smckusic node.i_nlink = 2; 5905336Smckusic node.i_size = sblock.fs_bsize; 5915336Smckusic node.i_db[0] = alloc(node.i_size, node.i_mode); 59214323Smckusick node.i_blocks = btodb(fragroundup(&sblock, node.i_size)); 5935934Smckusic wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, buf); 5945336Smckusic iput(&node); 59530381Smckusick #endif 5965336Smckusic /* 5975336Smckusic * create the root directory 5985336Smckusic */ 5995336Smckusic node.i_number = ROOTINO; 6005336Smckusic node.i_mode = IFDIR | UMASK; 6015336Smckusic node.i_nlink = PREDEFDIR; 6025934Smckusic node.i_size = makedir(root_dir, PREDEFDIR); 6035336Smckusic node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode); 60414323Smckusick node.i_blocks = btodb(fragroundup(&sblock, node.i_size)); 6055934Smckusic wtfs(fsbtodb(&sblock, node.i_db[0]), sblock.fs_fsize, buf); 6065336Smckusic iput(&node); 6074234Smckusick } 6084234Smckusick 6095336Smckusic /* 6105934Smckusic * construct a set of directory entries in "buf". 6115934Smckusic * return size of directory. 6125934Smckusic */ 6135934Smckusic makedir(protodir, entries) 6145934Smckusic register struct direct *protodir; 6155934Smckusic int entries; 6165934Smckusic { 6175934Smckusic char *cp; 6185934Smckusic int i, spcleft; 6195934Smckusic 6205934Smckusic spcleft = DIRBLKSIZ; 6215934Smckusic for (cp = buf, i = 0; i < entries - 1; i++) { 6225934Smckusic protodir[i].d_reclen = DIRSIZ(&protodir[i]); 6235934Smckusic bcopy(&protodir[i], cp, protodir[i].d_reclen); 6245934Smckusic cp += protodir[i].d_reclen; 6255934Smckusic spcleft -= protodir[i].d_reclen; 6265934Smckusic } 6275934Smckusic protodir[i].d_reclen = spcleft; 6285934Smckusic bcopy(&protodir[i], cp, DIRSIZ(&protodir[i])); 62923848Smckusick return (DIRBLKSIZ); 6305934Smckusic } 6315934Smckusic 6325934Smckusic /* 6335336Smckusic * allocate a block or frag 6345336Smckusic */ 6354234Smckusick daddr_t 6364427Smckusic alloc(size, mode) 6374427Smckusic int size; 6384427Smckusic int mode; 6394234Smckusick { 6405362Smckusic int i, frag; 6414234Smckusick daddr_t d; 6424234Smckusick 6435955Smckusic rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 6445955Smckusic (char *)&acg); 6456532Smckusick if (acg.cg_magic != CG_MAGIC) { 6466532Smckusick printf("cg 0: bad magic number\n"); 6476532Smckusick return (0); 6486532Smckusick } 6494788Smckusic if (acg.cg_cs.cs_nbfree == 0) { 6504234Smckusick printf("first cylinder group ran out of space\n"); 6514234Smckusick return (0); 6524234Smckusick } 6535324Smckusic for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 6545324Smckusic if (isblock(&sblock, acg.cg_free, d / sblock.fs_frag)) 6554234Smckusick goto goth; 6564234Smckusick printf("internal error: can't find block in cyl 0\n"); 6574234Smckusick return (0); 6584234Smckusick goth: 6595324Smckusic clrblock(&sblock, acg.cg_free, d / sblock.fs_frag); 6604788Smckusic acg.cg_cs.cs_nbfree--; 6614788Smckusic sblock.fs_cstotal.cs_nbfree--; 6624234Smckusick fscs[0].cs_nbfree--; 6634427Smckusic if (mode & IFDIR) { 6644788Smckusic acg.cg_cs.cs_ndir++; 6654788Smckusic sblock.fs_cstotal.cs_ndir++; 6664427Smckusic fscs[0].cs_ndir++; 6674427Smckusic } 6685370Smckusic acg.cg_btot[cbtocylno(&sblock, d)]--; 6695362Smckusic acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--; 6705324Smckusic if (size != sblock.fs_bsize) { 6715324Smckusic frag = howmany(size, sblock.fs_fsize); 6725324Smckusic fscs[0].cs_nffree += sblock.fs_frag - frag; 6735324Smckusic sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 6745324Smckusic acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 6755324Smckusic acg.cg_frsum[sblock.fs_frag - frag]++; 6765324Smckusic for (i = frag; i < sblock.fs_frag; i++) 6776532Smckusick setbit(acg.cg_free, d + i); 6784234Smckusick } 6795955Smckusic wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 6805955Smckusic (char *)&acg); 6814234Smckusick return (d); 6824234Smckusick } 6834234Smckusick 6845336Smckusic /* 6855336Smckusic * Allocate an inode on the disk 6865336Smckusic */ 6875336Smckusic iput(ip) 6885336Smckusic register struct inode *ip; 6894234Smckusick { 6905336Smckusic struct dinode buf[MAXINOPB]; 6915336Smckusic daddr_t d; 6925336Smckusic int c; 6934234Smckusick 6945383Smckusic c = itog(&sblock, ip->i_number); 6955955Smckusic rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 6965955Smckusic (char *)&acg); 6976532Smckusick if (acg.cg_magic != CG_MAGIC) { 6986532Smckusick printf("cg 0: bad magic number\n"); 6996532Smckusick exit(1); 7006532Smckusick } 7015336Smckusic acg.cg_cs.cs_nifree--; 7025336Smckusic setbit(acg.cg_iused, ip->i_number); 7035955Smckusic wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 7045955Smckusic (char *)&acg); 7055336Smckusic sblock.fs_cstotal.cs_nifree--; 7065336Smckusic fscs[0].cs_nifree--; 7075336Smckusic if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 7085336Smckusic printf("fsinit: inode value out of range (%d).\n", 7095336Smckusic ip->i_number); 7105336Smckusic exit(1); 7115336Smckusic } 7125383Smckusic d = fsbtodb(&sblock, itod(&sblock, ip->i_number)); 7135336Smckusic rdfs(d, sblock.fs_bsize, buf); 7145383Smckusic buf[itoo(&sblock, ip->i_number)].di_ic = ip->i_ic; 7155336Smckusic wtfs(d, sblock.fs_bsize, buf); 7164234Smckusick } 7174234Smckusick 7185336Smckusic /* 7195336Smckusic * read a block from the file system 7205336Smckusic */ 7215336Smckusic rdfs(bno, size, bf) 7225336Smckusic daddr_t bno; 7234427Smckusic int size; 7245336Smckusic char *bf; 7254234Smckusick { 7265336Smckusic int n; 7274234Smckusick 72830381Smckusick if (lseek(fsi, bno * sectorsize, 0) < 0) { 7295346Smckusic printf("seek error: %ld\n", bno); 7305346Smckusic perror("rdfs"); 7315346Smckusic exit(1); 7325346Smckusic } 7335336Smckusic n = read(fsi, bf, size); 7345336Smckusic if(n != size) { 7355336Smckusic printf("read error: %ld\n", bno); 7365346Smckusic perror("rdfs"); 7375336Smckusic exit(1); 7384234Smckusick } 7394234Smckusick } 7404234Smckusick 7415336Smckusic /* 7425336Smckusic * write a block to the file system 7435336Smckusic */ 7445336Smckusic wtfs(bno, size, bf) 7455336Smckusic daddr_t bno; 7465336Smckusic int size; 7475336Smckusic char *bf; 7484234Smckusick { 7495336Smckusic int n; 7504234Smckusick 75116944Smckusick if (Nflag) 75216944Smckusick return; 75330381Smckusick if (lseek(fso, bno * sectorsize, 0) < 0) { 7545346Smckusic printf("seek error: %ld\n", bno); 7555346Smckusic perror("wtfs"); 7565346Smckusic exit(1); 7575346Smckusic } 7585336Smckusic n = write(fso, bf, size); 7595336Smckusic if(n != size) { 7605336Smckusic printf("write error: %D\n", bno); 7615346Smckusic perror("wtfs"); 7624234Smckusick exit(1); 7634234Smckusick } 7644234Smckusick } 7655324Smckusic 7665324Smckusic /* 7675336Smckusic * check if a block is available 7685324Smckusic */ 7695324Smckusic isblock(fs, cp, h) 7705324Smckusic struct fs *fs; 7715324Smckusic unsigned char *cp; 7725324Smckusic int h; 7735324Smckusic { 7745324Smckusic unsigned char mask; 7755324Smckusic 7765324Smckusic switch (fs->fs_frag) { 7775324Smckusic case 8: 7785324Smckusic return (cp[h] == 0xff); 7795324Smckusic case 4: 7805324Smckusic mask = 0x0f << ((h & 0x1) << 2); 7815324Smckusic return ((cp[h >> 1] & mask) == mask); 7825324Smckusic case 2: 7835324Smckusic mask = 0x03 << ((h & 0x3) << 1); 7845324Smckusic return ((cp[h >> 2] & mask) == mask); 7855324Smckusic case 1: 7865324Smckusic mask = 0x01 << (h & 0x7); 7875324Smckusic return ((cp[h >> 3] & mask) == mask); 7885324Smckusic default: 7898140Smckusick #ifdef STANDALONE 7908140Smckusick printf("isblock bad fs_frag %d\n", fs->fs_frag); 7918140Smckusick #else 7925324Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 7938140Smckusick #endif 7945324Smckusic return; 7955324Smckusic } 7965324Smckusic } 7975324Smckusic 7985336Smckusic /* 7995336Smckusic * take a block out of the map 8005336Smckusic */ 8015324Smckusic clrblock(fs, cp, h) 8025324Smckusic struct fs *fs; 8035324Smckusic unsigned char *cp; 8045324Smckusic int h; 8055324Smckusic { 8065324Smckusic switch ((fs)->fs_frag) { 8075324Smckusic case 8: 8085324Smckusic cp[h] = 0; 8095324Smckusic return; 8105324Smckusic case 4: 8115324Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 8125324Smckusic return; 8135324Smckusic case 2: 8145324Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 8155324Smckusic return; 8165324Smckusic case 1: 8175324Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 8185324Smckusic return; 8195324Smckusic default: 8208140Smckusick #ifdef STANDALONE 8218140Smckusick printf("clrblock bad fs_frag %d\n", fs->fs_frag); 8228140Smckusick #else 8235324Smckusic fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 8248140Smckusick #endif 8255324Smckusic return; 8265324Smckusic } 8275324Smckusic } 8285324Smckusic 8295336Smckusic /* 8305336Smckusic * put a block into the map 8315336Smckusic */ 8325324Smckusic setblock(fs, cp, h) 8335324Smckusic struct fs *fs; 8345324Smckusic unsigned char *cp; 8355324Smckusic int h; 8365324Smckusic { 8375324Smckusic switch (fs->fs_frag) { 8385324Smckusic case 8: 8395324Smckusic cp[h] = 0xff; 8405324Smckusic return; 8415324Smckusic case 4: 8425324Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 8435324Smckusic return; 8445324Smckusic case 2: 8455324Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 8465324Smckusic return; 8475324Smckusic case 1: 8485324Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 8495324Smckusic return; 8505324Smckusic default: 8518140Smckusick #ifdef STANDALONE 8528140Smckusick printf("setblock bad fs_frag %d\n", fs->fs_frag); 8538140Smckusick #else 8545324Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 8558140Smckusick #endif 8565324Smckusic return; 8575324Smckusic } 8585324Smckusic } 859