Exemplo n.º 1
0
/*
 * Given a block directory (dp/block), calculate its size as a shortform (sf)
 * directory and a header for the sf directory, if it will fit it the
 * space currently present in the inode.  If it won't fit, the output
 * size is too big (but not accurate).
 */
int						/* size for sf form */
xfs_dir2_block_sfsize(
	xfs_inode_t		*dp,		/* incore inode pointer */
	xfs_dir2_block_t	*block,		/* block directory data */
	xfs_dir2_sf_hdr_t	*sfhp)		/* output: header for sf form */
{
	xfs_dir2_dataptr_t	addr;		/* data entry address */
	xfs_dir2_leaf_entry_t	*blp;		/* leaf area of the block */
	xfs_dir2_block_tail_t	*btp;		/* tail area of the block */
	int			count;		/* shortform entry count */
	xfs_dir2_data_entry_t	*dep;		/* data entry in the block */
	int			i;		/* block entry index */
	int			i8count;	/* count of big-inode entries */
	int			isdot;		/* entry is "." */
	int			isdotdot;	/* entry is ".." */
	xfs_mount_t		*mp;		/* mount structure pointer */
	int			namelen;	/* total name bytes */
	xfs_ino_t		parent = 0;	/* parent inode number */
	int			size=0;		/* total computed size */

	mp = dp->i_mount;

	count = i8count = namelen = 0;
	btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
	blp = XFS_DIR2_BLOCK_LEAF_P(btp);

	/*
	 * Iterate over the block's data entries by using the leaf pointers.
	 */
	for (i = 0; i < INT_GET(btp->count, ARCH_CONVERT); i++) {
		if ((addr = INT_GET(blp[i].address, ARCH_CONVERT)) == XFS_DIR2_NULL_DATAPTR)
			continue;
		/*
		 * Calculate the pointer to the entry at hand.
		 */
		dep = (xfs_dir2_data_entry_t *)
		      ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
		/*
		 * Detect . and .., so we can special-case them.
		 * . is not included in sf directories.
		 * .. is included by just the parent inode number.
		 */
		isdot = dep->namelen == 1 && dep->name[0] == '.';
		isdotdot =
			dep->namelen == 2 &&
			dep->name[0] == '.' && dep->name[1] == '.';
#if XFS_BIG_INUMS
		if (!isdot)
			i8count += INT_GET(dep->inumber, ARCH_CONVERT) > XFS_DIR2_MAX_SHORT_INUM;
#endif
		if (!isdot && !isdotdot) {
			count++;
			namelen += dep->namelen;
		} else if (isdotdot)
			parent = INT_GET(dep->inumber, ARCH_CONVERT);
		/*
		 * Calculate the new size, see if we should give up yet.
		 */
	/* Add by Jerry 2007/10/25
	   Fixed bug that XFS file system corrupted under Winthrax test.

	   This is the "special" structure alignment on the ARM.
	   Port a workaround solution from a patch on 
			http://lists.arm.linux.org.uk/pipermail/linux-arm-kernel/2004-March/020287.html
			and http://www.nas-central.org/index.php/Buffalo_ARM9_Kernel_Port#XFS_Arm_Issues
	   This patch was never accepted by XFS because the code is incorrect for all other platforms.			
	*/
#if 0
		size = XFS_DIR2_SF_HDR_SIZE(i8count) +		/* header */
		       count +					/* namelen */
		       count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
		       namelen +				/* name */
		       (i8count ?				/* inumber */
				(uint)sizeof(xfs_dir2_ino8_t) * count :
				(uint)sizeof(xfs_dir2_ino4_t) * count);
#else
		size = XFS_DIR2_SF_HDR_SIZE(i8count)		/* header */
				+ namelen
				+ (count * (sizeof(xfs_dir2_sf_entry_t) - 1))
				- (count * (((i8count == 0) ? 1 : 0) *
				(sizeof(xfs_dir2_ino8_t) - sizeof(xfs_dir2_ino4_t))));
#endif
		if (size > XFS_IFORK_DSIZE(dp))
			return size;		/* size value is a failure */
	}
	/*
	 * Create the output header, if it worked.
	 */
	sfhp->count = count;
	sfhp->i8count = i8count;
	XFS_DIR2_SF_PUT_INUMBER((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
	return size;
}
Exemplo n.º 2
0
xfs_dir2_data_aoff_t
xfs_dir2_dataptr_to_off(xfs_mount_t *mp, xfs_dir2_dataptr_t dp)
{
    return XFS_DIR2_DATAPTR_TO_OFF(mp, dp);
}
Exemplo n.º 3
0
/*
 * Given a block directory (dp/block), calculate its size as a shortform (sf)
 * directory and a header for the sf directory, if it will fit it the
 * space currently present in the inode.  If it won't fit, the output
 * size is too big (but not accurate).
 */
int						/* size for sf form */
xfs_dir2_block_sfsize(
    xfs_inode_t		*dp,		/* incore inode pointer */
    xfs_dir2_block_t	*block,		/* block directory data */
    xfs_dir2_sf_hdr_t	*sfhp)		/* output: header for sf form */
{
    xfs_dir2_dataptr_t	addr;		/* data entry address */
    xfs_dir2_leaf_entry_t	*blp;		/* leaf area of the block */
    xfs_dir2_block_tail_t	*btp;		/* tail area of the block */
    int			count;		/* shortform entry count */
    xfs_dir2_data_entry_t	*dep;		/* data entry in the block */
    int			i;		/* block entry index */
    int			i8count;	/* count of big-inode entries */
    int			isdot;		/* entry is "." */
    int			isdotdot;	/* entry is ".." */
    xfs_mount_t		*mp;		/* mount structure pointer */
    int			namelen;	/* total name bytes */
    xfs_ino_t		parent;		/* parent inode number */
    int			size=0;		/* total computed size */

    mp = dp->i_mount;

    count = i8count = namelen = 0;
    btp = XFS_DIR2_BLOCK_TAIL_P(mp, block);
    blp = XFS_DIR2_BLOCK_LEAF_P(btp);

    /*
     * Iterate over the block's data entries by using the leaf pointers.
     */
    for (i = 0; i < INT_GET(btp->count, ARCH_CONVERT); i++) {
        if ((addr = INT_GET(blp[i].address, ARCH_CONVERT)) == XFS_DIR2_NULL_DATAPTR)
            continue;
        /*
         * Calculate the pointer to the entry at hand.
         */
        dep = (xfs_dir2_data_entry_t *)
              ((char *)block + XFS_DIR2_DATAPTR_TO_OFF(mp, addr));
        /*
         * Detect . and .., so we can special-case them.
         * . is not included in sf directories.
         * .. is included by just the parent inode number.
         */
        isdot = dep->namelen == 1 && dep->name[0] == '.';
        isdotdot =
            dep->namelen == 2 &&
            dep->name[0] == '.' && dep->name[1] == '.';
#if XFS_BIG_INUMS
        if (!isdot)
            i8count += INT_GET(dep->inumber, ARCH_CONVERT) > XFS_DIR2_MAX_SHORT_INUM;
#endif
        if (!isdot && !isdotdot) {
            count++;
            namelen += dep->namelen;
        } else if (isdotdot)
            parent = INT_GET(dep->inumber, ARCH_CONVERT);
        /*
         * Calculate the new size, see if we should give up yet.
         */
        size = XFS_DIR2_SF_HDR_SIZE(i8count) +		/* header */
               count +					/* namelen */
               count * (uint)sizeof(xfs_dir2_sf_off_t) + /* offset */
               namelen +				/* name */
               (i8count ?				/* inumber */
                (uint)sizeof(xfs_dir2_ino8_t) * count :
                (uint)sizeof(xfs_dir2_ino4_t) * count);
        if (size > XFS_IFORK_DSIZE(dp))
            return size;		/* size value is a failure */
    }
    /*
     * Create the output header, if it worked.
     */
    sfhp->count = count;
    sfhp->i8count = i8count;
    XFS_DIR2_SF_PUT_INUMBER((xfs_dir2_sf_t *)sfhp, &parent, &sfhp->parent);
    return size;
}