📄 lfs.c
字号:
/* * Initialize dynamic accounting. The blocks available for * writing are the bfree blocks minus 1 segment summary for * each segment since you can't write any new data without * creating a segment summary - 2 segments that the cleaner * needs. */ lfsp->lfs_avail = lfsp->lfs_bfree - lfsp->lfs_nseg - fsbtodb(lfsp, 2 * lfsp->lfs_ssize); lfsp->lfs_uinodes = 0; /* * Ready to start writing segments. The first segment is different * because it contains the segment usage table and the ifile inode * as well as a superblock. For the rest of the segments, set the * time stamp to be 0 so that the first segment is the most recent. * For each segment that is supposed to contain a copy of the super * block, initialize its first few blocks and its segment summary * to indicate this. */ lfsp->lfs_nfiles = LFS_FIRST_INUM - 1; lfsp->lfs_cksum = cksum(lfsp, sizeof(struct lfs) - sizeof(lfsp->lfs_cksum)); /* Now create a block of disk inodes */ if (!(dpagep = malloc(lfsp->lfs_bsize))) fatal("%s", strerror(errno)); dip = (struct dinode *)dpagep; bzero(dip, lfsp->lfs_bsize); /* Create a block of IFILE structures. */ if (!(ipagep = malloc(lfsp->lfs_bsize))) fatal("%s", strerror(errno)); ifile = (IFILE *)ipagep; /* * Initialize IFILE. It is the next block following the * block of inodes (whose address has been calculated in * lfsp->lfs_idaddr; */ sb_addr = lfsp->lfs_idaddr + lfsp->lfs_bsize / lp->d_secsize; sb_addr = make_dinode(LFS_IFILE_INUM, dip, lfsp->lfs_cleansz + lfsp->lfs_segtabsz+1, sb_addr, lfsp); dip->di_mode = IFREG|IREAD|IWRITE; ip = &ifile[LFS_IFILE_INUM]; ip->if_version = 1; ip->if_daddr = lfsp->lfs_idaddr; /* Initialize the ROOT Directory */ sb_addr = make_dinode(ROOTINO, ++dip, 1, sb_addr, lfsp); dip->di_mode = IFDIR|IREAD|IWRITE|IEXEC; dip->di_size = DIRBLKSIZ; dip->di_nlink = 3; ip = &ifile[ROOTINO]; ip->if_version = 1; ip->if_daddr = lfsp->lfs_idaddr; /* Initialize the lost+found Directory */ sb_addr = make_dinode(LOSTFOUNDINO, ++dip, 1, sb_addr, lfsp); dip->di_mode = IFDIR|IREAD|IWRITE|IEXEC; dip->di_size = DIRBLKSIZ; dip->di_nlink = 2; ip = &ifile[LOSTFOUNDINO]; ip->if_version = 1; ip->if_daddr = lfsp->lfs_idaddr; /* Make all the other dinodes invalid */ for (i = INOPB(lfsp)-3, dip++; i; i--, dip++) dip->di_inumber = LFS_UNUSED_INUM; /* Link remaining IFILE entries in free list */ for (ip = &ifile[LFS_FIRST_INUM], i = LFS_FIRST_INUM; i < lfsp->lfs_ifpb; ++ip) { ip->if_version = 1; ip->if_daddr = LFS_UNUSED_DADDR; ip->if_nextfree = ++i; } ifile[lfsp->lfs_ifpb - 1].if_nextfree = LFS_UNUSED_INUM; /* Now, write the segment */ /* Compute a checksum across all the data you're writing */ dp = datasump = malloc (blocks_used * sizeof(u_long)); *dp++ = ((u_long *)dpagep)[0]; /* inode block */ for (i = 0; i < lfsp->lfs_cleansz; i++) *dp++ = ((u_long *)cleaninfo)[(i << lfsp->lfs_bshift) / sizeof(u_long)]; /* Cleaner info */ for (i = 0; i < lfsp->lfs_segtabsz; i++) *dp++ = ((u_long *)segtable)[(i << lfsp->lfs_bshift) / sizeof(u_long)]; /* Segusage table */ *dp++ = ((u_long *)ifile)[0]; /* Ifile */ /* Still need the root and l+f bytes; get them later */ /* Write out the inode block */ off = LFS_LABELPAD + LFS_SBPAD + LFS_SUMMARY_SIZE; put(fd, off, dpagep, lfsp->lfs_bsize); free(dpagep); off += lfsp->lfs_bsize; /* Write out the ifile */ put(fd, off, cleaninfo, lfsp->lfs_cleansz << lfsp->lfs_bshift); off += (lfsp->lfs_cleansz << lfsp->lfs_bshift); (void)free(cleaninfo); put(fd, off, segtable, lfsp->lfs_segtabsz << lfsp->lfs_bshift); off += (lfsp->lfs_segtabsz << lfsp->lfs_bshift); (void)free(segtable); put(fd, off, ifile, lfsp->lfs_bsize); off += lfsp->lfs_bsize; /* * use ipagep for space for writing out other stuff. It used to * contain the ifile, but we're done with it. */ /* Write out the root and lost and found directories */ bzero(ipagep, lfsp->lfs_bsize); make_dir(ipagep, lfs_root_dir, sizeof(lfs_root_dir) / sizeof(struct direct)); *dp++ = ((u_long *)ipagep)[0]; put(fd, off, ipagep, lfsp->lfs_bsize); off += lfsp->lfs_bsize; bzero(ipagep, lfsp->lfs_bsize); make_dir(ipagep, lfs_lf_dir, sizeof(lfs_lf_dir) / sizeof(struct direct)); *dp++ = ((u_long *)ipagep)[0]; put(fd, off, ipagep, lfsp->lfs_bsize); /* Write Supberblock */ lfsp->lfs_offset = (off + lfsp->lfs_bsize) / lp->d_secsize; put(fd, LFS_LABELPAD, lfsp, sizeof(struct lfs)); /* * Finally, calculate all the fields for the summary structure * and write it. */ summary.ss_next = lfsp->lfs_nextseg; summary.ss_create = lfsp->lfs_tstamp; summary.ss_nfinfo = 3; summary.ss_ninos = 3; summary.ss_datasum = cksum(datasump, sizeof(u_long) * blocks_used); /* * Make sure that we don't overflow a summary block. We have to * record: FINFO structures for ifile, root, and l+f. The number * of blocks recorded for the ifile is determined by the size of * the cleaner info and the segments usage table. There is room * for one block included in sizeof(FINFO) so we don't need to add * any extra space for the ROOT and L+F, and one block of the ifile * is already counted. Finally, we leave room for 1 inode block * address. */ sum_size = 3*sizeof(FINFO) + sizeof(SEGSUM) + sizeof(daddr_t) + (lfsp->lfs_cleansz + lfsp->lfs_segtabsz) * sizeof(u_long);#define SUMERR \"Multiple summary blocks in segment 1 not yet implemented\nsummary is %d bytes." if (sum_size > LFS_SUMMARY_SIZE) fatal(SUMERR, sum_size); block_array_size = lfsp->lfs_cleansz + lfsp->lfs_segtabsz + 1; if (!(block_array = malloc(block_array_size *sizeof(int)))) fatal("%s: %s", special, strerror(errno)); /* fill in the array */ for (i = 0; i < block_array_size; i++) block_array[i] = i; /* copy into segment */ sump = ipagep; bcopy(&summary, sump, sizeof(SEGSUM)); sump += sizeof(SEGSUM); /* Now, add the ifile */ file_info.fi_nblocks = block_array_size; file_info.fi_version = 1; file_info.fi_ino = LFS_IFILE_INUM; bcopy(&file_info, sump, sizeof(FINFO) - sizeof(u_long)); sump += sizeof(FINFO) - sizeof(u_long); bcopy(block_array, sump, sizeof(u_long) * file_info.fi_nblocks); sump += sizeof(u_long) * file_info.fi_nblocks; /* Now, add the root directory */ file_info.fi_nblocks = 1; file_info.fi_version = 1; file_info.fi_ino = ROOTINO; file_info.fi_blocks[0] = 0; bcopy(&file_info, sump, sizeof(FINFO)); sump += sizeof(FINFO); /* Now, add the lost and found */ file_info.fi_ino = LOSTFOUNDINO; bcopy(&file_info, sump, sizeof(FINFO)); ((daddr_t *)ipagep)[LFS_SUMMARY_SIZE / sizeof(daddr_t) - 1] = lfsp->lfs_idaddr; ((SEGSUM *)ipagep)->ss_sumsum = cksum(ipagep+sizeof(summary.ss_sumsum), LFS_SUMMARY_SIZE - sizeof(summary.ss_sumsum)); put(fd, LFS_LABELPAD + LFS_SBPAD, ipagep, LFS_SUMMARY_SIZE); sp = (SEGSUM *)ipagep; sp->ss_create = 0; sp->ss_nfinfo = 0; sp->ss_ninos = 0; sp->ss_datasum = 0; /* Now write the summary block for the next partial so it's invalid */ lfsp->lfs_tstamp = 0; off += lfsp->lfs_bsize; sp->ss_sumsum = cksum(&sp->ss_datasum, LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum)); put(fd, off, sp, LFS_SUMMARY_SIZE); /* Now, write rest of segments containing superblocks */ lfsp->lfs_cksum = cksum(lfsp, sizeof(struct lfs) - sizeof(lfsp->lfs_cksum)); for (seg_addr = last_addr = lfsp->lfs_sboffs[0], j = 1, i = 1; i < lfsp->lfs_nseg; i++) { seg_addr += lfsp->lfs_ssize << lfsp->lfs_fsbtodb; sp->ss_next = last_addr; last_addr = seg_addr; seg_seek = seg_addr * lp->d_secsize; if (seg_addr == lfsp->lfs_sboffs[j]) { if (j < (LFS_MAXNUMSB - 2)) j++; put(fd, seg_seek, lfsp, sizeof(struct lfs)); seg_seek += LFS_SBPAD; } /* Summary */ sp->ss_sumsum = cksum(&sp->ss_datasum, LFS_SUMMARY_SIZE - sizeof(sp->ss_sumsum)); put(fd, seg_seek, sp, LFS_SUMMARY_SIZE); } free(ipagep); close(fd); return (0);}static voidput(fd, off, p, len) int fd; off_t off; void *p; size_t len;{ int wbytes; if (lseek(fd, off, SEEK_SET) < 0) fatal("%s: %s", special, strerror(errno)); if ((wbytes = write(fd, p, len)) < 0) fatal("%s: %s", special, strerror(errno)); if (wbytes != len) fatal("%s: short write (%d, not %d)", special, wbytes, len);}/* * Create the root directory for this file system and the lost+found * directory. */ u_long d_ino; /* inode number of entry */ u_short d_reclen; /* length of this record */ u_short d_namlen; /* length of string in d_name */ char d_name[MAXNAMLEN + 1]; /* name with length <= MAXNAMLEN */voidlfsinit(){}static daddr_tmake_dinode(ino, dip, nblocks, saddr, lfsp) ino_t ino; /* inode we're creating */ struct dinode *dip; /* disk inode */ int nblocks; /* number of blocks in file */ daddr_t saddr; /* starting block address */ struct lfs *lfsp; /* superblock */{ int db_per_fb, i; dip->di_nlink = 1; dip->di_blocks = nblocks << lfsp->lfs_fsbtodb; dip->di_size = (nblocks << lfsp->lfs_bshift); dip->di_atime.ts_sec = dip->di_mtime.ts_sec = dip->di_ctime.ts_sec = lfsp->lfs_tstamp; dip->di_atime.ts_nsec = dip->di_mtime.ts_nsec = dip->di_ctime.ts_nsec = 0; dip->di_inumber = ino;#define SEGERR \"File requires more than the number of direct blocks; increase block or segment size." if (NDADDR < nblocks) fatal("%s", SEGERR); /* Assign the block addresses for the ifile */ db_per_fb = 1 << lfsp->lfs_fsbtodb; for (i = 0; i < nblocks; i++, saddr += db_per_fb) dip->di_db[i] = saddr; return (saddr);}/* * Construct a set of directory entries in "bufp". We assume that all the * entries in protodir fir in the first DIRBLKSIZ. */static voidmake_dir(bufp, protodir, entries) void *bufp; register struct direct *protodir; int entries;{ char *cp; int i, spcleft; spcleft = DIRBLKSIZ; for (cp = bufp, i = 0; i < entries - 1; i++) { protodir[i].d_reclen = DIRSIZ(NEWDIRFMT, &protodir[i]); bcopy(&protodir[i], cp, protodir[i].d_reclen); cp += protodir[i].d_reclen; if ((spcleft -= protodir[i].d_reclen) < 0) fatal("%s: %s", special, "directory too big"); } protodir[i].d_reclen = spcleft; bcopy(&protodir[i], cp, DIRSIZ(NEWDIRFMT, &protodir[i]));}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -