コード例 #1
0
void walk_internal_page(int	device,
			uint64	block,
			uint32	length,
			int64	*total_nblocks,
			int32	flag)
{
    int	rc;
    xtpage_t	xtree_page;
    int32	lastindex, index;
    uint64	first_block, cur_block, last_block;
    uint32	cur_length;
    int32	leafbad;

    /*
     * Read the internal page
     */
    rc = ujfs_rw_diskblocks( device, block << sb.s_l2bsize,
		length << sb.s_l2bsize, &xtree_page, GET );

    /*
     * Mark the blocks for the page; if internal page walk down page
     */
    leafbad = (xtree_page.header.flag & BT_LEAF) ? flag : 0;
    lastindex = xtree_page.header.nextindex;
    for( index = XTENTRYSTART; index < lastindex; index++ ) {
	/*
	 * This is actual data of the inode, mark these blocks
	 */
	first_block = addressXAD( &(xtree_page.xad[index]) );
	cur_length = lengthXAD( &(xtree_page.xad[index]) );
	*total_nblocks += cur_length;
	last_block = first_block + cur_length;
	for( cur_block = first_block; cur_block < last_block; cur_block++ ) {
	    markit( cur_block, leafbad );
	}

	if( xtree_page.header.flag & BT_INTERNAL ) {
	    /*
	     * This is an internal page of the b-tree.  Walk the page.
	     */
	    walk_internal_page(device, first_block, cur_length, total_nblocks,
			flag);
	}
    }
}
コード例 #2
0
void walk_internal_iag( int		device,
			xad_t		*top_page,
			boolean_t	is_primary,
			dinomap_t	*control_page,
			dinomap_t	*disk_cp,
			struct list_item	**top_iagfree,
			struct list_item	**top_inofree,
			struct list_item	**top_extfree,
			int32		inostamp )
{
    int32	rc, index, lastindex;
    uint64	block;
    uint32	length;
    xtpage_t	xtree_page;

    block = addressXAD(top_page);
    length = lengthXAD(top_page);

    rc = ujfs_rw_diskblocks( device, block << sb.s_l2bsize,
		length << sb.s_l2bsize, &xtree_page, GET );

    /*
     * Walk the IAG page unless this is another internal page, then we need to
     * walk it as an internal page again.
     */
    lastindex = xtree_page.header.nextindex;
    for( index = XTENTRYSTART; index < lastindex; index++ ) {
	if( xtree_page.header.flag & BT_LEAF ) {
	    walk_iag_extent( device, &(xtree_page.xad[index]), is_primary,
				control_page, disk_cp, top_iagfree,
				top_inofree, top_extfree, inostamp );
	} else {
	    walk_internal_iag( device, &(xtree_page.xad[index]), is_primary,
				control_page, disk_cp, top_iagfree,
				top_inofree, top_extfree, inostamp );
	}
    }
}
コード例 #3
0
void walk_inode_tree(int	device,
		     xtpage_t	*inode_root,
		     int64	*total_nblocks,
		     int32	flag)
{
    int32	index, lastindex;
    uint64	first_block, cur_block, last_block;
    uint32	length;
    int32	leafbad;

    /*
     * Have root of inode btree. Walk tree marking all blocks allocated.
     */
    leafbad = (inode_root->header.flag & BT_LEAF) ? flag : 0;
    lastindex = inode_root->header.nextindex;
    for( index = XTENTRYSTART; index < lastindex; index++ ) {
	/*
	 * This is actual data of the inode, mark these blocks
	 */
	first_block = addressXAD( &(inode_root->xad[index]) );
	length = lengthXAD( &(inode_root->xad[index]) );
	*total_nblocks += length;
	last_block = first_block + length;
	for( cur_block = first_block; cur_block < last_block; cur_block++ ) {
	    markit( cur_block, leafbad );
	}

	if( inode_root->header.flag & BT_INTERNAL ) {
	    /*
	     * This is an internal page of the b-tree.  Walk the page.
	     */
	    walk_internal_page(device, first_block, length, total_nblocks,
			flag);
	}
    }
}
コード例 #4
0
ファイル: inode.c プロジェクト: marc1706/desire_kernel_35
int jfs_get_block(struct inode *ip, sector_t lblock,
		  struct buffer_head *bh_result, int create)
{
	s64 lblock64 = lblock;
	int rc = 0;
	xad_t xad;
	s64 xaddr;
	int xflag;
	s32 xlen = bh_result->b_size >> ip->i_blkbits;

