Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9d23fc85 authored by Dave Chinner's avatar Dave Chinner Committed by Ben Myers
Browse files

xfs: vectorise directory data operations



Following from the initial patches to vectorise the shortform
directory encode/decode operations, convert half the data block
operations to use the vector. The rest will be done in a second
patch.

This further reduces the size of the built binary:

   text    data     bss     dec     hex filename
 794490   96802    1096  892388   d9de4 fs/xfs/xfs.o.orig
 792986   96802    1096  890884   d9804 fs/xfs/xfs.o.p1
 792350   96802    1096  890248   d9588 fs/xfs/xfs.o.p2
 789293   96802    1096  887191   d8997 fs/xfs/xfs.o.p3

Signed-off-by: default avatarDave Chinner <dchinner@redhat.com>
Reviewed-by: default avatarChristoph Hellwig <hch@lst.de>
Signed-off-by: default avatarBen Myers <bpm@sgi.com>
parent 4740175e
Loading
Loading
Loading
Loading
+217 −1
Original line number Diff line number Diff line
@@ -28,7 +28,9 @@
#include "xfs_inode.h"
#include "xfs_dir2.h"


/*
 * Shortform directory ops
 */
static int
xfs_dir2_sf_entsize(
	struct xfs_dir2_sf_hdr	*hdr,
@@ -203,6 +205,184 @@ xfs_dir3_sfe_put_ino(
			(xfs_dir2_inou_t *)&sfep->name[sfep->namelen + 1], ino);
}


/*
 * Directory data block operations
 */
static int
__xfs_dir3_data_entsize(
	bool	ftype,
	int	n)
{
	int	size = offsetof(struct xfs_dir2_data_entry, name[0]);

	size += n;
	size += sizeof(xfs_dir2_data_off_t);
	if (ftype)
		size += sizeof(__uint8_t);
	return roundup(size, XFS_DIR2_DATA_ALIGN);
}

static int
xfs_dir2_data_entsize(
	int			n)
{
	return __xfs_dir3_data_entsize(false, n);
}
static int
xfs_dir3_data_entsize(
	int			n)
{
	return __xfs_dir3_data_entsize(true, n);
}

static __uint8_t
xfs_dir2_data_get_ftype(
	struct xfs_dir2_data_entry *dep)
{
	return XFS_DIR3_FT_UNKNOWN;
}

static void
xfs_dir2_data_put_ftype(
	struct xfs_dir2_data_entry *dep,
	__uint8_t		ftype)
{
	ASSERT(ftype < XFS_DIR3_FT_MAX);
}

static __uint8_t
xfs_dir3_data_get_ftype(
	struct xfs_dir2_data_entry *dep)
{
	__uint8_t	ftype = dep->name[dep->namelen];

	ASSERT(ftype < XFS_DIR3_FT_MAX);
	if (ftype >= XFS_DIR3_FT_MAX)
		return XFS_DIR3_FT_UNKNOWN;
	return ftype;
}

static void
xfs_dir3_data_put_ftype(
	struct xfs_dir2_data_entry *dep,
	__uint8_t		type)
{
	ASSERT(type < XFS_DIR3_FT_MAX);
	ASSERT(dep->namelen != 0);

	dep->name[dep->namelen] = type;
}

/*
 * Pointer to an entry's tag word.
 */
static __be16 *
xfs_dir2_data_entry_tag_p(
	struct xfs_dir2_data_entry *dep)
{
	return (__be16 *)((char *)dep +
		xfs_dir2_data_entsize(dep->namelen) - sizeof(__be16));
}

static __be16 *
xfs_dir3_data_entry_tag_p(
	struct xfs_dir2_data_entry *dep)
{
	return (__be16 *)((char *)dep +
		xfs_dir3_data_entsize(dep->namelen) - sizeof(__be16));
}

/*
 * Offsets of . and .. in data space (always block 0)
 */
static xfs_dir2_data_aoff_t
xfs_dir2_data_dot_offset(void)
{
	return sizeof(struct xfs_dir2_data_hdr);
}

