1*8140Smckusick static char *sccsid = "@(#)mkfs.c 2.4 (Berkeley) 09/10/82"; 24234Smckusick 34234Smckusick /* 44234Smckusick * make file system for cylinder-group style file systems 54234Smckusick * 65336Smckusic * usage: mkfs special size [ nsect ntrak bsize fsize cpg ] 74234Smckusick */ 84234Smckusick 94234Smckusick #ifndef STANDALONE 104234Smckusick #include <stdio.h> 114234Smckusick #include <a.out.h> 124234Smckusick #endif 134234Smckusick 146495Smckusick #ifndef SIMFS 156495Smckusick #include <sys/param.h> 166495Smckusick #include <sys/inode.h> 176495Smckusick #include <sys/fs.h> 186495Smckusick #else 194234Smckusick #include "../h/param.h" 204234Smckusick #include "../h/inode.h" 214234Smckusick #include "../h/fs.h" 226495Smckusick #endif 238139Smckusick #include <dir.h> 244234Smckusick 255336Smckusic #define UMASK 0755 265346Smckusic #define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) 275336Smckusic #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 284234Smckusick 294234Smckusick union { 304234Smckusick struct fs fs; 315324Smckusic char pad[MAXBSIZE]; 324234Smckusick } fsun; 334234Smckusick #define sblock fsun.fs 344234Smckusick struct csum *fscs; 354234Smckusick 364234Smckusick union { 374234Smckusick struct cg cg; 385324Smckusic char pad[MAXBSIZE]; 394234Smckusick } cgun; 404234Smckusick #define acg cgun.cg 414234Smckusick 425336Smckusic struct dinode zino[MAXIPG]; 435336Smckusic 444234Smckusick char *fsys; 455336Smckusic time_t utime; 465336Smckusic int fsi; 475336Smckusic int fso; 484234Smckusick daddr_t alloc(); 494234Smckusick 504234Smckusick main(argc, argv) 515324Smckusic int argc; 525324Smckusic char *argv[]; 534234Smckusick { 546532Smckusick long cylno, rpos, blk, i, j, inos, fssize, warn = 0; 554234Smckusick 565336Smckusic #ifndef STANDALONE 574234Smckusick argc--, argv++; 584234Smckusick time(&utime); 595336Smckusic if (argc < 2) { 605336Smckusic printf("usage: mkfs special size [ nsect ntrak bsize fsize cpg ]\n"); 614234Smckusick exit(1); 624234Smckusick } 634234Smckusick fsys = argv[0]; 645336Smckusic fssize = atoi(argv[1]); 655336Smckusic fso = creat(fsys, 0666); 665336Smckusic if(fso < 0) { 675336Smckusic printf("%s: cannot create\n", fsys); 685336Smckusic exit(1); 695336Smckusic } 705336Smckusic fsi = open(fsys, 0); 715336Smckusic if(fsi < 0) { 725336Smckusic printf("%s: cannot open\n", fsys); 735336Smckusic exit(1); 745336Smckusic } 754234Smckusick #else 764234Smckusick { 774234Smckusick static char protos[60]; 785336Smckusic char fsbuf[100]; 794234Smckusick 804234Smckusick printf("file sys size: "); 814234Smckusick gets(protos); 825336Smckusic fssize = atoi(protos); 834234Smckusick do { 844234Smckusick printf("file system: "); 854234Smckusick gets(fsbuf); 864234Smckusick fso = open(fsbuf, 1); 874234Smckusick fsi = open(fsbuf, 0); 884234Smckusick } while (fso < 0 || fsi < 0); 894234Smckusick } 904234Smckusick argc = 0; 915336Smckusic #endif 925336Smckusic if (fssize <= 0) 935336Smckusic printf("preposterous size %d\n", fssize), exit(1); 945336Smckusic /* 955336Smckusic * collect and verify the sector and track info 965336Smckusic */ 975336Smckusic if (argc > 2) 985336Smckusic sblock.fs_nsect = atoi(argv[2]); 995336Smckusic else 1005336Smckusic sblock.fs_nsect = DFLNSECT; 1015336Smckusic if (argc > 3) 1025336Smckusic sblock.fs_ntrak = atoi(argv[3]); 1035336Smckusic else 1045336Smckusic sblock.fs_ntrak = DFLNTRAK; 1055336Smckusic if (sblock.fs_ntrak <= 0) 1065336Smckusic printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 1075336Smckusic if (sblock.fs_nsect <= 0) 1085336Smckusic printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 1095336Smckusic sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 1105336Smckusic /* 1115336Smckusic * collect and verify the block and fragment sizes 1125336Smckusic */ 1135336Smckusic if (argc > 4) 1145336Smckusic sblock.fs_bsize = atoi(argv[4]); 1155336Smckusic else 1165336Smckusic sblock.fs_bsize = MAXBSIZE; 1175336Smckusic if (argc > 5) 1185336Smckusic sblock.fs_fsize = atoi(argv[5]); 1195336Smckusic else 1205336Smckusic sblock.fs_fsize = MAX(sblock.fs_bsize / DESFRAG, DEV_BSIZE); 1215336Smckusic if (!POWEROF2(sblock.fs_bsize)) { 1225336Smckusic printf("block size must be a power of 2, not %d\n", 1235336Smckusic sblock.fs_bsize); 1244234Smckusick exit(1); 1254234Smckusick } 1265336Smckusic if (!POWEROF2(sblock.fs_fsize)) { 1275336Smckusic printf("fragment size must be a power of 2, not %d\n", 1285336Smckusic sblock.fs_fsize); 1294234Smckusick exit(1); 1304234Smckusick } 1315324Smckusic if (sblock.fs_fsize < DEV_BSIZE) { 1325324Smckusic printf("fragment size %d is too small, minimum is %d\n", 1335324Smckusic sblock.fs_fsize, DEV_BSIZE); 1345324Smckusic exit(1); 1355324Smckusic } 1365324Smckusic if (sblock.fs_bsize < MINBSIZE) { 1375324Smckusic printf("block size %d is too small, minimum is %d\n", 1385324Smckusic sblock.fs_bsize, MINBSIZE); 1395324Smckusic exit(1); 1405324Smckusic } 1415336Smckusic if (sblock.fs_bsize < sblock.fs_fsize) { 1425336Smckusic printf("block size (%d) cannot be smaller than fragment size (%d)\n", 1435336Smckusic sblock.fs_bsize, sblock.fs_fsize); 1444234Smckusick exit(1); 1454234Smckusick } 1465955Smckusic sblock.fs_bmask = ~(sblock.fs_bsize - 1); 1475955Smckusic sblock.fs_fmask = ~(sblock.fs_fsize - 1); 1485955Smckusic for (sblock.fs_bshift = 0, i = sblock.fs_bsize; i > 1; i >>= 1) 1495955Smckusic sblock.fs_bshift++; 1505955Smckusic for (sblock.fs_fshift = 0, i = sblock.fs_fsize; i > 1; i >>= 1) 1515955Smckusic sblock.fs_fshift++; 1525955Smckusic sblock.fs_frag = numfrags(&sblock, sblock.fs_bsize); 1535336Smckusic if (sblock.fs_frag > MAXFRAG) { 1545336Smckusic printf("fragment size %d is too small, minimum with block size %d is %d\n", 1555336Smckusic sblock.fs_fsize, sblock.fs_bsize, 1565336Smckusic sblock.fs_bsize / MAXFRAG); 1575336Smckusic exit(1); 1584234Smckusick } 1596532Smckusick sblock.fs_sblkno = 1605362Smckusic roundup(howmany(BBSIZE + SBSIZE, sblock.fs_fsize), sblock.fs_frag); 1616532Smckusick sblock.fs_cblkno = (daddr_t)(sblock.fs_sblkno + 1626532Smckusick roundup(howmany(SBSIZE, sblock.fs_fsize), sblock.fs_frag)); 1635362Smckusic sblock.fs_iblkno = sblock.fs_cblkno + sblock.fs_frag; 1646532Smckusick sblock.fs_cgoffset = roundup( 1656532Smckusick howmany(sblock.fs_nsect, sblock.fs_fsize / DEV_BSIZE), 1666532Smckusick sblock.fs_frag); 1676532Smckusick for (sblock.fs_cgmask = 0xffffffff, i = sblock.fs_ntrak; i > 1; i >>= 1) 1686532Smckusick sblock.fs_cgmask <<= 1; 1696532Smckusick if (!POWEROF2(sblock.fs_ntrak)) 1706532Smckusick sblock.fs_cgmask <<= 1; 1715399Smckusic for (sblock.fs_cpc = NSPB(&sblock), i = sblock.fs_spc; 1725399Smckusic sblock.fs_cpc > 1 && (i & 1) == 0; 1735399Smckusic sblock.fs_cpc >>= 1, i >>= 1) 1745399Smckusic /* void */; 1755605Smckusic if (sblock.fs_cpc > MAXCPG) { 1765605Smckusic printf("maximum block size with nsect %d and ntrak %d is %d\n", 1775605Smckusic sblock.fs_nsect, sblock.fs_ntrak, 1785605Smckusic sblock.fs_bsize / (sblock.fs_cpc / MAXCPG)); 1795605Smckusic exit(1); 1805605Smckusic } 1815336Smckusic /* 1825336Smckusic * collect and verify the number of cylinders per group 1834234Smckusick */ 1845336Smckusic if (argc > 6) { 1855336Smckusic sblock.fs_cpg = atoi(argv[6]); 1865336Smckusic sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1874234Smckusick } else { 1885399Smckusic sblock.fs_cpg = MAX(sblock.fs_cpc, DESCPG); 1895336Smckusic sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1905605Smckusic while (sblock.fs_fpg / sblock.fs_frag > MAXBPG(&sblock) && 1915605Smckusic sblock.fs_cpg > sblock.fs_cpc) { 1925605Smckusic sblock.fs_cpg -= sblock.fs_cpc; 1935336Smckusic sblock.fs_fpg = 1945336Smckusic (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1955336Smckusic } 1964234Smckusick } 1975336Smckusic if (sblock.fs_cpg < 1) { 1985336Smckusic printf("cylinder groups must have at least 1 cylinder\n"); 1995336Smckusic exit(1); 2005336Smckusic } 2015336Smckusic if (sblock.fs_cpg > MAXCPG) { 2025336Smckusic printf("cylinder groups are limited to %d cylinders\n", MAXCPG); 2035336Smckusic exit(1); 2045336Smckusic } 2055399Smckusic if (sblock.fs_cpg % sblock.fs_cpc != 0) { 2065399Smckusic printf("cylinder groups must have a multiple of %d cylinders\n", 2075399Smckusic sblock.fs_cpc); 2085399Smckusic exit(1); 2095399Smckusic } 2104234Smckusick /* 2115336Smckusic * Now have size for file system and nsect and ntrak. 2125336Smckusic * Determine number of cylinders and blocks in the file system. 2135336Smckusic */ 2145336Smckusic sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 2155336Smckusic sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 2165362Smckusic if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 2175362Smckusic sblock.fs_ncyl++; 2186532Smckusick warn = 1; 2195362Smckusic } 2205362Smckusic if (sblock.fs_ncyl < 1) { 2215362Smckusic printf("file systems must have at least one cylinder\n"); 2225336Smckusic exit(1); 2235336Smckusic } 2245336Smckusic /* 2255362Smckusic * determine feasability/values of rotational layout tables 2265362Smckusic */ 2275362Smckusic if (sblock.fs_ntrak == 1) { 2285362Smckusic sblock.fs_cpc = 0; 2295362Smckusic goto next; 2305362Smckusic } 2315362Smckusic if (sblock.fs_spc * sblock.fs_cpc > MAXBPC * NSPB(&sblock) || 2325362Smckusic sblock.fs_nsect > (1 << NBBY) * NSPB(&sblock)) { 2335362Smckusic printf("%s %s %d %s %d.%s", 2345362Smckusic "Warning: insufficient space in super block for\n", 2355362Smckusic "rotational layout tables with nsect", sblock.fs_nsect, 2365362Smckusic "and ntrak", sblock.fs_ntrak, 2375362Smckusic "\nFile system performance may be impared.\n"); 2385362Smckusic sblock.fs_cpc = 0; 2395362Smckusic goto next; 2405362Smckusic } 2415362Smckusic /* 2425362Smckusic * calculate the available blocks for each rotational position 2435362Smckusic */ 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. 3054234Smckusick * Start with one inode per NBPI bytes; adjust as necessary. 3064234Smckusick */ 3075362Smckusic i = sblock.fs_iblkno + MAXIPG / INOPF(&sblock); 3085362Smckusic inos = (fssize - sblock.fs_ncg * i) * sblock.fs_fsize / 3095362Smckusic MAX(NBPI, sblock.fs_fsize) / INOPB(&sblock); 3105336Smckusic if (inos <= 0) 3115336Smckusic inos = 1; 3125336Smckusic sblock.fs_ipg = ((inos / 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)); 3506532Smckusick fscs = (struct csum *)calloc(1, sblock.fs_cssize); 3515362Smckusic sblock.fs_magic = FS_MAGIC; 3525336Smckusic sblock.fs_rotdelay = ROTDELAY; 3535336Smckusic sblock.fs_minfree = MINFREE; 3546313Smckusick sblock.fs_rps = 60; /* assume disk speed == 60 HZ */ 3555336Smckusic sblock.fs_cgrotor = 0; 3565336Smckusic sblock.fs_cstotal.cs_ndir = 0; 3575336Smckusic sblock.fs_cstotal.cs_nbfree = 0; 3585336Smckusic sblock.fs_cstotal.cs_nifree = 0; 3595336Smckusic sblock.fs_cstotal.cs_nffree = 0; 3604234Smckusick sblock.fs_fmod = 0; 3614234Smckusick sblock.fs_ronly = 0; 3624234Smckusick /* 3635336Smckusic * Dump out summary information about file system. 3644234Smckusick */ 3654234Smckusick printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 3665336Smckusic fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 3675324Smckusic sblock.fs_ntrak, sblock.fs_nsect); 3684234Smckusick printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 3695324Smckusic (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg, 3705324Smckusic sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6, 3715324Smckusic sblock.fs_ipg); 3724234Smckusick /* 3734234Smckusick * Now build the cylinders group blocks and 3745336Smckusic * then print out indices of cylinder groups. 3754234Smckusick */ 3766532Smckusick printf("super-block backups (for fsck -b#) at:"); 3776532Smckusick for (cylno = 0; cylno < sblock.fs_ncg; cylno++) { 3785362Smckusic initcg(cylno); 3796532Smckusick if (cylno % 10 == 0) 3806532Smckusick printf("\n"); 3816532Smckusick printf(" %d,", fsbtodb(&sblock, cgsblock(&sblock, cylno))); 3826532Smckusick } 3836532Smckusick printf("\n%s\n%s\n", 3846532Smckusick "WRITE THESE NUMBERS DOWN!!!", 3856532Smckusick "fsck depends on them to recover this file system."); 3864234Smckusick /* 3875336Smckusic * Now construct the initial file system, 3884234Smckusick * then write out the super-block. 3894234Smckusick */ 3905336Smckusic fsinit(); 3914234Smckusick sblock.fs_time = utime; 3925336Smckusic wtfs(SBLOCK, SBSIZE, (char *)&sblock); 3935324Smckusic for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 3945955Smckusic wtfs(fsbtodb(&sblock, sblock.fs_csaddr + numfrags(&sblock, i)), 3956532Smckusick sblock.fs_cssize - i < sblock.fs_bsize ? 3966532Smckusick sblock.fs_cssize - i : sblock.fs_bsize, 3976532Smckusick ((char *)fscs) + i); 3985336Smckusic /* 3995336Smckusic * Write out the duplicate super blocks 4005336Smckusic */ 4015362Smckusic for (cylno = 1; cylno < sblock.fs_ncg; cylno++) 4026532Smckusick wtfs(fsbtodb(&sblock, cgsblock(&sblock, cylno)), 4036532Smckusick SBSIZE, (char *)&sblock); 4044234Smckusick #ifndef STANDALONE 4055336Smckusic exit(0); 4064234Smckusick #endif 4074234Smckusick } 4084234Smckusick 4094234Smckusick /* 4104234Smckusick * Initialize a cylinder group. 4114234Smckusick */ 4125362Smckusic initcg(cylno) 4135362Smckusic int cylno; 4144234Smckusick { 4156532Smckusick daddr_t cbase, d, dlower, dupper, dmax; 4164234Smckusick long i, j, s; 4174234Smckusick register struct csum *cs; 4184234Smckusick 4194234Smckusick /* 4204234Smckusick * Determine block bounds for cylinder group. 4214234Smckusick * Allow space for super block summary information in first 4224234Smckusick * cylinder group. 4234234Smckusick */ 4245383Smckusic cbase = cgbase(&sblock, cylno); 4254234Smckusick dmax = cbase + sblock.fs_fpg; 4264234Smckusick if (dmax > sblock.fs_size) 4274234Smckusick dmax = sblock.fs_size; 4286532Smckusick dlower = cgsblock(&sblock, cylno) - cbase; 4296532Smckusick dupper = cgdmin(&sblock, cylno) - cbase; 4305362Smckusic cs = fscs + cylno; 4314234Smckusick acg.cg_time = utime; 4324234Smckusick acg.cg_magic = CG_MAGIC; 4335362Smckusic acg.cg_cgx = cylno; 4348139Smckusick if (cylno == sblock.fs_ncg - 1) 4358139Smckusick acg.cg_ncyl = sblock.fs_ncyl % sblock.fs_cpg; 4368139Smckusick else 4378139Smckusick acg.cg_ncyl = sblock.fs_cpg; 4384234Smckusick acg.cg_niblk = sblock.fs_ipg; 4394234Smckusick acg.cg_ndblk = dmax - cbase; 4404788Smckusic acg.cg_cs.cs_ndir = 0; 4414788Smckusic acg.cg_cs.cs_nffree = 0; 4424788Smckusic acg.cg_cs.cs_nbfree = 0; 4434788Smckusic acg.cg_cs.cs_nifree = 0; 4446532Smckusick acg.cg_rotor = 0; 4456532Smckusick acg.cg_frotor = 0; 4464257Smckusic acg.cg_irotor = 0; 4475324Smckusic for (i = 0; i < sblock.fs_frag; i++) { 4484465Smckusic acg.cg_frsum[i] = 0; 4494465Smckusic } 4504465Smckusic for (i = 0; i < sblock.fs_ipg; ) { 4515324Smckusic for (j = INOPB(&sblock); j > 0; j--) { 4524234Smckusick clrbit(acg.cg_iused, i); 4534234Smckusick i++; 4544234Smckusick } 4555324Smckusic acg.cg_cs.cs_nifree += INOPB(&sblock); 4564234Smckusick } 4575362Smckusic if (cylno == 0) 4585336Smckusic for (i = 0; i < ROOTINO; i++) { 4595336Smckusic setbit(acg.cg_iused, i); 4605336Smckusic acg.cg_cs.cs_nifree--; 4615336Smckusic } 4624234Smckusick while (i < MAXIPG) { 4634234Smckusick clrbit(acg.cg_iused, i); 4644234Smckusick i++; 4654234Smckusick } 4665383Smckusic lseek(fso, fsbtodb(&sblock, cgimin(&sblock, cylno)) * DEV_BSIZE, 0); 4674234Smckusick if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != 4684234Smckusick sblock.fs_ipg * sizeof (struct dinode)) 4695955Smckusic printf("write error %D\n", numfrags(&sblock, tell(fso))); 4705370Smckusic for (i = 0; i < MAXCPG; i++) { 4715370Smckusic acg.cg_btot[i] = 0; 4724234Smckusick for (j = 0; j < NRPOS; j++) 4734234Smckusick acg.cg_b[i][j] = 0; 4745370Smckusic } 4755362Smckusic if (cylno == 0) { 4766532Smckusick /* 4776532Smckusick * reserve space for summary info and Boot block 4786532Smckusick */ 4796532Smckusick dupper += howmany(sblock.fs_cssize, sblock.fs_fsize); 4806532Smckusick for (d = 0; d < dlower; d += sblock.fs_frag) 4816532Smckusick clrblock(&sblock, acg.cg_free, d/sblock.fs_frag); 4826532Smckusick } else { 4836532Smckusick for (d = 0; d < dlower; d += sblock.fs_frag) { 4846532Smckusick setblock(&sblock, acg.cg_free, d/sblock.fs_frag); 4856532Smckusick acg.cg_cs.cs_nbfree++; 4866532Smckusick acg.cg_btot[cbtocylno(&sblock, d)]++; 4876532Smckusick acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++; 4886532Smckusick } 4896532Smckusick sblock.fs_dsize += dlower; 4904234Smckusick } 4916532Smckusick sblock.fs_dsize += acg.cg_ndblk - dupper; 4926532Smckusick for (; d < dupper; d += sblock.fs_frag) 4935324Smckusic clrblock(&sblock, acg.cg_free, d/sblock.fs_frag); 4946532Smckusick if (d > dupper) { 4956532Smckusick acg.cg_frsum[d - dupper]++; 4966532Smckusick for (i = d - 1; i >= dupper; i--) { 4976532Smckusick setbit(acg.cg_free, i); 4986532Smckusick acg.cg_cs.cs_nffree++; 4996532Smckusick } 5006532Smckusick } 5016532Smckusick while ((d + sblock.fs_frag) <= dmax - cbase) { 5025324Smckusic setblock(&sblock, acg.cg_free, d/sblock.fs_frag); 5034788Smckusic acg.cg_cs.cs_nbfree++; 5045370Smckusic acg.cg_btot[cbtocylno(&sblock, d)]++; 5055362Smckusic acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]++; 5065324Smckusic d += sblock.fs_frag; 5074234Smckusick } 5086532Smckusick if (d < dmax - cbase) { 5095362Smckusic acg.cg_frsum[dmax - cbase - d]++; 5104251Smckusic for (; d < dmax - cbase; d++) { 5114251Smckusic setbit(acg.cg_free, d); 5124788Smckusic acg.cg_cs.cs_nffree++; 5134251Smckusic } 5148139Smckusick for (; d % sblock.fs_frag != 0; d++) 5158139Smckusick clrbit(acg.cg_free, d); 5166532Smckusick } 5178139Smckusick for (d /= sblock.fs_frag; d < MAXBPG(&sblock); d ++) 5188139Smckusick clrblock(&sblock, acg.cg_free, d); 5194788Smckusic sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 5204788Smckusic sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 5214788Smckusic sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 5224788Smckusic sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 5234788Smckusic *cs = acg.cg_cs; 5245383Smckusic wtfs(fsbtodb(&sblock, cgtod(&sblock, cylno)), 5255324Smckusic sblock.fs_bsize, (char *)&acg); 5264234Smckusick } 5274234Smckusick 5285336Smckusic /* 5295336Smckusic * initialize the file system 5305336Smckusic */ 5315336Smckusic struct inode node; 5325336Smckusic #define PREDEFDIR 3 5335934Smckusic struct direct root_dir[] = { 5345934Smckusic { ROOTINO, sizeof(struct direct), 1, "." }, 5355934Smckusic { ROOTINO, sizeof(struct direct), 2, ".." }, 5365934Smckusic { LOSTFOUNDINO, sizeof(struct direct), 10, "lost+found" }, 5375336Smckusic }; 5385934Smckusic struct direct lost_found_dir[] = { 5395934Smckusic { LOSTFOUNDINO, sizeof(struct direct), 1, "." }, 5405934Smckusic { ROOTINO, sizeof(struct direct), 2, ".." }, 5415934Smckusic { 0, DIRBLKSIZ, 0, 0 }, 5425336Smckusic }; 5435934Smckusic char buf[MAXBSIZE]; 5445336Smckusic 5455336Smckusic fsinit() 5464234Smckusick { 5475934Smckusic int i; 5485934Smckusic 5494234Smckusick /* 5505336Smckusic * initialize the node 5514234Smckusick */ 5525336Smckusic node.i_atime = utime; 5535336Smckusic node.i_mtime = utime; 5545336Smckusic node.i_ctime = utime; 5554234Smckusick /* 5565336Smckusic * create the lost+found directory 5574234Smckusick */ 5585934Smckusic (void)makedir(lost_found_dir, 2); 5595934Smckusic for (i = DIRBLKSIZ; i < sblock.fs_bsize; i += DIRBLKSIZ) 5605934Smckusic bcopy(&lost_found_dir[2], &buf[i], DIRSIZ(&lost_found_dir[2])); 5615336Smckusic node.i_number = LOSTFOUNDINO; 5625336Smckusic node.i_mode = IFDIR | UMASK; 5635336Smckusic node.i_nlink = 2; 5645336Smckusic node.i_size = sblock.fs_bsize; 5655336Smckusic node.i_db[0] = alloc(node.i_size, node.i_mode); 5665934Smckusic wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, buf); 5675336Smckusic iput(&node); 5685336Smckusic /* 5695336Smckusic * create the root directory 5705336Smckusic */ 5715336Smckusic node.i_number = ROOTINO; 5725336Smckusic node.i_mode = IFDIR | UMASK; 5735336Smckusic node.i_nlink = PREDEFDIR; 5745934Smckusic node.i_size = makedir(root_dir, PREDEFDIR); 5755336Smckusic node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode); 5765934Smckusic wtfs(fsbtodb(&sblock, node.i_db[0]), sblock.fs_fsize, buf); 5775336Smckusic iput(&node); 5784234Smckusick } 5794234Smckusick 5805336Smckusic /* 5815934Smckusic * construct a set of directory entries in "buf". 5825934Smckusic * return size of directory. 5835934Smckusic */ 5845934Smckusic makedir(protodir, entries) 5855934Smckusic register struct direct *protodir; 5865934Smckusic int entries; 5875934Smckusic { 5885934Smckusic char *cp; 5895934Smckusic int i, spcleft; 5905934Smckusic 5915934Smckusic spcleft = DIRBLKSIZ; 5925934Smckusic for (cp = buf, i = 0; i < entries - 1; i++) { 5935934Smckusic protodir[i].d_reclen = DIRSIZ(&protodir[i]); 5945934Smckusic bcopy(&protodir[i], cp, protodir[i].d_reclen); 5955934Smckusic cp += protodir[i].d_reclen; 5965934Smckusic spcleft -= protodir[i].d_reclen; 5975934Smckusic } 5985934Smckusic protodir[i].d_reclen = spcleft; 5995934Smckusic bcopy(&protodir[i], cp, DIRSIZ(&protodir[i])); 6005934Smckusic cp += DIRSIZ(&protodir[i]); 6015934Smckusic return (cp - buf); 6025934Smckusic } 6035934Smckusic 6045934Smckusic /* 6055336Smckusic * allocate a block or frag 6065336Smckusic */ 6074234Smckusick daddr_t 6084427Smckusic alloc(size, mode) 6094427Smckusic int size; 6104427Smckusic int mode; 6114234Smckusick { 6125362Smckusic int i, frag; 6134234Smckusick daddr_t d; 6144234Smckusick 6155955Smckusic rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 6165955Smckusic (char *)&acg); 6176532Smckusick if (acg.cg_magic != CG_MAGIC) { 6186532Smckusick printf("cg 0: bad magic number\n"); 6196532Smckusick return (0); 6206532Smckusick } 6214788Smckusic if (acg.cg_cs.cs_nbfree == 0) { 6224234Smckusick printf("first cylinder group ran out of space\n"); 6234234Smckusick return (0); 6244234Smckusick } 6255324Smckusic for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 6265324Smckusic if (isblock(&sblock, acg.cg_free, d / sblock.fs_frag)) 6274234Smckusick goto goth; 6284234Smckusick printf("internal error: can't find block in cyl 0\n"); 6294234Smckusick return (0); 6304234Smckusick goth: 6315324Smckusic clrblock(&sblock, acg.cg_free, d / sblock.fs_frag); 6324788Smckusic acg.cg_cs.cs_nbfree--; 6334788Smckusic sblock.fs_cstotal.cs_nbfree--; 6344234Smckusick fscs[0].cs_nbfree--; 6354427Smckusic if (mode & IFDIR) { 6364788Smckusic acg.cg_cs.cs_ndir++; 6374788Smckusic sblock.fs_cstotal.cs_ndir++; 6384427Smckusic fscs[0].cs_ndir++; 6394427Smckusic } 6405370Smckusic acg.cg_btot[cbtocylno(&sblock, d)]--; 6415362Smckusic acg.cg_b[cbtocylno(&sblock, d)][cbtorpos(&sblock, d)]--; 6425324Smckusic if (size != sblock.fs_bsize) { 6435324Smckusic frag = howmany(size, sblock.fs_fsize); 6445324Smckusic fscs[0].cs_nffree += sblock.fs_frag - frag; 6455324Smckusic sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 6465324Smckusic acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 6475324Smckusic acg.cg_frsum[sblock.fs_frag - frag]++; 6485324Smckusic for (i = frag; i < sblock.fs_frag; i++) 6496532Smckusick setbit(acg.cg_free, d + i); 6504234Smckusick } 6515955Smckusic wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 6525955Smckusic (char *)&acg); 6534234Smckusick return (d); 6544234Smckusick } 6554234Smckusick 6565336Smckusic /* 6575336Smckusic * Allocate an inode on the disk 6585336Smckusic */ 6595336Smckusic iput(ip) 6605336Smckusic register struct inode *ip; 6614234Smckusick { 6625336Smckusic struct dinode buf[MAXINOPB]; 6635336Smckusic daddr_t d; 6645336Smckusic int c; 6654234Smckusick 6665383Smckusic c = itog(&sblock, ip->i_number); 6675955Smckusic rdfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 6685955Smckusic (char *)&acg); 6696532Smckusick if (acg.cg_magic != CG_MAGIC) { 6706532Smckusick printf("cg 0: bad magic number\n"); 6716532Smckusick exit(1); 6726532Smckusick } 6735336Smckusic acg.cg_cs.cs_nifree--; 6745336Smckusic setbit(acg.cg_iused, ip->i_number); 6755955Smckusic wtfs(fsbtodb(&sblock, cgtod(&sblock, 0)), sblock.fs_cgsize, 6765955Smckusic (char *)&acg); 6775336Smckusic sblock.fs_cstotal.cs_nifree--; 6785336Smckusic fscs[0].cs_nifree--; 6795336Smckusic if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 6805336Smckusic printf("fsinit: inode value out of range (%d).\n", 6815336Smckusic ip->i_number); 6825336Smckusic exit(1); 6835336Smckusic } 6845383Smckusic d = fsbtodb(&sblock, itod(&sblock, ip->i_number)); 6855336Smckusic rdfs(d, sblock.fs_bsize, buf); 6865383Smckusic buf[itoo(&sblock, ip->i_number)].di_ic = ip->i_ic; 6875336Smckusic wtfs(d, sblock.fs_bsize, buf); 6884234Smckusick } 6894234Smckusick 6905336Smckusic /* 6915336Smckusic * read a block from the file system 6925336Smckusic */ 6935336Smckusic rdfs(bno, size, bf) 6945336Smckusic daddr_t bno; 6954427Smckusic int size; 6965336Smckusic char *bf; 6974234Smckusick { 6985336Smckusic int n; 6994234Smckusick 7005346Smckusic if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) { 7015346Smckusic printf("seek error: %ld\n", bno); 7025346Smckusic perror("rdfs"); 7035346Smckusic exit(1); 7045346Smckusic } 7055336Smckusic n = read(fsi, bf, size); 7065336Smckusic if(n != size) { 7075336Smckusic printf("read error: %ld\n", bno); 7085346Smckusic perror("rdfs"); 7095336Smckusic exit(1); 7104234Smckusick } 7114234Smckusick } 7124234Smckusick 7135336Smckusic /* 7145336Smckusic * write a block to the file system 7155336Smckusic */ 7165336Smckusic wtfs(bno, size, bf) 7175336Smckusic daddr_t bno; 7185336Smckusic int size; 7195336Smckusic char *bf; 7204234Smckusick { 7215336Smckusic int n; 7224234Smckusick 7235336Smckusic lseek(fso, bno * DEV_BSIZE, 0); 7245346Smckusic if (lseek(fso, bno * DEV_BSIZE, 0) < 0) { 7255346Smckusic printf("seek error: %ld\n", bno); 7265346Smckusic perror("wtfs"); 7275346Smckusic exit(1); 7285346Smckusic } 7295336Smckusic n = write(fso, bf, size); 7305336Smckusic if(n != size) { 7315336Smckusic printf("write error: %D\n", bno); 7325346Smckusic perror("wtfs"); 7334234Smckusick exit(1); 7344234Smckusick } 7354234Smckusick } 7365324Smckusic 737*8140Smckusick #ifndef STANDALONE 7385324Smckusic /* 7395934Smckusic * copy a block 7405934Smckusic */ 7415934Smckusic bcopy(from, to, size) 7425934Smckusic char *from, *to; 7435934Smckusic int size; 7445934Smckusic { 7455934Smckusic asm(" movc3 12(ap),*4(ap),*8(ap)"); 7465934Smckusic } 747*8140Smckusick #endif 7485934Smckusic 7495934Smckusic /* 7505336Smckusic * check if a block is available 7515324Smckusic */ 7525324Smckusic isblock(fs, cp, h) 7535324Smckusic struct fs *fs; 7545324Smckusic unsigned char *cp; 7555324Smckusic int h; 7565324Smckusic { 7575324Smckusic unsigned char mask; 7585324Smckusic 7595324Smckusic switch (fs->fs_frag) { 7605324Smckusic case 8: 7615324Smckusic return (cp[h] == 0xff); 7625324Smckusic case 4: 7635324Smckusic mask = 0x0f << ((h & 0x1) << 2); 7645324Smckusic return ((cp[h >> 1] & mask) == mask); 7655324Smckusic case 2: 7665324Smckusic mask = 0x03 << ((h & 0x3) << 1); 7675324Smckusic return ((cp[h >> 2] & mask) == mask); 7685324Smckusic case 1: 7695324Smckusic mask = 0x01 << (h & 0x7); 7705324Smckusic return ((cp[h >> 3] & mask) == mask); 7715324Smckusic default: 772*8140Smckusick #ifdef STANDALONE 773*8140Smckusick printf("isblock bad fs_frag %d\n", fs->fs_frag); 774*8140Smckusick #else 7755324Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 776*8140Smckusick #endif 7775324Smckusic return; 7785324Smckusic } 7795324Smckusic } 7805324Smckusic 7815336Smckusic /* 7825336Smckusic * take a block out of the map 7835336Smckusic */ 7845324Smckusic clrblock(fs, cp, h) 7855324Smckusic struct fs *fs; 7865324Smckusic unsigned char *cp; 7875324Smckusic int h; 7885324Smckusic { 7895324Smckusic switch ((fs)->fs_frag) { 7905324Smckusic case 8: 7915324Smckusic cp[h] = 0; 7925324Smckusic return; 7935324Smckusic case 4: 7945324Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 7955324Smckusic return; 7965324Smckusic case 2: 7975324Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 7985324Smckusic return; 7995324Smckusic case 1: 8005324Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 8015324Smckusic return; 8025324Smckusic default: 803*8140Smckusick #ifdef STANDALONE 804*8140Smckusick printf("clrblock bad fs_frag %d\n", fs->fs_frag); 805*8140Smckusick #else 8065324Smckusic fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 807*8140Smckusick #endif 8085324Smckusic return; 8095324Smckusic } 8105324Smckusic } 8115324Smckusic 8125336Smckusic /* 8135336Smckusic * put a block into the map 8145336Smckusic */ 8155324Smckusic setblock(fs, cp, h) 8165324Smckusic struct fs *fs; 8175324Smckusic unsigned char *cp; 8185324Smckusic int h; 8195324Smckusic { 8205324Smckusic switch (fs->fs_frag) { 8215324Smckusic case 8: 8225324Smckusic cp[h] = 0xff; 8235324Smckusic return; 8245324Smckusic case 4: 8255324Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 8265324Smckusic return; 8275324Smckusic case 2: 8285324Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 8295324Smckusic return; 8305324Smckusic case 1: 8315324Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 8325324Smckusic return; 8335324Smckusic default: 834*8140Smckusick #ifdef STANDALONE 835*8140Smckusick printf("setblock bad fs_frag %d\n", fs->fs_frag); 836*8140Smckusick #else 8375324Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 838*8140Smckusick #endif 8395324Smckusic return; 8405324Smckusic } 8415324Smckusic } 842