1*5336Smckusic static char *sccsid = "@(#)mkfs.c 1.11 (Berkeley) 01/06/82"; 24234Smckusick 34234Smckusick /* 44234Smckusick * make file system for cylinder-group style file systems 54234Smckusick * 6*5336Smckusic * 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 19*5336Smckusic #define UMASK 0755 20*5336Smckusic #define MAXNDIR (MAXBSIZE / sizeof(struct direct)) 21*5336Smckusic #define POWEROF2(num) (((num) & ((num) - 1)) == 0) 224234Smckusick 234234Smckusick union { 244234Smckusick struct fs fs; 255324Smckusic char pad[MAXBSIZE]; 264234Smckusick } fsun; 274234Smckusick #define sblock fsun.fs 284234Smckusick struct csum *fscs; 294234Smckusick 304234Smckusick union { 314234Smckusick struct cg cg; 325324Smckusic char pad[MAXBSIZE]; 334234Smckusick } cgun; 344234Smckusick #define acg cgun.cg 354234Smckusick 36*5336Smckusic struct dinode zino[MAXIPG]; 37*5336Smckusic 384234Smckusick char *fsys; 39*5336Smckusic time_t utime; 40*5336Smckusic int fsi; 41*5336Smckusic int fso; 424234Smckusick daddr_t alloc(); 434234Smckusick 444234Smckusick main(argc, argv) 455324Smckusic int argc; 465324Smckusic char *argv[]; 474234Smckusick { 48*5336Smckusic long c, i, inos, fssize; 494234Smckusick 50*5336Smckusic #ifndef STANDALONE 514234Smckusick argc--, argv++; 524234Smckusick time(&utime); 53*5336Smckusic if (argc < 2) { 54*5336Smckusic printf("usage: mkfs special size [ nsect ntrak bsize fsize cpg ]\n"); 554234Smckusick exit(1); 564234Smckusick } 574234Smckusick fsys = argv[0]; 58*5336Smckusic fssize = atoi(argv[1]); 59*5336Smckusic fso = creat(fsys, 0666); 60*5336Smckusic if(fso < 0) { 61*5336Smckusic printf("%s: cannot create\n", fsys); 62*5336Smckusic exit(1); 63*5336Smckusic } 64*5336Smckusic fsi = open(fsys, 0); 65*5336Smckusic if(fsi < 0) { 66*5336Smckusic printf("%s: cannot open\n", fsys); 67*5336Smckusic exit(1); 68*5336Smckusic } 694234Smckusick #else 704234Smckusick { 714234Smckusick static char protos[60]; 72*5336Smckusic char fsbuf[100]; 734234Smckusick 744234Smckusick printf("file sys size: "); 754234Smckusick gets(protos); 76*5336Smckusic fssize = atoi(protos); 774234Smckusick do { 784234Smckusick printf("file system: "); 794234Smckusick gets(fsbuf); 804234Smckusick fso = open(fsbuf, 1); 814234Smckusick fsi = open(fsbuf, 0); 824234Smckusick } while (fso < 0 || fsi < 0); 834234Smckusick } 844234Smckusick argc = 0; 85*5336Smckusic #endif 86*5336Smckusic if (fssize <= 0) 87*5336Smckusic printf("preposterous size %d\n", fssize), exit(1); 88*5336Smckusic /* 89*5336Smckusic * collect and verify the sector and track info 90*5336Smckusic */ 91*5336Smckusic if (argc > 2) 92*5336Smckusic sblock.fs_nsect = atoi(argv[2]); 93*5336Smckusic else 94*5336Smckusic sblock.fs_nsect = DFLNSECT; 95*5336Smckusic if (argc > 3) 96*5336Smckusic sblock.fs_ntrak = atoi(argv[3]); 97*5336Smckusic else 98*5336Smckusic sblock.fs_ntrak = DFLNTRAK; 99*5336Smckusic if (sblock.fs_ntrak <= 0) 100*5336Smckusic printf("preposterous ntrak %d\n", sblock.fs_ntrak), exit(1); 101*5336Smckusic if (sblock.fs_nsect <= 0) 102*5336Smckusic printf("preposterous nsect %d\n", sblock.fs_nsect), exit(1); 103*5336Smckusic sblock.fs_spc = sblock.fs_ntrak * sblock.fs_nsect; 104*5336Smckusic /* 105*5336Smckusic * collect and verify the block and fragment sizes 106*5336Smckusic */ 107*5336Smckusic if (argc > 4) 108*5336Smckusic sblock.fs_bsize = atoi(argv[4]); 109*5336Smckusic else 110*5336Smckusic sblock.fs_bsize = MAXBSIZE; 111*5336Smckusic if (argc > 5) 112*5336Smckusic sblock.fs_fsize = atoi(argv[5]); 113*5336Smckusic else 114*5336Smckusic sblock.fs_fsize = MAX(sblock.fs_bsize / DESFRAG, DEV_BSIZE); 115*5336Smckusic if (!POWEROF2(sblock.fs_bsize)) { 116*5336Smckusic printf("block size must be a power of 2, not %d\n", 117*5336Smckusic sblock.fs_bsize); 1184234Smckusick exit(1); 1194234Smckusick } 120*5336Smckusic if (!POWEROF2(sblock.fs_fsize)) { 121*5336Smckusic printf("fragment size must be a power of 2, not %d\n", 122*5336Smckusic sblock.fs_fsize); 1234234Smckusick exit(1); 1244234Smckusick } 1255324Smckusic if (sblock.fs_fsize < DEV_BSIZE) { 1265324Smckusic printf("fragment size %d is too small, minimum is %d\n", 1275324Smckusic sblock.fs_fsize, DEV_BSIZE); 1285324Smckusic exit(1); 1295324Smckusic } 1305324Smckusic if (sblock.fs_bsize < MINBSIZE) { 1315324Smckusic printf("block size %d is too small, minimum is %d\n", 1325324Smckusic sblock.fs_bsize, MINBSIZE); 1335324Smckusic exit(1); 1345324Smckusic } 135*5336Smckusic if (sblock.fs_bsize < sblock.fs_fsize) { 136*5336Smckusic printf("block size (%d) cannot be smaller than fragment size (%d)\n", 137*5336Smckusic sblock.fs_bsize, sblock.fs_fsize); 1384234Smckusick exit(1); 1394234Smckusick } 140*5336Smckusic sblock.fs_frag = sblock.fs_bsize / sblock.fs_fsize; 141*5336Smckusic if (sblock.fs_frag > MAXFRAG) { 142*5336Smckusic printf("fragment size %d is too small, minimum with block size %d is %d\n", 143*5336Smckusic sblock.fs_fsize, sblock.fs_bsize, 144*5336Smckusic sblock.fs_bsize / MAXFRAG); 145*5336Smckusic exit(1); 1464234Smckusick } 147*5336Smckusic /* 148*5336Smckusic * collect and verify the number of cylinders per group 1494234Smckusick */ 150*5336Smckusic if (argc > 6) { 151*5336Smckusic sblock.fs_cpg = atoi(argv[6]); 152*5336Smckusic sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 1534234Smckusick } else { 1544234Smckusick sblock.fs_cpg = DESCPG; 155*5336Smckusic sblock.fs_fpg = (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 156*5336Smckusic while (sblock.fs_fpg / sblock.fs_frag > MAXBPG(&sblock)) { 1574234Smckusick --sblock.fs_cpg; 158*5336Smckusic sblock.fs_fpg = 159*5336Smckusic (sblock.fs_cpg * sblock.fs_spc) / NSPF(&sblock); 160*5336Smckusic } 1614234Smckusick } 162*5336Smckusic if (sblock.fs_cpg < 1) { 163*5336Smckusic printf("cylinder groups must have at least 1 cylinder\n"); 164*5336Smckusic exit(1); 165*5336Smckusic } 166*5336Smckusic if (sblock.fs_cpg > MAXCPG) { 167*5336Smckusic printf("cylinder groups are limited to %d cylinders\n", MAXCPG); 168*5336Smckusic exit(1); 169*5336Smckusic } 1704234Smckusick /* 171*5336Smckusic * Now have size for file system and nsect and ntrak. 172*5336Smckusic * Determine number of cylinders and blocks in the file system. 173*5336Smckusic */ 174*5336Smckusic sblock.fs_size = fssize = dbtofsb(&sblock, fssize); 175*5336Smckusic sblock.fs_ncyl = fssize * NSPF(&sblock) / sblock.fs_spc; 176*5336Smckusic if (sblock.fs_spc > MAXBPC * NSPB(&sblock)) { 177*5336Smckusic printf("too many sectors per cylinder (%d sectors)\n", 178*5336Smckusic sblock.fs_spc); 179*5336Smckusic while (sblock.fs_spc > MAXBPC * NSPB(&sblock)) 180*5336Smckusic sblock.fs_bsize <<= 1; 181*5336Smckusic printf("nsect %d, and ntrak %d, requires block size of %d\n", 182*5336Smckusic sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_bsize); 183*5336Smckusic exit(1); 184*5336Smckusic } 185*5336Smckusic /* 186*5336Smckusic * Validate specified/determined cpg. 187*5336Smckusic */ 188*5336Smckusic if (sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) { 189*5336Smckusic printf("too many sectors per cylinder (%d sectors)\n", 190*5336Smckusic sblock.fs_spc); 191*5336Smckusic while(sblock.fs_spc > MAXBPG(&sblock) * NSPB(&sblock)) { 192*5336Smckusic sblock.fs_bsize <<= 1; 193*5336Smckusic if (sblock.fs_frag < MAXFRAG) 194*5336Smckusic sblock.fs_frag <<= 1; 195*5336Smckusic else 196*5336Smckusic sblock.fs_fsize <<= 1; 197*5336Smckusic } 198*5336Smckusic printf("nsect %d, and ntrak %d, requires block size of %d,\n", 199*5336Smckusic sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_bsize); 200*5336Smckusic printf("\tand fragment size of %d\n", sblock.fs_fsize); 201*5336Smckusic exit(1); 202*5336Smckusic } 203*5336Smckusic if (sblock.fs_fpg > MAXBPG(&sblock) * sblock.fs_frag) { 204*5336Smckusic printf("cylinder group too large (%d cylinders); ", 205*5336Smckusic sblock.fs_cpg); 206*5336Smckusic printf("max: %d cylinders\n", 207*5336Smckusic MAXBPG(&sblock) * sblock.fs_frag / 208*5336Smckusic (sblock.fs_fpg / sblock.fs_cpg)); 209*5336Smckusic exit(1); 210*5336Smckusic } 211*5336Smckusic sblock.fs_cgsize = roundup(sizeof(struct cg) + 212*5336Smckusic howmany(sblock.fs_fpg, NBBY), sblock.fs_fsize); 213*5336Smckusic /* 2144234Smckusick * Compute/validate number of cylinder groups. 2154234Smckusick */ 216*5336Smckusic if (fssize * NSPF(&sblock) > sblock.fs_ncyl * sblock.fs_spc) { 217*5336Smckusic printf("%d sector(s) in last cylinder unused\n", 218*5336Smckusic fssize * NSPF(&sblock) - sblock.fs_ncyl * sblock.fs_spc); 219*5336Smckusic } 2204234Smckusick sblock.fs_ncg = sblock.fs_ncyl / sblock.fs_cpg; 2214234Smckusick if (sblock.fs_ncyl % sblock.fs_cpg) 2224234Smckusick sblock.fs_ncg++; 223*5336Smckusic if ((sblock.fs_spc * sblock.fs_cpg) % NSPF(&sblock)) { 2244234Smckusick printf("mkfs: nsect %d, ntrak %d, cpg %d is not tolerable\n", 2254234Smckusick sblock.fs_nsect, sblock.fs_ntrak, sblock.fs_cpg); 2264234Smckusick printf("as this would would have cyl groups whose size\n"); 2275324Smckusic printf("is not a multiple of %d; choke!\n", sblock.fs_fsize); 2284234Smckusick exit(1); 2294234Smckusick } 2304234Smckusick fscs = (struct csum *) 2315324Smckusic calloc(1, roundup(sblock.fs_ncg * sizeof (struct csum), 2325324Smckusic sblock.fs_bsize)); 2334234Smckusick /* 2344234Smckusick * Compute number of inode blocks per cylinder group. 2354234Smckusick * Start with one inode per NBPI bytes; adjust as necessary. 2364234Smckusick */ 237*5336Smckusic inos = ((fssize * sblock.fs_fsize) / MAX(NBPI, sblock.fs_fsize)) / 238*5336Smckusic INOPB(&sblock); 239*5336Smckusic if (inos <= 0) 240*5336Smckusic inos = 1; 241*5336Smckusic sblock.fs_ipg = ((inos / sblock.fs_ncg) + 1) * INOPB(&sblock); 2424234Smckusick if (sblock.fs_ipg > MAXIPG) 2434234Smckusick sblock.fs_ipg = MAXIPG; 2445324Smckusic if (cgdmin(0,&sblock) >= sblock.fs_fpg) { 2454234Smckusick printf("inode blocks/cyl group (%d) >= data blocks (%d)\n", 2465324Smckusic cgdmin(0,&sblock) / sblock.fs_frag, 2475324Smckusic sblock.fs_fpg / sblock.fs_frag); 248*5336Smckusic printf("number of cylinder per cylinder group must be increased\n"); 2495324Smckusic exit(1); 2505324Smckusic } 251*5336Smckusic /* 252*5336Smckusic * calculate the available blocks for each rotational position 253*5336Smckusic */ 254*5336Smckusic for (i = 0; i < NRPOS; i++) 255*5336Smckusic sblock.fs_postbl[i] = -1; 256*5336Smckusic for (i = 0; i < sblock.fs_spc; i += NSPB(&sblock)) 257*5336Smckusic /* void */; 258*5336Smckusic for (i -= NSPB(&sblock); i >= 0; i -= NSPB(&sblock)) { 259*5336Smckusic c = i % sblock.fs_nsect * NRPOS / sblock.fs_nsect; 260*5336Smckusic sblock.fs_rotbl[i / NSPB(&sblock)] = sblock.fs_postbl[c]; 261*5336Smckusic sblock.fs_postbl[c] = i / NSPB(&sblock); 262*5336Smckusic } 263*5336Smckusic /* 264*5336Smckusic * fill in remaining fields of the super block 265*5336Smckusic */ 2665324Smckusic sblock.fs_csaddr = cgdmin(0, &sblock); 2675324Smckusic sblock.fs_cssize = sblock.fs_ncg * sizeof(struct csum); 268*5336Smckusic sblock.fs_rotdelay = ROTDELAY; 269*5336Smckusic sblock.fs_minfree = MINFREE; 270*5336Smckusic sblock.fs_magic = FS_MAGIC; 2714234Smckusick sblock.fs_sblkno = SBLOCK; 272*5336Smckusic sblock.fs_cgrotor = 0; 273*5336Smckusic sblock.fs_cstotal.cs_ndir = 0; 274*5336Smckusic sblock.fs_cstotal.cs_nbfree = 0; 275*5336Smckusic sblock.fs_cstotal.cs_nifree = 0; 276*5336Smckusic sblock.fs_cstotal.cs_nffree = 0; 2774234Smckusick sblock.fs_fmod = 0; 2784234Smckusick sblock.fs_ronly = 0; 2794234Smckusick /* 280*5336Smckusic * Dump out summary information about file system. 2814234Smckusick */ 2824234Smckusick printf("%s:\t%d sectors in %d cylinders of %d tracks, %d sectors\n", 283*5336Smckusic fsys, sblock.fs_size * NSPF(&sblock), sblock.fs_ncyl, 2845324Smckusic sblock.fs_ntrak, sblock.fs_nsect); 2854234Smckusick printf("\t%.1fMb in %d cyl groups (%d c/g, %.2fMb/g, %d i/g)\n", 2865324Smckusic (float)sblock.fs_size * sblock.fs_fsize * 1e-6, sblock.fs_ncg, 2875324Smckusic sblock.fs_cpg, (float)sblock.fs_fpg * sblock.fs_fsize * 1e-6, 2885324Smckusic sblock.fs_ipg); 2894234Smckusick /* 2904234Smckusick * Now build the cylinders group blocks and 291*5336Smckusic * then print out indices of cylinder groups. 2924234Smckusick */ 2934234Smckusick for (c = 0; c < sblock.fs_ncg; c++) 2944234Smckusick initcg(c); 2955324Smckusic if (sblock.fs_ncg == 1) 2965324Smckusic printf("Warning, no super-block backups with only one cylinder group\n"); 2975324Smckusic else 2985324Smckusic printf("\tsuper-block backups (for fsck -b#) at %d+k*%d (%d .. %d)\n", 2995324Smckusic SBLOCK, fsbtodb(&sblock, sblock.fs_fpg), 3005324Smckusic SBLOCK + fsbtodb(&sblock, sblock.fs_fpg), 3015324Smckusic SBLOCK + fsbtodb(&sblock, (sblock.fs_ncg - 1) * 3025324Smckusic sblock.fs_fpg)); 3034234Smckusick /* 304*5336Smckusic * Now construct the initial file system, 3054234Smckusick * then write out the super-block. 3064234Smckusick */ 307*5336Smckusic fsinit(); 3084234Smckusick sblock.fs_time = utime; 309*5336Smckusic 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); 313*5336Smckusic /* 314*5336Smckusic * Write out the duplicate super blocks 315*5336Smckusic */ 316*5336Smckusic for (c = 1; c < sblock.fs_ncg; c++) 3175324Smckusic wtfs(fsbtodb(&sblock, cgsblock(c, &sblock)), 318*5336Smckusic SBSIZE, (char *)&sblock); 3194234Smckusick #ifndef STANDALONE 320*5336Smckusic 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 } 369*5336Smckusic if (c == 0) 370*5336Smckusic for (i = 0; i < ROOTINO; i++) { 371*5336Smckusic setbit(acg.cg_iused, i); 372*5336Smckusic acg.cg_cs.cs_nifree--; 373*5336Smckusic } 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 416*5336Smckusic /* 417*5336Smckusic * initialize the file system 418*5336Smckusic */ 419*5336Smckusic struct inode node; 420*5336Smckusic #define PREDEFDIR 3 421*5336Smckusic struct direct root_dir[MAXNDIR] = { 422*5336Smckusic { ROOTINO, ".", 0, IFDIR }, 423*5336Smckusic { ROOTINO, "..", 0, IFDIR }, 424*5336Smckusic { LOSTFOUNDINO, "lost+found", 0, IFDIR }, 425*5336Smckusic }; 426*5336Smckusic struct direct lost_found_dir[MAXNDIR] = { 427*5336Smckusic { LOSTFOUNDINO, ".", 0, IFDIR }, 428*5336Smckusic { ROOTINO, "..", 0, IFDIR }, 429*5336Smckusic }; 430*5336Smckusic 431*5336Smckusic fsinit() 4324234Smckusick { 4334234Smckusick /* 434*5336Smckusic * initialize the node 4354234Smckusick */ 436*5336Smckusic node.i_atime = utime; 437*5336Smckusic node.i_mtime = utime; 438*5336Smckusic node.i_ctime = utime; 4394234Smckusick /* 440*5336Smckusic * create the lost+found directory 4414234Smckusick */ 442*5336Smckusic node.i_number = LOSTFOUNDINO; 443*5336Smckusic node.i_mode = IFDIR | UMASK; 444*5336Smckusic node.i_nlink = 2; 445*5336Smckusic node.i_size = sblock.fs_bsize; 446*5336Smckusic node.i_db[0] = alloc(node.i_size, node.i_mode); 447*5336Smckusic wtfs(fsbtodb(&sblock, node.i_db[0]), node.i_size, lost_found_dir); 448*5336Smckusic iput(&node); 449*5336Smckusic /* 450*5336Smckusic * create the root directory 451*5336Smckusic */ 452*5336Smckusic node.i_number = ROOTINO; 453*5336Smckusic node.i_mode = IFDIR | UMASK; 454*5336Smckusic node.i_nlink = PREDEFDIR; 455*5336Smckusic node.i_size = PREDEFDIR * sizeof(struct direct); 456*5336Smckusic node.i_db[0] = alloc(sblock.fs_fsize, node.i_mode); 457*5336Smckusic wtfs(fsbtodb(&sblock, node.i_db[0]), sblock.fs_fsize, root_dir); 458*5336Smckusic iput(&node); 4594234Smckusick } 4604234Smckusick 461*5336Smckusic /* 462*5336Smckusic * allocate a block or frag 463*5336Smckusic */ 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)), 474*5336Smckusic 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 511*5336Smckusic /* 512*5336Smckusic * Allocate an inode on the disk 513*5336Smckusic */ 514*5336Smckusic iput(ip) 515*5336Smckusic register struct inode *ip; 5164234Smckusick { 517*5336Smckusic struct dinode buf[MAXINOPB]; 518*5336Smckusic daddr_t d; 519*5336Smckusic int c; 5204234Smckusick 521*5336Smckusic c = itog(ip->i_number, &sblock); 522*5336Smckusic rdfs(fsbtodb(&sblock, cgtod(c,&sblock)), 523*5336Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg); 524*5336Smckusic acg.cg_cs.cs_nifree--; 525*5336Smckusic setbit(acg.cg_iused, ip->i_number); 526*5336Smckusic wtfs(fsbtodb(&sblock, cgtod(c,&sblock)), 527*5336Smckusic roundup(sblock.fs_cgsize, DEV_BSIZE), (char *)&acg); 528*5336Smckusic sblock.fs_cstotal.cs_nifree--; 529*5336Smckusic fscs[0].cs_nifree--; 530*5336Smckusic if(ip->i_number >= sblock.fs_ipg * sblock.fs_ncg) { 531*5336Smckusic printf("fsinit: inode value out of range (%d).\n", 532*5336Smckusic ip->i_number); 533*5336Smckusic exit(1); 534*5336Smckusic } 535*5336Smckusic d = fsbtodb(&sblock, itod(ip->i_number, &sblock)); 536*5336Smckusic rdfs(d, sblock.fs_bsize, buf); 537*5336Smckusic buf[itoo(ip->i_number, &sblock)].di_ic = ip->i_ic; 538*5336Smckusic wtfs(d, sblock.fs_bsize, buf); 5394234Smckusick } 5404234Smckusick 541*5336Smckusic /* 542*5336Smckusic * read a block from the file system 543*5336Smckusic */ 544*5336Smckusic rdfs(bno, size, bf) 545*5336Smckusic daddr_t bno; 5464427Smckusic int size; 547*5336Smckusic char *bf; 5484234Smckusick { 549*5336Smckusic int n; 5504234Smckusick 551*5336Smckusic lseek(fsi, bno * DEV_BSIZE, 0); 552*5336Smckusic n = read(fsi, bf, size); 553*5336Smckusic if(n != size) { 554*5336Smckusic printf("read error: %ld\n", bno); 555*5336Smckusic exit(1); 5564234Smckusick } 5574234Smckusick } 5584234Smckusick 559*5336Smckusic /* 560*5336Smckusic * write a block to the file system 561*5336Smckusic */ 562*5336Smckusic wtfs(bno, size, bf) 563*5336Smckusic daddr_t bno; 564*5336Smckusic int size; 565*5336Smckusic char *bf; 5664234Smckusick { 567*5336Smckusic int n; 5684234Smckusick 569*5336Smckusic printf("wtfs: bno %d, size %d, buf %d\n", bno, size, bf); 570*5336Smckusic lseek(fso, bno * DEV_BSIZE, 0); 571*5336Smckusic n = write(fso, bf, size); 572*5336Smckusic if(n != size) { 573*5336Smckusic printf("write error: %D\n", bno); 5744234Smckusick exit(1); 5754234Smckusick } 5764234Smckusick } 5775324Smckusic 5785324Smckusic /* 579*5336Smckusic * check if a block is available 5805324Smckusic */ 5815324Smckusic isblock(fs, cp, h) 5825324Smckusic struct fs *fs; 5835324Smckusic unsigned char *cp; 5845324Smckusic int h; 5855324Smckusic { 5865324Smckusic unsigned char mask; 5875324Smckusic 5885324Smckusic switch (fs->fs_frag) { 5895324Smckusic case 8: 5905324Smckusic return (cp[h] == 0xff); 5915324Smckusic case 4: 5925324Smckusic mask = 0x0f << ((h & 0x1) << 2); 5935324Smckusic return ((cp[h >> 1] & mask) == mask); 5945324Smckusic case 2: 5955324Smckusic mask = 0x03 << ((h & 0x3) << 1); 5965324Smckusic return ((cp[h >> 2] & mask) == mask); 5975324Smckusic case 1: 5985324Smckusic mask = 0x01 << (h & 0x7); 5995324Smckusic return ((cp[h >> 3] & mask) == mask); 6005324Smckusic default: 6015324Smckusic fprintf(stderr, "isblock bad fs_frag %d\n", fs->fs_frag); 6025324Smckusic return; 6035324Smckusic } 6045324Smckusic } 6055324Smckusic 606*5336Smckusic /* 607*5336Smckusic * take a block out of the map 608*5336Smckusic */ 6095324Smckusic clrblock(fs, cp, h) 6105324Smckusic struct fs *fs; 6115324Smckusic unsigned char *cp; 6125324Smckusic int h; 6135324Smckusic { 6145324Smckusic switch ((fs)->fs_frag) { 6155324Smckusic case 8: 6165324Smckusic cp[h] = 0; 6175324Smckusic return; 6185324Smckusic case 4: 6195324Smckusic cp[h >> 1] &= ~(0x0f << ((h & 0x1) << 2)); 6205324Smckusic return; 6215324Smckusic case 2: 6225324Smckusic cp[h >> 2] &= ~(0x03 << ((h & 0x3) << 1)); 6235324Smckusic return; 6245324Smckusic case 1: 6255324Smckusic cp[h >> 3] &= ~(0x01 << (h & 0x7)); 6265324Smckusic return; 6275324Smckusic default: 6285324Smckusic fprintf(stderr, "clrblock bad fs_frag %d\n", fs->fs_frag); 6295324Smckusic return; 6305324Smckusic } 6315324Smckusic } 6325324Smckusic 633*5336Smckusic /* 634*5336Smckusic * put a block into the map 635*5336Smckusic */ 6365324Smckusic setblock(fs, cp, h) 6375324Smckusic struct fs *fs; 6385324Smckusic unsigned char *cp; 6395324Smckusic int h; 6405324Smckusic { 6415324Smckusic switch (fs->fs_frag) { 6425324Smckusic case 8: 6435324Smckusic cp[h] = 0xff; 6445324Smckusic return; 6455324Smckusic case 4: 6465324Smckusic cp[h >> 1] |= (0x0f << ((h & 0x1) << 2)); 6475324Smckusic return; 6485324Smckusic case 2: 6495324Smckusic cp[h >> 2] |= (0x03 << ((h & 0x3) << 1)); 6505324Smckusic return; 6515324Smckusic case 1: 6525324Smckusic cp[h >> 3] |= (0x01 << (h & 0x7)); 6535324Smckusic return; 6545324Smckusic default: 6555324Smckusic fprintf(stderr, "setblock bad fs_frag %d\n", fs->fs_frag); 6565324Smckusic return; 6575324Smckusic } 6585324Smckusic } 659