static xfs_dir2_data_aoff_t
xfs_dir2_data_dotdot_offset(void)
{
	return xfs_dir2_data_dot_offset() + xfs_dir2_data_entsize(1);
}

static xfs_dir2_data_aoff_t
xfs_dir2_data_first_offset(void)
{
	return xfs_dir2_data_dotdot_offset() + xfs_dir2_data_entsize(2);
}

static xfs_dir2_data_aoff_t
xfs_dir3_data_dot_offset(void)
{
	return sizeof(struct xfs_dir3_data_hdr);
}

static xfs_dir2_data_aoff_t
xfs_dir3_data_dotdot_offset(void)
{
	return xfs_dir3_data_dot_offset() + xfs_dir3_data_entsize(1);
}

static xfs_dir2_data_aoff_t
xfs_dir3_data_first_offset(void)
{
	return xfs_dir3_data_dotdot_offset() + xfs_dir3_data_entsize(2);
}

/*
 * location of . and .. in data space (always block 0)
 */
static struct xfs_dir2_data_entry *
xfs_dir2_data_dot_entry_p(
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir2_data_dot_offset());
}

static struct xfs_dir2_data_entry *
xfs_dir2_data_dotdot_entry_p(
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir2_data_dotdot_offset());
}

static struct xfs_dir2_data_entry *
xfs_dir2_data_first_entry_p(
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir2_data_first_offset());
}

static struct xfs_dir2_data_entry *
xfs_dir3_data_dot_entry_p(
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir3_data_dot_offset());
}

static struct xfs_dir2_data_entry *
xfs_dir3_data_dotdot_entry_p(
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir3_data_dotdot_offset());
}

static struct xfs_dir2_data_entry *
xfs_dir3_data_first_entry_p(
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir3_data_first_offset());
}

