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

📄 initmap.c

📁 在Linux内核从2.4升级到2.6时需要升级的软件包
💻 C
📖 第 1 页 / 共 3 页
字号:
					 control_page->dn_aglevel * L2LPERCTL);	control_page->dn_agheigth = l2nl >> 1;	control_page->dn_agwidth =	    1 << (l2nl - (control_page->dn_agheigth << 1));	for (index = 5 - control_page->dn_agheigth, control_page->dn_agstart =	     0, n = 1; index > 0; index--) {		control_page->dn_agstart += n;		n <<= 2;	}	/* control_page->dn_maxag is computed at finalization */	control_page->dn_agpref = 0;}/*-------------------------------------------------------------------- * NAME:        calc_map_size() * * FUNCTION:    Calculates the size of a block map and *              initializes memory for dmap pages of map. *              Later when we are ready to write the map to disk *              we will initialize the rest of the map pages. * *              N.B. map file is ALLOCATED as a single extent *              of physical pages covering full control level (L2) *              tree control pages for the dmap pages required: *              the tree will be INITIALIZED to cover only the *              the dmap pages required; * * PARAMETERS: *      number_of_blocks        - Number of blocks in aggregate *      aggr_inodes             - Array of aggregate inodes *      aggr_block_size         - Aggregate block size *      ag_size                 - Will be filled in with AG size in blocks *      inostamp                - Inode stamp value to be used. * * RETURNS:     0 for success */int calc_map_size(int64_t number_of_blocks,		  struct dinode *aggr_inodes,		  int aggr_block_size, int *ag_size, unsigned inostamp){	int rc = 0;	int64_t npages, ndmaps, nl0pages;	int64_t nb_diskmap;	int64_t size_of_map;	int64_t location;	/*	 * compute the number dmap pages required to cover number_of_blocks;	 * add one extra dmap page for extendfs(): this is added before	 * we figure out how many control pages are needed, so we get	 * the correct number of control pages.	 */	npages = ndmaps = ((number_of_blocks + BPERDMAP - 1) >> L2BPERDMAP) + 1;	/*	 * Make sure the number of dmaps needed is within the supported range	 */	if ((((int64_t) ndmaps) << L2BPERDMAP) > MAXMAPSIZE)		return (EINVAL);	/*	 * compute number of (logical) control pages at each level of the map	 */	/* account for L0 pages to cover dmap pages */	nl0pages = (ndmaps + LPERCTL - 1) >> L2LPERCTL;	npages += nl0pages;	if (nl0pages > 1) {		/* account for one L2 and actual L1 pages to cover L0 pages */		npages += 1 + ((nl0pages + LPERCTL - 1) >> L2LPERCTL);	} else {		/* account for one logical L2 and one logical L1 pages */		npages += 2;	}	/* account for global control page of map */	npages++;	/*	 * init the block allocation map inode	 */	size_of_map = npages << L2PSIZE;	nb_diskmap = size_of_map / aggr_block_size;	location = BMAP_OFF / aggr_block_size;	init_inode(&(aggr_inodes[BMAP_I]), AGGREGATE_I,	/* di_fileset */		   BMAP_I,	/* di_number */		   nb_diskmap,	/* di_nblocks */		   size_of_map,	/* di_size */		   location, IFJOURNAL | IFREG,	/* di_mode */		   max_extent_data, AITBL_OFF / aggr_block_size,		   aggr_block_size, inostamp);	/*	 *  Allocate dmap pages and initialize them for the aggregate blocks	 */	if ((rc = alloc_map(ndmaps)) != 0)		return rc;	initmap(number_of_blocks, ag_size, aggr_block_size);	/*	 * reset last_allocated to ignore the fsck working space	 */	last_allocated = 0;	return 0;}/*-------------------------------------------------------------------- * NAME:        markit() * * FUNCTION:    Mark specified block allocated/unallocated in block map * * PARAMETERS: *      block   - Map object to set or clear *      flag    - Indicates ALLOCATE or FREE of block.  Indicates if block is *                bad. * * RETURNS: NONE */int markit(int block, unsigned flag){	int page, rem, word, bit;	struct dmap *p1;	int agno;	int64_t num_blocks_left, nb;	/*	 * Keep track of the last allocated block to be filled into block map	 * inode.  Don't update last allocated for bad blocks.	 */	if (block > last_allocated && !(flag & BADBLOCK)) {		last_allocated = block;	}	/*	 *  calculate page number in map, and word and bit number in word.	 */	page = block / BPERDMAP;	rem = block - page * BPERDMAP;	word = rem >> L2DBWORD;	bit = rem - (word << L2DBWORD);	if (page > sz_block_map_array) {		fprintf(stderr,			"Internal error: %s(%d): Trying to mark block which doesn't exist.\n",			__FILE__, __LINE__);		return (-1);	}	/*	 * Determine if this dmap page has been allocated yet	 */	if (block_map_array[page] == NULL) {		num_blocks_left = control_page->dn_mapsize - (page * BPERDMAP);		nb = MIN(BPERDMAP, num_blocks_left);		block_map_array[page] = malloc(sizeof (struct dmap));		if (block_map_array[page] == NULL) {			message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG);			return (ENOMEM);		}		memset(block_map_array[page], 0, sizeof (struct dmap));		ujfs_idmap_page(block_map_array[page], nb);	}	p1 = block_map_array[page];	agno = block >> control_page->dn_agl2size;	/*	 *  now we process the first word.	 */	if (flag & ALLOC) {		p1->pmap[word] |= (UZWORD >> bit);		p1->wmap[word] |= (UZWORD >> bit);		/*		 * Update the stats		 */		p1->nfree--;		control_page->dn_nfree--;		control_page->dn_agfree[agno]--;	} else {		p1->pmap[word] &= ~(UZWORD >> bit);		p1->wmap[word] &= ~(UZWORD >> bit);		/*		 * Update the stats		 */		p1->nfree++;		control_page->dn_nfree++;		control_page->dn_agfree[agno]++;	}	return (0);}/*-------------------------------------------------------------------- * NAME:        write_block_map() * * FUNCTION:    Update tree part of block map to match rest of map and *              then write the block map to disk. *              Also write the block map inode to disk. * * PARAMETERS: *      dev_ptr         - open port of device to write map to *      size_of_map     - size of map *      aggr_block_size - size of an aggregate block in bytes * * RETURNS: 0 for success */int write_block_map(FILE *dev_ptr, int64_t number_of_blocks, int aggr_block_size){	int rc = 0;	/*	 * At this point all of the dmaps have been initialized except for their	 * trees.  Now we need to build the other levels of the map and adjust	 * the tree for each of the dmaps.	 */	cur_dmap_index = 0;	control_page->dn_maxag = last_allocated / control_page->dn_agsize;	rc = initbmap(dev_ptr, number_of_blocks);	return rc;}/*-------------------------------------------------------------------- * NAME: dbAlloc * * FUNCTION: Allocate the specified number of blocks * * PARAMETERS: *      xlen    - Number of blocks to allocate *      xaddr   - On return, filled in with starting block number of allocated *                blocks * * NOTES: *	This function is only called when adding blocks to the Bad Block Inode *	required a page for an xtree node.  LVM Bad Block processing must *	be in effect during this allocation.  This will not be the case if format *	is processing /L.  So, at entry to this routine, we check to see whether *	the LVM Bad Block processing is enabled and, if not, we enable it. *	At exit from this routine the LVM Bad Block processing will be as it *	was (i.e., enabled or disabled) on entry. * * RETURNS: 0 for success; Other indicates failure */static int dbAlloc(FILE *dev_ptr, int64_t xlen, int64_t * xaddr){	int rc = 0;	int page, word;	struct dmap *p1;	int64_t last_block, index;	unsigned mask, cmap;	int bitno;	int l2nb;	int8_t leafw;	/*	 * Start looking at last block allocated for a contiguous extent of xlen	 * blocks.  Since we may have bad blocks intermixed we can't just	 * take blocks starting at the last block allocated.  However,	 * last_allocated won't be updated with bad blocks, so it will be the	 * start of the real last place to start looking.  Once found, mark them	 * allocated and return the starting address in xaddr	 */	l2nb = log2shift(xlen);	for (page = last_allocated / BPERDMAP,	     word = (last_allocated & (BPERDMAP - 1)) >> L2DBWORD;	     page < sz_block_map_array; page++, word = 0) {		/*		 * Determine if this dmap page has been allocated yet; if not we		 * can take the first blocks from it for our allocation since we		 * know all the blocks in it are free.  (markit will handle		 * allocating the page for us, so we don't have to do that here.)		 */		if (block_map_array[page] == NULL) {			*xaddr = page << L2BPERDMAP;			last_block = *xaddr + xlen;			for (index = *xaddr;			     ((index < last_block) && (rc == 0)); index++) {				rc = markit(index, ALLOC);			}			if (rc != 0) {				return rc;			}			return 0;		}		/*		 * We have a dmap page which has had allocations before, we need		 * to check for free blocks starting with <word> to the end of		 * this dmap page.  If we don't find it in this page we will go		 * on to the next page.		 */		p1 = block_map_array[page];		for (; word < LPERDMAP; word++) {			/*			 * Determine if the leaf describes sufficient free space.			 * Since we have not yet completed the block map			 * initialization we will have to compute this on the-fly.			 */			leafw = ujfs_maxbuddy((char *) &p1->wmap[word]);			if (leafw < l2nb)				continue;			/*			 * We know this word has sufficient free space, find it			 * and allocate it			 */			*xaddr = (page << L2BPERDMAP) + (word << L2DBWORD);			if (leafw < BUDMIN) {				mask = ONES << (DBWORD - xlen);				cmap = ~(p1->wmap[word]);				/* scan the word for xlen free bits */				for (bitno = 0; mask != 0; bitno++, mask >>= 1) {					if ((mask & cmap) == mask)						break;				}				*xaddr += bitno;			}			/* Allocate the blocks */			last_block = *xaddr + xlen;			for (index = *xaddr;			     ((index < last_block) && (rc == 0)); index++) {				rc = markit(index, ALLOC);			}			if (rc != 0) {				return (rc);			}			return 0;		}	}	return 1;}/*-------------------------------------------------------------------- * NAME: xtSplitRoot * * FUNCTION: Split full root of xtree * * PARAMETERS: *      dev_ptr - Device handle *      ip      - Inode of xtree *      xroot   - Root of xtree *      offset  - Offset of extent to add *      nblocks - number of blocks for extent to add *      blkno   - starting block of extent to add * * RETURNS: 0 for success; Other indicates failure */static int xtSplitRoot(FILE *dev_ptr,		       struct dinode *ip,		       struct xtree_buf *xroot,		       int64_t offset, int nblocks, int64_t blkno){	xtpage_t *rootpage;	xtpage_t *newpage;	int64_t xaddr;	int nextindex;	xad_t *xad;	int rc = 0;	struct xtree_buf *newbuf;	int xlen;	/* Allocate and initialize buffer for new page to accomodate the split */	newbuf = malloc(sizeof (struct xtree_buf));	if (newbuf == NULL) {		message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG);		return (ENOMEM);	}	newbuf->up = xroot;	if (xroot->down == NULL) {		badblock_pages = newbuf;	} else {		xroot->down->up = newbuf;	}	newbuf->down = xroot->down;	xroot->down = newbuf;	newpage = newbuf->page = malloc(PSIZE);	if (newpage == NULL) {		message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG);		return (ENOMEM);	}	/* Allocate disk blocks for new page */	xlen = 1 << control_page->dn_l2nbperpage;	if ((rc = dbAlloc(dev_ptr, xlen, &xaddr)))		return rc;	rootpage = xroot->page;	/* Initialize new page */	newpage->header.flag =	    (rootpage->header.flag & BT_LEAF) ? BT_LEAF : BT_INTERNAL;	PXDlength(&(newpage->header.self), xlen);	PXDaddress(&(newpage->header.self), xaddr);	newpage->header.nextindex = XTENTRYSTART;	newpage->header.maxentry = PSIZE >> L2XTSLOTSIZE;	/* initialize sibling pointers */	newpage->header.next = 0;	newpage->header.prev = 0;	/* copy the in-line root page into new right page extent */	nextindex = rootpage->header.maxentry;	memcpy(&newpage->xad[XTENTRYSTART], &rootpage->xad[XTENTRYSTART],	       (nextindex - XTENTRYSTART) << L2XTSLOTSIZE);	/* insert the new entry into the new right/child page */	xad = &newpage->xad[nextindex];	XADoffset(xad, offset);	XADlength(xad, nblocks);	XADaddress(xad, blkno);	/* update page header */	newpage->header.nextindex = nextindex + 1;	/* init root with the single entry for the new right page */

⌨️ 快捷键说明

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