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;
}
Example #2
0
/******************************************************************
 * 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() */
Example #3
0
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);
    }
}
Example #4
0
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);
    }
}
Example #5
0
/*
 *	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 {
Example #6
0
/*
 *	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;
}
Example #7
0
/*
 * 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 {
Example #9
0
/****************************************************************************
 * 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() */
Example #10
0
/****************************************************************************
 * 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;
}
Example #12
0
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++;
	    }
	}
    }
}