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

📄 initmap.c

📁 在Linux内核从2.4升级到2.6时需要升级的软件包
💻 C
📖 第 1 页 / 共 3 页
字号:
/* *   Copyright (C) International Business Machines Corp., 2000-2005 * *   This program is free software;  you can redistribute it and/or modify *   it under the terms of the GNU General Public License as published by *   the Free Software Foundation; either version 2 of the License, or *   (at your option) any later version. * *   This program is distributed in the hope that it will be useful, *   but WITHOUT ANY WARRANTY;  without even the implied warranty of *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See *   the GNU General Public License for more details. * *   You should have received a copy of the GNU General Public License *   along with this program;  if not, write to the Free Software *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */#define _GNU_SOURCE	/* FOR O_DIRECT */#include <config.h>#include "jfs_types.h"#include <stdio.h>#include <stdlib.h>#include <string.h>#include <time.h>#include <unistd.h>#include <fcntl.h>#include <errno.h>#include "jfs_endian.h"#include "jfs_filsys.h"#include "jfs_dinode.h"#include "devices.h"#include "inodes.h"#include "jfs_dmap.h"#include "diskmap.h"#include "inode.h"#include "initmap.h"#include "message.h"#include "utilsubs.h"extern unsigned type_jfs;#define UZWORD  (0x80000000u)#define DBBYTE          8	/* number of bits per byte */#define L2DBBYTE        3	/* log2 of number of bits per byte */#define CHAR_ONES       (0xffu)static struct dmap **block_map_array;static unsigned sz_block_map_array;static unsigned cur_dmap_index;static struct dbmap *control_page;static unsigned last_allocated;static struct dmap *empty_page;struct xtree_buf {	struct xtree_buf *down;	/* next rightmost child */	struct xtree_buf *up;	/* parent */	xtpage_t *page;};static struct xtree_buf *badblock_pages;static int xtAppend(FILE *, struct dinode *, int64_t, int64_t, int,		    struct xtree_buf *, int);/*-------------------------------------------------------------------- * NAME:        initdmap() * * FUNCTION:    Initialize a dmap for the specified block range *              (blkno thru blkno+nblocks-1). * * PARAMETERS: *      dev_ptr - device to write map page to *      blkno   - Starting disk block number to be covered by this dmap. *      nblocks - Number of blocks covered by this dmap. *      treemax - Return value set as maximum free string found in this dmap *      start   - Logical block address of where this dmap should live on disk. * * NOTES: The wmap and pmap words along the leaves of the dmap tree are *      initialized, with the leaves initialized to the maximum free string of *      the wmap word they describe.  With this complete ujfs_adjtree() is *      called to combine all appropriate buddies and update the higher level of *      the tree to reflect the result of the buddy combination.  The maximum *      free string of the dmap (i.e. the root value of the tree) is returned *      in treemax. * * RETURNS: NONE */static int initdmap(FILE *dev_ptr, int64_t blkno, int64_t nblocks,		    int8_t * treemax, int64_t start){	int rc = 0;	/*	 * Determine if the dmap already exists	 */	if (block_map_array[cur_dmap_index] == NULL) {		if (nblocks == BPERDMAP) {			/*			 * alloc/init a template empty full page buffer			 */			if (empty_page == NULL) {				empty_page = malloc(sizeof (struct dmap));				if (empty_page == NULL) {					message_user(MSG_OSO_INSUFF_MEMORY,						     NULL, 0, OSO_MSG);					return (ENOMEM);				}				memset(empty_page, 0, sizeof (struct dmap));				ujfs_idmap_page(empty_page, nblocks);				ujfs_complete_dmap(empty_page, blkno, treemax);			} else {				/*				 * customize/reuse the template empty page				 */				empty_page->start = blkno;				*treemax = empty_page->tree.stree[0];			}			block_map_array[cur_dmap_index] = empty_page;		} else {			/*			 * alloc/init a special dmap page with the correct size			 */			block_map_array[cur_dmap_index] =			    malloc(sizeof (struct dmap));			if (block_map_array[cur_dmap_index] == NULL) {				message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0,					     OSO_MSG);				return (ENOMEM);			}			memset(block_map_array[cur_dmap_index], 0,			       sizeof (struct dmap));			ujfs_idmap_page(block_map_array[cur_dmap_index],					nblocks);			ujfs_complete_dmap(block_map_array[cur_dmap_index],					   blkno, treemax);		}	} else {		/*		 * Fill in rest of fields of special existing dmap page		 */		ujfs_complete_dmap(block_map_array[cur_dmap_index], blkno,				   treemax);	}	/*	 * Write the dmap page and free if special buffer	 */	/* swap if on big endian machine */	ujfs_swap_dmap(block_map_array[cur_dmap_index]);	rc = ujfs_rw_diskblocks(dev_ptr, start, PSIZE,				block_map_array[cur_dmap_index], PUT);	ujfs_swap_dmap(block_map_array[cur_dmap_index]);	if (rc != 0)		return rc;	if (block_map_array[cur_dmap_index] != empty_page) {		free(block_map_array[cur_dmap_index]);	}	cur_dmap_index++;	return (rc);}/*-------------------------------------------------------------------- * NAME:        initctl() * * FUNCTION:    Initialize a dmapctl for the specified block range *              (blkno thru blkno+nblocks-1) and *              level and initialize all dmapctls and dmaps under this dmapctl. * * PARAMETERS: *      dev_ptr - device to write page to *      blkno   - Starting disk block number to be covered by this dmapctl. *      nblocks - Number of blocks covered by this dmapctl. *      level   - The level of this dmapctl. *      treemax - Return value set as the maximum free string found in this *                dmapctl. *      start   - Logical block address of where this page should live on disk. * * NOTES: This routine is called recursively. On first invocation it is called *      for the top level dmapctl of the tree.  For each leaf of the dmapctl, *      the lower level dmap (level == 0) or dmapctl (level > 0) is created for *      the block range covered by the leaf and the leaf is set to the maximum *      free string found in the lower level object.  If the lower level object *      is a dmap, initdmap() is called to handle it's initialization. *      Otherwise, initctl() is called recursively to initialize the lower level *      dmapctl with the level specified as the current level - 1; once all *      leaves have been initialized ujfs_adjtree() is called to combine all *      appropriate buddies and update the higher level of the tree to reflect *      the result of the buddy combination.  The maximum free string of the *      dmapctl (i.e. the root value of the tree) is returned in treemax. * * RETURNS: None. */static int initctl(FILE *dev_ptr,		   int64_t blkno,		   int64_t nblocks,		   int level,		   int8_t * treemax,		   int64_t * start){	int index, rc = 0, l2cblks, nchild;	int8_t *cp, max;	struct dmapctl *dcp;	int64_t nb, cblks;	int64_t next_page;	/*	 * alloc/init current level dmapctl page buffer	 */	dcp = malloc(sizeof (struct dmapctl));	if (dcp == NULL) {		message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG);		return (ENOMEM);	}	memset(dcp, 0, sizeof (struct dmapctl));	dcp->height = 5;	dcp->leafidx = CTLLEAFIND;	dcp->nleafs = LPERCTL;	dcp->l2nleafs = L2LPERCTL;	dcp->budmin = L2BPERDMAP + level * L2LPERCTL;	/* Pick up the pointer to the first leaf of the dmapctl tree */	cp = dcp->stree + dcp->leafidx;	/*	 * Determine how many lower level dmapctls or dmaps will be described by	 * this dmapctl based upon the number of blocks covered by this dmapctl.	 */	l2cblks = L2BPERDMAP + level * L2LPERCTL;	cblks = (1 << l2cblks);	nchild = nblocks >> l2cblks;	nchild = (nblocks & (cblks - 1)) ? nchild + 1 : nchild;	next_page = *start + PSIZE;	for (index = 0; index < nchild; index++, nblocks -= nb, blkno += nb) {		/*		 * Determine how many blocks the lower level dmapctl or dmap will cover.		 */		nb = MIN(cblks, nblocks);		/*		 * If this is a level 0 dmapctl, initialize the dmap for the		 * block range (i.e. blkno thru blkno+nb-1).  Otherwise,		 * initialize the lower level dmapctl for this block range.		 * In either case, the pointer to the leaf covering this block		 * range is passed down and will be set to the length of the		 * maximum free string of blocks found at the lower level.		 */		if (level == 0) {			rc += initdmap(dev_ptr, blkno, nb, cp + index, next_page);			next_page += PSIZE;		} else {			rc += initctl(dev_ptr, blkno, nb, level - 1, cp + index,				    &next_page);		}	}	/*	 * Initialize the leaves for this dmapctl that were not covered by the	 * specified input block range (i.e. the leaves have no low level	 * dmapctl or dmap.	 */	for (; index < LPERCTL; index++) {		*(cp + index) = NOFREE;	}	/*	 * With the leaves initialized, adjust the tree for this dmapctl.	 */	max = ujfs_adjtree(dcp->stree, L2LPERCTL, l2cblks);	/*	 * Write and release the dmapctl page	 */	/* swap if on big endian machine */	ujfs_swap_dmapctl(dcp);	rc += ujfs_rw_diskblocks(dev_ptr, *start, PSIZE, dcp, PUT);	free(dcp);	/*	 * Set the treemax return value with the maximum free described by	 * this dmapctl.	 */	*treemax = max;	*start = next_page;	return (rc);}/*-------------------------------------------------------------------- * NAME:        initbmap() * * FUNCTION:    Initialize the disk block allocation map for an aggregate. * * PARAMETERS: *      dev_ptr - device to write page to *      nblocks - Number of blocks within the aggregate. * * NOTES: The bmap control page is created.  Next, the number dmapctl level *      required to described the aggregate size (number of blocks within the *      aggregate) is determined. initctl() is then called to initialize the *      appropriate dmapctl levels and corresponding dmaps. * * RETURNS: */static int initbmap(FILE *dev_ptr, int64_t nblocks){	int level, rc = 0;	int64_t next_page;	/*	 * get the level for the actual top dmapctl for the aggregate and	 * its physical address (N.B. map file has been allocated	 * to cover full control level hierarchy);	 */	level = BMAPSZTOLEV(nblocks);	next_page = BMAP_OFF + PSIZE + PSIZE * (2 - level);	/*	 * initialize only the dmapctls and the dmaps they describe	 * that covers the actual aggregate size.	 */	rc = initctl(dev_ptr, 0, nblocks, level, &control_page->dn_maxfreebud,		     &next_page);	if (rc != 0)		return (rc);	/*	 * Write the control page to disk.	 */	/* swap if on big endian machine */	ujfs_swap_dbmap(control_page);	rc = ujfs_rw_diskblocks(dev_ptr, BMAP_OFF, PSIZE, control_page, PUT);	ujfs_swap_dbmap(control_page);	return (rc);}/*-------------------------------------------------------------------- * NAME:        alloc_map() * * FUNCTION:    Allocate and initialize to zero the memory for dmap pages *              and the control page of block map. * * PARAMETERS: *      num_dmaps       - Indicates number of dmaps to allocate * * DATA STRUCTURES: Initializes file static variable block_map * * RETURNS:     0 for success */static int alloc_map(int num_dmaps){	if (num_dmaps <= 0)		return EINVAL;	/* alloc/init dmap page pointer array */	block_map_array = malloc(num_dmaps * sizeof (struct dmap *));	if (block_map_array == NULL) {		message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG);		return ENOMEM;	}	sz_block_map_array = num_dmaps;	memset(block_map_array, 0, num_dmaps * sizeof (struct dmap *));	/* alloc/init control page */	control_page = malloc(sizeof (struct dbmap));	if (control_page == NULL) {		message_user(MSG_OSO_INSUFF_MEMORY, NULL, 0, OSO_MSG);		return ENOMEM;	}	memset(control_page, 0, sizeof (struct dbmap));	return 0;}/*-------------------------------------------------------------------- * NAME:        initmap() * * FUNCTION:    Initialize control page * * PARAMETERS: *      nblocks - Number of blocks covered by this map *      ag_size - Will be filled in with AG size in blocks *      aggr_block_size         - Aggregate block size * * RETURNS: NONE */static void initmap(int64_t nblocks, int *ag_size, int aggr_block_size){	int index, nb, l2nl, n;	/*	 * Initialize base information	 */	control_page->dn_l2nbperpage = log2shift(PSIZE / aggr_block_size);	control_page->dn_mapsize = control_page->dn_nfree = nblocks;	control_page->dn_maxlevel = BMAPSZTOLEV(nblocks);	/* control_page->dn_maxfreebud is computed at finalization */	/*	 * Initialize allocation group information.	 */	control_page->dn_agl2size = ujfs_getagl2size(nblocks, aggr_block_size);	*ag_size = control_page->dn_agsize =	    (int64_t) 1 << control_page->dn_agl2size;	control_page->dn_numag = nblocks / control_page->dn_agsize;	control_page->dn_numag += (nblocks % control_page->dn_agsize) ? 1 : 0;	for (index = 0, nb = nblocks; index < control_page->dn_numag;	     index++, nb -= *ag_size) {		control_page->dn_agfree[index] = MIN(nb, *ag_size);	}	control_page->dn_aglevel = BMAPSZTOLEV(control_page->dn_agsize);	l2nl =	    control_page->dn_agl2size - (L2BPERDMAP +

⌨️ 快捷键说明

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