	/*
	 * Take appropriate lock on inode
	 */
	if (create)
		IWRITE_LOCK(ip, RDWRLOCK_NORMAL);
	else
		IREAD_LOCK(ip, RDWRLOCK_NORMAL);

	if (((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size) &&
	    (!xtLookup(ip, lblock64, xlen, &xflag, &xaddr, &xlen, 0)) &&
	    xaddr) {
		if (xflag & XAD_NOTRECORDED) {
			if (!create)
				/*
				 * Allocated but not recorded, read treats
				 * this as a hole
				 */
				goto unlock;
#ifdef _JFS_4K
			XADoffset(&xad, lblock64);
			XADlength(&xad, xlen);
			XADaddress(&xad, xaddr);
#else				/* _JFS_4K */
			/*
			 * As long as block size = 4K, this isn't a problem.
			 * We should mark the whole page not ABNR, but how
			 * will we know to mark the other blocks BH_New?
			 */
			BUG();
#endif				/* _JFS_4K */
			rc = extRecord(ip, &xad);
			if (rc)
				goto unlock;
			set_buffer_new(bh_result);
		}

		map_bh(bh_result, ip->i_sb, xaddr);
		bh_result->b_size = xlen << ip->i_blkbits;
		goto unlock;
	}
	if (!create)
		goto unlock;

	/*
	 * Allocate a new block
	 */
#ifdef _JFS_4K
	if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad)))
		goto unlock;
	rc = extAlloc(ip, xlen, lblock64, &xad, false);
	if (rc)
		goto unlock;

	set_buffer_new(bh_result);
	map_bh(bh_result, ip->i_sb, addressXAD(&xad));
	bh_result->b_size = lengthXAD(&xad) << ip->i_blkbits;

#else				/* _JFS_4K */
	/*
	 * We need to do whatever it takes to keep all but the last buffers
	 * in 4K pages - see jfs_write.c
	 */
	BUG();
#endif				/* _JFS_4K */

      unlock:
	/*
	 * Release lock on inode
	 */
	if (create)
		IWRITE_UNLOCK(ip);
	else
		IREAD_UNLOCK(ip);
	return rc;
}
コード例 #5
0
ファイル: inode.c プロジェクト: GodFox/magx_kernel_xpixl
static int
jfs_get_blocks(struct inode *ip, sector_t lblock, unsigned long max_blocks,
			struct buffer_head *bh_result, int create)
{
	s64 lblock64 = lblock;
	int no_size_check = 0;
	int rc = 0;
	int take_locks;
	xad_t xad;
	s64 xaddr;
	int xflag;
	s32 xlen;

	/*
	 * If this is a special inode (imap, dmap) or directory,
	 * the lock should already be taken
	 */
	take_locks = ((JFS_IP(ip)->fileset != AGGREGATE_I) &&
		      !S_ISDIR(ip->i_mode));
	/*
	 * Take appropriate lock on inode
	 */
	if (take_locks) {
		if (create)
			IWRITE_LOCK(ip);
		else
			IREAD_LOCK(ip);
	}

	/*
	 * A directory's "data" is the inode index table, but i_size is the
	 * size of the d-tree, so don't check the offset against i_size
	 */
	if (S_ISDIR(ip->i_mode))
		no_size_check = 1;