const struct xfs_dir_ops xfs_dir2_ops = {
	.sf_entsize = xfs_dir2_sf_entsize,
	.sf_nextentry = xfs_dir2_sf_nextentry,
@@ -212,6 +392,18 @@ const struct xfs_dir_ops xfs_dir2_ops = {
	.sf_put_ino = xfs_dir2_sfe_put_ino,
	.sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
	.sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,

	.data_entsize = xfs_dir2_data_entsize,
	.data_get_ftype = xfs_dir2_data_get_ftype,
	.data_put_ftype = xfs_dir2_data_put_ftype,
	.data_entry_tag_p = xfs_dir2_data_entry_tag_p,

	.data_dot_offset = xfs_dir2_data_dot_offset,
	.data_dotdot_offset = xfs_dir2_data_dotdot_offset,
	.data_first_offset = xfs_dir2_data_first_offset,
	.data_dot_entry_p = xfs_dir2_data_dot_entry_p,
	.data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p,
	.data_first_entry_p = xfs_dir2_data_first_entry_p,
};

const struct xfs_dir_ops xfs_dir2_ftype_ops = {
@@ -223,6 +415,18 @@ const struct xfs_dir_ops xfs_dir2_ftype_ops = {
	.sf_put_ino = xfs_dir3_sfe_put_ino,
	.sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
	.sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,

	.data_entsize = xfs_dir3_data_entsize,
	.data_get_ftype = xfs_dir3_data_get_ftype,
	.data_put_ftype = xfs_dir3_data_put_ftype,
	.data_entry_tag_p = xfs_dir3_data_entry_tag_p,

	.data_dot_offset = xfs_dir2_data_dot_offset,
	.data_dotdot_offset = xfs_dir2_data_dotdot_offset,
	.data_first_offset = xfs_dir2_data_first_offset,
	.data_dot_entry_p = xfs_dir2_data_dot_entry_p,
	.data_dotdot_entry_p = xfs_dir2_data_dotdot_entry_p,
	.data_first_entry_p = xfs_dir2_data_first_entry_p,
};

const struct xfs_dir_ops xfs_dir3_ops = {
@@ -234,4 +438,16 @@ const struct xfs_dir_ops xfs_dir3_ops = {
	.sf_put_ino = xfs_dir3_sfe_put_ino,
	.sf_get_parent_ino = xfs_dir2_sf_get_parent_ino,
	.sf_put_parent_ino = xfs_dir2_sf_put_parent_ino,

	.data_entsize = xfs_dir3_data_entsize,
	.data_get_ftype = xfs_dir3_data_get_ftype,
	.data_put_ftype = xfs_dir3_data_put_ftype,
	.data_entry_tag_p = xfs_dir3_data_entry_tag_p,

	.data_dot_offset = xfs_dir3_data_dot_offset,
	.data_dotdot_offset = xfs_dir3_data_dotdot_offset,
	.data_first_offset = xfs_dir3_data_first_offset,
	.data_dot_entry_p = xfs_dir3_data_dot_entry_p,
	.data_dotdot_entry_p = xfs_dir3_data_dotdot_entry_p,
	.data_first_entry_p = xfs_dir3_data_first_entry_p,
};
+0 −123
Original line number Diff line number Diff line
@@ -455,72 +455,6 @@ typedef struct xfs_dir2_data_unused {
	__be16			tag;		/* starting offset of us */
} xfs_dir2_data_unused_t;

/*
 * Size of a data entry.
 */
static inline int
__xfs_dir3_data_entsize(
	bool	ftype,
	int	n)
{
	int	size = offsetof(struct xfs_dir2_data_entry, name[0]);

	size += n;
	size += sizeof(xfs_dir2_data_off_t);
	if (ftype)
		size += sizeof(__uint8_t);
	return roundup(size, XFS_DIR2_DATA_ALIGN);
}
static inline int
xfs_dir3_data_entsize(
	struct xfs_mount	*mp,
	int			n)
{
	bool ftype = xfs_sb_version_hasftype(&mp->m_sb) ? true : false;
	return __xfs_dir3_data_entsize(ftype, n);
}

static inline __uint8_t
xfs_dir3_dirent_get_ftype(
	struct xfs_mount	*mp,
	struct xfs_dir2_data_entry *dep)
{
	if (xfs_sb_version_hasftype(&mp->m_sb)) {
		__uint8_t	type = dep->name[dep->namelen];

		ASSERT(type < XFS_DIR3_FT_MAX);
		if (type < XFS_DIR3_FT_MAX)
			return type;

	}
	return XFS_DIR3_FT_UNKNOWN;
}

static inline void
xfs_dir3_dirent_put_ftype(
	struct xfs_mount	*mp,
	struct xfs_dir2_data_entry *dep,
	__uint8_t		type)
{
	ASSERT(type < XFS_DIR3_FT_MAX);
	ASSERT(dep->namelen != 0);

	if (xfs_sb_version_hasftype(&mp->m_sb))
		dep->name[dep->namelen] = type;
}

/*
 * Pointer to an entry's tag word.
 */
static inline __be16 *
xfs_dir3_data_entry_tag_p(
	struct xfs_mount	*mp,
	struct xfs_dir2_data_entry *dep)
{
	return (__be16 *)((char *)dep +
		xfs_dir3_data_entsize(mp, dep->namelen) - sizeof(__be16));
}

/*
 * Pointer to a freespace's tag word.
 */
@@ -561,63 +495,6 @@ xfs_dir3_data_unused_p(struct xfs_dir2_data_hdr *hdr)
		((char *)hdr + xfs_dir3_data_entry_offset(hdr));
}

/*
 * Offsets of . and .. in data space (always block 0)
 *
 * XXX: there is scope for significant optimisation of the logic here. Right
 * now we are checking for "dir3 format" over and over again. Ideally we should
 * only do it once for each operation.
 */
static inline xfs_dir2_data_aoff_t
xfs_dir3_data_dot_offset(struct xfs_mount *mp)
{
	return xfs_dir3_data_hdr_size(xfs_sb_version_hascrc(&mp->m_sb));
}

static inline xfs_dir2_data_aoff_t
xfs_dir3_data_dotdot_offset(struct xfs_mount *mp)
{
	return xfs_dir3_data_dot_offset(mp) +
		xfs_dir3_data_entsize(mp, 1);
}

static inline xfs_dir2_data_aoff_t
xfs_dir3_data_first_offset(struct xfs_mount *mp)
{
	return xfs_dir3_data_dotdot_offset(mp) +
		xfs_dir3_data_entsize(mp, 2);
}

/*
 * location of . and .. in data space (always block 0)
 */
static inline struct xfs_dir2_data_entry *
xfs_dir3_data_dot_entry_p(
	struct xfs_mount	*mp,
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir3_data_dot_offset(mp));
}

static inline struct xfs_dir2_data_entry *
xfs_dir3_data_dotdot_entry_p(
	struct xfs_mount	*mp,
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir3_data_dotdot_offset(mp));
}

static inline struct xfs_dir2_data_entry *
xfs_dir3_data_first_entry_p(
	struct xfs_mount	*mp,
	struct xfs_dir2_data_hdr *hdr)
{
	return (struct xfs_dir2_data_entry *)
		((char *)hdr + xfs_dir3_data_first_offset(mp));
}

/*
 * Leaf block structures.
 *
+19 −3
Original line number Diff line number Diff line
@@ -50,6 +50,22 @@ struct xfs_dir_ops {
	xfs_ino_t (*sf_get_parent_ino)(struct xfs_dir2_sf_hdr *hdr);
	void	(*sf_put_parent_ino)(struct xfs_dir2_sf_hdr *hdr,
				     xfs_ino_t ino);

	int	(*data_entsize)(int len);
	__uint8_t (*data_get_ftype)(struct xfs_dir2_data_entry *dep);
	void	(*data_put_ftype)(struct xfs_dir2_data_entry *dep,
				__uint8_t ftype);
	__be16 * (*data_entry_tag_p)(struct xfs_dir2_data_entry *dep);

	xfs_dir2_data_aoff_t (*data_dot_offset)(void);
	xfs_dir2_data_aoff_t (*data_dotdot_offset)(void);
	xfs_dir2_data_aoff_t (*data_first_offset)(void);
	struct xfs_dir2_data_entry *
		(*data_dot_entry_p)(struct xfs_dir2_data_hdr *hdr);
	struct xfs_dir2_data_entry *
		(*data_dotdot_entry_p)(struct xfs_dir2_data_hdr *hdr);
	struct xfs_dir2_data_entry *
		(*data_first_entry_p)(struct xfs_dir2_data_hdr *hdr);
};

extern const struct xfs_dir_ops xfs_dir2_ops;
@@ -95,10 +111,10 @@ extern int xfs_dir2_isleaf(struct xfs_trans *tp, struct xfs_inode *dp, int *r);
extern int xfs_dir2_shrink_inode(struct xfs_da_args *args, xfs_dir2_db_t db,
				struct xfs_buf *bp);

extern void xfs_dir2_data_freescan(struct xfs_mount *mp,
extern void xfs_dir2_data_freescan(struct xfs_inode *dp,
		struct xfs_dir2_data_hdr *hdr, int *loghead);
extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_buf *bp,
		struct xfs_dir2_data_entry *dep);
extern void xfs_dir2_data_log_entry(struct xfs_trans *tp, struct xfs_inode *dp,
		struct xfs_buf *bp, struct xfs_dir2_data_entry *dep);
extern void xfs_dir2_data_log_header(struct xfs_trans *tp,
		struct xfs_buf *bp);
extern void xfs_dir2_data_log_unused(struct xfs_trans *tp, struct xfs_buf *bp,
+27 −27
Original line number Diff line number Diff line
@@ -280,6 +280,7 @@ xfs_dir2_block_need_space(
static void
xfs_dir2_block_compact(
	struct xfs_trans		*tp,
	struct xfs_inode		*dp,
	struct xfs_buf			*bp,
	struct xfs_dir2_data_hdr	*hdr,
	struct xfs_dir2_block_tail	*btp,
@@ -323,7 +324,7 @@ xfs_dir2_block_compact(
	 * This needs to happen before the next call to use_free.
	 */
	if (needscan)
		xfs_dir2_data_freescan(tp->t_mountp, hdr, needlog);
		xfs_dir2_data_freescan(dp, hdr, needlog);
}

