Commit f9f6dce0 authored by Barry Naujok's avatar Barry Naujok Committed by Niv Sardi
Browse files

[XFS] Split xfs_dir2_leafn_lookup_int into its two pieces of functionality



SGI-PV: 976035
SGI-Modid: xfs-linux-melb:xfs-kern:30834a

Signed-off-by: default avatarBarry Naujok <bnaujok@sgi.com>
Signed-off-by: default avatarChristoph Hellwig <hch@infradead.org>
Signed-off-by: default avatarLachlan McIlroy <lachlan@sgi.com>
parent c9272c4f
Loading
Loading
Loading
Loading
+202 −156
Original line number Diff line number Diff line
@@ -387,28 +387,26 @@ xfs_dir2_leafn_lasthash(
}

/*
 * Look up a leaf entry in a node-format leaf block.
 * If this is an addname then the extrablk in state is a freespace block,
 * otherwise it's a data block.
 * Look up a leaf entry for space to add a name in a node-format leaf block.
 * The extrablk in state is a freespace block.
 */
int
xfs_dir2_leafn_lookup_int(
STATIC int
xfs_dir2_leafn_lookup_for_addname(
	xfs_dabuf_t		*bp,		/* leaf buffer */
	xfs_da_args_t		*args,		/* operation arguments */
	int			*indexp,	/* out: leaf entry index */
	xfs_da_state_t		*state)		/* state to fill in */
{
	xfs_dabuf_t		*curbp;		/* current data/free buffer */
	xfs_dir2_db_t		curdb;		/* current data block number */
	xfs_dir2_db_t		curfdb;		/* current free block number */
	xfs_dir2_data_entry_t	*dep;		/* data block entry */
	xfs_dabuf_t		*curbp = NULL;	/* current data/free buffer */
	xfs_dir2_db_t		curdb = -1;	/* current data block number */
	xfs_dir2_db_t		curfdb = -1;	/* current free block number */
	xfs_inode_t		*dp;		/* incore directory inode */
	int			error;		/* error return value */
	int			fi;		/* free entry index */
	xfs_dir2_free_t		*free = NULL;	/* free block structure */
	int			index;		/* leaf entry index */
	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
	int			length=0;	/* length of new data entry */
	int			length;		/* length of new data entry */
	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
	xfs_mount_t		*mp;		/* filesystem mount point */
	xfs_dir2_db_t		newdb;		/* new data block number */
@@ -431,32 +429,19 @@ xfs_dir2_leafn_lookup_int(
	/*
	 * Do we have a buffer coming in?
	 */
	if (state->extravalid)
	if (state->extravalid) {
		/* If so, it's a free block buffer, get the block number. */
		curbp = state->extrablk.bp;
	else
		curbp = NULL;
	/*
	 * For addname, it's a free block buffer, get the block number.
	 */
	if (args->addname) {
		curfdb = curbp ? state->extrablk.blkno : -1;
		curdb = -1;
		length = xfs_dir2_data_entsize(args->namelen);
		if ((free = (curbp ? curbp->data : NULL)))
		curfdb = state->extrablk.blkno;
		free = curbp->data;
		ASSERT(be32_to_cpu(free->hdr.magic) == XFS_DIR2_FREE_MAGIC);
	}
	/*
	 * For others, it's a data block buffer, get the block number.
	 */
	else {
		curfdb = -1;
		curdb = curbp ? state->extrablk.blkno : -1;
	}
	length = xfs_dir2_data_entsize(args->namelen);
	/*
	 * Loop over leaf entries with the right hash value.
	 */
	for (lep = &leaf->ents[index];
	     index < be16_to_cpu(leaf->hdr.count) && be32_to_cpu(lep->hashval) == args->hashval;
	for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) &&
				be32_to_cpu(lep->hashval) == args->hashval;
				lep++, index++) {
		/*
		 * Skip stale leaf entries.
@@ -471,9 +456,7 @@ xfs_dir2_leafn_lookup_int(
		 * For addname, we're looking for a place to put the new entry.
		 * We want to use a data block with an entry of equal
		 * hash value to ours if there is one with room.
		 */
		if (args->addname) {
			/*
		 *
		 * If this block isn't the data block we already have
		 * in hand, take a look at it.
		 */
@@ -485,8 +468,7 @@ xfs_dir2_leafn_lookup_int(
			 */
			newfdb = xfs_dir2_db_to_fdb(mp, newdb);
			/*
				 * If it's not the one we have in hand,
				 * read it in.
			 * If it's not the one we have in hand, read it in.
			 */
			if (newfdb != curfdb) {
				/*
@@ -497,22 +479,18 @@ xfs_dir2_leafn_lookup_int(
				/*
				 * Read the free block.
				 */
					if ((error = xfs_da_read_buf(tp, dp,
							xfs_dir2_db_to_da(mp,
								newfdb),
							-1, &curbp,
							XFS_DATA_FORK))) {
				error = xfs_da_read_buf(tp, dp,
						xfs_dir2_db_to_da(mp, newfdb),
						-1, &curbp, XFS_DATA_FORK);
				if (error)
					return error;
					}
				free = curbp->data;
				ASSERT(be32_to_cpu(free->hdr.magic) ==
					XFS_DIR2_FREE_MAGIC);
				ASSERT((be32_to_cpu(free->hdr.firstdb) %
						XFS_DIR2_MAX_FREE_BESTS(mp)) ==
					       0);
					XFS_DIR2_MAX_FREE_BESTS(mp)) == 0);
				ASSERT(be32_to_cpu(free->hdr.firstdb) <= curdb);
					ASSERT(curdb <
					       be32_to_cpu(free->hdr.firstdb) +
				ASSERT(curdb < be32_to_cpu(free->hdr.firstdb) +
					be32_to_cpu(free->hdr.nvalid));
			}
			/*
@@ -530,25 +508,94 @@ xfs_dir2_leafn_lookup_int(
				return XFS_ERROR(EFSCORRUPTED);
			}
			curfdb = newfdb;
				if (be16_to_cpu(free->bests[fi]) >= length) {
					*indexp = index;
			if (be16_to_cpu(free->bests[fi]) >= length)
				goto out;
		}
	}
	/* Didn't find any space */
	fi = -1;
out:
	ASSERT(args->oknoent);
	if (curbp) {
		/* Giving back a free block. */
		state->extravalid = 1;
		state->extrablk.bp = curbp;
					state->extrablk.blkno = curfdb;
		state->extrablk.index = fi;
					state->extrablk.magic =
						XFS_DIR2_FREE_MAGIC;
					ASSERT(args->oknoent);
					return XFS_ERROR(ENOENT);
		state->extrablk.blkno = curfdb;
		state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
	} else {
		state->extravalid = 0;
	}
	/*
	 * Return the index, that will be the insertion point.
	 */
	*indexp = index;
	return XFS_ERROR(ENOENT);
}

/*
 * Look up a leaf entry in a node-format leaf block.
 * The extrablk in state a data block.
 */
STATIC int
xfs_dir2_leafn_lookup_for_entry(
	xfs_dabuf_t		*bp,		/* leaf buffer */
	xfs_da_args_t		*args,		/* operation arguments */
	int			*indexp,	/* out: leaf entry index */
	xfs_da_state_t		*state)		/* state to fill in */
{
	xfs_dabuf_t		*curbp = NULL;	/* current data/free buffer */
	xfs_dir2_db_t		curdb = -1;	/* current data block number */
	xfs_dir2_data_entry_t	*dep;		/* data block entry */
	xfs_inode_t		*dp;		/* incore directory inode */
	int			error;		/* error return value */
	int			di;		/* data entry index */
	int			index;		/* leaf entry index */
	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
	xfs_mount_t		*mp;		/* filesystem mount point */
	xfs_dir2_db_t		newdb;		/* new data block number */
	xfs_trans_t		*tp;		/* transaction pointer */

	dp = args->dp;
	tp = args->trans;
	mp = dp->i_mount;
	leaf = bp->data;
	ASSERT(be16_to_cpu(leaf->hdr.info.magic) == XFS_DIR2_LEAFN_MAGIC);
#ifdef __KERNEL__
	ASSERT(be16_to_cpu(leaf->hdr.count) > 0);
#endif
	xfs_dir2_leafn_check(dp, bp);
	/*
	 * Look up the hash value in the leaf entries.
	 */
	index = xfs_dir2_leaf_search_hash(args, bp);
	/*
	 * Do we have a buffer coming in?
	 */
	if (state->extravalid) {
		curbp = state->extrablk.bp;
		curdb = state->extrablk.blkno;
	}
	/*
		 * Not adding a new entry, so we really want to find
		 * the name given to us.
	 * Loop over leaf entries with the right hash value.
	 */
		else {
	for (lep = &leaf->ents[index]; index < be16_to_cpu(leaf->hdr.count) &&
				be32_to_cpu(lep->hashval) == args->hashval;
				lep++, index++) {
		/*
		 * Skip stale leaf entries.
		 */
		if (be32_to_cpu(lep->address) == XFS_DIR2_NULL_DATAPTR)
			continue;
		/*
		 * Pull the data block number from the entry.
		 */
		newdb = xfs_dir2_dataptr_to_db(mp, be32_to_cpu(lep->address));
		/*
		 * Not adding a new entry, so we really want to find
		 * the name given to us.
		 *
		 * If it's a different data block, go get it.
		 */
		if (newdb != curdb) {
@@ -560,69 +607,67 @@ xfs_dir2_leafn_lookup_int(
			/*
			 * Read the data block.
			 */
				if ((error =
				    xfs_da_read_buf(tp, dp,
					    xfs_dir2_db_to_da(mp, newdb), -1,
					    &curbp, XFS_DATA_FORK))) {
			error = xfs_da_read_buf(tp, dp, xfs_dir2_db_to_da(mp,
					newdb), -1, &curbp, XFS_DATA_FORK);
			if (error)
				return error;
				}
			xfs_dir2_data_check(dp, curbp);
			curdb = newdb;
		}
		/*
		 * Point to the data entry.
		 */
			dep = (xfs_dir2_data_entry_t *)
			      ((char *)curbp->data +
		dep = (xfs_dir2_data_entry_t *)((char *)curbp->data +
			xfs_dir2_dataptr_to_off(mp, be32_to_cpu(lep->address)));
		/*
		 * Compare the entry, return it if it matches.
		 */
			if (dep->namelen == args->namelen &&
			    dep->name[0] == args->name[0] &&
			    memcmp(dep->name, args->name, args->namelen) == 0) {
		if (dep->namelen == args->namelen && memcmp(dep->name,
					args->name, args->namelen) == 0) {
			args->inumber = be64_to_cpu(dep->inumber);
				*indexp = index;
			di = (int)((char *)dep - (char *)curbp->data);
			error = EEXIST;
			goto out;
		}
	}
	/* Didn't find a match. */
	error = ENOENT;
	di = -1;
	ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent);
out:
	if (curbp) {
		/* Giving back a data block. */
		state->extravalid = 1;
		state->extrablk.bp = curbp;
		state->extrablk.index = di;
		state->extrablk.blkno = curdb;
				state->extrablk.index =
					(int)((char *)dep -
					      (char *)curbp->data);
		state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
				return XFS_ERROR(EEXIST);
			}
		}
	}
	/*
	 * Didn't find a match.
	 * If we are holding a buffer, give it back in case our caller
	 * finds it useful.
	 */
	if ((state->extravalid = (curbp != NULL))) {
		state->extrablk.bp = curbp;
		state->extrablk.index = -1;
		/*
		 * For addname, giving back a free block.
		 */
		if (args->addname) {
			state->extrablk.blkno = curfdb;
			state->extrablk.magic = XFS_DIR2_FREE_MAGIC;
	} else {
		state->extravalid = 0;
	}
	/*
		 * For other callers, giving back a data block.
	 * Return the index, that will be the insertion point.
	 */
		else {
			state->extrablk.blkno = curdb;
			state->extrablk.magic = XFS_DIR2_DATA_MAGIC;
		}
	*indexp = index;
	return XFS_ERROR(error);
}

/*
	 * Return the final index, that will be the insertion point.
 * Look up a leaf entry in a node-format leaf block.
 * If this is an addname then the extrablk in state is a freespace block,
 * otherwise it's a data block.
 */
	*indexp = index;
	ASSERT(index == be16_to_cpu(leaf->hdr.count) || args->oknoent);
	return XFS_ERROR(ENOENT);
int
xfs_dir2_leafn_lookup_int(
	xfs_dabuf_t		*bp,		/* leaf buffer */
	xfs_da_args_t		*args,		/* operation arguments */
	int			*indexp,	/* out: leaf entry index */
	xfs_da_state_t		*state)		/* state to fill in */
{
	if (args->addname)
		return xfs_dir2_leafn_lookup_for_addname(bp, args, indexp,
							state);
	return xfs_dir2_leafn_lookup_for_entry(bp, args, indexp, state);
}

/*
@@ -825,7 +870,8 @@ xfs_dir2_leafn_rebalance(
		blk2->index = blk1->index - be16_to_cpu(leaf1->hdr.count);

	/*
	 * Finally sanity check just to make sure we are not returning a negative index 
	 * Finally sanity check just to make sure we are not returning a
	 * negative index
	 */
	if(blk2->index < 0) {
		state->inleaf = 1;