xref: /openbmc/linux/fs/xfs/libxfs/xfs_dir2_block.c (revision 30f712c9)
130f712c9SDave Chinner /*
230f712c9SDave Chinner  * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc.
330f712c9SDave Chinner  * Copyright (c) 2013 Red Hat, Inc.
430f712c9SDave Chinner  * All Rights Reserved.
530f712c9SDave Chinner  *
630f712c9SDave Chinner  * This program is free software; you can redistribute it and/or
730f712c9SDave Chinner  * modify it under the terms of the GNU General Public License as
830f712c9SDave Chinner  * published by the Free Software Foundation.
930f712c9SDave Chinner  *
1030f712c9SDave Chinner  * This program is distributed in the hope that it would be useful,
1130f712c9SDave Chinner  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1230f712c9SDave Chinner  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1330f712c9SDave Chinner  * GNU General Public License for more details.
1430f712c9SDave Chinner  *
1530f712c9SDave Chinner  * You should have received a copy of the GNU General Public License
1630f712c9SDave Chinner  * along with this program; if not, write the Free Software Foundation,
1730f712c9SDave Chinner  * Inc.,  51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
1830f712c9SDave Chinner  */
1930f712c9SDave Chinner #include "xfs.h"
2030f712c9SDave Chinner #include "xfs_fs.h"
2130f712c9SDave Chinner #include "xfs_format.h"
2230f712c9SDave Chinner #include "xfs_log_format.h"
2330f712c9SDave Chinner #include "xfs_trans_resv.h"
2430f712c9SDave Chinner #include "xfs_sb.h"
2530f712c9SDave Chinner #include "xfs_ag.h"
2630f712c9SDave Chinner #include "xfs_mount.h"
2730f712c9SDave Chinner #include "xfs_da_format.h"
2830f712c9SDave Chinner #include "xfs_da_btree.h"
2930f712c9SDave Chinner #include "xfs_inode.h"
3030f712c9SDave Chinner #include "xfs_trans.h"
3130f712c9SDave Chinner #include "xfs_inode_item.h"
3230f712c9SDave Chinner #include "xfs_bmap.h"
3330f712c9SDave Chinner #include "xfs_buf_item.h"
3430f712c9SDave Chinner #include "xfs_dir2.h"
3530f712c9SDave Chinner #include "xfs_dir2_priv.h"
3630f712c9SDave Chinner #include "xfs_error.h"
3730f712c9SDave Chinner #include "xfs_trace.h"
3830f712c9SDave Chinner #include "xfs_cksum.h"
3930f712c9SDave Chinner #include "xfs_dinode.h"
4030f712c9SDave Chinner 
4130f712c9SDave Chinner /*
4230f712c9SDave Chinner  * Local function prototypes.
4330f712c9SDave Chinner  */
4430f712c9SDave Chinner static void xfs_dir2_block_log_leaf(xfs_trans_t *tp, struct xfs_buf *bp,
4530f712c9SDave Chinner 				    int first, int last);
4630f712c9SDave Chinner static void xfs_dir2_block_log_tail(xfs_trans_t *tp, struct xfs_buf *bp);
4730f712c9SDave Chinner static int xfs_dir2_block_lookup_int(xfs_da_args_t *args, struct xfs_buf **bpp,
4830f712c9SDave Chinner 				     int *entno);
4930f712c9SDave Chinner static int xfs_dir2_block_sort(const void *a, const void *b);
5030f712c9SDave Chinner 
5130f712c9SDave Chinner static xfs_dahash_t xfs_dir_hash_dot, xfs_dir_hash_dotdot;
5230f712c9SDave Chinner 
5330f712c9SDave Chinner /*
5430f712c9SDave Chinner  * One-time startup routine called from xfs_init().
5530f712c9SDave Chinner  */
5630f712c9SDave Chinner void
5730f712c9SDave Chinner xfs_dir_startup(void)
5830f712c9SDave Chinner {
5930f712c9SDave Chinner 	xfs_dir_hash_dot = xfs_da_hashname((unsigned char *)".", 1);
6030f712c9SDave Chinner 	xfs_dir_hash_dotdot = xfs_da_hashname((unsigned char *)"..", 2);
6130f712c9SDave Chinner }
6230f712c9SDave Chinner 
6330f712c9SDave Chinner static bool
6430f712c9SDave Chinner xfs_dir3_block_verify(
6530f712c9SDave Chinner 	struct xfs_buf		*bp)
6630f712c9SDave Chinner {
6730f712c9SDave Chinner 	struct xfs_mount	*mp = bp->b_target->bt_mount;
6830f712c9SDave Chinner 	struct xfs_dir3_blk_hdr	*hdr3 = bp->b_addr;
6930f712c9SDave Chinner 
7030f712c9SDave Chinner 	if (xfs_sb_version_hascrc(&mp->m_sb)) {
7130f712c9SDave Chinner 		if (hdr3->magic != cpu_to_be32(XFS_DIR3_BLOCK_MAGIC))
7230f712c9SDave Chinner 			return false;
7330f712c9SDave Chinner 		if (!uuid_equal(&hdr3->uuid, &mp->m_sb.sb_uuid))
7430f712c9SDave Chinner 			return false;
7530f712c9SDave Chinner 		if (be64_to_cpu(hdr3->blkno) != bp->b_bn)
7630f712c9SDave Chinner 			return false;
7730f712c9SDave Chinner 	} else {
7830f712c9SDave Chinner 		if (hdr3->magic != cpu_to_be32(XFS_DIR2_BLOCK_MAGIC))
7930f712c9SDave Chinner 			return false;
8030f712c9SDave Chinner 	}
8130f712c9SDave Chinner 	if (__xfs_dir3_data_check(NULL, bp))
8230f712c9SDave Chinner 		return false;
8330f712c9SDave Chinner 	return true;
8430f712c9SDave Chinner }
8530f712c9SDave Chinner 
8630f712c9SDave Chinner static void
8730f712c9SDave Chinner xfs_dir3_block_read_verify(
8830f712c9SDave Chinner 	struct xfs_buf	*bp)
8930f712c9SDave Chinner {
9030f712c9SDave Chinner 	struct xfs_mount	*mp = bp->b_target->bt_mount;
9130f712c9SDave Chinner 
9230f712c9SDave Chinner 	if (xfs_sb_version_hascrc(&mp->m_sb) &&
9330f712c9SDave Chinner 	     !xfs_buf_verify_cksum(bp, XFS_DIR3_DATA_CRC_OFF))
9430f712c9SDave Chinner 		xfs_buf_ioerror(bp, EFSBADCRC);
9530f712c9SDave Chinner 	else if (!xfs_dir3_block_verify(bp))
9630f712c9SDave Chinner 		xfs_buf_ioerror(bp, EFSCORRUPTED);
9730f712c9SDave Chinner 
9830f712c9SDave Chinner 	if (bp->b_error)
9930f712c9SDave Chinner 		xfs_verifier_error(bp);
10030f712c9SDave Chinner }
10130f712c9SDave Chinner 
10230f712c9SDave Chinner static void
10330f712c9SDave Chinner xfs_dir3_block_write_verify(
10430f712c9SDave Chinner 	struct xfs_buf	*bp)
10530f712c9SDave Chinner {
10630f712c9SDave Chinner 	struct xfs_mount	*mp = bp->b_target->bt_mount;
10730f712c9SDave Chinner 	struct xfs_buf_log_item	*bip = bp->b_fspriv;
10830f712c9SDave Chinner 	struct xfs_dir3_blk_hdr	*hdr3 = bp->b_addr;
10930f712c9SDave Chinner 
11030f712c9SDave Chinner 	if (!xfs_dir3_block_verify(bp)) {
11130f712c9SDave Chinner 		xfs_buf_ioerror(bp, EFSCORRUPTED);
11230f712c9SDave Chinner 		xfs_verifier_error(bp);
11330f712c9SDave Chinner 		return;
11430f712c9SDave Chinner 	}
11530f712c9SDave Chinner 
11630f712c9SDave Chinner 	if (!xfs_sb_version_hascrc(&mp->m_sb))
11730f712c9SDave Chinner 		return;
11830f712c9SDave Chinner 
11930f712c9SDave Chinner 	if (bip)
12030f712c9SDave Chinner 		hdr3->lsn = cpu_to_be64(bip->bli_item.li_lsn);
12130f712c9SDave Chinner 
12230f712c9SDave Chinner 	xfs_buf_update_cksum(bp, XFS_DIR3_DATA_CRC_OFF);
12330f712c9SDave Chinner }
12430f712c9SDave Chinner 
12530f712c9SDave Chinner const struct xfs_buf_ops xfs_dir3_block_buf_ops = {
12630f712c9SDave Chinner 	.verify_read = xfs_dir3_block_read_verify,
12730f712c9SDave Chinner 	.verify_write = xfs_dir3_block_write_verify,
12830f712c9SDave Chinner };
12930f712c9SDave Chinner 
13030f712c9SDave Chinner int
13130f712c9SDave Chinner xfs_dir3_block_read(
13230f712c9SDave Chinner 	struct xfs_trans	*tp,
13330f712c9SDave Chinner 	struct xfs_inode	*dp,
13430f712c9SDave Chinner 	struct xfs_buf		**bpp)
13530f712c9SDave Chinner {
13630f712c9SDave Chinner 	struct xfs_mount	*mp = dp->i_mount;
13730f712c9SDave Chinner 	int			err;
13830f712c9SDave Chinner 
13930f712c9SDave Chinner 	err = xfs_da_read_buf(tp, dp, mp->m_dir_geo->datablk, -1, bpp,
14030f712c9SDave Chinner 				XFS_DATA_FORK, &xfs_dir3_block_buf_ops);
14130f712c9SDave Chinner 	if (!err && tp)
14230f712c9SDave Chinner 		xfs_trans_buf_set_type(tp, *bpp, XFS_BLFT_DIR_BLOCK_BUF);
14330f712c9SDave Chinner 	return err;
14430f712c9SDave Chinner }
14530f712c9SDave Chinner 
14630f712c9SDave Chinner static void
14730f712c9SDave Chinner xfs_dir3_block_init(
14830f712c9SDave Chinner 	struct xfs_mount	*mp,
14930f712c9SDave Chinner 	struct xfs_trans	*tp,
15030f712c9SDave Chinner 	struct xfs_buf		*bp,
15130f712c9SDave Chinner 	struct xfs_inode	*dp)
15230f712c9SDave Chinner {
15330f712c9SDave Chinner 	struct xfs_dir3_blk_hdr *hdr3 = bp->b_addr;
15430f712c9SDave Chinner 
15530f712c9SDave Chinner 	bp->b_ops = &xfs_dir3_block_buf_ops;
15630f712c9SDave Chinner 	xfs_trans_buf_set_type(tp, bp, XFS_BLFT_DIR_BLOCK_BUF);
15730f712c9SDave Chinner 
15830f712c9SDave Chinner 	if (xfs_sb_version_hascrc(&mp->m_sb)) {
15930f712c9SDave Chinner 		memset(hdr3, 0, sizeof(*hdr3));
16030f712c9SDave Chinner 		hdr3->magic = cpu_to_be32(XFS_DIR3_BLOCK_MAGIC);
16130f712c9SDave Chinner 		hdr3->blkno = cpu_to_be64(bp->b_bn);
16230f712c9SDave Chinner 		hdr3->owner = cpu_to_be64(dp->i_ino);
16330f712c9SDave Chinner 		uuid_copy(&hdr3->uuid, &mp->m_sb.sb_uuid);
16430f712c9SDave Chinner 		return;
16530f712c9SDave Chinner 
16630f712c9SDave Chinner 	}
16730f712c9SDave Chinner 	hdr3->magic = cpu_to_be32(XFS_DIR2_BLOCK_MAGIC);
16830f712c9SDave Chinner }
16930f712c9SDave Chinner 
17030f712c9SDave Chinner static void
17130f712c9SDave Chinner xfs_dir2_block_need_space(
17230f712c9SDave Chinner 	struct xfs_inode		*dp,
17330f712c9SDave Chinner 	struct xfs_dir2_data_hdr	*hdr,
17430f712c9SDave Chinner 	struct xfs_dir2_block_tail	*btp,
17530f712c9SDave Chinner 	struct xfs_dir2_leaf_entry	*blp,
17630f712c9SDave Chinner 	__be16				**tagpp,
17730f712c9SDave Chinner 	struct xfs_dir2_data_unused	**dupp,
17830f712c9SDave Chinner 	struct xfs_dir2_data_unused	**enddupp,
17930f712c9SDave Chinner 	int				*compact,
18030f712c9SDave Chinner 	int				len)
18130f712c9SDave Chinner {
18230f712c9SDave Chinner 	struct xfs_dir2_data_free	*bf;
18330f712c9SDave Chinner 	__be16				*tagp = NULL;
18430f712c9SDave Chinner 	struct xfs_dir2_data_unused	*dup = NULL;
18530f712c9SDave Chinner 	struct xfs_dir2_data_unused	*enddup = NULL;
18630f712c9SDave Chinner 
18730f712c9SDave Chinner 	*compact = 0;
18830f712c9SDave Chinner 	bf = dp->d_ops->data_bestfree_p(hdr);
18930f712c9SDave Chinner 
19030f712c9SDave Chinner 	/*
19130f712c9SDave Chinner 	 * If there are stale entries we'll use one for the leaf.
19230f712c9SDave Chinner 	 */
19330f712c9SDave Chinner 	if (btp->stale) {
19430f712c9SDave Chinner 		if (be16_to_cpu(bf[0].length) >= len) {
19530f712c9SDave Chinner 			/*
19630f712c9SDave Chinner 			 * The biggest entry enough to avoid compaction.
19730f712c9SDave Chinner 			 */
19830f712c9SDave Chinner 			dup = (xfs_dir2_data_unused_t *)
19930f712c9SDave Chinner 			      ((char *)hdr + be16_to_cpu(bf[0].offset));
20030f712c9SDave Chinner 			goto out;
20130f712c9SDave Chinner 		}
20230f712c9SDave Chinner 
20330f712c9SDave Chinner 		/*
20430f712c9SDave Chinner 		 * Will need to compact to make this work.
20530f712c9SDave Chinner 		 * Tag just before the first leaf entry.
20630f712c9SDave Chinner 		 */
20730f712c9SDave Chinner 		*compact = 1;
20830f712c9SDave Chinner 		tagp = (__be16 *)blp - 1;
20930f712c9SDave Chinner 
21030f712c9SDave Chinner 		/* Data object just before the first leaf entry.  */
21130f712c9SDave Chinner 		dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
21230f712c9SDave Chinner 
21330f712c9SDave Chinner 		/*
21430f712c9SDave Chinner 		 * If it's not free then the data will go where the
21530f712c9SDave Chinner 		 * leaf data starts now, if it works at all.
21630f712c9SDave Chinner 		 */
21730f712c9SDave Chinner 		if (be16_to_cpu(dup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
21830f712c9SDave Chinner 			if (be16_to_cpu(dup->length) + (be32_to_cpu(btp->stale) - 1) *
21930f712c9SDave Chinner 			    (uint)sizeof(*blp) < len)
22030f712c9SDave Chinner 				dup = NULL;
22130f712c9SDave Chinner 		} else if ((be32_to_cpu(btp->stale) - 1) * (uint)sizeof(*blp) < len)
22230f712c9SDave Chinner 			dup = NULL;
22330f712c9SDave Chinner 		else
22430f712c9SDave Chinner 			dup = (xfs_dir2_data_unused_t *)blp;
22530f712c9SDave Chinner 		goto out;
22630f712c9SDave Chinner 	}
22730f712c9SDave Chinner 
22830f712c9SDave Chinner 	/*
22930f712c9SDave Chinner 	 * no stale entries, so just use free space.
23030f712c9SDave Chinner 	 * Tag just before the first leaf entry.
23130f712c9SDave Chinner 	 */
23230f712c9SDave Chinner 	tagp = (__be16 *)blp - 1;
23330f712c9SDave Chinner 
23430f712c9SDave Chinner 	/* Data object just before the first leaf entry.  */
23530f712c9SDave Chinner 	enddup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
23630f712c9SDave Chinner 
23730f712c9SDave Chinner 	/*
23830f712c9SDave Chinner 	 * If it's not free then can't do this add without cleaning up:
23930f712c9SDave Chinner 	 * the space before the first leaf entry needs to be free so it
24030f712c9SDave Chinner 	 * can be expanded to hold the pointer to the new entry.
24130f712c9SDave Chinner 	 */
24230f712c9SDave Chinner 	if (be16_to_cpu(enddup->freetag) == XFS_DIR2_DATA_FREE_TAG) {
24330f712c9SDave Chinner 		/*
24430f712c9SDave Chinner 		 * Check out the biggest freespace and see if it's the same one.
24530f712c9SDave Chinner 		 */
24630f712c9SDave Chinner 		dup = (xfs_dir2_data_unused_t *)
24730f712c9SDave Chinner 		      ((char *)hdr + be16_to_cpu(bf[0].offset));
24830f712c9SDave Chinner 		if (dup != enddup) {
24930f712c9SDave Chinner 			/*
25030f712c9SDave Chinner 			 * Not the same free entry, just check its length.
25130f712c9SDave Chinner 			 */
25230f712c9SDave Chinner 			if (be16_to_cpu(dup->length) < len)
25330f712c9SDave Chinner 				dup = NULL;
25430f712c9SDave Chinner 			goto out;
25530f712c9SDave Chinner 		}
25630f712c9SDave Chinner 
25730f712c9SDave Chinner 		/*
25830f712c9SDave Chinner 		 * It is the biggest freespace, can it hold the leaf too?
25930f712c9SDave Chinner 		 */
26030f712c9SDave Chinner 		if (be16_to_cpu(dup->length) < len + (uint)sizeof(*blp)) {
26130f712c9SDave Chinner 			/*
26230f712c9SDave Chinner 			 * Yes, use the second-largest entry instead if it works.
26330f712c9SDave Chinner 			 */
26430f712c9SDave Chinner 			if (be16_to_cpu(bf[1].length) >= len)
26530f712c9SDave Chinner 				dup = (xfs_dir2_data_unused_t *)
26630f712c9SDave Chinner 				      ((char *)hdr + be16_to_cpu(bf[1].offset));
26730f712c9SDave Chinner 			else
26830f712c9SDave Chinner 				dup = NULL;
26930f712c9SDave Chinner 		}
27030f712c9SDave Chinner 	}
27130f712c9SDave Chinner out:
27230f712c9SDave Chinner 	*tagpp = tagp;
27330f712c9SDave Chinner 	*dupp = dup;
27430f712c9SDave Chinner 	*enddupp = enddup;
27530f712c9SDave Chinner }
27630f712c9SDave Chinner 
27730f712c9SDave Chinner /*
27830f712c9SDave Chinner  * compact the leaf entries.
27930f712c9SDave Chinner  * Leave the highest-numbered stale entry stale.
28030f712c9SDave Chinner  * XXX should be the one closest to mid but mid is not yet computed.
28130f712c9SDave Chinner  */
28230f712c9SDave Chinner static void
28330f712c9SDave Chinner xfs_dir2_block_compact(
28430f712c9SDave Chinner 	struct xfs_da_args		*args,
28530f712c9SDave Chinner 	struct xfs_buf			*bp,
28630f712c9SDave Chinner 	struct xfs_dir2_data_hdr	*hdr,
28730f712c9SDave Chinner 	struct xfs_dir2_block_tail	*btp,
28830f712c9SDave Chinner 	struct xfs_dir2_leaf_entry	*blp,
28930f712c9SDave Chinner 	int				*needlog,
29030f712c9SDave Chinner 	int				*lfloghigh,
29130f712c9SDave Chinner 	int				*lfloglow)
29230f712c9SDave Chinner {
29330f712c9SDave Chinner 	int			fromidx;	/* source leaf index */
29430f712c9SDave Chinner 	int			toidx;		/* target leaf index */
29530f712c9SDave Chinner 	int			needscan = 0;
29630f712c9SDave Chinner 	int			highstale;	/* high stale index */
29730f712c9SDave Chinner 
29830f712c9SDave Chinner 	fromidx = toidx = be32_to_cpu(btp->count) - 1;
29930f712c9SDave Chinner 	highstale = *lfloghigh = -1;
30030f712c9SDave Chinner 	for (; fromidx >= 0; fromidx--) {
30130f712c9SDave Chinner 		if (blp[fromidx].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR)) {
30230f712c9SDave Chinner 			if (highstale == -1)
30330f712c9SDave Chinner 				highstale = toidx;
30430f712c9SDave Chinner 			else {
30530f712c9SDave Chinner 				if (*lfloghigh == -1)
30630f712c9SDave Chinner 					*lfloghigh = toidx;
30730f712c9SDave Chinner 				continue;
30830f712c9SDave Chinner 			}
30930f712c9SDave Chinner 		}
31030f712c9SDave Chinner 		if (fromidx < toidx)
31130f712c9SDave Chinner 			blp[toidx] = blp[fromidx];
31230f712c9SDave Chinner 		toidx--;
31330f712c9SDave Chinner 	}
31430f712c9SDave Chinner 	*lfloglow = toidx + 1 - (be32_to_cpu(btp->stale) - 1);
31530f712c9SDave Chinner 	*lfloghigh -= be32_to_cpu(btp->stale) - 1;
31630f712c9SDave Chinner 	be32_add_cpu(&btp->count, -(be32_to_cpu(btp->stale) - 1));
31730f712c9SDave Chinner 	xfs_dir2_data_make_free(args, bp,
31830f712c9SDave Chinner 		(xfs_dir2_data_aoff_t)((char *)blp - (char *)hdr),
31930f712c9SDave Chinner 		(xfs_dir2_data_aoff_t)((be32_to_cpu(btp->stale) - 1) * sizeof(*blp)),
32030f712c9SDave Chinner 		needlog, &needscan);
32130f712c9SDave Chinner 	btp->stale = cpu_to_be32(1);
32230f712c9SDave Chinner 	/*
32330f712c9SDave Chinner 	 * If we now need to rebuild the bestfree map, do so.
32430f712c9SDave Chinner 	 * This needs to happen before the next call to use_free.
32530f712c9SDave Chinner 	 */
32630f712c9SDave Chinner 	if (needscan)
32730f712c9SDave Chinner 		xfs_dir2_data_freescan(args->dp, hdr, needlog);
32830f712c9SDave Chinner }
32930f712c9SDave Chinner 
33030f712c9SDave Chinner /*
33130f712c9SDave Chinner  * Add an entry to a block directory.
33230f712c9SDave Chinner  */
33330f712c9SDave Chinner int						/* error */
33430f712c9SDave Chinner xfs_dir2_block_addname(
33530f712c9SDave Chinner 	xfs_da_args_t		*args)		/* directory op arguments */
33630f712c9SDave Chinner {
33730f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr;		/* block header */
33830f712c9SDave Chinner 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
33930f712c9SDave Chinner 	struct xfs_buf		*bp;		/* buffer for block */
34030f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;		/* block tail */
34130f712c9SDave Chinner 	int			compact;	/* need to compact leaf ents */
34230f712c9SDave Chinner 	xfs_dir2_data_entry_t	*dep;		/* block data entry */
34330f712c9SDave Chinner 	xfs_inode_t		*dp;		/* directory inode */
34430f712c9SDave Chinner 	xfs_dir2_data_unused_t	*dup;		/* block unused entry */
34530f712c9SDave Chinner 	int			error;		/* error return value */
34630f712c9SDave Chinner 	xfs_dir2_data_unused_t	*enddup=NULL;	/* unused at end of data */
34730f712c9SDave Chinner 	xfs_dahash_t		hash;		/* hash value of found entry */
34830f712c9SDave Chinner 	int			high;		/* high index for binary srch */
34930f712c9SDave Chinner 	int			highstale;	/* high stale index */
35030f712c9SDave Chinner 	int			lfloghigh=0;	/* last final leaf to log */
35130f712c9SDave Chinner 	int			lfloglow=0;	/* first final leaf to log */
35230f712c9SDave Chinner 	int			len;		/* length of the new entry */
35330f712c9SDave Chinner 	int			low;		/* low index for binary srch */
35430f712c9SDave Chinner 	int			lowstale;	/* low stale index */
35530f712c9SDave Chinner 	int			mid=0;		/* midpoint for binary srch */
35630f712c9SDave Chinner 	xfs_mount_t		*mp;		/* filesystem mount point */
35730f712c9SDave Chinner 	int			needlog;	/* need to log header */
35830f712c9SDave Chinner 	int			needscan;	/* need to rescan freespace */
35930f712c9SDave Chinner 	__be16			*tagp;		/* pointer to tag value */
36030f712c9SDave Chinner 	xfs_trans_t		*tp;		/* transaction structure */
36130f712c9SDave Chinner 
36230f712c9SDave Chinner 	trace_xfs_dir2_block_addname(args);
36330f712c9SDave Chinner 
36430f712c9SDave Chinner 	dp = args->dp;
36530f712c9SDave Chinner 	tp = args->trans;
36630f712c9SDave Chinner 	mp = dp->i_mount;
36730f712c9SDave Chinner 
36830f712c9SDave Chinner 	/* Read the (one and only) directory block into bp. */
36930f712c9SDave Chinner 	error = xfs_dir3_block_read(tp, dp, &bp);
37030f712c9SDave Chinner 	if (error)
37130f712c9SDave Chinner 		return error;
37230f712c9SDave Chinner 
37330f712c9SDave Chinner 	len = dp->d_ops->data_entsize(args->namelen);
37430f712c9SDave Chinner 
37530f712c9SDave Chinner 	/*
37630f712c9SDave Chinner 	 * Set up pointers to parts of the block.
37730f712c9SDave Chinner 	 */
37830f712c9SDave Chinner 	hdr = bp->b_addr;
37930f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(args->geo, hdr);
38030f712c9SDave Chinner 	blp = xfs_dir2_block_leaf_p(btp);
38130f712c9SDave Chinner 
38230f712c9SDave Chinner 	/*
38330f712c9SDave Chinner 	 * Find out if we can reuse stale entries or whether we need extra
38430f712c9SDave Chinner 	 * space for entry and new leaf.
38530f712c9SDave Chinner 	 */
38630f712c9SDave Chinner 	xfs_dir2_block_need_space(dp, hdr, btp, blp, &tagp, &dup,
38730f712c9SDave Chinner 				  &enddup, &compact, len);
38830f712c9SDave Chinner 
38930f712c9SDave Chinner 	/*
39030f712c9SDave Chinner 	 * Done everything we need for a space check now.
39130f712c9SDave Chinner 	 */
39230f712c9SDave Chinner 	if (args->op_flags & XFS_DA_OP_JUSTCHECK) {
39330f712c9SDave Chinner 		xfs_trans_brelse(tp, bp);
39430f712c9SDave Chinner 		if (!dup)
39530f712c9SDave Chinner 			return ENOSPC;
39630f712c9SDave Chinner 		return 0;
39730f712c9SDave Chinner 	}
39830f712c9SDave Chinner 
39930f712c9SDave Chinner 	/*
40030f712c9SDave Chinner 	 * If we don't have space for the new entry & leaf ...
40130f712c9SDave Chinner 	 */
40230f712c9SDave Chinner 	if (!dup) {
40330f712c9SDave Chinner 		/* Don't have a space reservation: return no-space.  */
40430f712c9SDave Chinner 		if (args->total == 0)
40530f712c9SDave Chinner 			return ENOSPC;
40630f712c9SDave Chinner 		/*
40730f712c9SDave Chinner 		 * Convert to the next larger format.
40830f712c9SDave Chinner 		 * Then add the new entry in that format.
40930f712c9SDave Chinner 		 */
41030f712c9SDave Chinner 		error = xfs_dir2_block_to_leaf(args, bp);
41130f712c9SDave Chinner 		if (error)
41230f712c9SDave Chinner 			return error;
41330f712c9SDave Chinner 		return xfs_dir2_leaf_addname(args);
41430f712c9SDave Chinner 	}
41530f712c9SDave Chinner 
41630f712c9SDave Chinner 	needlog = needscan = 0;
41730f712c9SDave Chinner 
41830f712c9SDave Chinner 	/*
41930f712c9SDave Chinner 	 * If need to compact the leaf entries, do it now.
42030f712c9SDave Chinner 	 */
42130f712c9SDave Chinner 	if (compact) {
42230f712c9SDave Chinner 		xfs_dir2_block_compact(args, bp, hdr, btp, blp, &needlog,
42330f712c9SDave Chinner 				      &lfloghigh, &lfloglow);
42430f712c9SDave Chinner 		/* recalculate blp post-compaction */
42530f712c9SDave Chinner 		blp = xfs_dir2_block_leaf_p(btp);
42630f712c9SDave Chinner 	} else if (btp->stale) {
42730f712c9SDave Chinner 		/*
42830f712c9SDave Chinner 		 * Set leaf logging boundaries to impossible state.
42930f712c9SDave Chinner 		 * For the no-stale case they're set explicitly.
43030f712c9SDave Chinner 		 */
43130f712c9SDave Chinner 		lfloglow = be32_to_cpu(btp->count);
43230f712c9SDave Chinner 		lfloghigh = -1;
43330f712c9SDave Chinner 	}
43430f712c9SDave Chinner 
43530f712c9SDave Chinner 	/*
43630f712c9SDave Chinner 	 * Find the slot that's first lower than our hash value, -1 if none.
43730f712c9SDave Chinner 	 */
43830f712c9SDave Chinner 	for (low = 0, high = be32_to_cpu(btp->count) - 1; low <= high; ) {
43930f712c9SDave Chinner 		mid = (low + high) >> 1;
44030f712c9SDave Chinner 		if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval)
44130f712c9SDave Chinner 			break;
44230f712c9SDave Chinner 		if (hash < args->hashval)
44330f712c9SDave Chinner 			low = mid + 1;
44430f712c9SDave Chinner 		else
44530f712c9SDave Chinner 			high = mid - 1;
44630f712c9SDave Chinner 	}
44730f712c9SDave Chinner 	while (mid >= 0 && be32_to_cpu(blp[mid].hashval) >= args->hashval) {
44830f712c9SDave Chinner 		mid--;
44930f712c9SDave Chinner 	}
45030f712c9SDave Chinner 	/*
45130f712c9SDave Chinner 	 * No stale entries, will use enddup space to hold new leaf.
45230f712c9SDave Chinner 	 */
45330f712c9SDave Chinner 	if (!btp->stale) {
45430f712c9SDave Chinner 		/*
45530f712c9SDave Chinner 		 * Mark the space needed for the new leaf entry, now in use.
45630f712c9SDave Chinner 		 */
45730f712c9SDave Chinner 		xfs_dir2_data_use_free(args, bp, enddup,
45830f712c9SDave Chinner 			(xfs_dir2_data_aoff_t)
45930f712c9SDave Chinner 			((char *)enddup - (char *)hdr + be16_to_cpu(enddup->length) -
46030f712c9SDave Chinner 			 sizeof(*blp)),
46130f712c9SDave Chinner 			(xfs_dir2_data_aoff_t)sizeof(*blp),
46230f712c9SDave Chinner 			&needlog, &needscan);
46330f712c9SDave Chinner 		/*
46430f712c9SDave Chinner 		 * Update the tail (entry count).
46530f712c9SDave Chinner 		 */
46630f712c9SDave Chinner 		be32_add_cpu(&btp->count, 1);
46730f712c9SDave Chinner 		/*
46830f712c9SDave Chinner 		 * If we now need to rebuild the bestfree map, do so.
46930f712c9SDave Chinner 		 * This needs to happen before the next call to use_free.
47030f712c9SDave Chinner 		 */
47130f712c9SDave Chinner 		if (needscan) {
47230f712c9SDave Chinner 			xfs_dir2_data_freescan(dp, hdr, &needlog);
47330f712c9SDave Chinner 			needscan = 0;
47430f712c9SDave Chinner 		}
47530f712c9SDave Chinner 		/*
47630f712c9SDave Chinner 		 * Adjust pointer to the first leaf entry, we're about to move
47730f712c9SDave Chinner 		 * the table up one to open up space for the new leaf entry.
47830f712c9SDave Chinner 		 * Then adjust our index to match.
47930f712c9SDave Chinner 		 */
48030f712c9SDave Chinner 		blp--;
48130f712c9SDave Chinner 		mid++;
48230f712c9SDave Chinner 		if (mid)
48330f712c9SDave Chinner 			memmove(blp, &blp[1], mid * sizeof(*blp));
48430f712c9SDave Chinner 		lfloglow = 0;
48530f712c9SDave Chinner 		lfloghigh = mid;
48630f712c9SDave Chinner 	}
48730f712c9SDave Chinner 	/*
48830f712c9SDave Chinner 	 * Use a stale leaf for our new entry.
48930f712c9SDave Chinner 	 */
49030f712c9SDave Chinner 	else {
49130f712c9SDave Chinner 		for (lowstale = mid;
49230f712c9SDave Chinner 		     lowstale >= 0 &&
49330f712c9SDave Chinner 			blp[lowstale].address !=
49430f712c9SDave Chinner 			cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
49530f712c9SDave Chinner 		     lowstale--)
49630f712c9SDave Chinner 			continue;
49730f712c9SDave Chinner 		for (highstale = mid + 1;
49830f712c9SDave Chinner 		     highstale < be32_to_cpu(btp->count) &&
49930f712c9SDave Chinner 			blp[highstale].address !=
50030f712c9SDave Chinner 			cpu_to_be32(XFS_DIR2_NULL_DATAPTR) &&
50130f712c9SDave Chinner 			(lowstale < 0 || mid - lowstale > highstale - mid);
50230f712c9SDave Chinner 		     highstale++)
50330f712c9SDave Chinner 			continue;
50430f712c9SDave Chinner 		/*
50530f712c9SDave Chinner 		 * Move entries toward the low-numbered stale entry.
50630f712c9SDave Chinner 		 */
50730f712c9SDave Chinner 		if (lowstale >= 0 &&
50830f712c9SDave Chinner 		    (highstale == be32_to_cpu(btp->count) ||
50930f712c9SDave Chinner 		     mid - lowstale <= highstale - mid)) {
51030f712c9SDave Chinner 			if (mid - lowstale)
51130f712c9SDave Chinner 				memmove(&blp[lowstale], &blp[lowstale + 1],
51230f712c9SDave Chinner 					(mid - lowstale) * sizeof(*blp));
51330f712c9SDave Chinner 			lfloglow = MIN(lowstale, lfloglow);
51430f712c9SDave Chinner 			lfloghigh = MAX(mid, lfloghigh);
51530f712c9SDave Chinner 		}
51630f712c9SDave Chinner 		/*
51730f712c9SDave Chinner 		 * Move entries toward the high-numbered stale entry.
51830f712c9SDave Chinner 		 */
51930f712c9SDave Chinner 		else {
52030f712c9SDave Chinner 			ASSERT(highstale < be32_to_cpu(btp->count));
52130f712c9SDave Chinner 			mid++;
52230f712c9SDave Chinner 			if (highstale - mid)
52330f712c9SDave Chinner 				memmove(&blp[mid + 1], &blp[mid],
52430f712c9SDave Chinner 					(highstale - mid) * sizeof(*blp));
52530f712c9SDave Chinner 			lfloglow = MIN(mid, lfloglow);
52630f712c9SDave Chinner 			lfloghigh = MAX(highstale, lfloghigh);
52730f712c9SDave Chinner 		}
52830f712c9SDave Chinner 		be32_add_cpu(&btp->stale, -1);
52930f712c9SDave Chinner 	}
53030f712c9SDave Chinner 	/*
53130f712c9SDave Chinner 	 * Point to the new data entry.
53230f712c9SDave Chinner 	 */
53330f712c9SDave Chinner 	dep = (xfs_dir2_data_entry_t *)dup;
53430f712c9SDave Chinner 	/*
53530f712c9SDave Chinner 	 * Fill in the leaf entry.
53630f712c9SDave Chinner 	 */
53730f712c9SDave Chinner 	blp[mid].hashval = cpu_to_be32(args->hashval);
53830f712c9SDave Chinner 	blp[mid].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
53930f712c9SDave Chinner 				(char *)dep - (char *)hdr));
54030f712c9SDave Chinner 	xfs_dir2_block_log_leaf(tp, bp, lfloglow, lfloghigh);
54130f712c9SDave Chinner 	/*
54230f712c9SDave Chinner 	 * Mark space for the data entry used.
54330f712c9SDave Chinner 	 */
54430f712c9SDave Chinner 	xfs_dir2_data_use_free(args, bp, dup,
54530f712c9SDave Chinner 		(xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
54630f712c9SDave Chinner 		(xfs_dir2_data_aoff_t)len, &needlog, &needscan);
54730f712c9SDave Chinner 	/*
54830f712c9SDave Chinner 	 * Create the new data entry.
54930f712c9SDave Chinner 	 */
55030f712c9SDave Chinner 	dep->inumber = cpu_to_be64(args->inumber);
55130f712c9SDave Chinner 	dep->namelen = args->namelen;
55230f712c9SDave Chinner 	memcpy(dep->name, args->name, args->namelen);
55330f712c9SDave Chinner 	dp->d_ops->data_put_ftype(dep, args->filetype);
55430f712c9SDave Chinner 	tagp = dp->d_ops->data_entry_tag_p(dep);
55530f712c9SDave Chinner 	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
55630f712c9SDave Chinner 	/*
55730f712c9SDave Chinner 	 * Clean up the bestfree array and log the header, tail, and entry.
55830f712c9SDave Chinner 	 */
55930f712c9SDave Chinner 	if (needscan)
56030f712c9SDave Chinner 		xfs_dir2_data_freescan(dp, hdr, &needlog);
56130f712c9SDave Chinner 	if (needlog)
56230f712c9SDave Chinner 		xfs_dir2_data_log_header(args, bp);
56330f712c9SDave Chinner 	xfs_dir2_block_log_tail(tp, bp);
56430f712c9SDave Chinner 	xfs_dir2_data_log_entry(args, bp, dep);
56530f712c9SDave Chinner 	xfs_dir3_data_check(dp, bp);
56630f712c9SDave Chinner 	return 0;
56730f712c9SDave Chinner }
56830f712c9SDave Chinner 
56930f712c9SDave Chinner /*
57030f712c9SDave Chinner  * Log leaf entries from the block.
57130f712c9SDave Chinner  */
57230f712c9SDave Chinner static void
57330f712c9SDave Chinner xfs_dir2_block_log_leaf(
57430f712c9SDave Chinner 	xfs_trans_t		*tp,		/* transaction structure */
57530f712c9SDave Chinner 	struct xfs_buf		*bp,		/* block buffer */
57630f712c9SDave Chinner 	int			first,		/* index of first logged leaf */
57730f712c9SDave Chinner 	int			last)		/* index of last logged leaf */
57830f712c9SDave Chinner {
57930f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr = bp->b_addr;
58030f712c9SDave Chinner 	xfs_dir2_leaf_entry_t	*blp;
58130f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;
58230f712c9SDave Chinner 
58330f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr);
58430f712c9SDave Chinner 	blp = xfs_dir2_block_leaf_p(btp);
58530f712c9SDave Chinner 	xfs_trans_log_buf(tp, bp, (uint)((char *)&blp[first] - (char *)hdr),
58630f712c9SDave Chinner 		(uint)((char *)&blp[last + 1] - (char *)hdr - 1));
58730f712c9SDave Chinner }
58830f712c9SDave Chinner 
58930f712c9SDave Chinner /*
59030f712c9SDave Chinner  * Log the block tail.
59130f712c9SDave Chinner  */
59230f712c9SDave Chinner static void
59330f712c9SDave Chinner xfs_dir2_block_log_tail(
59430f712c9SDave Chinner 	xfs_trans_t		*tp,		/* transaction structure */
59530f712c9SDave Chinner 	struct xfs_buf		*bp)		/* block buffer */
59630f712c9SDave Chinner {
59730f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr = bp->b_addr;
59830f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;
59930f712c9SDave Chinner 
60030f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(tp->t_mountp->m_dir_geo, hdr);
60130f712c9SDave Chinner 	xfs_trans_log_buf(tp, bp, (uint)((char *)btp - (char *)hdr),
60230f712c9SDave Chinner 		(uint)((char *)(btp + 1) - (char *)hdr - 1));
60330f712c9SDave Chinner }
60430f712c9SDave Chinner 
60530f712c9SDave Chinner /*
60630f712c9SDave Chinner  * Look up an entry in the block.  This is the external routine,
60730f712c9SDave Chinner  * xfs_dir2_block_lookup_int does the real work.
60830f712c9SDave Chinner  */
60930f712c9SDave Chinner int						/* error */
61030f712c9SDave Chinner xfs_dir2_block_lookup(
61130f712c9SDave Chinner 	xfs_da_args_t		*args)		/* dir lookup arguments */
61230f712c9SDave Chinner {
61330f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr;		/* block header */
61430f712c9SDave Chinner 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
61530f712c9SDave Chinner 	struct xfs_buf		*bp;		/* block buffer */
61630f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;		/* block tail */
61730f712c9SDave Chinner 	xfs_dir2_data_entry_t	*dep;		/* block data entry */
61830f712c9SDave Chinner 	xfs_inode_t		*dp;		/* incore inode */
61930f712c9SDave Chinner 	int			ent;		/* entry index */
62030f712c9SDave Chinner 	int			error;		/* error return value */
62130f712c9SDave Chinner 	xfs_mount_t		*mp;		/* filesystem mount point */
62230f712c9SDave Chinner 
62330f712c9SDave Chinner 	trace_xfs_dir2_block_lookup(args);
62430f712c9SDave Chinner 
62530f712c9SDave Chinner 	/*
62630f712c9SDave Chinner 	 * Get the buffer, look up the entry.
62730f712c9SDave Chinner 	 * If not found (ENOENT) then return, have no buffer.
62830f712c9SDave Chinner 	 */
62930f712c9SDave Chinner 	if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent)))
63030f712c9SDave Chinner 		return error;
63130f712c9SDave Chinner 	dp = args->dp;
63230f712c9SDave Chinner 	mp = dp->i_mount;
63330f712c9SDave Chinner 	hdr = bp->b_addr;
63430f712c9SDave Chinner 	xfs_dir3_data_check(dp, bp);
63530f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(args->geo, hdr);
63630f712c9SDave Chinner 	blp = xfs_dir2_block_leaf_p(btp);
63730f712c9SDave Chinner 	/*
63830f712c9SDave Chinner 	 * Get the offset from the leaf entry, to point to the data.
63930f712c9SDave Chinner 	 */
64030f712c9SDave Chinner 	dep = (xfs_dir2_data_entry_t *)((char *)hdr +
64130f712c9SDave Chinner 			xfs_dir2_dataptr_to_off(args->geo,
64230f712c9SDave Chinner 						be32_to_cpu(blp[ent].address)));
64330f712c9SDave Chinner 	/*
64430f712c9SDave Chinner 	 * Fill in inode number, CI name if appropriate, release the block.
64530f712c9SDave Chinner 	 */
64630f712c9SDave Chinner 	args->inumber = be64_to_cpu(dep->inumber);
64730f712c9SDave Chinner 	args->filetype = dp->d_ops->data_get_ftype(dep);
64830f712c9SDave Chinner 	error = xfs_dir_cilookup_result(args, dep->name, dep->namelen);
64930f712c9SDave Chinner 	xfs_trans_brelse(args->trans, bp);
65030f712c9SDave Chinner 	return error;
65130f712c9SDave Chinner }
65230f712c9SDave Chinner 
65330f712c9SDave Chinner /*
65430f712c9SDave Chinner  * Internal block lookup routine.
65530f712c9SDave Chinner  */
65630f712c9SDave Chinner static int					/* error */
65730f712c9SDave Chinner xfs_dir2_block_lookup_int(
65830f712c9SDave Chinner 	xfs_da_args_t		*args,		/* dir lookup arguments */
65930f712c9SDave Chinner 	struct xfs_buf		**bpp,		/* returned block buffer */
66030f712c9SDave Chinner 	int			*entno)		/* returned entry number */
66130f712c9SDave Chinner {
66230f712c9SDave Chinner 	xfs_dir2_dataptr_t	addr;		/* data entry address */
66330f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr;		/* block header */
66430f712c9SDave Chinner 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
66530f712c9SDave Chinner 	struct xfs_buf		*bp;		/* block buffer */
66630f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;		/* block tail */
66730f712c9SDave Chinner 	xfs_dir2_data_entry_t	*dep;		/* block data entry */
66830f712c9SDave Chinner 	xfs_inode_t		*dp;		/* incore inode */
66930f712c9SDave Chinner 	int			error;		/* error return value */
67030f712c9SDave Chinner 	xfs_dahash_t		hash;		/* found hash value */
67130f712c9SDave Chinner 	int			high;		/* binary search high index */
67230f712c9SDave Chinner 	int			low;		/* binary search low index */
67330f712c9SDave Chinner 	int			mid;		/* binary search current idx */
67430f712c9SDave Chinner 	xfs_mount_t		*mp;		/* filesystem mount point */
67530f712c9SDave Chinner 	xfs_trans_t		*tp;		/* transaction pointer */
67630f712c9SDave Chinner 	enum xfs_dacmp		cmp;		/* comparison result */
67730f712c9SDave Chinner 
67830f712c9SDave Chinner 	dp = args->dp;
67930f712c9SDave Chinner 	tp = args->trans;
68030f712c9SDave Chinner 	mp = dp->i_mount;
68130f712c9SDave Chinner 
68230f712c9SDave Chinner 	error = xfs_dir3_block_read(tp, dp, &bp);
68330f712c9SDave Chinner 	if (error)
68430f712c9SDave Chinner 		return error;
68530f712c9SDave Chinner 
68630f712c9SDave Chinner 	hdr = bp->b_addr;
68730f712c9SDave Chinner 	xfs_dir3_data_check(dp, bp);
68830f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(args->geo, hdr);
68930f712c9SDave Chinner 	blp = xfs_dir2_block_leaf_p(btp);
69030f712c9SDave Chinner 	/*
69130f712c9SDave Chinner 	 * Loop doing a binary search for our hash value.
69230f712c9SDave Chinner 	 * Find our entry, ENOENT if it's not there.
69330f712c9SDave Chinner 	 */
69430f712c9SDave Chinner 	for (low = 0, high = be32_to_cpu(btp->count) - 1; ; ) {
69530f712c9SDave Chinner 		ASSERT(low <= high);
69630f712c9SDave Chinner 		mid = (low + high) >> 1;
69730f712c9SDave Chinner 		if ((hash = be32_to_cpu(blp[mid].hashval)) == args->hashval)
69830f712c9SDave Chinner 			break;
69930f712c9SDave Chinner 		if (hash < args->hashval)
70030f712c9SDave Chinner 			low = mid + 1;
70130f712c9SDave Chinner 		else
70230f712c9SDave Chinner 			high = mid - 1;
70330f712c9SDave Chinner 		if (low > high) {
70430f712c9SDave Chinner 			ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
70530f712c9SDave Chinner 			xfs_trans_brelse(tp, bp);
70630f712c9SDave Chinner 			return ENOENT;
70730f712c9SDave Chinner 		}
70830f712c9SDave Chinner 	}
70930f712c9SDave Chinner 	/*
71030f712c9SDave Chinner 	 * Back up to the first one with the right hash value.
71130f712c9SDave Chinner 	 */
71230f712c9SDave Chinner 	while (mid > 0 && be32_to_cpu(blp[mid - 1].hashval) == args->hashval) {
71330f712c9SDave Chinner 		mid--;
71430f712c9SDave Chinner 	}
71530f712c9SDave Chinner 	/*
71630f712c9SDave Chinner 	 * Now loop forward through all the entries with the
71730f712c9SDave Chinner 	 * right hash value looking for our name.
71830f712c9SDave Chinner 	 */
71930f712c9SDave Chinner 	do {
72030f712c9SDave Chinner 		if ((addr = be32_to_cpu(blp[mid].address)) == XFS_DIR2_NULL_DATAPTR)
72130f712c9SDave Chinner 			continue;
72230f712c9SDave Chinner 		/*
72330f712c9SDave Chinner 		 * Get pointer to the entry from the leaf.
72430f712c9SDave Chinner 		 */
72530f712c9SDave Chinner 		dep = (xfs_dir2_data_entry_t *)
72630f712c9SDave Chinner 			((char *)hdr + xfs_dir2_dataptr_to_off(args->geo, addr));
72730f712c9SDave Chinner 		/*
72830f712c9SDave Chinner 		 * Compare name and if it's an exact match, return the index
72930f712c9SDave Chinner 		 * and buffer. If it's the first case-insensitive match, store
73030f712c9SDave Chinner 		 * the index and buffer and continue looking for an exact match.
73130f712c9SDave Chinner 		 */
73230f712c9SDave Chinner 		cmp = mp->m_dirnameops->compname(args, dep->name, dep->namelen);
73330f712c9SDave Chinner 		if (cmp != XFS_CMP_DIFFERENT && cmp != args->cmpresult) {
73430f712c9SDave Chinner 			args->cmpresult = cmp;
73530f712c9SDave Chinner 			*bpp = bp;
73630f712c9SDave Chinner 			*entno = mid;
73730f712c9SDave Chinner 			if (cmp == XFS_CMP_EXACT)
73830f712c9SDave Chinner 				return 0;
73930f712c9SDave Chinner 		}
74030f712c9SDave Chinner 	} while (++mid < be32_to_cpu(btp->count) &&
74130f712c9SDave Chinner 			be32_to_cpu(blp[mid].hashval) == hash);
74230f712c9SDave Chinner 
74330f712c9SDave Chinner 	ASSERT(args->op_flags & XFS_DA_OP_OKNOENT);
74430f712c9SDave Chinner 	/*
74530f712c9SDave Chinner 	 * Here, we can only be doing a lookup (not a rename or replace).
74630f712c9SDave Chinner 	 * If a case-insensitive match was found earlier, return success.
74730f712c9SDave Chinner 	 */
74830f712c9SDave Chinner 	if (args->cmpresult == XFS_CMP_CASE)
74930f712c9SDave Chinner 		return 0;
75030f712c9SDave Chinner 	/*
75130f712c9SDave Chinner 	 * No match, release the buffer and return ENOENT.
75230f712c9SDave Chinner 	 */
75330f712c9SDave Chinner 	xfs_trans_brelse(tp, bp);
75430f712c9SDave Chinner 	return ENOENT;
75530f712c9SDave Chinner }
75630f712c9SDave Chinner 
75730f712c9SDave Chinner /*
75830f712c9SDave Chinner  * Remove an entry from a block format directory.
75930f712c9SDave Chinner  * If that makes the block small enough to fit in shortform, transform it.
76030f712c9SDave Chinner  */
76130f712c9SDave Chinner int						/* error */
76230f712c9SDave Chinner xfs_dir2_block_removename(
76330f712c9SDave Chinner 	xfs_da_args_t		*args)		/* directory operation args */
76430f712c9SDave Chinner {
76530f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr;		/* block header */
76630f712c9SDave Chinner 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf pointer */
76730f712c9SDave Chinner 	struct xfs_buf		*bp;		/* block buffer */
76830f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;		/* block tail */
76930f712c9SDave Chinner 	xfs_dir2_data_entry_t	*dep;		/* block data entry */
77030f712c9SDave Chinner 	xfs_inode_t		*dp;		/* incore inode */
77130f712c9SDave Chinner 	int			ent;		/* block leaf entry index */
77230f712c9SDave Chinner 	int			error;		/* error return value */
77330f712c9SDave Chinner 	xfs_mount_t		*mp;		/* filesystem mount point */
77430f712c9SDave Chinner 	int			needlog;	/* need to log block header */
77530f712c9SDave Chinner 	int			needscan;	/* need to fixup bestfree */
77630f712c9SDave Chinner 	xfs_dir2_sf_hdr_t	sfh;		/* shortform header */
77730f712c9SDave Chinner 	int			size;		/* shortform size */
77830f712c9SDave Chinner 	xfs_trans_t		*tp;		/* transaction pointer */
77930f712c9SDave Chinner 
78030f712c9SDave Chinner 	trace_xfs_dir2_block_removename(args);
78130f712c9SDave Chinner 
78230f712c9SDave Chinner 	/*
78330f712c9SDave Chinner 	 * Look up the entry in the block.  Gets the buffer and entry index.
78430f712c9SDave Chinner 	 * It will always be there, the vnodeops level does a lookup first.
78530f712c9SDave Chinner 	 */
78630f712c9SDave Chinner 	if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) {
78730f712c9SDave Chinner 		return error;
78830f712c9SDave Chinner 	}
78930f712c9SDave Chinner 	dp = args->dp;
79030f712c9SDave Chinner 	tp = args->trans;
79130f712c9SDave Chinner 	mp = dp->i_mount;
79230f712c9SDave Chinner 	hdr = bp->b_addr;
79330f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(args->geo, hdr);
79430f712c9SDave Chinner 	blp = xfs_dir2_block_leaf_p(btp);
79530f712c9SDave Chinner 	/*
79630f712c9SDave Chinner 	 * Point to the data entry using the leaf entry.
79730f712c9SDave Chinner 	 */
79830f712c9SDave Chinner 	dep = (xfs_dir2_data_entry_t *)((char *)hdr +
79930f712c9SDave Chinner 			xfs_dir2_dataptr_to_off(args->geo,
80030f712c9SDave Chinner 						be32_to_cpu(blp[ent].address)));
80130f712c9SDave Chinner 	/*
80230f712c9SDave Chinner 	 * Mark the data entry's space free.
80330f712c9SDave Chinner 	 */
80430f712c9SDave Chinner 	needlog = needscan = 0;
80530f712c9SDave Chinner 	xfs_dir2_data_make_free(args, bp,
80630f712c9SDave Chinner 		(xfs_dir2_data_aoff_t)((char *)dep - (char *)hdr),
80730f712c9SDave Chinner 		dp->d_ops->data_entsize(dep->namelen), &needlog, &needscan);
80830f712c9SDave Chinner 	/*
80930f712c9SDave Chinner 	 * Fix up the block tail.
81030f712c9SDave Chinner 	 */
81130f712c9SDave Chinner 	be32_add_cpu(&btp->stale, 1);
81230f712c9SDave Chinner 	xfs_dir2_block_log_tail(tp, bp);
81330f712c9SDave Chinner 	/*
81430f712c9SDave Chinner 	 * Remove the leaf entry by marking it stale.
81530f712c9SDave Chinner 	 */
81630f712c9SDave Chinner 	blp[ent].address = cpu_to_be32(XFS_DIR2_NULL_DATAPTR);
81730f712c9SDave Chinner 	xfs_dir2_block_log_leaf(tp, bp, ent, ent);
81830f712c9SDave Chinner 	/*
81930f712c9SDave Chinner 	 * Fix up bestfree, log the header if necessary.
82030f712c9SDave Chinner 	 */
82130f712c9SDave Chinner 	if (needscan)
82230f712c9SDave Chinner 		xfs_dir2_data_freescan(dp, hdr, &needlog);
82330f712c9SDave Chinner 	if (needlog)
82430f712c9SDave Chinner 		xfs_dir2_data_log_header(args, bp);
82530f712c9SDave Chinner 	xfs_dir3_data_check(dp, bp);
82630f712c9SDave Chinner 	/*
82730f712c9SDave Chinner 	 * See if the size as a shortform is good enough.
82830f712c9SDave Chinner 	 */
82930f712c9SDave Chinner 	size = xfs_dir2_block_sfsize(dp, hdr, &sfh);
83030f712c9SDave Chinner 	if (size > XFS_IFORK_DSIZE(dp))
83130f712c9SDave Chinner 		return 0;
83230f712c9SDave Chinner 
83330f712c9SDave Chinner 	/*
83430f712c9SDave Chinner 	 * If it works, do the conversion.
83530f712c9SDave Chinner 	 */
83630f712c9SDave Chinner 	return xfs_dir2_block_to_sf(args, bp, size, &sfh);
83730f712c9SDave Chinner }
83830f712c9SDave Chinner 
83930f712c9SDave Chinner /*
84030f712c9SDave Chinner  * Replace an entry in a V2 block directory.
84130f712c9SDave Chinner  * Change the inode number to the new value.
84230f712c9SDave Chinner  */
84330f712c9SDave Chinner int						/* error */
84430f712c9SDave Chinner xfs_dir2_block_replace(
84530f712c9SDave Chinner 	xfs_da_args_t		*args)		/* directory operation args */
84630f712c9SDave Chinner {
84730f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr;		/* block header */
84830f712c9SDave Chinner 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
84930f712c9SDave Chinner 	struct xfs_buf		*bp;		/* block buffer */
85030f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;		/* block tail */
85130f712c9SDave Chinner 	xfs_dir2_data_entry_t	*dep;		/* block data entry */
85230f712c9SDave Chinner 	xfs_inode_t		*dp;		/* incore inode */
85330f712c9SDave Chinner 	int			ent;		/* leaf entry index */
85430f712c9SDave Chinner 	int			error;		/* error return value */
85530f712c9SDave Chinner 	xfs_mount_t		*mp;		/* filesystem mount point */
85630f712c9SDave Chinner 
85730f712c9SDave Chinner 	trace_xfs_dir2_block_replace(args);
85830f712c9SDave Chinner 
85930f712c9SDave Chinner 	/*
86030f712c9SDave Chinner 	 * Lookup the entry in the directory.  Get buffer and entry index.
86130f712c9SDave Chinner 	 * This will always succeed since the caller has already done a lookup.
86230f712c9SDave Chinner 	 */
86330f712c9SDave Chinner 	if ((error = xfs_dir2_block_lookup_int(args, &bp, &ent))) {
86430f712c9SDave Chinner 		return error;
86530f712c9SDave Chinner 	}
86630f712c9SDave Chinner 	dp = args->dp;
86730f712c9SDave Chinner 	mp = dp->i_mount;
86830f712c9SDave Chinner 	hdr = bp->b_addr;
86930f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(args->geo, hdr);
87030f712c9SDave Chinner 	blp = xfs_dir2_block_leaf_p(btp);
87130f712c9SDave Chinner 	/*
87230f712c9SDave Chinner 	 * Point to the data entry we need to change.
87330f712c9SDave Chinner 	 */
87430f712c9SDave Chinner 	dep = (xfs_dir2_data_entry_t *)((char *)hdr +
87530f712c9SDave Chinner 			xfs_dir2_dataptr_to_off(args->geo,
87630f712c9SDave Chinner 						be32_to_cpu(blp[ent].address)));
87730f712c9SDave Chinner 	ASSERT(be64_to_cpu(dep->inumber) != args->inumber);
87830f712c9SDave Chinner 	/*
87930f712c9SDave Chinner 	 * Change the inode number to the new value.
88030f712c9SDave Chinner 	 */
88130f712c9SDave Chinner 	dep->inumber = cpu_to_be64(args->inumber);
88230f712c9SDave Chinner 	dp->d_ops->data_put_ftype(dep, args->filetype);
88330f712c9SDave Chinner 	xfs_dir2_data_log_entry(args, bp, dep);
88430f712c9SDave Chinner 	xfs_dir3_data_check(dp, bp);
88530f712c9SDave Chinner 	return 0;
88630f712c9SDave Chinner }
88730f712c9SDave Chinner 
88830f712c9SDave Chinner /*
88930f712c9SDave Chinner  * Qsort comparison routine for the block leaf entries.
89030f712c9SDave Chinner  */
89130f712c9SDave Chinner static int					/* sort order */
89230f712c9SDave Chinner xfs_dir2_block_sort(
89330f712c9SDave Chinner 	const void			*a,	/* first leaf entry */
89430f712c9SDave Chinner 	const void			*b)	/* second leaf entry */
89530f712c9SDave Chinner {
89630f712c9SDave Chinner 	const xfs_dir2_leaf_entry_t	*la;	/* first leaf entry */
89730f712c9SDave Chinner 	const xfs_dir2_leaf_entry_t	*lb;	/* second leaf entry */
89830f712c9SDave Chinner 
89930f712c9SDave Chinner 	la = a;
90030f712c9SDave Chinner 	lb = b;
90130f712c9SDave Chinner 	return be32_to_cpu(la->hashval) < be32_to_cpu(lb->hashval) ? -1 :
90230f712c9SDave Chinner 		(be32_to_cpu(la->hashval) > be32_to_cpu(lb->hashval) ? 1 : 0);
90330f712c9SDave Chinner }
90430f712c9SDave Chinner 
90530f712c9SDave Chinner /*
90630f712c9SDave Chinner  * Convert a V2 leaf directory to a V2 block directory if possible.
90730f712c9SDave Chinner  */
90830f712c9SDave Chinner int						/* error */
90930f712c9SDave Chinner xfs_dir2_leaf_to_block(
91030f712c9SDave Chinner 	xfs_da_args_t		*args,		/* operation arguments */
91130f712c9SDave Chinner 	struct xfs_buf		*lbp,		/* leaf buffer */
91230f712c9SDave Chinner 	struct xfs_buf		*dbp)		/* data buffer */
91330f712c9SDave Chinner {
91430f712c9SDave Chinner 	__be16			*bestsp;	/* leaf bests table */
91530f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr;		/* block header */
91630f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;		/* block tail */
91730f712c9SDave Chinner 	xfs_inode_t		*dp;		/* incore directory inode */
91830f712c9SDave Chinner 	xfs_dir2_data_unused_t	*dup;		/* unused data entry */
91930f712c9SDave Chinner 	int			error;		/* error return value */
92030f712c9SDave Chinner 	int			from;		/* leaf from index */
92130f712c9SDave Chinner 	xfs_dir2_leaf_t		*leaf;		/* leaf structure */
92230f712c9SDave Chinner 	xfs_dir2_leaf_entry_t	*lep;		/* leaf entry */
92330f712c9SDave Chinner 	xfs_dir2_leaf_tail_t	*ltp;		/* leaf tail structure */
92430f712c9SDave Chinner 	xfs_mount_t		*mp;		/* file system mount point */
92530f712c9SDave Chinner 	int			needlog;	/* need to log data header */
92630f712c9SDave Chinner 	int			needscan;	/* need to scan for bestfree */
92730f712c9SDave Chinner 	xfs_dir2_sf_hdr_t	sfh;		/* shortform header */
92830f712c9SDave Chinner 	int			size;		/* bytes used */
92930f712c9SDave Chinner 	__be16			*tagp;		/* end of entry (tag) */
93030f712c9SDave Chinner 	int			to;		/* block/leaf to index */
93130f712c9SDave Chinner 	xfs_trans_t		*tp;		/* transaction pointer */
93230f712c9SDave Chinner 	struct xfs_dir2_leaf_entry *ents;
93330f712c9SDave Chinner 	struct xfs_dir3_icleaf_hdr leafhdr;
93430f712c9SDave Chinner 
93530f712c9SDave Chinner 	trace_xfs_dir2_leaf_to_block(args);
93630f712c9SDave Chinner 
93730f712c9SDave Chinner 	dp = args->dp;
93830f712c9SDave Chinner 	tp = args->trans;
93930f712c9SDave Chinner 	mp = dp->i_mount;
94030f712c9SDave Chinner 	leaf = lbp->b_addr;
94130f712c9SDave Chinner 	dp->d_ops->leaf_hdr_from_disk(&leafhdr, leaf);
94230f712c9SDave Chinner 	ents = dp->d_ops->leaf_ents_p(leaf);
94330f712c9SDave Chinner 	ltp = xfs_dir2_leaf_tail_p(args->geo, leaf);
94430f712c9SDave Chinner 
94530f712c9SDave Chinner 	ASSERT(leafhdr.magic == XFS_DIR2_LEAF1_MAGIC ||
94630f712c9SDave Chinner 	       leafhdr.magic == XFS_DIR3_LEAF1_MAGIC);
94730f712c9SDave Chinner 	/*
94830f712c9SDave Chinner 	 * If there are data blocks other than the first one, take this
94930f712c9SDave Chinner 	 * opportunity to remove trailing empty data blocks that may have
95030f712c9SDave Chinner 	 * been left behind during no-space-reservation operations.
95130f712c9SDave Chinner 	 * These will show up in the leaf bests table.
95230f712c9SDave Chinner 	 */
95330f712c9SDave Chinner 	while (dp->i_d.di_size > args->geo->blksize) {
95430f712c9SDave Chinner 		int hdrsz;
95530f712c9SDave Chinner 
95630f712c9SDave Chinner 		hdrsz = dp->d_ops->data_entry_offset;
95730f712c9SDave Chinner 		bestsp = xfs_dir2_leaf_bests_p(ltp);
95830f712c9SDave Chinner 		if (be16_to_cpu(bestsp[be32_to_cpu(ltp->bestcount) - 1]) ==
95930f712c9SDave Chinner 					    args->geo->blksize - hdrsz) {
96030f712c9SDave Chinner 			if ((error =
96130f712c9SDave Chinner 			    xfs_dir2_leaf_trim_data(args, lbp,
96230f712c9SDave Chinner 				    (xfs_dir2_db_t)(be32_to_cpu(ltp->bestcount) - 1))))
96330f712c9SDave Chinner 				return error;
96430f712c9SDave Chinner 		} else
96530f712c9SDave Chinner 			return 0;
96630f712c9SDave Chinner 	}
96730f712c9SDave Chinner 	/*
96830f712c9SDave Chinner 	 * Read the data block if we don't already have it, give up if it fails.
96930f712c9SDave Chinner 	 */
97030f712c9SDave Chinner 	if (!dbp) {
97130f712c9SDave Chinner 		error = xfs_dir3_data_read(tp, dp, args->geo->datablk, -1, &dbp);
97230f712c9SDave Chinner 		if (error)
97330f712c9SDave Chinner 			return error;
97430f712c9SDave Chinner 	}
97530f712c9SDave Chinner 	hdr = dbp->b_addr;
97630f712c9SDave Chinner 	ASSERT(hdr->magic == cpu_to_be32(XFS_DIR2_DATA_MAGIC) ||
97730f712c9SDave Chinner 	       hdr->magic == cpu_to_be32(XFS_DIR3_DATA_MAGIC));
97830f712c9SDave Chinner 
97930f712c9SDave Chinner 	/*
98030f712c9SDave Chinner 	 * Size of the "leaf" area in the block.
98130f712c9SDave Chinner 	 */
98230f712c9SDave Chinner 	size = (uint)sizeof(xfs_dir2_block_tail_t) +
98330f712c9SDave Chinner 	       (uint)sizeof(*lep) * (leafhdr.count - leafhdr.stale);
98430f712c9SDave Chinner 	/*
98530f712c9SDave Chinner 	 * Look at the last data entry.
98630f712c9SDave Chinner 	 */
98730f712c9SDave Chinner 	tagp = (__be16 *)((char *)hdr + args->geo->blksize) - 1;
98830f712c9SDave Chinner 	dup = (xfs_dir2_data_unused_t *)((char *)hdr + be16_to_cpu(*tagp));
98930f712c9SDave Chinner 	/*
99030f712c9SDave Chinner 	 * If it's not free or is too short we can't do it.
99130f712c9SDave Chinner 	 */
99230f712c9SDave Chinner 	if (be16_to_cpu(dup->freetag) != XFS_DIR2_DATA_FREE_TAG ||
99330f712c9SDave Chinner 	    be16_to_cpu(dup->length) < size)
99430f712c9SDave Chinner 		return 0;
99530f712c9SDave Chinner 
99630f712c9SDave Chinner 	/*
99730f712c9SDave Chinner 	 * Start converting it to block form.
99830f712c9SDave Chinner 	 */
99930f712c9SDave Chinner 	xfs_dir3_block_init(mp, tp, dbp, dp);
100030f712c9SDave Chinner 
100130f712c9SDave Chinner 	needlog = 1;
100230f712c9SDave Chinner 	needscan = 0;
100330f712c9SDave Chinner 	/*
100430f712c9SDave Chinner 	 * Use up the space at the end of the block (blp/btp).
100530f712c9SDave Chinner 	 */
100630f712c9SDave Chinner 	xfs_dir2_data_use_free(args, dbp, dup, args->geo->blksize - size, size,
100730f712c9SDave Chinner 		&needlog, &needscan);
100830f712c9SDave Chinner 	/*
100930f712c9SDave Chinner 	 * Initialize the block tail.
101030f712c9SDave Chinner 	 */
101130f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(args->geo, hdr);
101230f712c9SDave Chinner 	btp->count = cpu_to_be32(leafhdr.count - leafhdr.stale);
101330f712c9SDave Chinner 	btp->stale = 0;
101430f712c9SDave Chinner 	xfs_dir2_block_log_tail(tp, dbp);
101530f712c9SDave Chinner 	/*
101630f712c9SDave Chinner 	 * Initialize the block leaf area.  We compact out stale entries.
101730f712c9SDave Chinner 	 */
101830f712c9SDave Chinner 	lep = xfs_dir2_block_leaf_p(btp);
101930f712c9SDave Chinner 	for (from = to = 0; from < leafhdr.count; from++) {
102030f712c9SDave Chinner 		if (ents[from].address == cpu_to_be32(XFS_DIR2_NULL_DATAPTR))
102130f712c9SDave Chinner 			continue;
102230f712c9SDave Chinner 		lep[to++] = ents[from];
102330f712c9SDave Chinner 	}
102430f712c9SDave Chinner 	ASSERT(to == be32_to_cpu(btp->count));
102530f712c9SDave Chinner 	xfs_dir2_block_log_leaf(tp, dbp, 0, be32_to_cpu(btp->count) - 1);
102630f712c9SDave Chinner 	/*
102730f712c9SDave Chinner 	 * Scan the bestfree if we need it and log the data block header.
102830f712c9SDave Chinner 	 */
102930f712c9SDave Chinner 	if (needscan)
103030f712c9SDave Chinner 		xfs_dir2_data_freescan(dp, hdr, &needlog);
103130f712c9SDave Chinner 	if (needlog)
103230f712c9SDave Chinner 		xfs_dir2_data_log_header(args, dbp);
103330f712c9SDave Chinner 	/*
103430f712c9SDave Chinner 	 * Pitch the old leaf block.
103530f712c9SDave Chinner 	 */
103630f712c9SDave Chinner 	error = xfs_da_shrink_inode(args, args->geo->leafblk, lbp);
103730f712c9SDave Chinner 	if (error)
103830f712c9SDave Chinner 		return error;
103930f712c9SDave Chinner 
104030f712c9SDave Chinner 	/*
104130f712c9SDave Chinner 	 * Now see if the resulting block can be shrunken to shortform.
104230f712c9SDave Chinner 	 */
104330f712c9SDave Chinner 	size = xfs_dir2_block_sfsize(dp, hdr, &sfh);
104430f712c9SDave Chinner 	if (size > XFS_IFORK_DSIZE(dp))
104530f712c9SDave Chinner 		return 0;
104630f712c9SDave Chinner 
104730f712c9SDave Chinner 	return xfs_dir2_block_to_sf(args, dbp, size, &sfh);
104830f712c9SDave Chinner }
104930f712c9SDave Chinner 
105030f712c9SDave Chinner /*
105130f712c9SDave Chinner  * Convert the shortform directory to block form.
105230f712c9SDave Chinner  */
105330f712c9SDave Chinner int						/* error */
105430f712c9SDave Chinner xfs_dir2_sf_to_block(
105530f712c9SDave Chinner 	xfs_da_args_t		*args)		/* operation arguments */
105630f712c9SDave Chinner {
105730f712c9SDave Chinner 	xfs_dir2_db_t		blkno;		/* dir-relative block # (0) */
105830f712c9SDave Chinner 	xfs_dir2_data_hdr_t	*hdr;		/* block header */
105930f712c9SDave Chinner 	xfs_dir2_leaf_entry_t	*blp;		/* block leaf entries */
106030f712c9SDave Chinner 	struct xfs_buf		*bp;		/* block buffer */
106130f712c9SDave Chinner 	xfs_dir2_block_tail_t	*btp;		/* block tail pointer */
106230f712c9SDave Chinner 	xfs_dir2_data_entry_t	*dep;		/* data entry pointer */
106330f712c9SDave Chinner 	xfs_inode_t		*dp;		/* incore directory inode */
106430f712c9SDave Chinner 	int			dummy;		/* trash */
106530f712c9SDave Chinner 	xfs_dir2_data_unused_t	*dup;		/* unused entry pointer */
106630f712c9SDave Chinner 	int			endoffset;	/* end of data objects */
106730f712c9SDave Chinner 	int			error;		/* error return value */
106830f712c9SDave Chinner 	int			i;		/* index */
106930f712c9SDave Chinner 	xfs_mount_t		*mp;		/* filesystem mount point */
107030f712c9SDave Chinner 	int			needlog;	/* need to log block header */
107130f712c9SDave Chinner 	int			needscan;	/* need to scan block freespc */
107230f712c9SDave Chinner 	int			newoffset;	/* offset from current entry */
107330f712c9SDave Chinner 	int			offset;		/* target block offset */
107430f712c9SDave Chinner 	xfs_dir2_sf_entry_t	*sfep;		/* sf entry pointer */
107530f712c9SDave Chinner 	xfs_dir2_sf_hdr_t	*oldsfp;	/* old shortform header  */
107630f712c9SDave Chinner 	xfs_dir2_sf_hdr_t	*sfp;		/* shortform header  */
107730f712c9SDave Chinner 	__be16			*tagp;		/* end of data entry */
107830f712c9SDave Chinner 	xfs_trans_t		*tp;		/* transaction pointer */
107930f712c9SDave Chinner 	struct xfs_name		name;
108030f712c9SDave Chinner 	struct xfs_ifork	*ifp;
108130f712c9SDave Chinner 
108230f712c9SDave Chinner 	trace_xfs_dir2_sf_to_block(args);
108330f712c9SDave Chinner 
108430f712c9SDave Chinner 	dp = args->dp;
108530f712c9SDave Chinner 	tp = args->trans;
108630f712c9SDave Chinner 	mp = dp->i_mount;
108730f712c9SDave Chinner 	ifp = XFS_IFORK_PTR(dp, XFS_DATA_FORK);
108830f712c9SDave Chinner 	ASSERT(ifp->if_flags & XFS_IFINLINE);
108930f712c9SDave Chinner 	/*
109030f712c9SDave Chinner 	 * Bomb out if the shortform directory is way too short.
109130f712c9SDave Chinner 	 */
109230f712c9SDave Chinner 	if (dp->i_d.di_size < offsetof(xfs_dir2_sf_hdr_t, parent)) {
109330f712c9SDave Chinner 		ASSERT(XFS_FORCED_SHUTDOWN(mp));
109430f712c9SDave Chinner 		return EIO;
109530f712c9SDave Chinner 	}
109630f712c9SDave Chinner 
109730f712c9SDave Chinner 	oldsfp = (xfs_dir2_sf_hdr_t *)ifp->if_u1.if_data;
109830f712c9SDave Chinner 
109930f712c9SDave Chinner 	ASSERT(ifp->if_bytes == dp->i_d.di_size);
110030f712c9SDave Chinner 	ASSERT(ifp->if_u1.if_data != NULL);
110130f712c9SDave Chinner 	ASSERT(dp->i_d.di_size >= xfs_dir2_sf_hdr_size(oldsfp->i8count));
110230f712c9SDave Chinner 	ASSERT(dp->i_d.di_nextents == 0);
110330f712c9SDave Chinner 
110430f712c9SDave Chinner 	/*
110530f712c9SDave Chinner 	 * Copy the directory into a temporary buffer.
110630f712c9SDave Chinner 	 * Then pitch the incore inode data so we can make extents.
110730f712c9SDave Chinner 	 */
110830f712c9SDave Chinner 	sfp = kmem_alloc(ifp->if_bytes, KM_SLEEP);
110930f712c9SDave Chinner 	memcpy(sfp, oldsfp, ifp->if_bytes);
111030f712c9SDave Chinner 
111130f712c9SDave Chinner 	xfs_idata_realloc(dp, -ifp->if_bytes, XFS_DATA_FORK);
111230f712c9SDave Chinner 	xfs_bmap_local_to_extents_empty(dp, XFS_DATA_FORK);
111330f712c9SDave Chinner 	dp->i_d.di_size = 0;
111430f712c9SDave Chinner 
111530f712c9SDave Chinner 	/*
111630f712c9SDave Chinner 	 * Add block 0 to the inode.
111730f712c9SDave Chinner 	 */
111830f712c9SDave Chinner 	error = xfs_dir2_grow_inode(args, XFS_DIR2_DATA_SPACE, &blkno);
111930f712c9SDave Chinner 	if (error) {
112030f712c9SDave Chinner 		kmem_free(sfp);
112130f712c9SDave Chinner 		return error;
112230f712c9SDave Chinner 	}
112330f712c9SDave Chinner 	/*
112430f712c9SDave Chinner 	 * Initialize the data block, then convert it to block format.
112530f712c9SDave Chinner 	 */
112630f712c9SDave Chinner 	error = xfs_dir3_data_init(args, blkno, &bp);
112730f712c9SDave Chinner 	if (error) {
112830f712c9SDave Chinner 		kmem_free(sfp);
112930f712c9SDave Chinner 		return error;
113030f712c9SDave Chinner 	}
113130f712c9SDave Chinner 	xfs_dir3_block_init(mp, tp, bp, dp);
113230f712c9SDave Chinner 	hdr = bp->b_addr;
113330f712c9SDave Chinner 
113430f712c9SDave Chinner 	/*
113530f712c9SDave Chinner 	 * Compute size of block "tail" area.
113630f712c9SDave Chinner 	 */
113730f712c9SDave Chinner 	i = (uint)sizeof(*btp) +
113830f712c9SDave Chinner 	    (sfp->count + 2) * (uint)sizeof(xfs_dir2_leaf_entry_t);
113930f712c9SDave Chinner 	/*
114030f712c9SDave Chinner 	 * The whole thing is initialized to free by the init routine.
114130f712c9SDave Chinner 	 * Say we're using the leaf and tail area.
114230f712c9SDave Chinner 	 */
114330f712c9SDave Chinner 	dup = dp->d_ops->data_unused_p(hdr);
114430f712c9SDave Chinner 	needlog = needscan = 0;
114530f712c9SDave Chinner 	xfs_dir2_data_use_free(args, bp, dup, args->geo->blksize - i,
114630f712c9SDave Chinner 			       i, &needlog, &needscan);
114730f712c9SDave Chinner 	ASSERT(needscan == 0);
114830f712c9SDave Chinner 	/*
114930f712c9SDave Chinner 	 * Fill in the tail.
115030f712c9SDave Chinner 	 */
115130f712c9SDave Chinner 	btp = xfs_dir2_block_tail_p(args->geo, hdr);
115230f712c9SDave Chinner 	btp->count = cpu_to_be32(sfp->count + 2);	/* ., .. */
115330f712c9SDave Chinner 	btp->stale = 0;
115430f712c9SDave Chinner 	blp = xfs_dir2_block_leaf_p(btp);
115530f712c9SDave Chinner 	endoffset = (uint)((char *)blp - (char *)hdr);
115630f712c9SDave Chinner 	/*
115730f712c9SDave Chinner 	 * Remove the freespace, we'll manage it.
115830f712c9SDave Chinner 	 */
115930f712c9SDave Chinner 	xfs_dir2_data_use_free(args, bp, dup,
116030f712c9SDave Chinner 		(xfs_dir2_data_aoff_t)((char *)dup - (char *)hdr),
116130f712c9SDave Chinner 		be16_to_cpu(dup->length), &needlog, &needscan);
116230f712c9SDave Chinner 	/*
116330f712c9SDave Chinner 	 * Create entry for .
116430f712c9SDave Chinner 	 */
116530f712c9SDave Chinner 	dep = dp->d_ops->data_dot_entry_p(hdr);
116630f712c9SDave Chinner 	dep->inumber = cpu_to_be64(dp->i_ino);
116730f712c9SDave Chinner 	dep->namelen = 1;
116830f712c9SDave Chinner 	dep->name[0] = '.';
116930f712c9SDave Chinner 	dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
117030f712c9SDave Chinner 	tagp = dp->d_ops->data_entry_tag_p(dep);
117130f712c9SDave Chinner 	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
117230f712c9SDave Chinner 	xfs_dir2_data_log_entry(args, bp, dep);
117330f712c9SDave Chinner 	blp[0].hashval = cpu_to_be32(xfs_dir_hash_dot);
117430f712c9SDave Chinner 	blp[0].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
117530f712c9SDave Chinner 				(char *)dep - (char *)hdr));
117630f712c9SDave Chinner 	/*
117730f712c9SDave Chinner 	 * Create entry for ..
117830f712c9SDave Chinner 	 */
117930f712c9SDave Chinner 	dep = dp->d_ops->data_dotdot_entry_p(hdr);
118030f712c9SDave Chinner 	dep->inumber = cpu_to_be64(dp->d_ops->sf_get_parent_ino(sfp));
118130f712c9SDave Chinner 	dep->namelen = 2;
118230f712c9SDave Chinner 	dep->name[0] = dep->name[1] = '.';
118330f712c9SDave Chinner 	dp->d_ops->data_put_ftype(dep, XFS_DIR3_FT_DIR);
118430f712c9SDave Chinner 	tagp = dp->d_ops->data_entry_tag_p(dep);
118530f712c9SDave Chinner 	*tagp = cpu_to_be16((char *)dep - (char *)hdr);
118630f712c9SDave Chinner 	xfs_dir2_data_log_entry(args, bp, dep);
118730f712c9SDave Chinner 	blp[1].hashval = cpu_to_be32(xfs_dir_hash_dotdot);
118830f712c9SDave Chinner 	blp[1].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
118930f712c9SDave Chinner 				(char *)dep - (char *)hdr));
119030f712c9SDave Chinner 	offset = dp->d_ops->data_first_offset;
119130f712c9SDave Chinner 	/*
119230f712c9SDave Chinner 	 * Loop over existing entries, stuff them in.
119330f712c9SDave Chinner 	 */
119430f712c9SDave Chinner 	i = 0;
119530f712c9SDave Chinner 	if (!sfp->count)
119630f712c9SDave Chinner 		sfep = NULL;
119730f712c9SDave Chinner 	else
119830f712c9SDave Chinner 		sfep = xfs_dir2_sf_firstentry(sfp);
119930f712c9SDave Chinner 	/*
120030f712c9SDave Chinner 	 * Need to preserve the existing offset values in the sf directory.
120130f712c9SDave Chinner 	 * Insert holes (unused entries) where necessary.
120230f712c9SDave Chinner 	 */
120330f712c9SDave Chinner 	while (offset < endoffset) {
120430f712c9SDave Chinner 		/*
120530f712c9SDave Chinner 		 * sfep is null when we reach the end of the list.
120630f712c9SDave Chinner 		 */
120730f712c9SDave Chinner 		if (sfep == NULL)
120830f712c9SDave Chinner 			newoffset = endoffset;
120930f712c9SDave Chinner 		else
121030f712c9SDave Chinner 			newoffset = xfs_dir2_sf_get_offset(sfep);
121130f712c9SDave Chinner 		/*
121230f712c9SDave Chinner 		 * There should be a hole here, make one.
121330f712c9SDave Chinner 		 */
121430f712c9SDave Chinner 		if (offset < newoffset) {
121530f712c9SDave Chinner 			dup = (xfs_dir2_data_unused_t *)((char *)hdr + offset);
121630f712c9SDave Chinner 			dup->freetag = cpu_to_be16(XFS_DIR2_DATA_FREE_TAG);
121730f712c9SDave Chinner 			dup->length = cpu_to_be16(newoffset - offset);
121830f712c9SDave Chinner 			*xfs_dir2_data_unused_tag_p(dup) = cpu_to_be16(
121930f712c9SDave Chinner 				((char *)dup - (char *)hdr));
122030f712c9SDave Chinner 			xfs_dir2_data_log_unused(args, bp, dup);
122130f712c9SDave Chinner 			xfs_dir2_data_freeinsert(hdr,
122230f712c9SDave Chinner 						 dp->d_ops->data_bestfree_p(hdr),
122330f712c9SDave Chinner 						 dup, &dummy);
122430f712c9SDave Chinner 			offset += be16_to_cpu(dup->length);
122530f712c9SDave Chinner 			continue;
122630f712c9SDave Chinner 		}
122730f712c9SDave Chinner 		/*
122830f712c9SDave Chinner 		 * Copy a real entry.
122930f712c9SDave Chinner 		 */
123030f712c9SDave Chinner 		dep = (xfs_dir2_data_entry_t *)((char *)hdr + newoffset);
123130f712c9SDave Chinner 		dep->inumber = cpu_to_be64(dp->d_ops->sf_get_ino(sfp, sfep));
123230f712c9SDave Chinner 		dep->namelen = sfep->namelen;
123330f712c9SDave Chinner 		dp->d_ops->data_put_ftype(dep, dp->d_ops->sf_get_ftype(sfep));
123430f712c9SDave Chinner 		memcpy(dep->name, sfep->name, dep->namelen);
123530f712c9SDave Chinner 		tagp = dp->d_ops->data_entry_tag_p(dep);
123630f712c9SDave Chinner 		*tagp = cpu_to_be16((char *)dep - (char *)hdr);
123730f712c9SDave Chinner 		xfs_dir2_data_log_entry(args, bp, dep);
123830f712c9SDave Chinner 		name.name = sfep->name;
123930f712c9SDave Chinner 		name.len = sfep->namelen;
124030f712c9SDave Chinner 		blp[2 + i].hashval = cpu_to_be32(mp->m_dirnameops->
124130f712c9SDave Chinner 							hashname(&name));
124230f712c9SDave Chinner 		blp[2 + i].address = cpu_to_be32(xfs_dir2_byte_to_dataptr(
124330f712c9SDave Chinner 						 (char *)dep - (char *)hdr));
124430f712c9SDave Chinner 		offset = (int)((char *)(tagp + 1) - (char *)hdr);
124530f712c9SDave Chinner 		if (++i == sfp->count)
124630f712c9SDave Chinner 			sfep = NULL;
124730f712c9SDave Chinner 		else
124830f712c9SDave Chinner 			sfep = dp->d_ops->sf_nextentry(sfp, sfep);
124930f712c9SDave Chinner 	}
125030f712c9SDave Chinner 	/* Done with the temporary buffer */
125130f712c9SDave Chinner 	kmem_free(sfp);
125230f712c9SDave Chinner 	/*
125330f712c9SDave Chinner 	 * Sort the leaf entries by hash value.
125430f712c9SDave Chinner 	 */
125530f712c9SDave Chinner 	xfs_sort(blp, be32_to_cpu(btp->count), sizeof(*blp), xfs_dir2_block_sort);
125630f712c9SDave Chinner 	/*
125730f712c9SDave Chinner 	 * Log the leaf entry area and tail.
125830f712c9SDave Chinner 	 * Already logged the header in data_init, ignore needlog.
125930f712c9SDave Chinner 	 */
126030f712c9SDave Chinner 	ASSERT(needscan == 0);
126130f712c9SDave Chinner 	xfs_dir2_block_log_leaf(tp, bp, 0, be32_to_cpu(btp->count) - 1);
126230f712c9SDave Chinner 	xfs_dir2_block_log_tail(tp, bp);
126330f712c9SDave Chinner 	xfs_dir3_data_check(dp, bp);
126430f712c9SDave Chinner 	return 0;
126530f712c9SDave Chinner }
1266