/*
@@ -369,7 +370,7 @@ xfs_dir2_block_addname(
	if (error)
		return error;

	len = xfs_dir3_data_entsize(mp, args->namelen);
	len = dp->d_ops->data_entsize(args->namelen);

	/*
	 * Set up pointers to parts of the block.
@@ -418,7 +419,7 @@ xfs_dir2_block_addname(
	 * If need to compact the leaf entries, do it now.
	 */
	if (compact) {
		xfs_dir2_block_compact(tp, bp, hdr, btp, blp, &needlog,
		xfs_dir2_block_compact(tp, dp, bp, hdr, btp, blp, &needlog,
				      &lfloghigh, &lfloglow);
		/* recalculate blp post-compaction */
		blp = xfs_dir2_block_leaf_p(btp);
@@ -468,7 +469,7 @@ xfs_dir2_block_addname(
		 * This needs to happen before the next call to use_free.
		 */
		if (needscan) {
			xfs_dir2_data_freescan(mp, hdr, &needlog);
			xfs_dir2_data_freescan(dp, hdr, &needlog);
			needscan = 0;
		}
		/*
@@ -549,18 +550,18 @@ xfs_dir2_block_addname(
	dep->inumber = cpu_to_be64(args->inumber);
	dep->namelen = args->namelen;
	memcpy(dep->name, args->name, args->namelen);
	xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
	tagp = xfs_dir3_data_entry_tag_p(mp, dep);
	dp->d_ops->data_put_ftype(dep, args->filetype);
	tagp = dp->d_ops->data_entry_tag_p(dep);
	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
	/*
	 * Clean up the bestfree array and log the header, tail, and entry.
	 */
	if (needscan)
		xfs_dir2_data_freescan(mp, hdr, &needlog);
		xfs_dir2_data_freescan(dp, hdr, &needlog);
	if (needlog)
		xfs_dir2_data_log_header(tp, bp);
	xfs_dir2_block_log_tail(tp, bp);
	xfs_dir2_data_log_entry(tp, bp, dep);
	xfs_dir2_data_log_entry(tp, dp, bp, dep);
	xfs_dir3_data_check(dp, bp);
	return 0;
}
@@ -642,7 +643,7 @@ xfs_dir2_block_lookup(
	 * Fill in inode number, CI name if appropriate, release the block.
	 */
	args->inumber = be64_to_cpu(dep->inumber);
	args->filetype = xfs_dir3_dirent_get_ftype(mp, dep);
	args->filetype = dp->d_ops->data_get_ftype(dep);
	error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
	xfs_trans_brelse(args->trans, bp);
	return XFS_ERROR(error);
@@ -801,7 +802,7 @@ xfs_dir2_block_removename(
	needlog = needscan = 0;
	xfs_dir2_data_make_free(tp, bp,
		(xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
		xfs_dir3_data_entsize(mp, dep->namelen), &needlog, &needscan);
		dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
	/*
	 * Fix up the block tail.
	 */
@@ -816,7 +817,7 @@ xfs_dir2_block_removename(
	 * Fix up bestfree, log the header if necessary.
	 */
	if (needscan)
		xfs_dir2_data_freescan(mp, hdr, &needlog);
		xfs_dir2_data_freescan(dp, hdr, &needlog);
	if (needlog)
		xfs_dir2_data_log_header(tp, bp);
	xfs_dir3_data_check(dp, bp);
@@ -875,8 +876,8 @@ xfs_dir2_block_replace(
	 * Change the inode number to the new value.
	 */
	dep->inumber = cpu_to_be64(args->inumber);
	xfs_dir3_dirent_put_ftype(mp, dep, args->filetype);
	xfs_dir2_data_log_entry(args->trans, bp, dep);
	dp->d_ops->data_put_ftype(dep, args->filetype);
	xfs_dir2_data_log_entry(args->trans, dp, bp, dep);
	xfs_dir3_data_check(dp, bp);
	return 0;
}
@@ -1023,7 +1024,7 @@ xfs_dir2_leaf_to_block(
	 * Scan the bestfree if we need it and log the data block header.
	 */
	if (needscan)
		xfs_dir2_data_freescan(mp, hdr, &needlog);
		xfs_dir2_data_freescan(dp, hdr, &needlog);
	if (needlog)
		xfs_dir2_data_log_header(tp, dbp);
	/*
@@ -1158,32 +1159,32 @@ xfs_dir2_sf_to_block(
	/*
	 * Create entry for .
	 */
	dep = xfs_dir3_data_dot_entry_p(mp, hdr);
	dep = dp->d_ops->data_dot_entry_p(hdr);
	dep->inumber = cpu_to_be64(dp->i_ino);
	dep->namelen = 1;
	dep->name[0] = '.';
	xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
	tagp = xfs_dir3_data_entry_tag_p(mp, dep);
	dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
	tagp = dp->d_ops->data_entry_tag_p(dep);
	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
	xfs_dir2_data_log_entry(tp, bp, dep);
	xfs_dir2_data_log_entry(tp, dp, bp, dep);
	blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
	blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
				(char *)dep - (char *)hdr));
	/*
	 * Create entry for ..
	 */
	dep = xfs_dir3_data_dotdot_entry_p(mp, hdr);
	dep = dp->d_ops->data_dotdot_entry_p(hdr);
	dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp));
	dep->namelen = 2;
	dep->name[0] = dep->name[1] = '.';
	xfs_dir3_dirent_put_ftype(mp, dep, XFS_DIR3_FT_DIR);
	tagp = xfs_dir3_data_entry_tag_p(mp, dep);
	dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
	tagp = dp->d_ops->data_entry_tag_p(dep);
	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
	xfs_dir2_data_log_entry(tp, bp, dep);
	xfs_dir2_data_log_entry(tp, dp, bp, dep);
	blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
	blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(mp,
				(char *)dep - (char *)hdr));
	offset = xfs_dir3_data_first_offset(mp);
	offset = dp->d_ops->data_first_offset();
	/*
	 * Loop over existing entries, stuff them in.
	 */
@@ -1224,12 +1225,11 @@ xfs_dir2_sf_to_block(
		dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset);
		dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep));
		dep->namelen = sfep->namelen;
		xfs_dir3_dirent_put_ftype(mp, dep,
					  dp->d_ops->sf_get_ftype(sfep));
		dp->d_ops->data_put_ftype(dep, dp->d_ops->sf_get_ftype(sfep));
		memcpy(dep->name, sfep->name, dep->namelen);
		tagp = xfs_dir3_data_entry_tag_p(mp, dep);
		tagp = dp->d_ops->data_entry_tag_p(dep);
		*tagp = cpu_to_be16((char *)dep - (char *)hdr);
		xfs_dir2_data_log_entry(tp, bp, dep);
		xfs_dir2_data_log_entry(tp, dp, bp, dep);
		name.name = sfep->name;
		name.len = sfep->namelen;
		blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->
