/*
 * In short-form directory entries the inode numbers are stored at variable
 * offset behind the entry name. If the entry stores a filetype value, then it
 * sits between the name and the inode number. Hence the inode numbers may only
 * be accessed through the helpers below.
 */
static xfs_dir2_inou_t *
xfs_dir3_sfe_inop(
	struct xfs_mount	*mp,
	struct xfs_dir2_sf_entry *sfep)
{
	__uint8_t	*ptr = &sfep->name[sfep->namelen];
	if (xfs_sb_version_hasftype(&mp->m_sb))
		ptr++;
	return (xfs_dir2_inou_t *)ptr;
}
Exemple #2
0
unsigned char
xfs_dir3_get_dtype(
	struct xfs_mount	*mp,
	__uint8_t		filetype)
{
	if (!xfs_sb_version_hasftype(&mp->m_sb))
		return DT_UNKNOWN;

	if (filetype >= XFS_DIR3_FT_MAX)
		return DT_UNKNOWN;

	return xfs_dir3_filetype_table[filetype];
}
Exemple #3
0
static __uint8_t *
alloc_ftypes_array(
	struct xfs_mount *mp)
{
	__uint8_t	*ptr;

	if (!xfs_sb_version_hasftype(&mp->m_sb))
		return NULL;

	ptr = calloc(XFS_INODES_PER_CHUNK, sizeof(*ptr));
	if (!ptr)
		do_error(_("could not allocate ftypes array\n"));
	return ptr;
}
Exemple #4
0
static int
inode_u_sfdir3_count(
	void		*obj,
	int		startoff)
{
	xfs_dinode_t	*dip;

	ASSERT(bitoffs(startoff) == 0);
	ASSERT(obj == iocur_top->data);
	dip = obj;
	ASSERT((char *)XFS_DFORK_DPTR(dip) - (char *)dip == byteize(startoff));
	return dip->di_format == XFS_DINODE_FMT_LOCAL &&
	       (be16_to_cpu(dip->di_mode) & S_IFMT) == S_IFDIR &&
	       xfs_sb_version_hasftype(&mp->m_sb);
}
/*
 * Return the ops structure according to the current config.  If we are passed
 * an inode, then that overrides the default config we use which is based on
 * feature bits.
 */
const struct xfs_dir_ops *
xfs_dir_get_ops(
	struct xfs_mount	*mp,
	struct xfs_inode	*dp)
{
	if (dp)
		return dp->d_ops;
	if (mp->m_dir_inode_ops)
		return mp->m_dir_inode_ops;
	if (xfs_sb_version_hascrc(&mp->m_sb))
		return &xfs_dir3_ops;
	if (xfs_sb_version_hasftype(&mp->m_sb))
		return &xfs_dir2_ftype_ops;
	return &xfs_dir2_ops;
}
Exemple #6
0
static char *
version_string(
	xfs_sb_t	*sbp)
{
	static char	s[1024];

	if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_1)
		strcpy(s, "V1");
	else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_2)
		strcpy(s, "V2");
	else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_3)
		strcpy(s, "V3");
	else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_4)
		strcpy(s, "V4");
	else if (XFS_SB_VERSION_NUM(sbp) == XFS_SB_VERSION_5)
		strcpy(s, "V5");

	/*
	 * We assume the state of these features now, so macros don't exist for
	 * them any more.
	 */
	if (sbp->sb_versionnum & XFS_SB_VERSION_NLINKBIT)
		strcat(s, ",NLINK");
	if (sbp->sb_versionnum & XFS_SB_VERSION_SHAREDBIT)
		strcat(s, ",SHARED");
	if (sbp->sb_versionnum & XFS_SB_VERSION_DIRV2BIT)
		strcat(s, ",DIRV2");

	if (xfs_sb_version_hasattr(sbp))
		strcat(s, ",ATTR");
	if (xfs_sb_version_hasquota(sbp))
		strcat(s, ",QUOTA");
	if (xfs_sb_version_hasalign(sbp))
		strcat(s, ",ALIGN");
	if (xfs_sb_version_hasdalign(sbp))
		strcat(s, ",DALIGN");
	if (xfs_sb_version_haslogv2(sbp))
		strcat(s, ",LOGV2");
	if (xfs_sb_version_hasextflgbit(sbp))
		strcat(s, ",EXTFLG");
	if (xfs_sb_version_hassector(sbp))
		strcat(s, ",SECTOR");
	if (xfs_sb_version_hasasciici(sbp))
		strcat(s, ",ASCII_CI");
	if (xfs_sb_version_hasmorebits(sbp))
		strcat(s, ",MOREBITS");
	if (xfs_sb_version_hasattr2(sbp))
		strcat(s, ",ATTR2");
	if (xfs_sb_version_haslazysbcount(sbp))
		strcat(s, ",LAZYSBCOUNT");
	if (xfs_sb_version_hasprojid32bit(sbp))
		strcat(s, ",PROJID32BIT");
	if (xfs_sb_version_hascrc(sbp))
		strcat(s, ",CRC");
	if (xfs_sb_version_hasftype(sbp))
		strcat(s, ",FTYPE");
	if (xfs_sb_version_hasfinobt(sbp))
		strcat(s, ",FINOBT");
	if (xfs_sb_version_hassparseinodes(sbp))
		strcat(s, ",SPARSE_INODES");
	if (xfs_sb_version_hasmetauuid(sbp))
		strcat(s, ",META_UUID");
	return s;
}
Exemple #7
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_data_hdr_t	*hdr,		/* 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 */
	int			has_ftype;
	struct xfs_da_geometry	*geo;

	mp = dp->i_mount;
	geo = mp->m_dir_geo;

	/*
	 * if there is a filetype field, add the extra byte to the namelen
	 * for each entry that we see.
	 */
	has_ftype = xfs_sb_version_hasftype(&mp->m_sb) ? 1 : 0;

	count = i8count = namelen = 0;
	btp = xfs_dir2_block_tail_p(geo, hdr);
	blp = xfs_dir2_block_leaf_p(btp);

	/*
	 * Iterate over the block's data entries by using the leaf pointers.
	 */
	for (i = 0; i < be32_to_cpu(btp->count); i++) {
		if ((addr = be32_to_cpu(blp[i].address)) == XFS_DIR2_NULL_DATAPTR)
			continue;
		/*
		 * Calculate the pointer to the entry at hand.
		 */
		dep = (xfs_dir2_data_entry_t *)((char *)hdr +
				xfs_dir2_dataptr_to_off(geo, 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 += be64_to_cpu(dep->inumber) > XFS_DIR2_MAX_SHORT_INUM;
#endif
		/* take into account the file type field */
		if (!isdot && !isdotdot) {
			count++;
			namelen += dep->namelen + has_ftype;
		} else if (isdotdot)
			parent = be64_to_cpu(dep->inumber);
		/*
		 * 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;
	dp->d_ops->sf_put_parent_ino(sfhp, parent);
	return size;
}