	if ((no_size_check ||
	     ((lblock64 << ip->i_sb->s_blocksize_bits) < ip->i_size)) &&
	    (xtLookup(ip, lblock64, max_blocks, &xflag, &xaddr, &xlen, no_size_check)
	     == 0) && xlen) {
		if (xflag & XAD_NOTRECORDED) {
			if (!create)
				/*
				 * Allocated but not recorded, read treats
				 * this as a hole
				 */
				goto unlock;
#ifdef _JFS_4K
			XADoffset(&xad, lblock64);
			XADlength(&xad, xlen);
			XADaddress(&xad, xaddr);
#else				/* _JFS_4K */
			/*
			 * As long as block size = 4K, this isn't a problem.
			 * We should mark the whole page not ABNR, but how
			 * will we know to mark the other blocks BH_New?
			 */
			BUG();
#endif				/* _JFS_4K */
			rc = extRecord(ip, &xad);
			if (rc)
				goto unlock;
			set_buffer_new(bh_result);
		}

		map_bh(bh_result, ip->i_sb, xaddr);
		bh_result->b_size = xlen << ip->i_blkbits;
		goto unlock;
	}
	if (!create)
		goto unlock;

	/*
	 * Allocate a new block
	 */
#ifdef _JFS_4K
	if ((rc = extHint(ip, lblock64 << ip->i_sb->s_blocksize_bits, &xad)))
		goto unlock;
	rc = extAlloc(ip, max_blocks, lblock64, &xad, FALSE);
	if (rc)
		goto unlock;

	set_buffer_new(bh_result);
	map_bh(bh_result, ip->i_sb, addressXAD(&xad));
	bh_result->b_size = lengthXAD(&xad) << ip->i_blkbits;

#else				/* _JFS_4K */
	/*
	 * We need to do whatever it takes to keep all but the last buffers
	 * in 4K pages - see jfs_write.c
	 */
	BUG();
#endif				/* _JFS_4K */

      unlock:
	/*
	 * Release lock on inode
	 */
	if (take_locks) {
		if (create)
			IWRITE_UNLOCK(ip);
		else
			IREAD_UNLOCK(ip);
	}
	return rc;
}
コード例 #6
0
/****************************************************************************
 * NAME: 	 process_Inode_Xtree
 *		
 * FUNCTION:	Traverse the xtree of the given inode looking for
 *		allocated extents containing bad blocks.
 *
 * PARAMETERS:	
 *	dip		ptr to the owning disk inode in a buffer
 *
 *	doRelocate	 0 => this is not the JFS Bad Block inode
 *			!0 => this is the JFS Bad Block inode
 *
 * NOTES:	
 *
 * RETURNS:
 *      success: 0
 *      failure: something else
 */
int32 process_Inode_Xtree( dinode_t *dip, int8 doRelocate )
{
    int32		pix_rc = 0;
    int32		relocate_rc;
    xtpage_t	*p; 
    int32		xlen, i;
    int64		xaddr, xoff, xlastblk;
    int8		didRelocate = 0;
    int32		xtype;
    cbbl_bdblk_recptr bdblk_recptr = NULL;
    int32		pList;
    ULONG 	pListLen = 0;
    clrbblks_t	pData;
    ULONG 	pDataLen = 0;

    int64	lmxaddr;	/* address of left-most child		*/
    xtpage_t next_xtpg;  	/* next xtpage to work on for the inode */
    xtpage_t *pnext_xtpg;
    int32 nxtpg_inx; 		/* the next index in next_xtpg to work on */

	/* 
	 * we start with the root 
	 */
    pnext_xtpg = p = (xtpage_t *)&dip->di_btroot;
    if (p->header.flag & BT_LEAF)  {
	xtype = DATAEXT;
	}
    else  {
	xtype = XTPAGE;
	p->header.next = 0;
		/* 
		 * save leftmost child xtpage xaddr 
		 */
	lmxaddr = addressXAD(&p->xad[XTENTRYSTART]);
	}

    nxtpg_inx = XTENTRYSTART;

	/*
	 * scan each level of xtree
	 */
    while(1)  {
		/*
		 * scan each xtpage of current level of xtree
		 */
	while(1)  {
		/*
		 * scan each xad in current xtpage
		 */
	    for (i = nxtpg_inx; i < p->header.nextindex; i++)  {
			/* 
			 * does the extent contain at least 1 
			 * bad block? 
			 */ 
		xoff = offsetXAD(&p->xad[i]);
		xaddr = addressXAD(&p->xad[i]) ;
		xlen = lengthXAD(&p->xad[i]) ;

		pix_rc = baltree_search( xaddr, &bdblk_recptr );
		if( pix_rc != 0 ) {  /* something fatal on search */
		    return( pix_rc );
		    }
		else if( bdblk_recptr == NULL ) {  /* hit end of tree w/o match */
		    continue;
		    }  /* end hit end of tree w/o match */

		xlastblk = xaddr + xlen - 1;
		if( bdblk_recptr->fs_blkno <= xlastblk ) { /*
				* the extent contains at least 1 bad block
				*/
#ifdef _JFS_DEBUG
	printf("bad block 0x0%llx found in xtree for inode %d\n", 
		bdblk_recptr->fs_blkno, dip->di_number );
#endif
		    if( !doRelocate ) { /* relocation not requested */
			pix_rc = we_DidntTryTo_Relocate( xaddr,
							     xlastblk,
							     bdblk_recptr
							    );
			}  /* end relocation not requested */
		    else {  /* relocation is requested */
			pDataLen = sizeof(clrbblks_t);
			pData.flag = CLRBBLKS_RELOCATE | IFREG | xtype;
//PS24072004			pData.dev = lvMount->LVNumber;
			pData.dev = LVNumber;
			pData.fileset = dip->di_fileset;
			pData.inostamp = dip->di_inostamp;
			pData.ino = dip->di_number;
			pData.gen = dip->di_gen;
			pData.xoff = xoff;	/* offset within the file */
			pData.old_xaddr = xaddr;
			pData.new_xaddr = 0;
			pData.xlen = xlen;
			pData.agg_blksize = agg_recptr->fs_blksize;
				/*
				 * attempt to relocate the extent
				 */
			didRelocate = 0;
			relocate_rc = fscntl(	JFSCTL_CLRBBLKS,
						(void *)&pList, &pListLen,
						(void *)&pData, &pDataLen
						);
			if( (relocate_rc == 0) && 
			    (pData.new_xaddr != 0) ) {  /*
				* extent has been relocated 
				*/
			    didRelocate = -1;
			    }  /* end extent has been relocated */	
				/*
				 * Now handle the individual bad block(s) 
				 * in the extent
				 */
			if( didRelocate ) {  /* 
				* actually did relocate 
				*/
			    pix_rc = we_Did_Relocate( xaddr, 
							  xlastblk,
							  bdblk_recptr 
							  );
			    }  /* end actually did relocate */
			else {  /* tried but failed to relocate */
			    pix_rc = we_Couldnt_Relocate( xaddr, 
							      xlastblk,
							      bdblk_recptr, 
							      relocate_rc 
							     );
			    }  /* end else tried but failed to relocate */
			}  /* end else relocation is requested */
		    }  /* end the extent contains at least 1 bad block */
		}  /* end for current xtpage scan */

		/*
		 * read in next/right sibling xtpage 
		 */
	    if (p->header.next != 0) {
		xaddr = p->header.next;
		pix_rc = pRead(fsMount, xaddr, fsMount->nbperpage, &next_xtpg);
		if ( pix_rc != 0 )  {
		    return CBBL_CANTREADNEXTXTPG; /* i/o error */
		    }

		pnext_xtpg = p = &next_xtpg;
		nxtpg_inx = XTENTRYSTART;
		}
	    else
		break;
	    } /* end while current level scan */

		/*
		 * descend: 	read leftmost xtpage of next 
		 * 		lower level of xtree
		 */
	if (xtype == XTPAGE)  {
		/* 
		 * get the leftmost child page  
		 */
	    pix_rc = pRead(fsMount, lmxaddr, fsMount->nbperpage, &next_xtpg);
	    if ( pix_rc != 0 )  {
		return CBBL_CANTREADLMXTCHILD; /* i/o error */
		}

	    pnext_xtpg = p = &next_xtpg;
	    nxtpg_inx = XTENTRYSTART;
	    if (p->header.flag & BT_LEAF)  {
		xtype = DATAEXT;
		}
	    else  {
		xtype = XTPAGE;
			/* 
			 * save leftmost child xtpage xaddr 
			 */
		lmxaddr = addressXAD(&p->xad[XTENTRYSTART]);
		}
	    }   /* end xtype == XTPAGE */
		else
			break;
	} /* end while level scan */

	/* 
	 * this inode is done: reset variables 
	 */
    pnext_xtpg = NULL;

    return 0;
}					/* end process_Inode_Xtree() */
コード例 #7
0
/*
 * Read the specified extent as an extent of IAG's
 * If its offset is 0 skip the first page since this is a control page.
 * For all other IAGs need to mark blocks:
 *	- mark the blocks for any allocated extents for the IAG
 *	- read the extent and mark blocks for any allocated inodes
 * Note: the blocks owned by the table itself will be marked when the inode for
 *	 the table is seen.
 */
void walk_iag_extent( int	device,
		      xad_t	*extent,
		      boolean_t	is_primary,
		      dinomap_t	*control_page,
		      dinomap_t	*disk_cp,
		      struct list_item	**top_iagfree,
		      struct list_item	**top_inofree,
		      struct list_item	**top_extfree,
		      int32	inostamp )
{
    uint64	offset, address, count, end;
    uint32	length, page_length;
    iag_t	iag_buffer;
    int32	index, rc, extdx;
    pxd_t	*inoext_ptr;
    uint32	map, found_map;
    uint32	agno;
    ino_t	start_inum;
    uint32	mymap[EXTSPERIAG];
    int16	seen_extent = 0, free_inodes = 0;

    offset = offsetXAD( extent );
    address = addressXAD( extent );
    length = lengthXAD( extent );
    page_length = PSIZE >> sb.s_l2bsize;

    if( offset == 0 ) {
	/*
	 * Read in the disk control page now.  We will compare it after all the
	 * other pages of the map have been processed.
	 */
	rc = ujfs_rw_diskblocks( device, address << sb.s_l2bsize,
				 sizeof(dinomap_t), disk_cp, GET );
	if( rc != 0 ) exit(rc);

	address += page_length;
	length -= page_length;
    }

    while( length > 0 ) {
	/*
	 * Clear map to use for tracking inodes seen
	 */
	memset( mymap, 0, EXTSPERIAG * sizeof(uint32));

	/*
	 * Read next IAG
	 */
	rc = ujfs_rw_diskblocks( device, address << sb.s_l2bsize, PSIZE,
				 &iag_buffer, GET );
	if( rc != 0 ) exit(rc);
	length -= page_length;
	address += page_length;

	control_page->in_nextiag = iag_buffer.iagnum + 1;
	if( iag_buffer.iagfree != -1 ) {
	    /*
	     * We have an item on the iagfree list following this one.
	     */
	    rc = search_and_add(top_iagfree, iag_buffer.iagfree, DISK_LIST);
	    if( rc != 0 ) {
		printf("Bad iagfree item on-disk: %d\n", iag_buffer.iagfree);
	    }
	}

	agno = iag_buffer.agstart / sb.s_agsize;
	if( iag_buffer.extfreefwd != -1 ) {
	    /*
	     * We have an item on the extfree list following this one.
	     */
	    rc = search_and_add(&(top_extfree[agno]), iag_buffer.extfreefwd,
			DISK_LIST);
	    if( rc != 0 ) {
		printf("Bad extfree[%d] item on-disk: %d\n", agno,
			iag_buffer.extfreefwd);
	    }
	}

	if( iag_buffer.inofreefwd != -1 ) {
	    /*
	     * We have an item on the inofree list following this one.
	     */
	    rc = search_and_add(&(top_inofree[agno]), iag_buffer.inofreefwd,
			DISK_LIST);
	    if( rc != 0 ) {
		printf("Bad inofree[%d] item on-disk: %d\n", agno,
			iag_buffer.inofreefwd);
	    }
	}

	/*
	 * Mark blocks for any allocated inode extents
	 */
	for( index = 0; index < SMAPSZ; index++ ) {
	    map = iag_buffer.extsmap[index];
	    inoext_ptr = iag_buffer.inoext + (index * EXTSPERSUM);
	    for( extdx = 0; extdx < EXTSPERSUM, map != 0; extdx++, map <<= 1) {
		if( (map & HIGHORDER) != 0 ) {
		    seen_extent++;

		    /*
		     * Count inodes for allocated inode extents
		     */
		    control_page->in_numinos += NUM_INODE_PER_EXTENT;
		    control_page->in_agctl[agno].numinos +=
					NUM_INODE_PER_EXTENT;

		    address = count = addressPXD(inoext_ptr + extdx);
		    end = count + inoext_ptr[extdx].len;
		    for( ; count < end; count++) {
			markit( count, 0 );
		    }

		    if( is_primary == TRUE ) {
			/*
			 * Now need to read inodes and mark blocks for them
			 * Only do this for the primary inode table
			 */
			start_inum = (iag_buffer.iagnum << L2INOSPERIAG) +
				(index << (L2EXTSPERSUM + L2INOSPEREXT)) +
				(extdx << L2INOSPEREXT);
			walk_inoext( device, address, inoext_ptr[extdx].len,
				iag_buffer.wmap[(index * EXTSPERSUM) + extdx],
				control_page, agno, start_inum, &found_map,
				inostamp );
			mymap[(index * EXTSPERSUM) + extdx] = found_map;
			if( ~found_map != 0 ) free_inodes = 1;
		    }
		}
	    }
	}

	if( seen_extent == 0 ) {
	    /*
	     * No extents for this IAG, add it to iagfree list
	     */
	    rc = search_and_add(top_iagfree, iag_buffer.iagnum, FOUND_LIST);
	    if( rc != 0 ) {
		printf("Bad iagfree item found: %d\n", iag_buffer.iagnum);
	    }
	} else if( seen_extent != EXTSPERIAG ) {
	    /*
	     * Have free extents in this IAG, add to AG free extent list
	     */
	    rc = search_and_add(&(top_extfree[agno]), iag_buffer.iagnum,
			FOUND_LIST);
	    if( rc != 0 ) {
		printf("Bad extfree[%d] item found: %d\n", agno,
			iag_buffer.iagnum);
	    }
	}
	if( free_inodes != 0 ) {
	    /*
	     * We have some free inodes in the extent
	     */
	    rc = search_and_add(&(top_inofree[agno]), iag_buffer.iagnum,
			FOUND_LIST);
	    if( rc != 0 ) {
		printf("Bad inofree[%d] item found: %d\n", agno,
			iag_buffer.iagnum);
	    }
	}

	if( is_primary ) {
	    /*
	     * Compare map found by walking extents to the on-disk version
	     */
	    rc = memcmp( mymap, iag_buffer.wmap, EXTSPERIAG * sizeof(uint32));
	    if( rc != 0 ) {
		error++;
		printf("Miscompare of inode wmap of IAG %d.\n",
			iag_buffer.iagnum);
		print_uint_array ("Found map:", mymap, EXTSPERIAG);
		print_uint_array ("Disk wmap:", iag_buffer.wmap, EXTSPERIAG);
	    }

	    rc = memcmp( mymap, iag_buffer.pmap, EXTSPERIAG * sizeof(uint32));
	    if( rc != 0 ) {
		error++;
		printf("Miscompare of inode pmap of IAG %d.\n",
			iag_buffer.iagnum);
		print_uint_array ("Found map:", mymap, EXTSPERIAG);
		print_uint_array ("Disk pmap:", iag_buffer.pmap, EXTSPERIAG);
	    }
	}
    }
}