+26 −12
Original line number Diff line number Diff line
@@ -62,12 +62,26 @@ __xfs_dir3_data_check(
	char			*p;		/* current data position */
	int			stale;		/* count of stale leaves */
	struct xfs_name		name;
	const struct xfs_dir_ops *ops;

	mp = bp->b_target->bt_mount;
	hdr = bp->b_addr;
	bf = xfs_dir3_data_bestfree_p(hdr);
	p = (char *)xfs_dir3_data_entry_p(hdr);

	/*
	 * We can be passed a null dp here from a verifier, so manually
	 * configure the ops here in that case.
	 */
	if (dp)
		ops = dp->d_ops;
	else if (xfs_sb_version_hascrc(&mp->m_sb))
		ops = &xfs_dir3_ops;
	else if (xfs_sb_version_hasftype(&mp->m_sb))
		ops = &xfs_dir2_ftype_ops;
	else
		ops = &xfs_dir2_ops;

	switch (hdr->magic) {
	case cpu_to_be32(XFS_DIR3_BLOCK_MAGIC):
	case cpu_to_be32(XFS_DIR2_BLOCK_MAGIC):
@@ -146,10 +160,10 @@ __xfs_dir3_data_check(
		XFS_WANT_CORRUPTED_RETURN(
			!xfs_dir_ino_validate(mp, be64_to_cpu(dep->inumber)));
		XFS_WANT_CORRUPTED_RETURN(
			be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)) ==
			be16_to_cpu(*ops->data_entry_tag_p(dep)) ==
					       (char *)dep - (char *)hdr);
		XFS_WANT_CORRUPTED_RETURN(
			xfs_dir3_dirent_get_ftype(mp, dep) < XFS_DIR3_FT_MAX);
				ops->data_get_ftype(dep) < XFS_DIR3_FT_MAX);
		count++;
		lastfree = 0;
		if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
