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

📄 lfs.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 2 页
字号:
/*- * Copyright (c) 1991, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */#ifndef lintstatic char sccsid[] = "@(#)lfs.c	8.1 (Berkeley) 6/5/93";#endif /* not lint */#include <sys/param.h>#include <sys/disklabel.h>#include <sys/time.h>#include <sys/mount.h>#include <ufs/ufs/dir.h>#include <ufs/ufs/quota.h>#include <ufs/ufs/dinode.h>#include <ufs/lfs/lfs.h>#include <unistd.h>#include <errno.h>#include <stdlib.h>#include <string.h>#include "config.h"#include "extern.h"/* * This table is indexed by the log base 2 of the block size. * It returns the maximum file size allowed in a file system * with the specified block size.  For block sizes smaller than * 8K, the size is limited by tha maximum number of blocks that * can be reached by triply indirect blocks: *	NDADDR + INOPB(bsize) + INOPB(bsize)^2 + INOPB(bsize)^3 * For block size of 8K or larger, the file size is limited by the * number of blocks that can be represented in the file system.  Since * we use negative block numbers to represent indirect blocks, we can * have a maximum of 2^31 blocks. */u_quad_t maxtable[] = {	/*    1 */ -1,	/*    2 */ -1,	/*    4 */ -1,	/*    8 */ -1,	/*   16 */ -1,	/*   32 */ -1,	/*   64 */ -1,	/*  128 */ -1,	/*  256 */ -1,	/*  512 */ NDADDR + 128 + 128 * 128 + 128 * 128 * 128,	/* 1024 */ NDADDR + 256 + 256 * 256 + 256 * 256 * 256,	/* 2048 */ NDADDR + 512 + 512 * 512 + 512 * 512 * 512,	/* 4096 */ NDADDR + 1024 + 1024 * 1024 + 1024 * 1024 * 1024,	/* 8192 */ 1 << 31,	/* 16 K */ 1 << 31,	/* 32 K */ 1 << 31,};static struct lfs lfs_default =  {	/* lfs_magic */		LFS_MAGIC,	/* lfs_version */	LFS_VERSION,	/* lfs_size */		0,	/* lfs_ssize */		DFL_LFSSEG/DFL_LFSBLOCK,	/* lfs_dsize */		0,	/* lfs_bsize */		DFL_LFSBLOCK,	/* lfs_fsize */		DFL_LFSBLOCK,	/* lfs_frag */		1,	/* lfs_free */		LFS_FIRST_INUM,	/* lfs_bfree */		0,	/* lfs_nfiles */	0,	/* lfs_avail */		0,	/* lfs_uinodes */	0,	/* lfs_idaddr */	0,	/* lfs_ifile */		LFS_IFILE_INUM,	/* lfs_lastseg */	0,	/* lfs_nextseg */	0,	/* lfs_curseg */	0,	/* lfs_offset */	0,	/* lfs_lastpseg */	0,	/* lfs_tstamp */	0,	/* lfs_minfree */	MINFREE,	/* lfs_maxfilesize */	0,	/* lfs_dbpseg */	DFL_LFSSEG/DEV_BSIZE,	/* lfs_inopb */		DFL_LFSBLOCK/sizeof(struct dinode),	/* lfs_ifpb */		DFL_LFSBLOCK/sizeof(IFILE),	/* lfs_sepb */		DFL_LFSBLOCK/sizeof(SEGUSE),	/* lfs_nindir */	DFL_LFSBLOCK/sizeof(daddr_t),	/* lfs_nseg */		0,	/* lfs_nspf */		0,	/* lfs_cleansz */	0,	/* lfs_segtabsz */	0,	/* lfs_segmask */	DFL_LFSSEG_MASK,	/* lfs_segshift */	DFL_LFSSEG_SHIFT,	/* lfs_bmask */		DFL_LFSBLOCK_MASK,	/* lfs_bshift */	DFL_LFSBLOCK_SHIFT,	/* lfs_ffmask */	0,	/* lfs_ffshift */	0,	/* lfs_fbmask */	0,	/* lfs_fbshift */	0,	/* lfs_fsbtodb */	0,	/* lfs_sushift */	0,	/* lfs_sboffs */	{ 0 },	/* lfs_sp */		NULL,	/* lfs_ivnode */	NULL,	/* lfs_seglock */	0,	/* lfs_lockpid */	0,	/* lfs_iocount */	0,	/* lfs_writer */	0,	/* lfs_dirops */	0,	/* lfs_doifile */	0,	/* lfs_nactive */	0,	/* lfs_fmod */		0,	/* lfs_clean */		0,	/* lfs_ronly */		0,	/* lfs_flags */		0,	/* lfs_fsmnt */		{ 0 },	/* lfs_pad */		{ 0 },	/* lfs_cksum */		0};struct direct lfs_root_dir[] = {	{ ROOTINO, sizeof(struct direct), DT_DIR, 1, "."},	{ ROOTINO, sizeof(struct direct), DT_DIR, 2, ".."},	{ LFS_IFILE_INUM, sizeof(struct direct), DT_REG, 5, "ifile"},	{ LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 10, "lost+found"},};struct direct lfs_lf_dir[] = {        { LOSTFOUNDINO, sizeof(struct direct), DT_DIR, 1, "." },        { ROOTINO, sizeof(struct direct), DT_DIR, 2, ".." },};static daddr_t make_dinode 	__P((ino_t, struct dinode *, int, daddr_t, struct lfs *));static void make_dir __P(( void *, struct direct *, int));static void put __P((int, off_t, void *, size_t));intmake_lfs(fd, lp, partp, minfree, block_size, seg_size)	int fd;	struct disklabel *lp;	struct partition *partp;	int minfree;	int block_size;	int seg_size;{	struct dinode *dip;	/* Pointer to a disk inode */	struct dinode *dpagep;	/* Pointer to page of disk inodes */	CLEANERINFO *cleaninfo;	/* Segment cleaner information table */	FINFO file_info;	/* File info structure in summary blocks */	IFILE *ifile;		/* Pointer to array of ifile structures */	IFILE *ip;		/* Pointer to array of ifile structures */	struct lfs *lfsp;	/* Superblock */	SEGUSE *segp;		/* Segment usage table */	SEGUSE *segtable;	/* Segment usage table */	SEGSUM summary;		/* Segment summary structure */	SEGSUM *sp;		/* Segment summary pointer */	daddr_t	last_sb_addr;	/* Address of superblocks */	daddr_t last_addr;	/* Previous segment address */	daddr_t	sb_addr;	/* Address of superblocks */	daddr_t	seg_addr;	/* Address of current segment */	void *ipagep;		/* Pointer to the page we use to write stuff */	void *sump;		/* Used to copy stuff into segment buffer */	u_long *block_array;	/* Array of logical block nos to put in sum */	u_long blocks_used;	/* Number of blocks in first segment */	u_long *dp;		/* Used to computed checksum on data */	u_long *datasump;	/* Used to computed checksum on data */	int block_array_size;	/* How many entries in block array */	int bsize;		/* Block size */	int db_per_fb;		/* Disk blocks per file block */	int i, j;	int off;		/* Offset at which to write */	int sb_interval;	/* number of segs between super blocks */	int seg_seek;		/* Seek offset for a segment */	int ssize;		/* Segment size */	int sum_size;		/* Size of the summary block */	lfsp = &lfs_default;	if (!(bsize = block_size))		bsize = DFL_LFSBLOCK;	if (!(ssize = seg_size))		ssize = DFL_LFSSEG;	/* Modify parts of superblock overridden by command line arguments */	if (bsize != DFL_LFSBLOCK) {		lfsp->lfs_bshift = log2(bsize);		if (1 << lfsp->lfs_bshift != bsize)			fatal("%d: block size not a power of 2", bsize);		lfsp->lfs_bsize = bsize;		lfsp->lfs_fsize = bsize;		lfsp->lfs_bmask = bsize - 1;		lfsp->lfs_inopb = bsize / sizeof(struct dinode);/* MIS -- should I round to power of 2 */		lfsp->lfs_ifpb = bsize / sizeof(IFILE);		lfsp->lfs_sepb = bsize / sizeof(SEGUSE);		lfsp->lfs_nindir = bsize / sizeof(daddr_t);	}	if (ssize != DFL_LFSSEG) {		lfsp->lfs_segshift = log2(ssize);		if (1 << lfsp->lfs_segshift != ssize)			fatal("%d: segment size not power of 2", ssize);		lfsp->lfs_ssize = ssize;		lfsp->lfs_segmask = ssize - 1;		lfsp->lfs_dbpseg = ssize / DEV_BSIZE;	}	lfsp->lfs_ssize = ssize >> lfsp->lfs_bshift;	if (minfree)		lfsp->lfs_minfree = minfree;	/*	 * Fill in parts of superblock that can be computed from file system	 * size, disk geometry and current time.	 */	db_per_fb = bsize/lp->d_secsize;	lfsp->lfs_fsbtodb = log2(db_per_fb);	lfsp->lfs_sushift = log2(lfsp->lfs_sepb);	lfsp->lfs_size = partp->p_size >> lfsp->lfs_fsbtodb;	lfsp->lfs_dsize = lfsp->lfs_size - (LFS_LABELPAD >> lfsp->lfs_bshift);	lfsp->lfs_nseg = lfsp->lfs_dsize / lfsp->lfs_ssize;	lfsp->lfs_maxfilesize = maxtable[lfsp->lfs_bshift] << lfsp->lfs_bshift;	/* 	 * The number of free blocks is set from the number of segments times	 * the segment size - 2 (that we never write because we need to make	 * sure the cleaner can run).  Then we'll subtract off the room for the	 * superblocks ifile entries and segment usage table.	 */	lfsp->lfs_dsize = fsbtodb(lfsp, (lfsp->lfs_nseg - 2) * lfsp->lfs_ssize);	lfsp->lfs_bfree = lfsp->lfs_dsize;	lfsp->lfs_segtabsz = SEGTABSIZE_SU(lfsp);	lfsp->lfs_cleansz = CLEANSIZE_SU(lfsp);	if ((lfsp->lfs_tstamp = time(NULL)) == -1)		fatal("time: %s", strerror(errno));	if ((sb_interval = lfsp->lfs_nseg / LFS_MAXNUMSB) < LFS_MIN_SBINTERVAL)		sb_interval = LFS_MIN_SBINTERVAL;	/*	 * Now, lay out the file system.  We need to figure out where	 * the superblocks go, initialize the checkpoint information	 * for the first two superblocks, initialize the segment usage	 * information, put the segusage information in the ifile, create	 * the first block of IFILE structures, and link all the IFILE	 * structures into a free list.	 */	/* Figure out where the superblocks are going to live */	lfsp->lfs_sboffs[0] = LFS_LABELPAD/lp->d_secsize;	for (i = 1; i < LFS_MAXNUMSB; i++) {		sb_addr = ((i * sb_interval) << 		    (lfsp->lfs_segshift - lfsp->lfs_bshift + lfsp->lfs_fsbtodb))		    + lfsp->lfs_sboffs[0];		if (sb_addr > partp->p_size)			break;		lfsp->lfs_sboffs[i] = sb_addr;	}	last_sb_addr = lfsp->lfs_sboffs[i - 1];	lfsp->lfs_lastseg = lfsp->lfs_sboffs[0];	lfsp->lfs_nextseg = 	    lfsp->lfs_sboffs[1] ? lfsp->lfs_sboffs[1] : lfsp->lfs_sboffs[0];	lfsp->lfs_curseg = lfsp->lfs_lastseg;	/*	 * Initialize the segment usage table.  The first segment will	 * contain the superblock, the cleanerinfo (cleansz), the segusage 	 * table * (segtabsz), 1 block's worth of IFILE entries, the root 	 * directory, the lost+found directory and one block's worth of 	 * inodes (containing the ifile, root, and l+f inodes).	 */	if (!(cleaninfo = malloc(lfsp->lfs_cleansz << lfsp->lfs_bshift)))		fatal("%s", strerror(errno));	cleaninfo->clean = lfsp->lfs_nseg - 1;	cleaninfo->dirty = 1;	if (!(segtable = malloc(lfsp->lfs_segtabsz << lfsp->lfs_bshift)))		fatal("%s", strerror(errno));	segp = segtable;	blocks_used = lfsp->lfs_segtabsz + lfsp->lfs_cleansz + 4;	segp->su_nbytes = ((blocks_used - 1) << lfsp->lfs_bshift) +	    3 * sizeof(struct dinode) + LFS_SUMMARY_SIZE;	segp->su_lastmod = lfsp->lfs_tstamp;	segp->su_nsums = 1;	/* 1 summary blocks */	segp->su_ninos = 1;	/* 1 inode block */	segp->su_flags = SEGUSE_SUPERBLOCK | SEGUSE_DIRTY;	lfsp->lfs_bfree -= LFS_SUMMARY_SIZE / lp->d_secsize;	lfsp->lfs_bfree -=	     fsbtodb(lfsp, lfsp->lfs_cleansz + lfsp->lfs_segtabsz + 4);	/* 	 * Now figure out the address of the ifile inode. The inode block	 * appears immediately after the segment summary.	 */	lfsp->lfs_idaddr = (LFS_LABELPAD + LFS_SBPAD + LFS_SUMMARY_SIZE) /	    lp->d_secsize;	for (segp = segtable + 1, i = 1; i < lfsp->lfs_nseg; i++, segp++) {		if ((i % sb_interval) == 0) {			segp->su_flags = SEGUSE_SUPERBLOCK;			lfsp->lfs_bfree -= (LFS_SBPAD / lp->d_secsize);		} else			segp->su_flags = 0;		segp->su_lastmod = 0;		segp->su_nbytes = 0;		segp->su_ninos = 0;		segp->su_nsums = 0;	}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -