char display_internal_xads( xad_t *xad, int16 nextindex, int32 *changed) { int32 i; idtentry_t *entry; int64 node_address; char result; int32 slot_number; for (i = 2; i < nextindex; i++) { printf("XAD # = %d\n", i); printf("[1] xad.flag\t %x\t\t", xad[i].flag); printf("[4] xad.len\t 0x%06x\n", xad[i].len); printf("[2] xad.off1\t 0x%02x\t\t", xad[i].off1); printf("[5] xad.addr1\t 0x%02x\n", xad[i].addr1); printf("[3] xad.off2\t 0x%08x\t", xad[i].off2); printf("[6] xad.addr2\t 0x%08x\n", xad[i].addr2); printf(" xad.off \t %lld\t\t", offsetXAD(&(xad[i]))); printf(" xad.addr\t %lld\n", addressXAD(&(xad[i]))); result = prompt("xtree: press enter for next or [u]p, [d]own or e[x]it > "); if (result == 'x' || result == 'u' ) return result; else if (result == 'd') { result = display_internal_xtpage(xad[i]); return result; } } return result; }
/**************************************************************************** * 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() */
/* * 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); } } } }