@@ -167,7 +181,7 @@ __xfs_dir3_data_check(
			}
			XFS_WANT_CORRUPTED_RETURN(i < be32_to_cpu(btp->count));
		}
		p += xfs_dir3_data_entsize(mp, dep->namelen);
		p += ops->data_entsize(dep->namelen);
	}
	/*
	 * Need to have seen all the entries and all the bestfree slots.
@@ -485,9 +499,9 @@ xfs_dir2_data_freeremove(
 */
void
xfs_dir2_data_freescan(
	xfs_mount_t		*mp,		/* filesystem mount point */
	xfs_dir2_data_hdr_t	*hdr,		/* data block header */
	int			*loghead)	/* out: log data header */
	struct xfs_inode	*dp,
	struct xfs_dir2_data_hdr *hdr,
	int			*loghead)
{
	xfs_dir2_block_tail_t	*btp;		/* block tail */
	xfs_dir2_data_entry_t	*dep;		/* active data entry */
@@ -513,10 +527,10 @@ xfs_dir2_data_freescan(
	p = (char *)xfs_dir3_data_entry_p(hdr);
	if (hdr->magic == cpu_to_be32(XFS_DIR2_BLOCK_MAGIC) ||
	    hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC)) {
		btp = xfs_dir2_block_tail_p(mp, hdr);
		btp = xfs_dir2_block_tail_p(dp->i_mount, hdr);
		endp = (char *)xfs_dir2_block_leaf_p(btp);
	} else
		endp = (char *)hdr + mp->m_dirblksize;
		endp = (char *)hdr + dp->i_mount->m_dirblksize;
	/*
	 * Loop over the block's entries.
	 */
@@ -537,8 +551,8 @@ xfs_dir2_data_freescan(
		else {
			dep = (xfs_dir2_data_entry_t *)p;
			ASSERT((char *)dep - (char *)hdr ==
			       be16_to_cpu(*xfs_dir3_data_entry_tag_p(mp, dep)));
			p += xfs_dir3_data_entsize(mp, dep->namelen);
			       be16_to_cpu(*dp->d_ops->data_entry_tag_p(dep)));
			p += dp->d_ops->data_entsize(dep->namelen);
		}
	}
}
@@ -625,11 +639,11 @@ xfs_dir3_data_init(
void
xfs_dir2_data_log_entry(
	struct xfs_trans	*tp,
	struct xfs_inode	*dp,
	struct xfs_buf		*bp,
	xfs_dir2_data_entry_t	*dep)		/* data entry pointer */
{
	struct xfs_dir2_data_hdr *hdr = bp->b_addr;
	struct xfs_mount	*mp = tp->t_mountp;

	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
	       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC) ||
@@ -637,7 +651,7 @@ xfs_dir2_data_log_entry(
	       hdr->magic == cpu_to_be32(XFS_DIR3_BLOCK_MAGIC));

	xfs_trans_log_buf(tp, bp, (uint)((char *)dep - (char *)hdr),
		(uint)((char *)(xfs_dir3_data_entry_tag_p(mp, dep) + 1) -
		(uint)((char *)(dp->d_ops->data_entry_tag_p(dep) + 1) -
		       (char *)hdr - 1));
}

Loading