⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lfs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
	/* 	 * 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 + -