/* * NAME: free_ea_wmap(inode) * * FUNCTION: free uncommitted extended attributes from working map * */ static inline void free_ea_wmap(struct inode *inode) { dxd_t *ea = &JFS_IP(inode)->ea; if (ea->flag & DXD_EXTENT) { /* free EA pages from cache */ invalidate_dxd_metapages(inode, *ea); dbFree(inode, addressDXD(ea), lengthDXD(ea)); } ea->flag = 0; }
/* * NAME: jfs_free_zero_link() * * FUNCTION: for non-directory, called by iClose(), * free resources of a file from cache and WORKING map * for a file previously committed with zero link count * while associated with a pager object, * * PARAMETER: ip - pointer to inode of file. */ void jfs_free_zero_link(struct inode *ip) { int type; jfs_info("jfs_free_zero_link: ip = 0x%p", ip); /* return if not reg or symbolic link or if size is * already ok. */ type = ip->i_mode & S_IFMT; switch (type) { case S_IFREG: break; case S_IFLNK: /* if its contained in inode nothing to do */ if (ip->i_size < IDATASIZE) return; break; default: return; } /* * free EA */ if (JFS_IP(ip)->ea.flag & DXD_EXTENT) { s64 xaddr = addressDXD(&JFS_IP(ip)->ea); int xlen = lengthDXD(&JFS_IP(ip)->ea); struct maplock maplock; /* maplock for COMMIT_WMAP */ struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ /* free EA pages from cache */ invalidate_dxd_metapages(ip, JFS_IP(ip)->ea); /* free EA extent from working block map */ maplock.index = 1; pxdlock = (struct pxd_lock *) & maplock; pxdlock->flag = mlckFREEPXD; PXDaddress(&pxdlock->pxd, xaddr); PXDlength(&pxdlock->pxd, xlen); txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); } /* * free ACL */ if (JFS_IP(ip)->acl.flag & DXD_EXTENT) { s64 xaddr = addressDXD(&JFS_IP(ip)->acl); int xlen = lengthDXD(&JFS_IP(ip)->acl); struct maplock maplock; /* maplock for COMMIT_WMAP */ struct pxd_lock *pxdlock; /* maplock for COMMIT_WMAP */ invalidate_dxd_metapages(ip, JFS_IP(ip)->acl); /* free ACL extent from working block map */ maplock.index = 1; pxdlock = (struct pxd_lock *) & maplock; pxdlock->flag = mlckFREEPXD; PXDaddress(&pxdlock->pxd, xaddr); PXDlength(&pxdlock->pxd, xlen); txFreeMap(ip, pxdlock, NULL, COMMIT_WMAP); } /* * free xtree/data (truncate to zero length): * free xtree/data pages from cache, and * free xtree/data blocks from working block map; */ if (ip->i_size) xtTruncate(0, ip, 0, COMMIT_WMAP); }
/**************************************************************************** * NAME: process_Inode_EA * * FUNCTION: If the extent containing the Extended Attributes for the * given inode contains any bad blocks, handle it. * * 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 * * didRelocate ptr to var in which to return: * 0 if the extent was not relocated * !0 if the extent was relocated * * NOTES: * * RETURNS: * success: 0 * failure: something else */ int32 process_Inode_EA( dinode_t *dip, int8 doRelocate, int8 *didRelocate ) { int32 sea_rc = 0; int32 relocate_rc = 0; int64 ext_firstblk, ext_lastblk; int32 ext_len; cbbl_bdblk_recptr bdblk_recptr = NULL; cbbl_bdblk_recptr next_bdblk_recptr; int32 pList; ULONG pListLen = 0; clrbblks_t pData; ULONG pDataLen = 0; ext_firstblk = addressDXD( &(dip->di_ea) ); ext_len = lengthDXD( &(dip->di_ea) ); ext_lastblk = ext_firstblk + ext_len - 1; /* * find the first entry in bad block list with key greater * than or equal to the first block in this extent */ sea_rc = baltree_search( ext_firstblk, &bdblk_recptr ); if( sea_rc != 0 ) { /* something fatal on search */ return( sea_rc ); } else if( bdblk_recptr == NULL ) { /* hit end of tree w/o match */ return( sea_rc ); } /* end hit end of tree w/o match */ if( bdblk_recptr->fs_blkno <= ext_lastblk ) { /* * the extent contains at least 1 bad block */ #ifdef _JFS_DEBUG printf("bad block 0x0%llx found in EA for inode %d\n", bdblk_recptr->fs_blkno, dip->di_number ); #endif if( !doRelocate ) { /* relocation not requested */ sea_rc = we_DidntTryTo_Relocate( ext_firstblk, ext_lastblk, bdblk_recptr ); } /* end not asked to relocate */ else { /* relocation is requested */ pDataLen = sizeof(clrbblks_t); pData.flag = CLRBBLKS_RELOCATE | CLRBBLKS_EA; //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.old_xaddr = ext_firstblk; pData.new_xaddr = 0; pData.xlen = ext_len; 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 EA */ if( !(*didRelocate) ) { /* tried and failed to relocate */ sea_rc = we_Couldnt_Relocate( ext_firstblk, ext_lastblk, bdblk_recptr, relocate_rc ); } /* end tried and failed to relocate */ else { /* actually did relocate */ sea_rc = we_Did_Relocate( ext_firstblk, ext_lastblk, bdblk_recptr ); } /* else end actually did relocate */ } /* end else relocation is requested */ } /* end the extent contains at least 1 bad block */ return( sea_rc ); } /* end process_Inode_EA() */
void walk_inoext( int device, uint64 address, uint32 length, uint32 wmap, dinomap_t *control_page, uint32 agno, ino_t start_inum, uint32 *found_map, int32 inostamp ) { dinode_t *next_inode; uint32 left_to_read = length << sb.s_l2bsize; uint64 cur_address = address << sb.s_l2bsize; int32 index, rc; uint32 map = wmap; char page_buffer[PSIZE]; ino_t cur_inum = start_inum; uint32 mask = HIGHORDER; uint64 first_block, cur_block, last_block; uint32 num_blocks; int64 total_nblocks; *found_map = 0; while( (left_to_read > 0) ) { /* * Read next page of inodes for this extent */ rc = ujfs_rw_diskblocks( device, cur_address, PSIZE, page_buffer, GET ); cur_address += PSIZE; left_to_read -= PSIZE; next_inode = (dinode_t *)page_buffer; for( index = 0; index < INOSPERPAGE; index++, next_inode++, cur_inum++, map <<= 1, mask >>= 1 ) { /* * Initialize count for this inode's number of blocks */ total_nblocks = 0; /* * If this inode is allocated, mark blocks for its b-tree */ if( (map & HIGHORDER) != 0 ) { if( next_inode->di_nlink <= 0 ) { error++; printf("Inode %d (fileset: %d) link count bad: %d\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nlink); } else { *found_map |= mask; } /* * Account for any blocks used by EA for this inode */ if( next_inode->di_ea.flag & DXD_EXTENT ) { first_block = addressDXD(&(next_inode->di_ea)); num_blocks = lengthDXD(&(next_inode->di_ea)); total_nblocks += num_blocks; last_block = first_block + num_blocks; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } } if( (next_inode->di_fileset == AGGREGATE_I) && (next_inode->di_number == FILESYSTEM_I) ) { /* * Need to account for inode map's blocks */ walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, 0); /* * Need to walk this tree of inodes */ rc = walk_ait( device, next_inode, TRUE ); if( rc != 0 ) { error++; printf("Problem with Fileset Inode Allocation Map.\n"); } } else if( (next_inode->di_fileset == AGGREGATE_I) && (next_inode->di_number == BADBLOCK_I) ) { walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, BADBLOCK); } else if( next_inode->di_mode & IFDIR ) { /* * Need to walk the extents as directory extents */ walk_dir( device, (dtroot_t *)&(next_inode->di_btroot), &total_nblocks); } else { walk_inode_tree(device, (xtpage_t *)&next_inode->di_btroot, &total_nblocks, 0); } /* * Now total_nblocks contains the total number of blocks * actually allocated for this inode. Compare this to the * on-disk information. */ if( next_inode->di_nblocks != total_nblocks ) { error++; printf( "Inode %d (fileset: %d) nblocks bad, disk: %lld, actual: %lld\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nblocks, total_nblocks); } } else { if( next_inode->di_number == cur_inum && next_inode->di_inostamp == inostamp && addressPXD(&(next_inode->di_ixpxd)) == address && lengthPXD(&(next_inode->di_ixpxd)) == length && next_inode->di_nlink > 0 ) { error++; printf("Inode %d (fileset: %d) link count bad: %d\n", next_inode->di_number, next_inode->di_fileset, next_inode->di_nlink); *found_map |= mask; } control_page->in_numfree++; control_page->in_agctl[agno].numfree++; } } } }