1*5346Smckusic static char *sccsid = "@(#)mkfs.c 1.12 (Berkeley) 01/06/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 144234Smckusick #include "../h/param.h" 154234Smckusick #include "../h/inode.h" 164234Smckusick #include "../h/fs.h" 174234Smckusick #include "../h/dir.h" 184234Smckusick 195336Smckusic #define UMASK 0755 205336Smckusic #define MAXNDIR (MAXBSIZE / sizeof(struct direct)) 21*5346Smckusic #define MAXINOPB (MAXBSIZE / sizeof(struct dinode)) 225336Smckusic #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 234234Smckusick 244234Smckusick union { 254234Smckusick struct fs fs; 265324Smckusic char pad[MAXBSIZE]; 274234Smckusick } fsun; 284234Smckusick #define sblock fsun.fs 294234Smckusick struct csum *fscs; 304234Smckusick 314234Smckusick union { 324234Smckusick struct cg cg; 335324Smckusic char pad[MAXBSIZE]; 344234Smckusick } cgun; 354234Smckusick #define acg cgun.cg 364234Smckusick 375336Smckusic struct dinode zino[MAXIPG]; 385336Smckusic 394234Smckusick char *fsys; 405336Smckusic time_t utime; 415336Smckusic int fsi; 425336Smckusic int fso; 434234Smckusick daddr_t alloc(); 444234Smckusick 454234Smckusick main(argc, argv) 465324Smckusic int argc; 475324Smckusic char *argv[]; 484234Smckusick { 495336Smckusic long c, i, inos, fssize; 504234Smckusick 515336Smckusic #ifndef STANDALONE 524234Smckusick argc--, argv++; 534234Smckusick time(&utime); 545336Smckusic if (argc < 2) { 555336Smckusic printf("usage: mkfs special size [ nsect ntrak bsize fsize cpg ]\n"); 564234Smckusick exit(1); 574234Smckusick } 584234Smckusick fsys = argv[0]; 595336Smckusic fssize = atoi(argv[1]); 605336Smckusic fso = creat(fsys, 0666); 615336Smckusic if(fso < 0) { 625336Smckusic printf("%s: cannot create\n", fsys); 635336Smckusic exit(1); 645336Smckusic } 655336Smckusic fsi = open(fsys, 0); 665336Smckusic if(fsi < 0) { 675336Smckusic printf("%s: cannot open\n", fsys); 685336Smckusic exit(1); 695336Smckusic } 704234Smckusick #else 714234Smckusick { 724234Smckusick static char protos[60]; 735336Smckusic char fsbuf[100]; 744234Smckusick 754234Smckusick printf("file sys size: "); 764234Smckusick gets(protos); 775336Smckusic fssize = atoi(protos); 784234Smckusick do { 794234Smckusick printf("file system: "); 804234Smckusick gets(fsbuf); 814234Smckusick fso = open(fsbuf, 1); 824234Smckusick fsi = open(fsbuf, 0); 834234Smckusick } while (fso < 0 || fsi < 0); 844234Smckusick } 854234Smckusick argc = 0; 865336Smckusic #endif 875336Smckusic if (fssize <= 0) 885336Smckusic printf("preposterous size %d\n", fssize), exit(1); 895336Smckusic /* 905336Smckusic * collect and verify the sector and track info 915336Smckusic */ 925336Smckusic if (argc > 2) 935336Smckusic sblock.fs_nsect = atoi(argv[2]); 945336Smckusic else 955336Smckusic sblock.fs_nsect = DFLNSECT; 965336Smckusic if (argc > 3) 975336Smckusic sblock.fs_ntrak = atoi(argv[3]); 985336Smckusic else 995336Smckusic sblock.fs_ntrak = DFLNTRAK; 1005336Smckusic if (sblock.fs_ntrak <= 0) 1015336Smckusic printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 1025336Smckusic if (sblock.fs_nsect <= 0) 1035336Smckusic printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 1045336Smckusic sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 1055336Smckusic /* 1065336Smckusic * collect and verify the block and fragment sizes 1075336Smckusic */ 1085336Smckusic if (argc > 4) 1095336Smckusic sblock.fs_bsize = atoi(argv[4]); 1105336Smckusic else 1115336Smckusic sblock.fs_bsize = MAXBSIZE; 1125336Smckusic if (argc > 5) 1135336Smckusic sblock.fs_fsize = atoi(argv[5]); 1145336Smckusic else 1155336Smckusic sblock.fs_fsize = MAX(sblock.fs_bsize / DESFRAG, DEV_BSIZE); 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 } 1265324Smckusic if (sblock.fs_fsize < DEV_BSIZE) { 1275324Smckusic printf("fragment size %d is too small, minimum is %d\n", 1285324Smckusic sblock.fs_fsize, DEV_BSIZE); 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 } 1415336Smckusic sblock.fs_frag = sblock.fs_bsize / sblock.fs_fsize; 1425336Smckusic if (sblock.fs_frag > MAXFRAG) { 1435336Smckusic printf("fragment size %d is too small, minimum with block size %d is %d\n", 1445336Smckusic sblock.fs_fsize, sblock.fs_bsize, 1455336Smckusic sblock.fs_bsize / MAXFRAG); 1465336Smckusic exit(1); 1474234Smckusick } 1485336Smckusic /* 1495336Smckusic * collect and verify the number of cylinders per group 1504234Smckusick */ 1515336Smckusic if (argc > 6) { 1525336Smckusic sblock.fs_cpg = atoi(argv[6]); 1535336Smckusic sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1544234Smckusick } else { 1554234Smckusick sblock.fs_cpg = DESCPG; 1565336Smckusic sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1575336Smckusic while (sblock.fs_fpg / sblock.fs_frag > MAXBPG(&sblock)) { 1584234Smckusick --sblock.fs_cpg; 1595336Smckusic sblock.fs_fpg = 1605336Smckusic (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1615336Smckusic } 1624234Smckusick } 1635336Smckusic if (sblock.fs_cpg < 1) { 1645336Smckusic printf("cylinder groups must have at least 1 cylinder\n"); 1655336Smckusic exit(1); 1665336Smckusic } 1675336Smckusic if (sblock.fs_cpg > MAXCPG) { 1685336Smckusic printf("cylinder groups are limited to %d cylinders\n", MAXCPG); 1695336Smckusic exit(1); 1705336Smckusic } 1714234Smckusick /* 1725336Smckusic * Now have size for file system and nsect and ntrak. 1735336Smckusic * Determine number of cylinders and blocks in the file system. 1745336Smckusic */ 1755336Smckusic sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 1765336Smckusic sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 1775336Smckusic if (sblock.fs_spc > MAXBPC * NSPB(&sblock)) { 1785336Smckusic printf("too many sectors per cylinder (%d sectors)\n", 1795336Smckusic sblock.fs_spc); 1805336Smckusic while (sblock.fs_spc > MAXBPC * NSPB(&sblock)) 1815336Smckusic sblock.fs_bsize <<= 1; 1825336Smckusic printf("nsect %d, and ntrak %d, requires block size of %d\n", 1835336Smckusic sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_bsize); 1845336Smckusic exit(1); 1855336Smckusic } 1865336Smckusic /* 1875336Smckusic * Validate specified/determined cpg. 1885336Smckusic */ 1895336Smckusic if (sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) { 1905336Smckusic printf("too many sectors per cylinder (%d sectors)\n", 1915336Smckusic sblock.fs_spc); 1925336Smckusic while(sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) { 1935336Smckusic sblock.fs_bsize <<= 1; 1945336Smckusic if (sblock.fs_frag < MAXFRAG) 1955336Smckusic sblock.fs_frag <<= 1; 1965336Smckusic else 1975336Smckusic sblock.fs_fsize <<= 1; 1985336Smckusic } 1995336Smckusic printf("nsect %d, and ntrak %d, requires block size of %d,\n", 2005336Smckusic sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_bsize); 2015336Smckusic printf("\tand fragment size of %d\n", sblock.fs_fsize); 2025336Smckusic exit(1); 2035336Smckusic } 2045336Smckusic if (sblock.fs_fpg > MAXBPG(&sblock) * sblock.fs_frag) { 2055336Smckusic printf("cylinder group too large (%d cylinders); ", 2065336Smckusic sblock.fs_cpg); 2075336Smckusic printf("max: %d cylinders\n", 2085336Smckusic MAXBPG(&sblock) * sblock.fs_frag / 2095336Smckusic (sblock.fs_fpg / sblock.fs_cpg)); 2105336Smckusic exit(1); 2115336Smckusic } 2125336Smckusic sblock.fs_cgsize = roundup(sizeof(struct cg) + 2135336Smckusic howmany(sblock.fs_fpg, NBBY), sblock.fs_fsize); 2145336Smckusic /* 2154234Smckusick * Compute/validate number of cylinder groups. 2164234Smckusick */ 2175336Smckusic if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 2185336Smckusic printf("%d sector(s) in last cylinder unused\n", 2195336Smckusic fssize * NSPF(&sblock) - sblock.fs_ncyl * sblock.fs_spc); 2205336Smckusic } 2214234Smckusick sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 2224234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) 2234234Smckusick sblock.fs_ncg++; 2245336Smckusic if ((sblock.fs_spc * sblock.fs_cpg) % NSPF(&sblock)) { 2254234Smckusick printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 2264234Smckusick sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 2274234Smckusick printf("as this would would have cyl groups whose size\n"); 2285324Smckusic printf("is not a multiple of %d; choke!\n", sblock.fs_fsize); 2294234Smckusick exit(1); 2304234Smckusick } 2314234Smckusick fscs = (struct csum *) 2325324Smckusic calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), 2335324Smckusic sblock.fs_bsize)); 2344234Smckusick /* 2354234Smckusick * Compute number of inode blocks per cylinder group. 2364234Smckusick * Start with one inode per NBPI bytes; adjust as necessary. 2374234Smckusick */ 2385336Smckusic inos = ((fssize * sblock.fs_fsize) / MAX(NBPI, sblock.fs_fsize)) / 2395336Smckusic INOPB(&sblock); 2405336Smckusic if (inos <= 0) 2415336Smckusic inos = 1; 2425336Smckusic sblock.fs_ipg = ((inos / sblock.fs_ncg) + 1) * INOPB(&sblock); 2434234Smckusick if (sblock.fs_ipg > MAXIPG) 2444234Smckusick sblock.fs_ipg = MAXIPG; 2455324Smckusic if (cgdmin(0,&sblock) >= sblock.fs_fpg) { 2464234Smckusick printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 2475324Smckusic cgdmin(0,&sblock) / sblock.fs_frag, 2485324Smckusic sblock.fs_fpg / sblock.fs_frag); 2495336Smckusic printf("number of cylinder per cylinder group must be increased\n"); 2505324Smckusic exit(1); 2515324Smckusic } 2525336Smckusic /* 2535336Smckusic * calculate the available blocks for each rotational position 2545336Smckusic */ 2555336Smckusic for (i = 0; i < NRPOS; i++) 2565336Smckusic sblock.fs_postbl[i] = -1; 2575336Smckusic for (i = 0; i < sblock.fs_spc; i += NSPB(&sblock)) 2585336Smckusic /* void */; 2595336Smckusic for (i -= NSPB(&sblock); i >= 0; i -= NSPB(&sblock)) { 2605336Smckusic c = i % sblock.fs_nsect * NRPOS / sblock.fs_nsect; 2615336Smckusic sblock.fs_rotbl[i / NSPB(&sblock)] = sblock.fs_postbl[c]; 2625336Smckusic sblock.fs_postbl[c] = i / NSPB(&sblock); 2635336Smckusic } 2645336Smckusic /* 2655336Smckusic * fill in remaining fields of the super block 2665336Smckusic */ 2675324Smckusic sblock.fs_csaddr = cgdmin(0, &sblock); 2685324Smckusic sblock.fs_cssize = sblock.fs_ncg * sizeof(struct csum); 2695336Smckusic sblock.fs_rotdelay = ROTDELAY; 2705336Smckusic sblock.fs_minfree = MINFREE; 2715336Smckusic sblock.fs_magic = FS_MAGIC; 2724234Smckusick sblock.fs_sblkno = SBLOCK; 2735336Smckusic sblock.fs_cgrotor = 0; 2745336Smckusic sblock.fs_cstotal.cs_ndir = 0; 2755336Smckusic sblock.fs_cstotal.cs_nbfree = 0; 2765336Smckusic sblock.fs_cstotal.cs_nifree = 0; 2775336Smckusic sblock.fs_cstotal.cs_nffree = 0; 2784234Smckusick sblock.fs_fmod = 0; 2794234Smckusick sblock.fs_ronly = 0; 2804234Smckusick /* 2815336Smckusic * Dump out summary information about file system. 2824234Smckusick */ 2834234Smckusick printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 2845336Smckusic fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 2855324Smckusic sblock.fs_ntrak, sblock.fs_nsect); 2864234Smckusick printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 2875324Smckusic (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg, 2885324Smckusic sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6, 2895324Smckusic sblock.fs_ipg); 2904234Smckusick /* 2914234Smckusick * Now build the cylinders group blocks and 2925336Smckusic * then print out indices of cylinder groups. 2934234Smckusick */ 2944234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 2954234Smckusick initcg(c); 2965324Smckusic if (sblock.fs_ncg == 1) 2975324Smckusic printf("Warning, no super-block backups with only one cylinder group\n"); 2985324Smckusic else 2995324Smckusic printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n", 300*5346Smckusic SBLOCK, fsbtodb(&sblock, cgsblock(1, &sblock)) - SBLOCK, 301*5346Smckusic fsbtodb(&sblock, cgsblock(1, &sblock)), 302*5346Smckusic fsbtodb(&sblock, cgsblock(sblock.fs_ncg - 1, &sblock))); 3034234Smckusick /* 3045336Smckusic * Now construct the initial file system, 3054234Smckusick * then write out the super-block. 3064234Smckusick */ 3075336Smckusic fsinit(); 3084234Smckusick sblock.fs_time = utime; 3095336Smckusic wtfs(SBLOCK, SBSIZE, (char *)&sblock); 3105324Smckusic for (i = 0; i < sblock.fs_cssize; i += sblock.fs_bsize) 3115324Smckusic wtfs(fsbtodb(&sblock, sblock.fs_csaddr + i / sblock.fs_fsize), 3125324Smckusic sblock.fs_bsize, ((char *)fscs) + i); 3135336Smckusic /* 3145336Smckusic * Write out the duplicate super blocks 3155336Smckusic */ 3165336Smckusic for (c = 1; c < sblock.fs_ncg; c++) 3175324Smckusic wtfs(fsbtodb(&sblock, cgsblock(c, &sblock)), 3185336Smckusic SBSIZE, (char *)&sblock); 3194234Smckusick #ifndef STANDALONE 3205336Smckusic exit(0); 3214234Smckusick #endif 3224234Smckusick } 3234234Smckusick 3244234Smckusick /* 3254234Smckusick * Initialize a cylinder group. 3264234Smckusick */ 3274234Smckusick initcg(c) 3284234Smckusick int c; 3294234Smckusick { 3304234Smckusick daddr_t cbase, d, dmin, dmax; 3314234Smckusick long i, j, s; 3324234Smckusick register struct csum *cs; 3334234Smckusick 3344234Smckusick /* 3354234Smckusick * Determine block bounds for cylinder group. 3364234Smckusick * Allow space for super block summary information in first 3374234Smckusick * cylinder group. 3384234Smckusick */ 3394234Smckusick cbase = cgbase(c,&sblock); 3404234Smckusick dmax = cbase + sblock.fs_fpg; 3414234Smckusick if (dmax > sblock.fs_size) 3424234Smckusick dmax = sblock.fs_size; 3434465Smckusic dmin = cgdmin(c,&sblock) - cbase; 3444234Smckusick d = cbase; 3454234Smckusick cs = fscs+c; 3464234Smckusick acg.cg_time = utime; 3474234Smckusick acg.cg_magic = CG_MAGIC; 3484234Smckusick acg.cg_cgx = c; 3494234Smckusick acg.cg_ncyl = sblock.fs_cpg; 3504234Smckusick acg.cg_niblk = sblock.fs_ipg; 3514234Smckusick acg.cg_ndblk = dmax - cbase; 3524788Smckusic acg.cg_cs.cs_ndir = 0; 3534788Smckusic acg.cg_cs.cs_nffree = 0; 3544788Smckusic acg.cg_cs.cs_nbfree = 0; 3554788Smckusic acg.cg_cs.cs_nifree = 0; 3564465Smckusic acg.cg_rotor = dmin; 3574465Smckusic acg.cg_frotor = dmin; 3584257Smckusic acg.cg_irotor = 0; 3595324Smckusic for (i = 0; i < sblock.fs_frag; i++) { 3604465Smckusic acg.cg_frsum[i] = 0; 3614465Smckusic } 3624465Smckusic for (i = 0; i < sblock.fs_ipg; ) { 3635324Smckusic for (j = INOPB(&sblock); j > 0; j--) { 3644234Smckusick clrbit(acg.cg_iused, i); 3654234Smckusick i++; 3664234Smckusick } 3675324Smckusic acg.cg_cs.cs_nifree += INOPB(&sblock); 3684234Smckusick } 3695336Smckusic if (c == 0) 3705336Smckusic for (i = 0; i < ROOTINO; i++) { 3715336Smckusic setbit(acg.cg_iused, i); 3725336Smckusic acg.cg_cs.cs_nifree--; 3735336Smckusic } 3744234Smckusick while (i < MAXIPG) { 3754234Smckusick clrbit(acg.cg_iused, i); 3764234Smckusick i++; 3774234Smckusick } 3785324Smckusic lseek(fso, fsbtodb(&sblock, cgimin(c,&sblock)) * DEV_BSIZE, 0); 3794234Smckusick if (write(fso, (char *)zino, sblock.fs_ipg * sizeof (struct dinode)) != 3804234Smckusick sblock.fs_ipg * sizeof (struct dinode)) 3815324Smckusic printf("write error %D\n", tell(fso) / sblock.fs_bsize); 3824234Smckusick for (i = 0; i < MAXCPG; i++) 3834234Smckusick for (j = 0; j < NRPOS; j++) 3844234Smckusick acg.cg_b[i][j] = 0; 3854234Smckusick if (c == 0) { 3865324Smckusic dmin += howmany(sblock.fs_cssize, sblock.fs_bsize) * 3875324Smckusic sblock.fs_frag; 3884234Smckusick } 3895324Smckusic for (d = 0; d < dmin; d += sblock.fs_frag) 3905324Smckusic clrblock(&sblock, acg.cg_free, d/sblock.fs_frag); 3915324Smckusic while ((d+sblock.fs_frag) <= dmax - cbase) { 3925324Smckusic setblock(&sblock, acg.cg_free, d/sblock.fs_frag); 3934788Smckusic acg.cg_cs.cs_nbfree++; 3945324Smckusic s = d * NSPF(&sblock); 3955324Smckusic acg.cg_b[s / sblock.fs_spc] 3965324Smckusic [s % sblock.fs_nsect * NRPOS / sblock.fs_nsect]++; 3975324Smckusic d += sblock.fs_frag; 3984234Smckusick } 3994234Smckusick if (d < dmax - cbase) 4004251Smckusic for (; d < dmax - cbase; d++) { 4014251Smckusic setbit(acg.cg_free, d); 4024788Smckusic acg.cg_cs.cs_nffree++; 4034251Smckusic } 4045324Smckusic for (; d < MAXBPG(&sblock); d++) 4054234Smckusick clrbit(acg.cg_free, d); 4064788Smckusic sblock.fs_dsize += acg.cg_ndblk - dmin; 4074788Smckusic sblock.fs_cstotal.cs_ndir += acg.cg_cs.cs_ndir; 4084788Smckusic sblock.fs_cstotal.cs_nffree += acg.cg_cs.cs_nffree; 4094788Smckusic sblock.fs_cstotal.cs_nbfree += acg.cg_cs.cs_nbfree; 4104788Smckusic sblock.fs_cstotal.cs_nifree += acg.cg_cs.cs_nifree; 4114788Smckusic *cs = acg.cg_cs; 4125324Smckusic wtfs(fsbtodb(&sblock, cgtod(c, &sblock)), 4135324Smckusic sblock.fs_bsize, (char *)&acg); 4144234Smckusick } 4154234Smckusick 4165336Smckusic /* 4175336Smckusic * initialize the file system 4185336Smckusic */ 4195336Smckusic struct inode node; 4205336Smckusic #define PREDEFDIR 3 4215336Smckusic struct direct root_dir[MAXNDIR] = { 4225336Smckusic { ROOTINO, ".", 0, IFDIR }, 4235336Smckusic { ROOTINO, "..", 0, IFDIR }, 4245336Smckusic { LOSTFOUNDINO, "lost+found", 0, IFDIR }, 4255336Smckusic }; 4265336Smckusic struct direct lost_found_dir[MAXNDIR] = { 4275336Smckusic { LOSTFOUNDINO, ".", 0, IFDIR }, 4285336Smckusic { ROOTINO, "..", 0, IFDIR }, 4295336Smckusic }; 4305336Smckusic 4315336Smckusic fsinit() 4324234Smckusick { 4334234Smckusick /* 4345336Smckusic * initialize the node 4354234Smckusick */ 4365336Smckusic node.i_atime = utime; 4375336Smckusic node.i_mtime = utime; 4385336Smckusic node.i_ctime = utime; 4394234Smckusick /* 4405336Smckusic * create the lost+found directory 4414234Smckusick */ 4425336Smckusic node.i_number = LOSTFOUNDINO; 4435336Smckusic node.i_mode = IFDIR | UMASK; 4445336Smckusic node.i_nlink = 2; 4455336Smckusic node.i_size = sblock.fs_bsize; 4465336Smckusic node.i_db[0] = alloc(node.i_size, node.i_mode); 4475336Smckusic wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, lost_found_dir); 4485336Smckusic iput(&node); 4495336Smckusic /* 4505336Smckusic * create the root directory 4515336Smckusic */ 4525336Smckusic node.i_number = ROOTINO; 4535336Smckusic node.i_mode = IFDIR | UMASK; 4545336Smckusic node.i_nlink = PREDEFDIR; 4555336Smckusic node.i_size = PREDEFDIR * sizeof(struct direct); 4565336Smckusic node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode); 4575336Smckusic wtfs(fsbtodb(&sblock, node.i_db[0]), sblock.fs_fsize, root_dir); 4585336Smckusic iput(&node); 4594234Smckusick } 4604234Smckusick 4615336Smckusic /* 4625336Smckusic * allocate a block or frag 4635336Smckusic */ 4644234Smckusick daddr_t 4654427Smckusic alloc(size, mode) 4664427Smckusic int size; 4674427Smckusic int mode; 4684234Smckusick { 4694234Smckusick int c, i, s, frag; 4704234Smckusick daddr_t d; 4714234Smckusick 4724234Smckusick c = 0; 4735324Smckusic rdfs(fsbtodb(&sblock, cgtod(0,&sblock)), 4745336Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg); 4754788Smckusic if (acg.cg_cs.cs_nbfree == 0) { 4764234Smckusick printf("first cylinder group ran out of space\n"); 4774234Smckusick return (0); 4784234Smckusick } 4795324Smckusic for (d = 0; d < acg.cg_ndblk; d += sblock.fs_frag) 4805324Smckusic if (isblock(&sblock, acg.cg_free, d / sblock.fs_frag)) 4814234Smckusick goto goth; 4824234Smckusick printf("internal error: can't find block in cyl 0\n"); 4834234Smckusick return (0); 4844234Smckusick goth: 4855324Smckusic clrblock(&sblock, acg.cg_free, d / sblock.fs_frag); 4864788Smckusic acg.cg_cs.cs_nbfree--; 4874788Smckusic sblock.fs_cstotal.cs_nbfree--; 4884234Smckusick fscs[0].cs_nbfree--; 4894427Smckusic if (mode & IFDIR) { 4904788Smckusic acg.cg_cs.cs_ndir++; 4914788Smckusic sblock.fs_cstotal.cs_ndir++; 4924427Smckusic fscs[0].cs_ndir++; 4934427Smckusic } 4945324Smckusic s = d * NSPF(&sblock); 4955324Smckusic acg.cg_b[s / sblock.fs_spc] 4965324Smckusic [s % sblock.fs_nsect * NRPOS / sblock.fs_nsect]--; 4975324Smckusic if (size != sblock.fs_bsize) { 4985324Smckusic frag = howmany(size, sblock.fs_fsize); 4995324Smckusic fscs[0].cs_nffree += sblock.fs_frag - frag; 5005324Smckusic sblock.fs_cstotal.cs_nffree += sblock.fs_frag - frag; 5015324Smckusic acg.cg_cs.cs_nffree += sblock.fs_frag - frag; 5025324Smckusic acg.cg_frsum[sblock.fs_frag - frag]++; 5035324Smckusic for (i = frag; i < sblock.fs_frag; i++) 5044234Smckusick setbit(acg.cg_free, d+i); 5054234Smckusick } 5065324Smckusic wtfs(fsbtodb(&sblock, cgtod(0,&sblock)), 5075324Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg); 5084234Smckusick return (d); 5094234Smckusick } 5104234Smckusick 5115336Smckusic /* 5125336Smckusic * Allocate an inode on the disk 5135336Smckusic */ 5145336Smckusic iput(ip) 5155336Smckusic register struct inode *ip; 5164234Smckusick { 5175336Smckusic struct dinode buf[MAXINOPB]; 5185336Smckusic daddr_t d; 5195336Smckusic int c; 5204234Smckusick 5215336Smckusic c = itog(ip->i_number, &sblock); 5225336Smckusic rdfs(fsbtodb(&sblock, cgtod(c,&sblock)), 5235336Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg); 5245336Smckusic acg.cg_cs.cs_nifree--; 5255336Smckusic setbit(acg.cg_iused, ip->i_number); 5265336Smckusic wtfs(fsbtodb(&sblock, cgtod(c,&sblock)), 5275336Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg); 5285336Smckusic sblock.fs_cstotal.cs_nifree--; 5295336Smckusic fscs[0].cs_nifree--; 5305336Smckusic if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 5315336Smckusic printf("fsinit: inode value out of range (%d).\n", 5325336Smckusic ip->i_number); 5335336Smckusic exit(1); 5345336Smckusic } 5355336Smckusic d = fsbtodb(&sblock, itod(ip->i_number, &sblock)); 5365336Smckusic rdfs(d, sblock.fs_bsize, buf); 5375336Smckusic buf[itoo(ip->i_number, &sblock)].di_ic = ip->i_ic; 5385336Smckusic wtfs(d, sblock.fs_bsize, buf); 5394234Smckusick } 5404234Smckusick 5415336Smckusic /* 5425336Smckusic * read a block from the file system 5435336Smckusic */ 5445336Smckusic rdfs(bno, size, bf) 5455336Smckusic daddr_t bno; 5464427Smckusic int size; 5475336Smckusic char *bf; 5484234Smckusick { 5495336Smckusic int n; 5504234Smckusick 551*5346Smckusic if (lseek(fsi, bno * DEV_BSIZE, 0) < 0) { 552*5346Smckusic printf("seek error: %ld\n", bno); 553*5346Smckusic perror("rdfs"); 554*5346Smckusic exit(1); 555*5346Smckusic } 5565336Smckusic n = read(fsi, bf, size); 5575336Smckusic if(n != size) { 5585336Smckusic printf("read error: %ld\n", bno); 559*5346Smckusic perror("rdfs"); 5605336Smckusic exit(1); 5614234Smckusick } 5624234Smckusick } 5634234Smckusick 5645336Smckusic /* 5655336Smckusic * write a block to the file system 5665336Smckusic */ 5675336Smckusic wtfs(bno, size, bf) 5685336Smckusic daddr_t bno; 5695336Smckusic int size; 5705336Smckusic char *bf; 5714234Smckusick { 5725336Smckusic int n; 5734234Smckusick 5745336Smckusic lseek(fso, bno * DEV_BSIZE, 0); 575*5346Smckusic if (lseek(fso, bno * DEV_BSIZE, 0) < 0) { 576*5346Smckusic printf("seek error: %ld\n", bno); 577*5346Smckusic perror("wtfs"); 578*5346Smckusic exit(1); 579*5346Smckusic } 5805336Smckusic n = write(fso, bf, size); 5815336Smckusic if(n != size) { 5825336Smckusic printf("write error: %D\n", bno); 583*5346Smckusic perror("wtfs"); 5844234Smckusick exit(1); 5854234Smckusick } 5864234Smckusick } 5875324Smckusic 5885324Smckusic /* 5895336Smckusic * check if a block is available 5905324Smckusic */ 5915324Smckusic isblock(fs, cp, h) 5925324Smckusic struct fs *fs; 5935324Smckusic unsigned char *cp; 5945324Smckusic int h; 5955324Smckusic { 5965324Smckusic unsigned char mask; 5975324Smckusic 5985324Smckusic switch (fs->fs_frag) { 5995324Smckusic case 8: 6005324Smckusic return (cp[h] == 0xff); 6015324Smckusic case 4: 6025324Smckusic mask = 0x0f << ((h & 0x1) << 2); 6035324Smckusic return ((cp[h >> 1] & mask) == mask); 6045324Smckusic case 2: 6055324Smckusic mask = 0x03 << ((h & 0x3) << 1); 6065324Smckusic return ((cp[h >> 2] & mask) == mask); 6075324Smckusic case 1: 6085324Smckusic mask = 0x01 << (h & 0x7); 6095324Smckusic return ((cp[h >> 3] & mask) == mask); 6105324Smckusic default: 6115324Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 6125324Smckusic return; 6135324Smckusic } 6145324Smckusic } 6155324Smckusic 6165336Smckusic /* 6175336Smckusic * take a block out of the map 6185336Smckusic */ 6195324Smckusic clrblock(fs, cp, h) 6205324Smckusic struct fs *fs; 6215324Smckusic unsigned char *cp; 6225324Smckusic int h; 6235324Smckusic { 6245324Smckusic switch ((fs)->fs_frag) { 6255324Smckusic case 8: 6265324Smckusic cp[h] = 0; 6275324Smckusic return; 6285324Smckusic case 4: 6295324Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 6305324Smckusic return; 6315324Smckusic case 2: 6325324Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 6335324Smckusic return; 6345324Smckusic case 1: 6355324Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 6365324Smckusic return; 6375324Smckusic default: 6385324Smckusic fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 6395324Smckusic return; 6405324Smckusic } 6415324Smckusic } 6425324Smckusic 6435336Smckusic /* 6445336Smckusic * put a block into the map 6455336Smckusic */ 6465324Smckusic setblock(fs, cp, h) 6475324Smckusic struct fs *fs; 6485324Smckusic unsigned char *cp; 6495324Smckusic int h; 6505324Smckusic { 6515324Smckusic switch (fs->fs_frag) { 6525324Smckusic case 8: 6535324Smckusic cp[h] = 0xff; 6545324Smckusic return; 6555324Smckusic case 4: 6565324Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 6575324Smckusic return; 6585324Smckusic case 2: 6595324Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 6605324Smckusic return; 6615324Smckusic case 1: 6625324Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 6635324Smckusic return; 6645324Smckusic default: 6655324Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 6665324Smckusic return; 6675324Smckusic } 6685324Smckusic } 669