int sba_jfs_find_journal_entries(void) { char *data; if ((data = read_block(JFS_SUPER)) != NULL) { int i; struct jfs_superblock *jfs_sb = (struct jfs_superblock *)data; sba_debug(1, "magic number = %s\n", jfs_sb->s_magic); sba_debug(1, "block size = %d\n", jfs_sb->s_bsize); jfs_jour_start = addressPXD(&jfs_sb->s_logpxd); jfs_jour_size = lengthPXD(&jfs_sb->s_logpxd); sba_debug(1, "log address = %d\n", jfs_jour_start); sba_debug(1, "log size = %d\n", jfs_jour_size); for (i = 0; i < jfs_jour_size; i ++) { ht_add(h_sba_jfs_journal, i+jfs_jour_start); } sba_debug(1, "Added log blocks from %d to %d\n", jfs_jour_start, jfs_jour_start + jfs_jour_size - 1); free_page((int)data); } return 1; }
/****************************************************************** * NAME: OpenFilSys * * FUNCTION: Read the superblock into a buffer. * Extract various pieces of information. * Release the buffer. * * PARAMETERS: none * * NOTES: * * RETURNS: * success: 0 * failure: something else */ int32 OpenFilSys( void ) { int32 rc; struct superblock *sb; buf_t *bp; /* * validate and retrieve fs parameters from superblock */ /* try to read the primary superblock */ rc = bRawRead(LVHandle, (int64)SUPER1_OFF, (int32)PAGESIZE, &bp); if (rc != 0) { /* try to read the secondary superblock */ rc = bRawRead(LVHandle, (int64)SUPER2_OFF, (int32)PAGESIZE, &bp); if (rc != 0) { #ifdef _JFS_DEBUG printf("OpenFilSys: i/o error: rc=%d\n", rc); #endif return CBBL_CANTREADSBLKS; } } sb = (struct superblock *)bp->b_data; /* check magic/version number */ if (strncmp(sb->s_magic,JFS_MAGIC,(unsigned)strlen(JFS_MAGIC)) || (sb->s_version != JFS_VERSION)) { return CBBL_INVALMAGORVERS; } if (sb->s_state & FM_DIRTY) { return CBBL_FSDIRTY; } fsMount->bsize = sb->s_bsize; fsMount->l2bsize = sb->s_l2bsize; fsMount->l2bfactor = sb->s_l2bfactor; fsMount->nbperpage = PAGESIZE >> fsMount->l2bsize; fsMount->l2nbperpage = log2shift(fsMount->nbperpage); fsMount->FSSize = sb->s_size >> sb->s_l2bfactor; fsMount->AGSize = sb->s_agsize; #ifdef _JFS_DEBUG printf("superblock: attribute:0x%08x state:0x%08x\n", sb->s_flag, sb->s_state); printf("superblock: bsize:%d FSSize:%lld\n", fsMount->bsize, fsMount->FSSize); #endif agg_recptr->fs_blksize = sb->s_bsize; /* aggregate block size */ agg_recptr->lv_blksize = sb->s_pbsize; /* device block size */ agg_recptr->fs_lv_ratio = sb->s_bsize / sb->s_pbsize; agg_recptr->fs_last_metablk = addressPXD( &sb->s_aim2 ) + lengthPXD( &sb->s_aim2); agg_recptr->fs_first_wspblk = addressPXD( &sb->s_fsckpxd ); bRelease(bp); return rc; } /* end OpenFilSys() */
void walk_dtree( int device, uint64 block, uint32 length, int64 *total_nblocks) { int rc; dtpage_t dtree_buffer; uint8 *stbl; idtentry_t *cur_entry; uint64 first_block, cur_block, last_block; uint32 cur_length; int32 lastindex, index; int32 thisindex; /* * Read the page from disk */ rc = ujfs_rw_diskblocks( device, block << sb.s_l2bsize, length << sb.s_l2bsize, &dtree_buffer, GET ); if( dtree_buffer.header.flag & BT_LEAF ) { /* * Nothing to do, since the data here is not pointing to blocks */ return; } /* * Mark blocks for each entry and visit that page */ lastindex = dtree_buffer.header.nextindex; stbl = (uint8 *)&(dtree_buffer.slot[dtree_buffer.header.stblindex]); for( index = 0; index < lastindex; index++ ) { /* * This is an internal page of the d-tree. Mark these blocks and * then walk that page */ thisindex = stbl[index]; cur_entry = (idtentry_t *)&(dtree_buffer.slot[thisindex]); first_block = addressPXD( &(cur_entry->xd) ); cur_length = lengthPXD( &(cur_entry->xd) ); *total_nblocks += cur_length; last_block = first_block + cur_length; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } walk_dtree( device, first_block, cur_length, total_nblocks); } }
void walk_dir( int device, dtroot_t *root_header, int64 *total_nblocks) { int32 index, lastindex; uint64 first_block, cur_block, last_block; idtentry_t *cur_entry; uint32 length; if( root_header->header.flag & BT_LEAF ) { /* * Nothing to do, since the data here is not pointing to blocks */ return; } /* * Have root of directory inode btree. * Walk tree marking all blocks allocated. */ lastindex = root_header->header.nextindex; for( index = 0; index < lastindex; index++ ) { /* * This is an internal page of the d-tree. Mark these blocks and * then walk that page */ cur_entry = (idtentry_t *)&(root_header->slot[root_header->header.stbl[index]]); first_block = addressPXD( &(cur_entry->xd) ); length = lengthPXD( &(cur_entry->xd) ); *total_nblocks += length; last_block = first_block + length; for( cur_block = first_block; cur_block < last_block; cur_block++ ) { markit( cur_block, 0 ); } walk_dtree( device, first_block, length, total_nblocks); } }
/* * jfs_extendfs() * * function: extend file system; * * |-------------------------------|----------|----------| * file system space fsck inline log * workspace space * * input: * new LVSize: in LV blocks (required) * new LogSize: in LV blocks (optional) * new FSSize: in LV blocks (optional) * * new configuration: * 1. set new LogSize as specified or default from new LVSize; * 2. compute new FSCKSize from new LVSize; * 3. set new FSSize as MIN(FSSize, LVSize-(LogSize+FSCKSize)) where * assert(new FSSize >= old FSSize), * i.e., file system must not be shrinked; */ int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) { int rc = 0; struct jfs_sb_info *sbi = JFS_SBI(sb); struct inode *ipbmap = sbi->ipbmap; struct inode *ipbmap2; struct inode *ipimap = sbi->ipimap; struct jfs_log *log = sbi->log; struct bmap *bmp = sbi->bmap; s64 newLogAddress, newFSCKAddress; int newFSCKSize; s64 newMapSize = 0, mapSize; s64 XAddress, XSize, nblocks, xoff, xaddr, t64; s64 oldLVSize; s64 newFSSize; s64 VolumeSize; int newNpages = 0, nPages, newPage, xlen, t32; int tid; int log_formatted = 0; struct inode *iplist[1]; struct jfs_superblock *j_sb, *j_sb2; uint old_agsize; struct buffer_head *bh, *bh2; /* If the volume hasn't grown, get out now */ if (sbi->mntflag & JFS_INLINELOG) oldLVSize = addressPXD(&sbi->logpxd) + lengthPXD(&sbi->logpxd); else oldLVSize = addressPXD(&sbi->fsckpxd) + lengthPXD(&sbi->fsckpxd); if (oldLVSize >= newLVSize) { printk(KERN_WARNING "jfs_extendfs: volume hasn't grown, returning\n"); goto out; } VolumeSize = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; if (VolumeSize) { if (newLVSize > VolumeSize) { printk(KERN_WARNING "jfs_extendfs: invalid size\n"); rc = -EINVAL; goto out; } } else { /* check the device */ bh = sb_bread(sb, newLVSize - 1); if (!bh) { printk(KERN_WARNING "jfs_extendfs: invalid size\n"); rc = -EINVAL; goto out; } bforget(bh); } /* Can't extend write-protected drive */ if (isReadOnly(ipbmap)) { printk(KERN_WARNING "jfs_extendfs: read-only file system\n"); rc = -EROFS; goto out; } /* * reconfigure LV spaces * --------------------- * * validate new size, or, if not specified, determine new size */ /* * reconfigure inline log space: */ if ((sbi->mntflag & JFS_INLINELOG)) { if (newLogSize == 0) { /* * no size specified: default to 1/256 of aggregate * size; rounded up to a megabyte boundary; */ newLogSize = newLVSize >> 8; t32 = (1 << (20 - sbi->l2bsize)) - 1; newLogSize = (newLogSize + t32) & ~t32; newLogSize = min(newLogSize, MEGABYTE32 >> sbi->l2bsize); } else {
/* * chkSuper() * * validate the superblock of the file system to be mounted and * get the file system parameters. * * returns * 0 with fragsize set if check successful * error code if not successful */ static int chkSuper(struct super_block *sb) { int rc = 0; struct jfs_sb_info *sbi = JFS_SBI(sb); struct jfs_superblock *j_sb; struct buffer_head *bh; int AIM_bytesize, AIT_bytesize; int expected_AIM_bytesize, expected_AIT_bytesize; s64 AIM_byte_addr, AIT_byte_addr, fsckwsp_addr; s64 byte_addr_diff0, byte_addr_diff1; s32 bsize; if ((rc = readSuper(sb, &bh))) return rc; j_sb = (struct jfs_superblock *)bh->b_data; /* * validate superblock */ /* validate fs signature */ if (strncmp(j_sb->s_magic, JFS_MAGIC, 4) || le32_to_cpu(j_sb->s_version) > JFS_VERSION) { rc = -EINVAL; goto out; } bsize = le32_to_cpu(j_sb->s_bsize); #ifdef _JFS_4K if (bsize != PSIZE) { jfs_err("Currently only 4K block size supported!"); rc = -EINVAL; goto out; } #endif /* _JFS_4K */ jfs_info("superblock: flag:0x%08x state:0x%08x size:0x%Lx", le32_to_cpu(j_sb->s_flag), le32_to_cpu(j_sb->s_state), (unsigned long long) le64_to_cpu(j_sb->s_size)); /* validate the descriptors for Secondary AIM and AIT */ if ((j_sb->s_flag & cpu_to_le32(JFS_BAD_SAIT)) != cpu_to_le32(JFS_BAD_SAIT)) { expected_AIM_bytesize = 2 * PSIZE; AIM_bytesize = lengthPXD(&(j_sb->s_aim2)) * bsize; expected_AIT_bytesize = 4 * PSIZE; AIT_bytesize = lengthPXD(&(j_sb->s_ait2)) * bsize; AIM_byte_addr = addressPXD(&(j_sb->s_aim2)) * bsize; AIT_byte_addr = addressPXD(&(j_sb->s_ait2)) * bsize; byte_addr_diff0 = AIT_byte_addr - AIM_byte_addr; fsckwsp_addr = addressPXD(&(j_sb->s_fsckpxd)) * bsize; byte_addr_diff1 = fsckwsp_addr - AIT_byte_addr; if ((AIM_bytesize != expected_AIM_bytesize) || (AIT_bytesize != expected_AIT_bytesize) || (byte_addr_diff0 != AIM_bytesize) || (byte_addr_diff1 <= AIT_bytesize)) j_sb->s_flag |= cpu_to_le32(JFS_BAD_SAIT); } if ((j_sb->s_flag & cpu_to_le32(JFS_GROUPCOMMIT)) != cpu_to_le32(JFS_GROUPCOMMIT)) j_sb->s_flag |= cpu_to_le32(JFS_GROUPCOMMIT); /* validate fs state */ if (j_sb->s_state != cpu_to_le32(FM_CLEAN) && !(sb->s_flags & MS_RDONLY)) { jfs_err("jfs_mount: Mount Failure: File System Dirty."); rc = -EINVAL; goto out; } sbi->state = le32_to_cpu(j_sb->s_state); sbi->mntflag = le32_to_cpu(j_sb->s_flag); /* * JFS always does I/O by 4K pages. Don't tell the buffer cache * that we use anything else (leave s_blocksize alone). */ sbi->bsize = bsize; sbi->l2bsize = le16_to_cpu(j_sb->s_l2bsize); /* * For now, ignore s_pbsize, l2bfactor. All I/O going through buffer * cache. */ sbi->nbperpage = PSIZE >> sbi->l2bsize; sbi->l2nbperpage = L2PSIZE - sbi->l2bsize; sbi->l2niperblk = sbi->l2bsize - L2DISIZE; if (sbi->mntflag & JFS_INLINELOG) sbi->logpxd = j_sb->s_logpxd; else { sbi->logdev = new_decode_dev(le32_to_cpu(j_sb->s_logdev)); memcpy(sbi->uuid, j_sb->s_uuid, sizeof(sbi->uuid)); memcpy(sbi->loguuid, j_sb->s_loguuid, sizeof(sbi->uuid)); } sbi->fsckpxd = j_sb->s_fsckpxd; sbi->ait2 = j_sb->s_ait2; out: brelse(bh); return rc; }
/* * NAME: jfs_statfs(vfsp, sfsp, crp) * * FUNCTION: get file system status <sfsp> from vfs <vfsp> * * PARAMETER: vfsp - virtual file system * sfsp - file status information structure * crp - credential * * RETURN: zero on success, non-zero on failure * * serialization: statfs() and extendfs() serializes by inode lock * of the inode map for both inode map and block allocation map. * All other access to fragment allocation map is serialized * under VMM locking. * * note: percolation of file system information: * support struct statfs (sys/statfs.h) for get file system status * service call statfs(). * (XPG4.2 defines struct statvfs in sys/statvfs.h for statvfs() * which requires statfs() and additional information) */ jfs_statfs( register struct vfs *vfsp, register struct statfs *statfsp, struct ucred *crp) { register int32 rc; register inode_t *ipmnt; /* mount inode */ inode_t *ipimap, *ipbmap; cbuf_t *bpsuper; struct superblock *sb = NULL; int32 fsck_length, log_length; NOISE(1,("jfs_statfs: vfs:0x%08x\n", vfsp)); /* * get the file system stats from the superblock */ ipimap = (struct inode *)vfsp->vfs_data; ipmnt = ipimap->i_ipmnt; if (rc = readSuper(ipmnt, &bpsuper)) goto out; sb = (struct superblock *)(bpsuper->cm_cdata); /* bcopy(sb->s_fname, statfsp->f_fname, sizeof(sb->s_fname)); */ bcopy(sb->s_fpack, statfsp->f_fpack, sizeof(sb->s_fpack)); statfsp->f_bsize = PSIZE; /* preferred i/o block size */ statfsp->f_fsize = sb->s_bsize; /* fundamental block size */ fsck_length = lengthPXD(&(sb->s_fsckpxd)); log_length = lengthPXD(&(sb->s_logpxd)); rawRelease(bpsuper); /* statfs()/extendfs() serialized by inode lock of the inode map * for both inode map and block allocation map. */ IREAD_LOCK(ipimap); /* * get the block stats from the bmap */ ipbmap = ipmnt->i_ipbmap; statfsp->f_blocks = (ipbmap->i_bmap->db_mapsize + fsck_length + log_length) >> ipbmap->i_bmap->db_l2nbperpage; statfsp->f_bfree = statfsp->f_bavail = ipbmap->i_bmap->db_nfree >> ipbmap->i_bmap->db_l2nbperpage; /* * get the file stats from the ipimap */ statfsp->f_files = ipimap->i_imap->im_numinos; statfsp->f_ffree = ipimap->i_imap->im_numfree; /* * fill in from vfs */ statfsp->f_fsid = vfsp->vfs_fsid; statfsp->f_vfstype = MNT_XJFS; statfsp->f_vfsnumber = vfsp->vfs_number; statfsp->f_name_max = JFS_NAME_MAX; /* * fields in the statfs structure that we don't fill in ... * long f_version; version/type of statfs, 0 for now long f_type; type of info, 0 for now long f_vfsoff; reserved, for vfs specific data offset long f_vfslen; reserved, for len of vfs specific data long f_vfsvers; reserved, for vers of vfs specific data */ out: IREAD_UNLOCK(ipimap); return rc; }
int jfs_extendfs(struct super_block *sb, s64 newLVSize, int newLogSize) { int rc = 0; struct jfs_sb_info *sbi = JFS_SBI(sb); struct inode *ipbmap = sbi->ipbmap; struct inode *ipbmap2; struct inode *ipimap = sbi->ipimap; struct jfs_log *log = sbi->log; struct bmap *bmp = sbi->bmap; s64 newLogAddress, newFSCKAddress; int newFSCKSize; s64 newMapSize = 0, mapSize; s64 XAddress, XSize, nblocks, xoff, xaddr, t64; s64 oldLVSize; s64 newFSSize; s64 VolumeSize; int newNpages = 0, nPages, newPage, xlen, t32; int tid; int log_formatted = 0; struct inode *iplist[1]; struct jfs_superblock *j_sb, *j_sb2; s64 old_agsize; int agsizechanged = 0; struct buffer_head *bh, *bh2; if (sbi->mntflag & JFS_INLINELOG) oldLVSize = addressPXD(&sbi->logpxd) + lengthPXD(&sbi->logpxd); else oldLVSize = addressPXD(&sbi->fsckpxd) + lengthPXD(&sbi->fsckpxd); if (oldLVSize >= newLVSize) { printk(KERN_WARNING "jfs_extendfs: volume hasn't grown, returning\n"); goto out; } VolumeSize = sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits; if (VolumeSize) { if (newLVSize > VolumeSize) { printk(KERN_WARNING "jfs_extendfs: invalid size\n"); rc = -EINVAL; goto out; } } else { bh = sb_bread(sb, newLVSize - 1); if (!bh) { printk(KERN_WARNING "jfs_extendfs: invalid size\n"); rc = -EINVAL; goto out; } bforget(bh); } if (isReadOnly(ipbmap)) { printk(KERN_WARNING "jfs_extendfs: read-only file system\n"); rc = -EROFS; goto out; } if ((sbi->mntflag & JFS_INLINELOG)) { if (newLogSize == 0) { newLogSize = newLVSize >> 8; t32 = (1 << (20 - sbi->l2bsize)) - 1; newLogSize = (newLogSize + t32) & ~t32; newLogSize = min(newLogSize, MEGABYTE32 >> sbi->l2bsize); } else {
/**************************************************************************** * NAME: process_Inode_Dtree * * FUNCTION: Traverse the dtree of the given directory 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_Dtree( dinode_t *dip, int8 doRelocate ) { int32 pid_rc = 0; int32 relocate_rc = 0; dtpage_t *p; int8 *stbl; int32 i; pxd_t *pxd; int64 xaddr, lmxaddr, xlastblk; int32 xlen; int8 didRelocate = 0; cbbl_bdblk_recptr bdblk_recptr = NULL; int32 pList; ULONG pListLen = 0; clrbblks_t pData; ULONG pDataLen = 0; int64 lmpg_addr; int32 lmxlen; dtpage_t next_dtpg; /* next dtpage to work on */ dtpage_t *pnext_dtpg; int32 ndtpg_inx; /* the next index in next_dtpg to work on */ /* * we start with the root */ pnext_dtpg = p = (dtpage_t *)&dip->di_btroot; /* * is it leaf, i.e., inode inline data ? */ if (p->header.flag & BT_LEAF) { goto out; } p->header.next = 0; /* * save leftmost dtpage xaddr */ lmpg_addr = 0; stbl = DT_GETSTBL(p); pxd = (pxd_t *)&p->slot[stbl[0]]; /* * save leftmost child dtpage extent */ lmxaddr = addressPXD(pxd); /* leftmost child xaddr */ lmxlen = lengthPXD(pxd); ndtpg_inx = 0; /* * scan each level of dtree */ while(1) { /* * scan each dtpage of current level of dtree */ while(1) { stbl = DT_GETSTBL(p); /* * scan each idtentry in current dtpage */ for (i = ndtpg_inx; i < p->header.nextindex; i++) { pxd = (pxd_t *)&p->slot[stbl[i]]; /* * does the extent contain at least 1 * bad block? */ xaddr = addressPXD(pxd); xlen = lengthPXD(pxd); pid_rc = baltree_search( xaddr, &bdblk_recptr ); if( pid_rc != 0 ) { /* something fatal on search */ return( pid_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 dtree for inode %d\n", bdblk_recptr->fs_blkno, dip->di_number ); #endif if( !doRelocate ) { /* relocation not requested */ pid_rc = we_DidntTryTo_Relocate( xaddr, xlastblk, bdblk_recptr ); } /* end relocation not requested */ else { /* relocation is requested */ pDataLen = sizeof(clrbblks_t); pData.flag = CLRBBLKS_RELOCATE | IFDIR | DTPAGE; //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 = lmpg_addr; /* leftmost page * describing this level */ 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 */ pid_rc = we_Did_Relocate( xaddr, xlastblk, bdblk_recptr ); } /* end actually did relocate */ else { /* tried but failed to relocate */ pid_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 loop */ /* * read in next/right sibling dtpage */ if (p->header.next != 0) { xaddr = p->header.next; pid_rc = pRead(fsMount, xaddr, fsMount->nbperpage, &next_dtpg); if (pid_rc != 0) { return CBBL_CANTREADNEXTDTPG; /* i/o error */ } pnext_dtpg = p = &next_dtpg; ndtpg_inx = 0; } else break; } /* end while current level scan */ /* * descend: read leftmost dtpage of next lower level of dtree */ /* * the first child of the dtroot split may not have PSIZE */ pid_rc = pRead(fsMount, lmxaddr, lmxlen, &next_dtpg); if ( pid_rc != 0 ) { return CBBL_CANTREADLMDTCHILD; /* i/o error */ } pnext_dtpg = p = &next_dtpg; /* * for dir, the leaf contains data, its pxd info * has been reported by the parent page. so we stop here */ if (p->header.flag & BT_LEAF) { break; } /* * save leftmost dtpage xaddr */ lmpg_addr = lmxaddr; stbl = DT_GETSTBL(p); pxd = (pxd_t *)&p->slot[stbl[0]]; /* * save leftmost child dtpage extent */ lmxaddr = addressPXD(pxd); /* leftmost child xaddr */ lmxlen = lengthPXD(pxd); ndtpg_inx = 0; } /* end while scan each level of tree */ /* reset global state variable for the inode */ out: pnext_dtpg = NULL; return pid_rc; } /* end process_Inode_Dtree() */
/**************************************************************************** * NAME: process_FilesetInodes * * FUNCTION: Reads in the fileset inode extents, one by one, and for * each in-use inode, calls process_Inode() to scan for * blocks on the bad block list and handle any that are * detected. * * PARAMETERS: none * * NOTES: * * RETURNS: * success: 0 * failure: something else */ int32 process_FilesetInodes ( ) { int32 pfsi_rc = 0; dinode_t *inoptr = NULL; dinomap_t *icp; int64 xaddr; int32 xlen; int8 isBadBlockInode = 0; /* * scan each IAG in the file set */ icp = (dinomap_t *)&IMap.ctl; for ( agg_recptr->iag_idx = 0; ( (agg_recptr->iag_idx < icp->in_nextiag) && (pfsi_rc == 0) && (agg_recptr->bdblk_baltree.seq_list != NULL) ); agg_recptr->iag_idx++) { /* for each IAG */ /* * read in the next IAG */ pfsi_rc = readIMapSequential(&iagbuf); /* * process the extents described by the IAG */ for ( agg_recptr->extent_idx = 0; ( (agg_recptr->extent_idx < EXTSPERIAG) && (pfsi_rc == 0) && (agg_recptr->bdblk_baltree.seq_list != NULL) ); agg_recptr->extent_idx++) { /* for each extent in the IAG */ /* * Get the address and length of the extent */ xaddr = addressPXD(&iagbuf.inoext[agg_recptr->extent_idx]); xlen = lengthPXD(&iagbuf.inoext[agg_recptr->extent_idx]); /* * If the extent isn't allocated, bump current inode number */ if( xaddr == 0 ) { /* not allocated */ agg_recptr->this_inonum += INOSPEREXT; } else { /* extent is allocated */ /* * Otherwise, read in the inode extent */ pfsi_rc = pRead(fsMount, xaddr, xlen, (void *)ixbuf); /* * process the inodes in the extent */ for ( agg_recptr->inode_idx = 0; ( (agg_recptr->inode_idx < INOSPEREXT) && (pfsi_rc == 0) && (agg_recptr->bdblk_baltree.seq_list != NULL) ); agg_recptr->inode_idx++) { /* * for each inode in the extent */ inoptr = &ixbuf[agg_recptr->inode_idx]; /* * if the inode isn't in use, just * increment the inode number */ if( (inoptr->di_nlink == 0) || (inoptr->di_inostamp != DIIMap.di_inostamp) ) { agg_recptr->this_inonum += 1; } /* * otherwise, scan the inode for bad blocks * allocated to it and, if possible, relocate * their contents and get them transferred to * the JFS Bad Block Inode */ else { /* the inode is in use */ pfsi_rc = process_Inode( isBadBlockInode, inoptr ); /* * increment to the next inode */ agg_recptr->this_inonum += 1; } /* end else the inode is in use */ } /* end for each inode in the extent */ } /* end else extent is allocated */ } /* end for each extent in the IAG */ } /* end for each IAG */ return( pfsi_rc ); } /* end process_FilesetInodes() */
/* look at jfs_logredo() and logRead() from logredo in jfsutils */ int sba_jfs_handle_journal_block(int sector, char *data) { int off; int ret; struct logpage *lp; struct lrd *ld; char *log_data_ptr; void *ptr; int ld_flag; int nwords; int type = JOURNAL_DATA_BLOCK; if (sba_jfs_journal_super_block(sector)) { return JOURNAL_SUPER_BLOCK; } /* each log page that is written is of the form "struct logpage" */ lp = (struct logpage *)data; off = lp->h.eor & (LOGPSIZE - 1); sba_debug(0, "The end of log offset of last record write = %d (h), %d (t)\n", lp->h.eor, lp->t.eor); sba_debug(0, "offset is %d head %u tail %u\n", off, (unsigned int)&(lp->h), (unsigned int)&(lp->t)); ld = kmalloc(sizeof(struct logpage), GFP_KERNEL); log_data_ptr = kmalloc(4096, GFP_KERNEL); nwords = LOGRDSIZE/4; ret = sba_jfs_get_next_log_record(nwords, (int *)ld, data, &off); ld_flag = 1; while (ret >= 0) { if (ld_flag) { sba_debug(0, "Length = %d , Backchain = %d\n", ld->length, ld->backchain); long long blocknr = -1; switch (ld->type) { case LOG_COMMIT: sba_debug(0, "Found a LOG_COMMIT record\n"); type = JOURNAL_COMMIT_BLOCK; break; case LOG_MOUNT: sba_debug(0, "Found a LOG_MOUNT record\n"); break; case LOG_SYNCPT: sba_debug(0, "Found a LOG_SYNCPT record\n"); break; case LOG_REDOPAGE: sba_debug(0, "Found a LOG_REDOPAGE record (address %lld, length %d)\n", addressPXD(&ld->log.redopage.pxd), lengthPXD(&ld->log.redopage.pxd)); blocknr = addressPXD(&ld->log.redopage.pxd); break; case LOG_NOREDOPAGE: sba_debug(0, "Found a LOG_NOREDOPAGE record (address %lld length %d)\n", addressPXD(&ld->log.noredopage.pxd), lengthPXD(&ld->log.noredopage.pxd)); blocknr = addressPXD(&ld->log.noredopage.pxd); break; case LOG_NOREDOINOEXT: sba_debug(0, "Found a LOG_NOREDOINOEXT record (address %lld length %d)\n", addressPXD(&ld->log.noredoinoext.pxd), lengthPXD(&ld->log.noredoinoext.pxd)); blocknr = addressPXD(&ld->log.noredoinoext.pxd); break; case LOG_UPDATEMAP: sba_debug(0, "Found a LOG_UPDATEMAP record (address %lld length %d nxd %d)\n", addressPXD(&ld->log.updatemap.pxd), lengthPXD(&ld->log.updatemap.pxd), ld->log.updatemap.nxd); blocknr = addressPXD(&ld->log.updatemap.pxd); break; default: sba_debug(1, "Found an UNKNOWN record\n"); break; } if (blocknr != -1) { if (sba_jfs_insert_journaled_blocks(blocknr) == -1) { sba_debug(1, "Error: inserting blk=%lld into journaled blocks list\n", blocknr); } } sba_debug(0, "Next offset = %d\n", off); } else { sba_debug(0, "Skipping data = %d words\n", nwords); } if (ld_flag) { if (ld->length > 0) { nwords = (ld->length + 3) / 4; ptr = log_data_ptr; ld_flag = 0; } else { nwords = LOGRDSIZE/4; ptr = ld; ld_flag = 1; } } else { nwords = LOGRDSIZE/4; ptr = ld; ld_flag = 1; } ret = sba_jfs_get_next_log_record(nwords, (int *)ptr, data, &off); } return type; }
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++; } } } }