162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * dir.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Creates, reads, walks and deletes directory-nodes
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
862306a36Sopenharmony_ci *
962306a36Sopenharmony_ci *  Portions of this code from linux/fs/ext3/dir.c
1062306a36Sopenharmony_ci *
1162306a36Sopenharmony_ci *  Copyright (C) 1992, 1993, 1994, 1995
1262306a36Sopenharmony_ci *  Remy Card (card@masi.ibp.fr)
1362306a36Sopenharmony_ci *  Laboratoire MASI - Institut Blaise pascal
1462306a36Sopenharmony_ci *  Universite Pierre et Marie Curie (Paris VI)
1562306a36Sopenharmony_ci *
1662306a36Sopenharmony_ci *   from
1762306a36Sopenharmony_ci *
1862306a36Sopenharmony_ci *   linux/fs/minix/dir.c
1962306a36Sopenharmony_ci *
2062306a36Sopenharmony_ci *   Copyright (C) 1991, 1992 Linus Torvalds
2162306a36Sopenharmony_ci */
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/fs.h>
2462306a36Sopenharmony_ci#include <linux/types.h>
2562306a36Sopenharmony_ci#include <linux/slab.h>
2662306a36Sopenharmony_ci#include <linux/highmem.h>
2762306a36Sopenharmony_ci#include <linux/quotaops.h>
2862306a36Sopenharmony_ci#include <linux/sort.h>
2962306a36Sopenharmony_ci#include <linux/iversion.h>
3062306a36Sopenharmony_ci
3162306a36Sopenharmony_ci#include <cluster/masklog.h>
3262306a36Sopenharmony_ci
3362306a36Sopenharmony_ci#include "ocfs2.h"
3462306a36Sopenharmony_ci
3562306a36Sopenharmony_ci#include "alloc.h"
3662306a36Sopenharmony_ci#include "blockcheck.h"
3762306a36Sopenharmony_ci#include "dir.h"
3862306a36Sopenharmony_ci#include "dlmglue.h"
3962306a36Sopenharmony_ci#include "extent_map.h"
4062306a36Sopenharmony_ci#include "file.h"
4162306a36Sopenharmony_ci#include "inode.h"
4262306a36Sopenharmony_ci#include "journal.h"
4362306a36Sopenharmony_ci#include "namei.h"
4462306a36Sopenharmony_ci#include "suballoc.h"
4562306a36Sopenharmony_ci#include "super.h"
4662306a36Sopenharmony_ci#include "sysfile.h"
4762306a36Sopenharmony_ci#include "uptodate.h"
4862306a36Sopenharmony_ci#include "ocfs2_trace.h"
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci#include "buffer_head_io.h"
5162306a36Sopenharmony_ci
5262306a36Sopenharmony_ci#define NAMEI_RA_CHUNKS  2
5362306a36Sopenharmony_ci#define NAMEI_RA_BLOCKS  4
5462306a36Sopenharmony_ci#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_cistatic int ocfs2_do_extend_dir(struct super_block *sb,
5762306a36Sopenharmony_ci			       handle_t *handle,
5862306a36Sopenharmony_ci			       struct inode *dir,
5962306a36Sopenharmony_ci			       struct buffer_head *parent_fe_bh,
6062306a36Sopenharmony_ci			       struct ocfs2_alloc_context *data_ac,
6162306a36Sopenharmony_ci			       struct ocfs2_alloc_context *meta_ac,
6262306a36Sopenharmony_ci			       struct buffer_head **new_bh);
6362306a36Sopenharmony_cistatic int ocfs2_dir_indexed(struct inode *inode);
6462306a36Sopenharmony_ci
6562306a36Sopenharmony_ci/*
6662306a36Sopenharmony_ci * These are distinct checks because future versions of the file system will
6762306a36Sopenharmony_ci * want to have a trailing dirent structure independent of indexing.
6862306a36Sopenharmony_ci */
6962306a36Sopenharmony_cistatic int ocfs2_supports_dir_trailer(struct inode *dir)
7062306a36Sopenharmony_ci{
7162306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
7462306a36Sopenharmony_ci		return 0;
7562306a36Sopenharmony_ci
7662306a36Sopenharmony_ci	return ocfs2_meta_ecc(osb) || ocfs2_dir_indexed(dir);
7762306a36Sopenharmony_ci}
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci/*
8062306a36Sopenharmony_ci * "new' here refers to the point at which we're creating a new
8162306a36Sopenharmony_ci * directory via "mkdir()", but also when we're expanding an inline
8262306a36Sopenharmony_ci * directory. In either case, we don't yet have the indexing bit set
8362306a36Sopenharmony_ci * on the directory, so the standard checks will fail in when metaecc
8462306a36Sopenharmony_ci * is turned off. Only directory-initialization type functions should
8562306a36Sopenharmony_ci * use this then. Everything else wants ocfs2_supports_dir_trailer()
8662306a36Sopenharmony_ci */
8762306a36Sopenharmony_cistatic int ocfs2_new_dir_wants_trailer(struct inode *dir)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	return ocfs2_meta_ecc(osb) ||
9262306a36Sopenharmony_ci		ocfs2_supports_indexed_dirs(osb);
9362306a36Sopenharmony_ci}
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_cistatic inline unsigned int ocfs2_dir_trailer_blk_off(struct super_block *sb)
9662306a36Sopenharmony_ci{
9762306a36Sopenharmony_ci	return sb->s_blocksize - sizeof(struct ocfs2_dir_block_trailer);
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci#define ocfs2_trailer_from_bh(_bh, _sb) ((struct ocfs2_dir_block_trailer *) ((_bh)->b_data + ocfs2_dir_trailer_blk_off((_sb))))
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci/* XXX ocfs2_block_dqtrailer() is similar but not quite - can we make
10362306a36Sopenharmony_ci * them more consistent? */
10462306a36Sopenharmony_cistruct ocfs2_dir_block_trailer *ocfs2_dir_trailer_from_size(int blocksize,
10562306a36Sopenharmony_ci							    void *data)
10662306a36Sopenharmony_ci{
10762306a36Sopenharmony_ci	char *p = data;
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci	p += blocksize - sizeof(struct ocfs2_dir_block_trailer);
11062306a36Sopenharmony_ci	return (struct ocfs2_dir_block_trailer *)p;
11162306a36Sopenharmony_ci}
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci/*
11462306a36Sopenharmony_ci * XXX: This is executed once on every dirent. We should consider optimizing
11562306a36Sopenharmony_ci * it.
11662306a36Sopenharmony_ci */
11762306a36Sopenharmony_cistatic int ocfs2_skip_dir_trailer(struct inode *dir,
11862306a36Sopenharmony_ci				  struct ocfs2_dir_entry *de,
11962306a36Sopenharmony_ci				  unsigned long offset,
12062306a36Sopenharmony_ci				  unsigned long blklen)
12162306a36Sopenharmony_ci{
12262306a36Sopenharmony_ci	unsigned long toff = blklen - sizeof(struct ocfs2_dir_block_trailer);
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci	if (!ocfs2_supports_dir_trailer(dir))
12562306a36Sopenharmony_ci		return 0;
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	if (offset != toff)
12862306a36Sopenharmony_ci		return 0;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci	return 1;
13162306a36Sopenharmony_ci}
13262306a36Sopenharmony_ci
13362306a36Sopenharmony_cistatic void ocfs2_init_dir_trailer(struct inode *inode,
13462306a36Sopenharmony_ci				   struct buffer_head *bh, u16 rec_len)
13562306a36Sopenharmony_ci{
13662306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(bh, inode->i_sb);
13962306a36Sopenharmony_ci	strcpy(trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE);
14062306a36Sopenharmony_ci	trailer->db_compat_rec_len =
14162306a36Sopenharmony_ci			cpu_to_le16(sizeof(struct ocfs2_dir_block_trailer));
14262306a36Sopenharmony_ci	trailer->db_parent_dinode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
14362306a36Sopenharmony_ci	trailer->db_blkno = cpu_to_le64(bh->b_blocknr);
14462306a36Sopenharmony_ci	trailer->db_free_rec_len = cpu_to_le16(rec_len);
14562306a36Sopenharmony_ci}
14662306a36Sopenharmony_ci/*
14762306a36Sopenharmony_ci * Link an unindexed block with a dir trailer structure into the index free
14862306a36Sopenharmony_ci * list. This function will modify dirdata_bh, but assumes you've already
14962306a36Sopenharmony_ci * passed it to the journal.
15062306a36Sopenharmony_ci */
15162306a36Sopenharmony_cistatic int ocfs2_dx_dir_link_trailer(struct inode *dir, handle_t *handle,
15262306a36Sopenharmony_ci				     struct buffer_head *dx_root_bh,
15362306a36Sopenharmony_ci				     struct buffer_head *dirdata_bh)
15462306a36Sopenharmony_ci{
15562306a36Sopenharmony_ci	int ret;
15662306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
15762306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
16062306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
16162306a36Sopenharmony_ci	if (ret) {
16262306a36Sopenharmony_ci		mlog_errno(ret);
16362306a36Sopenharmony_ci		goto out;
16462306a36Sopenharmony_ci	}
16562306a36Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(dirdata_bh, dir->i_sb);
16662306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
16762306a36Sopenharmony_ci
16862306a36Sopenharmony_ci	trailer->db_free_next = dx_root->dr_free_blk;
16962306a36Sopenharmony_ci	dx_root->dr_free_blk = cpu_to_le64(dirdata_bh->b_blocknr);
17062306a36Sopenharmony_ci
17162306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ciout:
17462306a36Sopenharmony_ci	return ret;
17562306a36Sopenharmony_ci}
17662306a36Sopenharmony_ci
17762306a36Sopenharmony_cistatic int ocfs2_free_list_at_root(struct ocfs2_dir_lookup_result *res)
17862306a36Sopenharmony_ci{
17962306a36Sopenharmony_ci	return res->dl_prev_leaf_bh == NULL;
18062306a36Sopenharmony_ci}
18162306a36Sopenharmony_ci
18262306a36Sopenharmony_civoid ocfs2_free_dir_lookup_result(struct ocfs2_dir_lookup_result *res)
18362306a36Sopenharmony_ci{
18462306a36Sopenharmony_ci	brelse(res->dl_dx_root_bh);
18562306a36Sopenharmony_ci	brelse(res->dl_leaf_bh);
18662306a36Sopenharmony_ci	brelse(res->dl_dx_leaf_bh);
18762306a36Sopenharmony_ci	brelse(res->dl_prev_leaf_bh);
18862306a36Sopenharmony_ci}
18962306a36Sopenharmony_ci
19062306a36Sopenharmony_cistatic int ocfs2_dir_indexed(struct inode *inode)
19162306a36Sopenharmony_ci{
19262306a36Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INDEXED_DIR_FL)
19362306a36Sopenharmony_ci		return 1;
19462306a36Sopenharmony_ci	return 0;
19562306a36Sopenharmony_ci}
19662306a36Sopenharmony_ci
19762306a36Sopenharmony_cistatic inline int ocfs2_dx_root_inline(struct ocfs2_dx_root_block *dx_root)
19862306a36Sopenharmony_ci{
19962306a36Sopenharmony_ci	return dx_root->dr_flags & OCFS2_DX_FLAG_INLINE;
20062306a36Sopenharmony_ci}
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci/*
20362306a36Sopenharmony_ci * Hashing code adapted from ext3
20462306a36Sopenharmony_ci */
20562306a36Sopenharmony_ci#define DELTA 0x9E3779B9
20662306a36Sopenharmony_ci
20762306a36Sopenharmony_cistatic void TEA_transform(__u32 buf[4], __u32 const in[])
20862306a36Sopenharmony_ci{
20962306a36Sopenharmony_ci	__u32	sum = 0;
21062306a36Sopenharmony_ci	__u32	b0 = buf[0], b1 = buf[1];
21162306a36Sopenharmony_ci	__u32	a = in[0], b = in[1], c = in[2], d = in[3];
21262306a36Sopenharmony_ci	int	n = 16;
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci	do {
21562306a36Sopenharmony_ci		sum += DELTA;
21662306a36Sopenharmony_ci		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
21762306a36Sopenharmony_ci		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
21862306a36Sopenharmony_ci	} while (--n);
21962306a36Sopenharmony_ci
22062306a36Sopenharmony_ci	buf[0] += b0;
22162306a36Sopenharmony_ci	buf[1] += b1;
22262306a36Sopenharmony_ci}
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
22562306a36Sopenharmony_ci{
22662306a36Sopenharmony_ci	__u32	pad, val;
22762306a36Sopenharmony_ci	int	i;
22862306a36Sopenharmony_ci
22962306a36Sopenharmony_ci	pad = (__u32)len | ((__u32)len << 8);
23062306a36Sopenharmony_ci	pad |= pad << 16;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	val = pad;
23362306a36Sopenharmony_ci	if (len > num*4)
23462306a36Sopenharmony_ci		len = num * 4;
23562306a36Sopenharmony_ci	for (i = 0; i < len; i++) {
23662306a36Sopenharmony_ci		if ((i % 4) == 0)
23762306a36Sopenharmony_ci			val = pad;
23862306a36Sopenharmony_ci		val = msg[i] + (val << 8);
23962306a36Sopenharmony_ci		if ((i % 4) == 3) {
24062306a36Sopenharmony_ci			*buf++ = val;
24162306a36Sopenharmony_ci			val = pad;
24262306a36Sopenharmony_ci			num--;
24362306a36Sopenharmony_ci		}
24462306a36Sopenharmony_ci	}
24562306a36Sopenharmony_ci	if (--num >= 0)
24662306a36Sopenharmony_ci		*buf++ = val;
24762306a36Sopenharmony_ci	while (--num >= 0)
24862306a36Sopenharmony_ci		*buf++ = pad;
24962306a36Sopenharmony_ci}
25062306a36Sopenharmony_ci
25162306a36Sopenharmony_cistatic void ocfs2_dx_dir_name_hash(struct inode *dir, const char *name, int len,
25262306a36Sopenharmony_ci				   struct ocfs2_dx_hinfo *hinfo)
25362306a36Sopenharmony_ci{
25462306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
25562306a36Sopenharmony_ci	const char	*p;
25662306a36Sopenharmony_ci	__u32		in[8], buf[4];
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_ci	/*
25962306a36Sopenharmony_ci	 * XXX: Is this really necessary, if the index is never looked
26062306a36Sopenharmony_ci	 * at by readdir? Is a hash value of '0' a bad idea?
26162306a36Sopenharmony_ci	 */
26262306a36Sopenharmony_ci	if ((len == 1 && !strncmp(".", name, 1)) ||
26362306a36Sopenharmony_ci	    (len == 2 && !strncmp("..", name, 2))) {
26462306a36Sopenharmony_ci		buf[0] = buf[1] = 0;
26562306a36Sopenharmony_ci		goto out;
26662306a36Sopenharmony_ci	}
26762306a36Sopenharmony_ci
26862306a36Sopenharmony_ci#ifdef OCFS2_DEBUG_DX_DIRS
26962306a36Sopenharmony_ci	/*
27062306a36Sopenharmony_ci	 * This makes it very easy to debug indexing problems. We
27162306a36Sopenharmony_ci	 * should never allow this to be selected without hand editing
27262306a36Sopenharmony_ci	 * this file though.
27362306a36Sopenharmony_ci	 */
27462306a36Sopenharmony_ci	buf[0] = buf[1] = len;
27562306a36Sopenharmony_ci	goto out;
27662306a36Sopenharmony_ci#endif
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	memcpy(buf, osb->osb_dx_seed, sizeof(buf));
27962306a36Sopenharmony_ci
28062306a36Sopenharmony_ci	p = name;
28162306a36Sopenharmony_ci	while (len > 0) {
28262306a36Sopenharmony_ci		str2hashbuf(p, len, in, 4);
28362306a36Sopenharmony_ci		TEA_transform(buf, in);
28462306a36Sopenharmony_ci		len -= 16;
28562306a36Sopenharmony_ci		p += 16;
28662306a36Sopenharmony_ci	}
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ciout:
28962306a36Sopenharmony_ci	hinfo->major_hash = buf[0];
29062306a36Sopenharmony_ci	hinfo->minor_hash = buf[1];
29162306a36Sopenharmony_ci}
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci/*
29462306a36Sopenharmony_ci * bh passed here can be an inode block or a dir data block, depending
29562306a36Sopenharmony_ci * on the inode inline data flag.
29662306a36Sopenharmony_ci */
29762306a36Sopenharmony_cistatic int ocfs2_check_dir_entry(struct inode * dir,
29862306a36Sopenharmony_ci				 struct ocfs2_dir_entry * de,
29962306a36Sopenharmony_ci				 struct buffer_head * bh,
30062306a36Sopenharmony_ci				 unsigned long offset)
30162306a36Sopenharmony_ci{
30262306a36Sopenharmony_ci	const char *error_msg = NULL;
30362306a36Sopenharmony_ci	const int rlen = le16_to_cpu(de->rec_len);
30462306a36Sopenharmony_ci
30562306a36Sopenharmony_ci	if (unlikely(rlen < OCFS2_DIR_REC_LEN(1)))
30662306a36Sopenharmony_ci		error_msg = "rec_len is smaller than minimal";
30762306a36Sopenharmony_ci	else if (unlikely(rlen % 4 != 0))
30862306a36Sopenharmony_ci		error_msg = "rec_len % 4 != 0";
30962306a36Sopenharmony_ci	else if (unlikely(rlen < OCFS2_DIR_REC_LEN(de->name_len)))
31062306a36Sopenharmony_ci		error_msg = "rec_len is too small for name_len";
31162306a36Sopenharmony_ci	else if (unlikely(
31262306a36Sopenharmony_ci		 ((char *) de - bh->b_data) + rlen > dir->i_sb->s_blocksize))
31362306a36Sopenharmony_ci		error_msg = "directory entry across blocks";
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci	if (unlikely(error_msg != NULL))
31662306a36Sopenharmony_ci		mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
31762306a36Sopenharmony_ci		     "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n",
31862306a36Sopenharmony_ci		     (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg,
31962306a36Sopenharmony_ci		     offset, (unsigned long long)le64_to_cpu(de->inode), rlen,
32062306a36Sopenharmony_ci		     de->name_len);
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	return error_msg == NULL ? 1 : 0;
32362306a36Sopenharmony_ci}
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_cistatic inline int ocfs2_match(int len,
32662306a36Sopenharmony_ci			      const char * const name,
32762306a36Sopenharmony_ci			      struct ocfs2_dir_entry *de)
32862306a36Sopenharmony_ci{
32962306a36Sopenharmony_ci	if (len != de->name_len)
33062306a36Sopenharmony_ci		return 0;
33162306a36Sopenharmony_ci	if (!de->inode)
33262306a36Sopenharmony_ci		return 0;
33362306a36Sopenharmony_ci	return !memcmp(name, de->name, len);
33462306a36Sopenharmony_ci}
33562306a36Sopenharmony_ci
33662306a36Sopenharmony_ci/*
33762306a36Sopenharmony_ci * Returns 0 if not found, -1 on failure, and 1 on success
33862306a36Sopenharmony_ci */
33962306a36Sopenharmony_cistatic inline int ocfs2_search_dirblock(struct buffer_head *bh,
34062306a36Sopenharmony_ci					struct inode *dir,
34162306a36Sopenharmony_ci					const char *name, int namelen,
34262306a36Sopenharmony_ci					unsigned long offset,
34362306a36Sopenharmony_ci					char *first_de,
34462306a36Sopenharmony_ci					unsigned int bytes,
34562306a36Sopenharmony_ci					struct ocfs2_dir_entry **res_dir)
34662306a36Sopenharmony_ci{
34762306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
34862306a36Sopenharmony_ci	char *dlimit, *de_buf;
34962306a36Sopenharmony_ci	int de_len;
35062306a36Sopenharmony_ci	int ret = 0;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	de_buf = first_de;
35362306a36Sopenharmony_ci	dlimit = de_buf + bytes;
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_ci	while (de_buf < dlimit) {
35662306a36Sopenharmony_ci		/* this code is executed quadratically often */
35762306a36Sopenharmony_ci		/* do minimal checking `by hand' */
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *) de_buf;
36062306a36Sopenharmony_ci
36162306a36Sopenharmony_ci		if (de_buf + namelen <= dlimit &&
36262306a36Sopenharmony_ci		    ocfs2_match(namelen, name, de)) {
36362306a36Sopenharmony_ci			/* found a match - just to be sure, do a full check */
36462306a36Sopenharmony_ci			if (!ocfs2_check_dir_entry(dir, de, bh, offset)) {
36562306a36Sopenharmony_ci				ret = -1;
36662306a36Sopenharmony_ci				goto bail;
36762306a36Sopenharmony_ci			}
36862306a36Sopenharmony_ci			*res_dir = de;
36962306a36Sopenharmony_ci			ret = 1;
37062306a36Sopenharmony_ci			goto bail;
37162306a36Sopenharmony_ci		}
37262306a36Sopenharmony_ci
37362306a36Sopenharmony_ci		/* prevent looping on a bad block */
37462306a36Sopenharmony_ci		de_len = le16_to_cpu(de->rec_len);
37562306a36Sopenharmony_ci		if (de_len <= 0) {
37662306a36Sopenharmony_ci			ret = -1;
37762306a36Sopenharmony_ci			goto bail;
37862306a36Sopenharmony_ci		}
37962306a36Sopenharmony_ci
38062306a36Sopenharmony_ci		de_buf += de_len;
38162306a36Sopenharmony_ci		offset += de_len;
38262306a36Sopenharmony_ci	}
38362306a36Sopenharmony_ci
38462306a36Sopenharmony_cibail:
38562306a36Sopenharmony_ci	trace_ocfs2_search_dirblock(ret);
38662306a36Sopenharmony_ci	return ret;
38762306a36Sopenharmony_ci}
38862306a36Sopenharmony_ci
38962306a36Sopenharmony_cistatic struct buffer_head *ocfs2_find_entry_id(const char *name,
39062306a36Sopenharmony_ci					       int namelen,
39162306a36Sopenharmony_ci					       struct inode *dir,
39262306a36Sopenharmony_ci					       struct ocfs2_dir_entry **res_dir)
39362306a36Sopenharmony_ci{
39462306a36Sopenharmony_ci	int ret, found;
39562306a36Sopenharmony_ci	struct buffer_head *di_bh = NULL;
39662306a36Sopenharmony_ci	struct ocfs2_dinode *di;
39762306a36Sopenharmony_ci	struct ocfs2_inline_data *data;
39862306a36Sopenharmony_ci
39962306a36Sopenharmony_ci	ret = ocfs2_read_inode_block(dir, &di_bh);
40062306a36Sopenharmony_ci	if (ret) {
40162306a36Sopenharmony_ci		mlog_errno(ret);
40262306a36Sopenharmony_ci		goto out;
40362306a36Sopenharmony_ci	}
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
40662306a36Sopenharmony_ci	data = &di->id2.i_data;
40762306a36Sopenharmony_ci
40862306a36Sopenharmony_ci	found = ocfs2_search_dirblock(di_bh, dir, name, namelen, 0,
40962306a36Sopenharmony_ci				      data->id_data, i_size_read(dir), res_dir);
41062306a36Sopenharmony_ci	if (found == 1)
41162306a36Sopenharmony_ci		return di_bh;
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	brelse(di_bh);
41462306a36Sopenharmony_ciout:
41562306a36Sopenharmony_ci	return NULL;
41662306a36Sopenharmony_ci}
41762306a36Sopenharmony_ci
41862306a36Sopenharmony_cistatic int ocfs2_validate_dir_block(struct super_block *sb,
41962306a36Sopenharmony_ci				    struct buffer_head *bh)
42062306a36Sopenharmony_ci{
42162306a36Sopenharmony_ci	int rc;
42262306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer =
42362306a36Sopenharmony_ci		ocfs2_trailer_from_bh(bh, sb);
42462306a36Sopenharmony_ci
42562306a36Sopenharmony_ci
42662306a36Sopenharmony_ci	/*
42762306a36Sopenharmony_ci	 * We don't validate dirents here, that's handled
42862306a36Sopenharmony_ci	 * in-place when the code walks them.
42962306a36Sopenharmony_ci	 */
43062306a36Sopenharmony_ci	trace_ocfs2_validate_dir_block((unsigned long long)bh->b_blocknr);
43162306a36Sopenharmony_ci
43262306a36Sopenharmony_ci	BUG_ON(!buffer_uptodate(bh));
43362306a36Sopenharmony_ci
43462306a36Sopenharmony_ci	/*
43562306a36Sopenharmony_ci	 * If the ecc fails, we return the error but otherwise
43662306a36Sopenharmony_ci	 * leave the filesystem running.  We know any error is
43762306a36Sopenharmony_ci	 * local to this block.
43862306a36Sopenharmony_ci	 *
43962306a36Sopenharmony_ci	 * Note that we are safe to call this even if the directory
44062306a36Sopenharmony_ci	 * doesn't have a trailer.  Filesystems without metaecc will do
44162306a36Sopenharmony_ci	 * nothing, and filesystems with it will have one.
44262306a36Sopenharmony_ci	 */
44362306a36Sopenharmony_ci	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &trailer->db_check);
44462306a36Sopenharmony_ci	if (rc)
44562306a36Sopenharmony_ci		mlog(ML_ERROR, "Checksum failed for dinode %llu\n",
44662306a36Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	return rc;
44962306a36Sopenharmony_ci}
45062306a36Sopenharmony_ci
45162306a36Sopenharmony_ci/*
45262306a36Sopenharmony_ci * Validate a directory trailer.
45362306a36Sopenharmony_ci *
45462306a36Sopenharmony_ci * We check the trailer here rather than in ocfs2_validate_dir_block()
45562306a36Sopenharmony_ci * because that function doesn't have the inode to test.
45662306a36Sopenharmony_ci */
45762306a36Sopenharmony_cistatic int ocfs2_check_dir_trailer(struct inode *dir, struct buffer_head *bh)
45862306a36Sopenharmony_ci{
45962306a36Sopenharmony_ci	int rc = 0;
46062306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(bh, dir->i_sb);
46362306a36Sopenharmony_ci	if (!OCFS2_IS_VALID_DIR_TRAILER(trailer)) {
46462306a36Sopenharmony_ci		rc = ocfs2_error(dir->i_sb,
46562306a36Sopenharmony_ci				 "Invalid dirblock #%llu: signature = %.*s\n",
46662306a36Sopenharmony_ci				 (unsigned long long)bh->b_blocknr, 7,
46762306a36Sopenharmony_ci				 trailer->db_signature);
46862306a36Sopenharmony_ci		goto out;
46962306a36Sopenharmony_ci	}
47062306a36Sopenharmony_ci	if (le64_to_cpu(trailer->db_blkno) != bh->b_blocknr) {
47162306a36Sopenharmony_ci		rc = ocfs2_error(dir->i_sb,
47262306a36Sopenharmony_ci				 "Directory block #%llu has an invalid db_blkno of %llu\n",
47362306a36Sopenharmony_ci				 (unsigned long long)bh->b_blocknr,
47462306a36Sopenharmony_ci				 (unsigned long long)le64_to_cpu(trailer->db_blkno));
47562306a36Sopenharmony_ci		goto out;
47662306a36Sopenharmony_ci	}
47762306a36Sopenharmony_ci	if (le64_to_cpu(trailer->db_parent_dinode) !=
47862306a36Sopenharmony_ci	    OCFS2_I(dir)->ip_blkno) {
47962306a36Sopenharmony_ci		rc = ocfs2_error(dir->i_sb,
48062306a36Sopenharmony_ci				 "Directory block #%llu on dinode #%llu has an invalid parent_dinode of %llu\n",
48162306a36Sopenharmony_ci				 (unsigned long long)bh->b_blocknr,
48262306a36Sopenharmony_ci				 (unsigned long long)OCFS2_I(dir)->ip_blkno,
48362306a36Sopenharmony_ci				 (unsigned long long)le64_to_cpu(trailer->db_blkno));
48462306a36Sopenharmony_ci		goto out;
48562306a36Sopenharmony_ci	}
48662306a36Sopenharmony_ciout:
48762306a36Sopenharmony_ci	return rc;
48862306a36Sopenharmony_ci}
48962306a36Sopenharmony_ci
49062306a36Sopenharmony_ci/*
49162306a36Sopenharmony_ci * This function forces all errors to -EIO for consistency with its
49262306a36Sopenharmony_ci * predecessor, ocfs2_bread().  We haven't audited what returning the
49362306a36Sopenharmony_ci * real error codes would do to callers.  We log the real codes with
49462306a36Sopenharmony_ci * mlog_errno() before we squash them.
49562306a36Sopenharmony_ci */
49662306a36Sopenharmony_cistatic int ocfs2_read_dir_block(struct inode *inode, u64 v_block,
49762306a36Sopenharmony_ci				struct buffer_head **bh, int flags)
49862306a36Sopenharmony_ci{
49962306a36Sopenharmony_ci	int rc = 0;
50062306a36Sopenharmony_ci	struct buffer_head *tmp = *bh;
50162306a36Sopenharmony_ci
50262306a36Sopenharmony_ci	rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, flags,
50362306a36Sopenharmony_ci				    ocfs2_validate_dir_block);
50462306a36Sopenharmony_ci	if (rc) {
50562306a36Sopenharmony_ci		mlog_errno(rc);
50662306a36Sopenharmony_ci		goto out;
50762306a36Sopenharmony_ci	}
50862306a36Sopenharmony_ci
50962306a36Sopenharmony_ci	if (!(flags & OCFS2_BH_READAHEAD) &&
51062306a36Sopenharmony_ci	    ocfs2_supports_dir_trailer(inode)) {
51162306a36Sopenharmony_ci		rc = ocfs2_check_dir_trailer(inode, tmp);
51262306a36Sopenharmony_ci		if (rc) {
51362306a36Sopenharmony_ci			if (!*bh)
51462306a36Sopenharmony_ci				brelse(tmp);
51562306a36Sopenharmony_ci			mlog_errno(rc);
51662306a36Sopenharmony_ci			goto out;
51762306a36Sopenharmony_ci		}
51862306a36Sopenharmony_ci	}
51962306a36Sopenharmony_ci
52062306a36Sopenharmony_ci	/* If ocfs2_read_virt_blocks() got us a new bh, pass it up. */
52162306a36Sopenharmony_ci	if (!*bh)
52262306a36Sopenharmony_ci		*bh = tmp;
52362306a36Sopenharmony_ci
52462306a36Sopenharmony_ciout:
52562306a36Sopenharmony_ci	return rc ? -EIO : 0;
52662306a36Sopenharmony_ci}
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ci/*
52962306a36Sopenharmony_ci * Read the block at 'phys' which belongs to this directory
53062306a36Sopenharmony_ci * inode. This function does no virtual->physical block translation -
53162306a36Sopenharmony_ci * what's passed in is assumed to be a valid directory block.
53262306a36Sopenharmony_ci */
53362306a36Sopenharmony_cistatic int ocfs2_read_dir_block_direct(struct inode *dir, u64 phys,
53462306a36Sopenharmony_ci				       struct buffer_head **bh)
53562306a36Sopenharmony_ci{
53662306a36Sopenharmony_ci	int ret;
53762306a36Sopenharmony_ci	struct buffer_head *tmp = *bh;
53862306a36Sopenharmony_ci
53962306a36Sopenharmony_ci	ret = ocfs2_read_block(INODE_CACHE(dir), phys, &tmp,
54062306a36Sopenharmony_ci			       ocfs2_validate_dir_block);
54162306a36Sopenharmony_ci	if (ret) {
54262306a36Sopenharmony_ci		mlog_errno(ret);
54362306a36Sopenharmony_ci		goto out;
54462306a36Sopenharmony_ci	}
54562306a36Sopenharmony_ci
54662306a36Sopenharmony_ci	if (ocfs2_supports_dir_trailer(dir)) {
54762306a36Sopenharmony_ci		ret = ocfs2_check_dir_trailer(dir, tmp);
54862306a36Sopenharmony_ci		if (ret) {
54962306a36Sopenharmony_ci			if (!*bh)
55062306a36Sopenharmony_ci				brelse(tmp);
55162306a36Sopenharmony_ci			mlog_errno(ret);
55262306a36Sopenharmony_ci			goto out;
55362306a36Sopenharmony_ci		}
55462306a36Sopenharmony_ci	}
55562306a36Sopenharmony_ci
55662306a36Sopenharmony_ci	if (!ret && !*bh)
55762306a36Sopenharmony_ci		*bh = tmp;
55862306a36Sopenharmony_ciout:
55962306a36Sopenharmony_ci	return ret;
56062306a36Sopenharmony_ci}
56162306a36Sopenharmony_ci
56262306a36Sopenharmony_cistatic int ocfs2_validate_dx_root(struct super_block *sb,
56362306a36Sopenharmony_ci				  struct buffer_head *bh)
56462306a36Sopenharmony_ci{
56562306a36Sopenharmony_ci	int ret;
56662306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
56762306a36Sopenharmony_ci
56862306a36Sopenharmony_ci	BUG_ON(!buffer_uptodate(bh));
56962306a36Sopenharmony_ci
57062306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) bh->b_data;
57162306a36Sopenharmony_ci
57262306a36Sopenharmony_ci	ret = ocfs2_validate_meta_ecc(sb, bh->b_data, &dx_root->dr_check);
57362306a36Sopenharmony_ci	if (ret) {
57462306a36Sopenharmony_ci		mlog(ML_ERROR,
57562306a36Sopenharmony_ci		     "Checksum failed for dir index root block %llu\n",
57662306a36Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
57762306a36Sopenharmony_ci		return ret;
57862306a36Sopenharmony_ci	}
57962306a36Sopenharmony_ci
58062306a36Sopenharmony_ci	if (!OCFS2_IS_VALID_DX_ROOT(dx_root)) {
58162306a36Sopenharmony_ci		ret = ocfs2_error(sb,
58262306a36Sopenharmony_ci				  "Dir Index Root # %llu has bad signature %.*s\n",
58362306a36Sopenharmony_ci				  (unsigned long long)le64_to_cpu(dx_root->dr_blkno),
58462306a36Sopenharmony_ci				  7, dx_root->dr_signature);
58562306a36Sopenharmony_ci	}
58662306a36Sopenharmony_ci
58762306a36Sopenharmony_ci	return ret;
58862306a36Sopenharmony_ci}
58962306a36Sopenharmony_ci
59062306a36Sopenharmony_cistatic int ocfs2_read_dx_root(struct inode *dir, struct ocfs2_dinode *di,
59162306a36Sopenharmony_ci			      struct buffer_head **dx_root_bh)
59262306a36Sopenharmony_ci{
59362306a36Sopenharmony_ci	int ret;
59462306a36Sopenharmony_ci	u64 blkno = le64_to_cpu(di->i_dx_root);
59562306a36Sopenharmony_ci	struct buffer_head *tmp = *dx_root_bh;
59662306a36Sopenharmony_ci
59762306a36Sopenharmony_ci	ret = ocfs2_read_block(INODE_CACHE(dir), blkno, &tmp,
59862306a36Sopenharmony_ci			       ocfs2_validate_dx_root);
59962306a36Sopenharmony_ci
60062306a36Sopenharmony_ci	/* If ocfs2_read_block() got us a new bh, pass it up. */
60162306a36Sopenharmony_ci	if (!ret && !*dx_root_bh)
60262306a36Sopenharmony_ci		*dx_root_bh = tmp;
60362306a36Sopenharmony_ci
60462306a36Sopenharmony_ci	return ret;
60562306a36Sopenharmony_ci}
60662306a36Sopenharmony_ci
60762306a36Sopenharmony_cistatic int ocfs2_validate_dx_leaf(struct super_block *sb,
60862306a36Sopenharmony_ci				  struct buffer_head *bh)
60962306a36Sopenharmony_ci{
61062306a36Sopenharmony_ci	int ret;
61162306a36Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf = (struct ocfs2_dx_leaf *)bh->b_data;
61262306a36Sopenharmony_ci
61362306a36Sopenharmony_ci	BUG_ON(!buffer_uptodate(bh));
61462306a36Sopenharmony_ci
61562306a36Sopenharmony_ci	ret = ocfs2_validate_meta_ecc(sb, bh->b_data, &dx_leaf->dl_check);
61662306a36Sopenharmony_ci	if (ret) {
61762306a36Sopenharmony_ci		mlog(ML_ERROR,
61862306a36Sopenharmony_ci		     "Checksum failed for dir index leaf block %llu\n",
61962306a36Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
62062306a36Sopenharmony_ci		return ret;
62162306a36Sopenharmony_ci	}
62262306a36Sopenharmony_ci
62362306a36Sopenharmony_ci	if (!OCFS2_IS_VALID_DX_LEAF(dx_leaf)) {
62462306a36Sopenharmony_ci		ret = ocfs2_error(sb, "Dir Index Leaf has bad signature %.*s\n",
62562306a36Sopenharmony_ci				  7, dx_leaf->dl_signature);
62662306a36Sopenharmony_ci	}
62762306a36Sopenharmony_ci
62862306a36Sopenharmony_ci	return ret;
62962306a36Sopenharmony_ci}
63062306a36Sopenharmony_ci
63162306a36Sopenharmony_cistatic int ocfs2_read_dx_leaf(struct inode *dir, u64 blkno,
63262306a36Sopenharmony_ci			      struct buffer_head **dx_leaf_bh)
63362306a36Sopenharmony_ci{
63462306a36Sopenharmony_ci	int ret;
63562306a36Sopenharmony_ci	struct buffer_head *tmp = *dx_leaf_bh;
63662306a36Sopenharmony_ci
63762306a36Sopenharmony_ci	ret = ocfs2_read_block(INODE_CACHE(dir), blkno, &tmp,
63862306a36Sopenharmony_ci			       ocfs2_validate_dx_leaf);
63962306a36Sopenharmony_ci
64062306a36Sopenharmony_ci	/* If ocfs2_read_block() got us a new bh, pass it up. */
64162306a36Sopenharmony_ci	if (!ret && !*dx_leaf_bh)
64262306a36Sopenharmony_ci		*dx_leaf_bh = tmp;
64362306a36Sopenharmony_ci
64462306a36Sopenharmony_ci	return ret;
64562306a36Sopenharmony_ci}
64662306a36Sopenharmony_ci
64762306a36Sopenharmony_ci/*
64862306a36Sopenharmony_ci * Read a series of dx_leaf blocks. This expects all buffer_head
64962306a36Sopenharmony_ci * pointers to be NULL on function entry.
65062306a36Sopenharmony_ci */
65162306a36Sopenharmony_cistatic int ocfs2_read_dx_leaves(struct inode *dir, u64 start, int num,
65262306a36Sopenharmony_ci				struct buffer_head **dx_leaf_bhs)
65362306a36Sopenharmony_ci{
65462306a36Sopenharmony_ci	int ret;
65562306a36Sopenharmony_ci
65662306a36Sopenharmony_ci	ret = ocfs2_read_blocks(INODE_CACHE(dir), start, num, dx_leaf_bhs, 0,
65762306a36Sopenharmony_ci				ocfs2_validate_dx_leaf);
65862306a36Sopenharmony_ci	if (ret)
65962306a36Sopenharmony_ci		mlog_errno(ret);
66062306a36Sopenharmony_ci
66162306a36Sopenharmony_ci	return ret;
66262306a36Sopenharmony_ci}
66362306a36Sopenharmony_ci
66462306a36Sopenharmony_cistatic struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
66562306a36Sopenharmony_ci					       struct inode *dir,
66662306a36Sopenharmony_ci					       struct ocfs2_dir_entry **res_dir)
66762306a36Sopenharmony_ci{
66862306a36Sopenharmony_ci	struct super_block *sb;
66962306a36Sopenharmony_ci	struct buffer_head *bh_use[NAMEI_RA_SIZE];
67062306a36Sopenharmony_ci	struct buffer_head *bh, *ret = NULL;
67162306a36Sopenharmony_ci	unsigned long start, block, b;
67262306a36Sopenharmony_ci	int ra_max = 0;		/* Number of bh's in the readahead
67362306a36Sopenharmony_ci				   buffer, bh_use[] */
67462306a36Sopenharmony_ci	int ra_ptr = 0;		/* Current index into readahead
67562306a36Sopenharmony_ci				   buffer */
67662306a36Sopenharmony_ci	int num = 0;
67762306a36Sopenharmony_ci	int nblocks, i;
67862306a36Sopenharmony_ci
67962306a36Sopenharmony_ci	sb = dir->i_sb;
68062306a36Sopenharmony_ci
68162306a36Sopenharmony_ci	nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
68262306a36Sopenharmony_ci	start = OCFS2_I(dir)->ip_dir_start_lookup;
68362306a36Sopenharmony_ci	if (start >= nblocks)
68462306a36Sopenharmony_ci		start = 0;
68562306a36Sopenharmony_ci	block = start;
68662306a36Sopenharmony_ci
68762306a36Sopenharmony_cirestart:
68862306a36Sopenharmony_ci	do {
68962306a36Sopenharmony_ci		/*
69062306a36Sopenharmony_ci		 * We deal with the read-ahead logic here.
69162306a36Sopenharmony_ci		 */
69262306a36Sopenharmony_ci		if (ra_ptr >= ra_max) {
69362306a36Sopenharmony_ci			/* Refill the readahead buffer */
69462306a36Sopenharmony_ci			ra_ptr = 0;
69562306a36Sopenharmony_ci			b = block;
69662306a36Sopenharmony_ci			for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
69762306a36Sopenharmony_ci				/*
69862306a36Sopenharmony_ci				 * Terminate if we reach the end of the
69962306a36Sopenharmony_ci				 * directory and must wrap, or if our
70062306a36Sopenharmony_ci				 * search has finished at this block.
70162306a36Sopenharmony_ci				 */
70262306a36Sopenharmony_ci				if (b >= nblocks || (num && block == start)) {
70362306a36Sopenharmony_ci					bh_use[ra_max] = NULL;
70462306a36Sopenharmony_ci					break;
70562306a36Sopenharmony_ci				}
70662306a36Sopenharmony_ci				num++;
70762306a36Sopenharmony_ci
70862306a36Sopenharmony_ci				bh = NULL;
70962306a36Sopenharmony_ci				ocfs2_read_dir_block(dir, b++, &bh,
71062306a36Sopenharmony_ci							   OCFS2_BH_READAHEAD);
71162306a36Sopenharmony_ci				bh_use[ra_max] = bh;
71262306a36Sopenharmony_ci			}
71362306a36Sopenharmony_ci		}
71462306a36Sopenharmony_ci		if ((bh = bh_use[ra_ptr++]) == NULL)
71562306a36Sopenharmony_ci			goto next;
71662306a36Sopenharmony_ci		if (ocfs2_read_dir_block(dir, block, &bh, 0)) {
71762306a36Sopenharmony_ci			/* read error, skip block & hope for the best.
71862306a36Sopenharmony_ci			 * ocfs2_read_dir_block() has released the bh. */
71962306a36Sopenharmony_ci			mlog(ML_ERROR, "reading directory %llu, "
72062306a36Sopenharmony_ci				    "offset %lu\n",
72162306a36Sopenharmony_ci				    (unsigned long long)OCFS2_I(dir)->ip_blkno,
72262306a36Sopenharmony_ci				    block);
72362306a36Sopenharmony_ci			goto next;
72462306a36Sopenharmony_ci		}
72562306a36Sopenharmony_ci		i = ocfs2_search_dirblock(bh, dir, name, namelen,
72662306a36Sopenharmony_ci					  block << sb->s_blocksize_bits,
72762306a36Sopenharmony_ci					  bh->b_data, sb->s_blocksize,
72862306a36Sopenharmony_ci					  res_dir);
72962306a36Sopenharmony_ci		if (i == 1) {
73062306a36Sopenharmony_ci			OCFS2_I(dir)->ip_dir_start_lookup = block;
73162306a36Sopenharmony_ci			ret = bh;
73262306a36Sopenharmony_ci			goto cleanup_and_exit;
73362306a36Sopenharmony_ci		} else {
73462306a36Sopenharmony_ci			brelse(bh);
73562306a36Sopenharmony_ci			if (i < 0)
73662306a36Sopenharmony_ci				goto cleanup_and_exit;
73762306a36Sopenharmony_ci		}
73862306a36Sopenharmony_ci	next:
73962306a36Sopenharmony_ci		if (++block >= nblocks)
74062306a36Sopenharmony_ci			block = 0;
74162306a36Sopenharmony_ci	} while (block != start);
74262306a36Sopenharmony_ci
74362306a36Sopenharmony_ci	/*
74462306a36Sopenharmony_ci	 * If the directory has grown while we were searching, then
74562306a36Sopenharmony_ci	 * search the last part of the directory before giving up.
74662306a36Sopenharmony_ci	 */
74762306a36Sopenharmony_ci	block = nblocks;
74862306a36Sopenharmony_ci	nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
74962306a36Sopenharmony_ci	if (block < nblocks) {
75062306a36Sopenharmony_ci		start = 0;
75162306a36Sopenharmony_ci		goto restart;
75262306a36Sopenharmony_ci	}
75362306a36Sopenharmony_ci
75462306a36Sopenharmony_cicleanup_and_exit:
75562306a36Sopenharmony_ci	/* Clean up the read-ahead blocks */
75662306a36Sopenharmony_ci	for (; ra_ptr < ra_max; ra_ptr++)
75762306a36Sopenharmony_ci		brelse(bh_use[ra_ptr]);
75862306a36Sopenharmony_ci
75962306a36Sopenharmony_ci	trace_ocfs2_find_entry_el(ret);
76062306a36Sopenharmony_ci	return ret;
76162306a36Sopenharmony_ci}
76262306a36Sopenharmony_ci
76362306a36Sopenharmony_cistatic int ocfs2_dx_dir_lookup_rec(struct inode *inode,
76462306a36Sopenharmony_ci				   struct ocfs2_extent_list *el,
76562306a36Sopenharmony_ci				   u32 major_hash,
76662306a36Sopenharmony_ci				   u32 *ret_cpos,
76762306a36Sopenharmony_ci				   u64 *ret_phys_blkno,
76862306a36Sopenharmony_ci				   unsigned int *ret_clen)
76962306a36Sopenharmony_ci{
77062306a36Sopenharmony_ci	int ret = 0, i, found;
77162306a36Sopenharmony_ci	struct buffer_head *eb_bh = NULL;
77262306a36Sopenharmony_ci	struct ocfs2_extent_block *eb;
77362306a36Sopenharmony_ci	struct ocfs2_extent_rec *rec = NULL;
77462306a36Sopenharmony_ci
77562306a36Sopenharmony_ci	if (el->l_tree_depth) {
77662306a36Sopenharmony_ci		ret = ocfs2_find_leaf(INODE_CACHE(inode), el, major_hash,
77762306a36Sopenharmony_ci				      &eb_bh);
77862306a36Sopenharmony_ci		if (ret) {
77962306a36Sopenharmony_ci			mlog_errno(ret);
78062306a36Sopenharmony_ci			goto out;
78162306a36Sopenharmony_ci		}
78262306a36Sopenharmony_ci
78362306a36Sopenharmony_ci		eb = (struct ocfs2_extent_block *) eb_bh->b_data;
78462306a36Sopenharmony_ci		el = &eb->h_list;
78562306a36Sopenharmony_ci
78662306a36Sopenharmony_ci		if (el->l_tree_depth) {
78762306a36Sopenharmony_ci			ret = ocfs2_error(inode->i_sb,
78862306a36Sopenharmony_ci					  "Inode %lu has non zero tree depth in btree tree block %llu\n",
78962306a36Sopenharmony_ci					  inode->i_ino,
79062306a36Sopenharmony_ci					  (unsigned long long)eb_bh->b_blocknr);
79162306a36Sopenharmony_ci			goto out;
79262306a36Sopenharmony_ci		}
79362306a36Sopenharmony_ci	}
79462306a36Sopenharmony_ci
79562306a36Sopenharmony_ci	found = 0;
79662306a36Sopenharmony_ci	for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {
79762306a36Sopenharmony_ci		rec = &el->l_recs[i];
79862306a36Sopenharmony_ci
79962306a36Sopenharmony_ci		if (le32_to_cpu(rec->e_cpos) <= major_hash) {
80062306a36Sopenharmony_ci			found = 1;
80162306a36Sopenharmony_ci			break;
80262306a36Sopenharmony_ci		}
80362306a36Sopenharmony_ci	}
80462306a36Sopenharmony_ci
80562306a36Sopenharmony_ci	if (!found) {
80662306a36Sopenharmony_ci		ret = ocfs2_error(inode->i_sb,
80762306a36Sopenharmony_ci				  "Inode %lu has bad extent record (%u, %u, 0) in btree\n",
80862306a36Sopenharmony_ci				  inode->i_ino,
80962306a36Sopenharmony_ci				  le32_to_cpu(rec->e_cpos),
81062306a36Sopenharmony_ci				  ocfs2_rec_clusters(el, rec));
81162306a36Sopenharmony_ci		goto out;
81262306a36Sopenharmony_ci	}
81362306a36Sopenharmony_ci
81462306a36Sopenharmony_ci	if (ret_phys_blkno)
81562306a36Sopenharmony_ci		*ret_phys_blkno = le64_to_cpu(rec->e_blkno);
81662306a36Sopenharmony_ci	if (ret_cpos)
81762306a36Sopenharmony_ci		*ret_cpos = le32_to_cpu(rec->e_cpos);
81862306a36Sopenharmony_ci	if (ret_clen)
81962306a36Sopenharmony_ci		*ret_clen = le16_to_cpu(rec->e_leaf_clusters);
82062306a36Sopenharmony_ci
82162306a36Sopenharmony_ciout:
82262306a36Sopenharmony_ci	brelse(eb_bh);
82362306a36Sopenharmony_ci	return ret;
82462306a36Sopenharmony_ci}
82562306a36Sopenharmony_ci
82662306a36Sopenharmony_ci/*
82762306a36Sopenharmony_ci * Returns the block index, from the start of the cluster which this
82862306a36Sopenharmony_ci * hash belongs too.
82962306a36Sopenharmony_ci */
83062306a36Sopenharmony_cistatic inline unsigned int __ocfs2_dx_dir_hash_idx(struct ocfs2_super *osb,
83162306a36Sopenharmony_ci						   u32 minor_hash)
83262306a36Sopenharmony_ci{
83362306a36Sopenharmony_ci	return minor_hash & osb->osb_dx_mask;
83462306a36Sopenharmony_ci}
83562306a36Sopenharmony_ci
83662306a36Sopenharmony_cistatic inline unsigned int ocfs2_dx_dir_hash_idx(struct ocfs2_super *osb,
83762306a36Sopenharmony_ci					  struct ocfs2_dx_hinfo *hinfo)
83862306a36Sopenharmony_ci{
83962306a36Sopenharmony_ci	return __ocfs2_dx_dir_hash_idx(osb, hinfo->minor_hash);
84062306a36Sopenharmony_ci}
84162306a36Sopenharmony_ci
84262306a36Sopenharmony_cistatic int ocfs2_dx_dir_lookup(struct inode *inode,
84362306a36Sopenharmony_ci			       struct ocfs2_extent_list *el,
84462306a36Sopenharmony_ci			       struct ocfs2_dx_hinfo *hinfo,
84562306a36Sopenharmony_ci			       u32 *ret_cpos,
84662306a36Sopenharmony_ci			       u64 *ret_phys_blkno)
84762306a36Sopenharmony_ci{
84862306a36Sopenharmony_ci	int ret = 0;
84962306a36Sopenharmony_ci	unsigned int cend, clen;
85062306a36Sopenharmony_ci	u32 cpos;
85162306a36Sopenharmony_ci	u64 blkno;
85262306a36Sopenharmony_ci	u32 name_hash = hinfo->major_hash;
85362306a36Sopenharmony_ci
85462306a36Sopenharmony_ci	ret = ocfs2_dx_dir_lookup_rec(inode, el, name_hash, &cpos, &blkno,
85562306a36Sopenharmony_ci				      &clen);
85662306a36Sopenharmony_ci	if (ret) {
85762306a36Sopenharmony_ci		mlog_errno(ret);
85862306a36Sopenharmony_ci		goto out;
85962306a36Sopenharmony_ci	}
86062306a36Sopenharmony_ci
86162306a36Sopenharmony_ci	cend = cpos + clen;
86262306a36Sopenharmony_ci	if (name_hash >= cend) {
86362306a36Sopenharmony_ci		/* We want the last cluster */
86462306a36Sopenharmony_ci		blkno += ocfs2_clusters_to_blocks(inode->i_sb, clen - 1);
86562306a36Sopenharmony_ci		cpos += clen - 1;
86662306a36Sopenharmony_ci	} else {
86762306a36Sopenharmony_ci		blkno += ocfs2_clusters_to_blocks(inode->i_sb,
86862306a36Sopenharmony_ci						  name_hash - cpos);
86962306a36Sopenharmony_ci		cpos = name_hash;
87062306a36Sopenharmony_ci	}
87162306a36Sopenharmony_ci
87262306a36Sopenharmony_ci	/*
87362306a36Sopenharmony_ci	 * We now have the cluster which should hold our entry. To
87462306a36Sopenharmony_ci	 * find the exact block from the start of the cluster to
87562306a36Sopenharmony_ci	 * search, we take the lower bits of the hash.
87662306a36Sopenharmony_ci	 */
87762306a36Sopenharmony_ci	blkno += ocfs2_dx_dir_hash_idx(OCFS2_SB(inode->i_sb), hinfo);
87862306a36Sopenharmony_ci
87962306a36Sopenharmony_ci	if (ret_phys_blkno)
88062306a36Sopenharmony_ci		*ret_phys_blkno = blkno;
88162306a36Sopenharmony_ci	if (ret_cpos)
88262306a36Sopenharmony_ci		*ret_cpos = cpos;
88362306a36Sopenharmony_ci
88462306a36Sopenharmony_ciout:
88562306a36Sopenharmony_ci
88662306a36Sopenharmony_ci	return ret;
88762306a36Sopenharmony_ci}
88862306a36Sopenharmony_ci
88962306a36Sopenharmony_cistatic int ocfs2_dx_dir_search(const char *name, int namelen,
89062306a36Sopenharmony_ci			       struct inode *dir,
89162306a36Sopenharmony_ci			       struct ocfs2_dx_root_block *dx_root,
89262306a36Sopenharmony_ci			       struct ocfs2_dir_lookup_result *res)
89362306a36Sopenharmony_ci{
89462306a36Sopenharmony_ci	int ret, i, found;
89562306a36Sopenharmony_ci	u64 phys;
89662306a36Sopenharmony_ci	struct buffer_head *dx_leaf_bh = NULL;
89762306a36Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
89862306a36Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry = NULL;
89962306a36Sopenharmony_ci	struct buffer_head *dir_ent_bh = NULL;
90062306a36Sopenharmony_ci	struct ocfs2_dir_entry *dir_ent = NULL;
90162306a36Sopenharmony_ci	struct ocfs2_dx_hinfo *hinfo = &res->dl_hinfo;
90262306a36Sopenharmony_ci	struct ocfs2_extent_list *dr_el;
90362306a36Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
90462306a36Sopenharmony_ci
90562306a36Sopenharmony_ci	ocfs2_dx_dir_name_hash(dir, name, namelen, &res->dl_hinfo);
90662306a36Sopenharmony_ci
90762306a36Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root)) {
90862306a36Sopenharmony_ci		entry_list = &dx_root->dr_entries;
90962306a36Sopenharmony_ci		goto search;
91062306a36Sopenharmony_ci	}
91162306a36Sopenharmony_ci
91262306a36Sopenharmony_ci	dr_el = &dx_root->dr_list;
91362306a36Sopenharmony_ci
91462306a36Sopenharmony_ci	ret = ocfs2_dx_dir_lookup(dir, dr_el, hinfo, NULL, &phys);
91562306a36Sopenharmony_ci	if (ret) {
91662306a36Sopenharmony_ci		mlog_errno(ret);
91762306a36Sopenharmony_ci		goto out;
91862306a36Sopenharmony_ci	}
91962306a36Sopenharmony_ci
92062306a36Sopenharmony_ci	trace_ocfs2_dx_dir_search((unsigned long long)OCFS2_I(dir)->ip_blkno,
92162306a36Sopenharmony_ci				  namelen, name, hinfo->major_hash,
92262306a36Sopenharmony_ci				  hinfo->minor_hash, (unsigned long long)phys);
92362306a36Sopenharmony_ci
92462306a36Sopenharmony_ci	ret = ocfs2_read_dx_leaf(dir, phys, &dx_leaf_bh);
92562306a36Sopenharmony_ci	if (ret) {
92662306a36Sopenharmony_ci		mlog_errno(ret);
92762306a36Sopenharmony_ci		goto out;
92862306a36Sopenharmony_ci	}
92962306a36Sopenharmony_ci
93062306a36Sopenharmony_ci	dx_leaf = (struct ocfs2_dx_leaf *) dx_leaf_bh->b_data;
93162306a36Sopenharmony_ci
93262306a36Sopenharmony_ci	trace_ocfs2_dx_dir_search_leaf_info(
93362306a36Sopenharmony_ci			le16_to_cpu(dx_leaf->dl_list.de_num_used),
93462306a36Sopenharmony_ci			le16_to_cpu(dx_leaf->dl_list.de_count));
93562306a36Sopenharmony_ci
93662306a36Sopenharmony_ci	entry_list = &dx_leaf->dl_list;
93762306a36Sopenharmony_ci
93862306a36Sopenharmony_cisearch:
93962306a36Sopenharmony_ci	/*
94062306a36Sopenharmony_ci	 * Empty leaf is legal, so no need to check for that.
94162306a36Sopenharmony_ci	 */
94262306a36Sopenharmony_ci	found = 0;
94362306a36Sopenharmony_ci	for (i = 0; i < le16_to_cpu(entry_list->de_num_used); i++) {
94462306a36Sopenharmony_ci		dx_entry = &entry_list->de_entries[i];
94562306a36Sopenharmony_ci
94662306a36Sopenharmony_ci		if (hinfo->major_hash != le32_to_cpu(dx_entry->dx_major_hash)
94762306a36Sopenharmony_ci		    || hinfo->minor_hash != le32_to_cpu(dx_entry->dx_minor_hash))
94862306a36Sopenharmony_ci			continue;
94962306a36Sopenharmony_ci
95062306a36Sopenharmony_ci		/*
95162306a36Sopenharmony_ci		 * Search unindexed leaf block now. We're not
95262306a36Sopenharmony_ci		 * guaranteed to find anything.
95362306a36Sopenharmony_ci		 */
95462306a36Sopenharmony_ci		ret = ocfs2_read_dir_block_direct(dir,
95562306a36Sopenharmony_ci					  le64_to_cpu(dx_entry->dx_dirent_blk),
95662306a36Sopenharmony_ci					  &dir_ent_bh);
95762306a36Sopenharmony_ci		if (ret) {
95862306a36Sopenharmony_ci			mlog_errno(ret);
95962306a36Sopenharmony_ci			goto out;
96062306a36Sopenharmony_ci		}
96162306a36Sopenharmony_ci
96262306a36Sopenharmony_ci		/*
96362306a36Sopenharmony_ci		 * XXX: We should check the unindexed block here,
96462306a36Sopenharmony_ci		 * before using it.
96562306a36Sopenharmony_ci		 */
96662306a36Sopenharmony_ci
96762306a36Sopenharmony_ci		found = ocfs2_search_dirblock(dir_ent_bh, dir, name, namelen,
96862306a36Sopenharmony_ci					      0, dir_ent_bh->b_data,
96962306a36Sopenharmony_ci					      dir->i_sb->s_blocksize, &dir_ent);
97062306a36Sopenharmony_ci		if (found == 1)
97162306a36Sopenharmony_ci			break;
97262306a36Sopenharmony_ci
97362306a36Sopenharmony_ci		if (found == -1) {
97462306a36Sopenharmony_ci			/* This means we found a bad directory entry. */
97562306a36Sopenharmony_ci			ret = -EIO;
97662306a36Sopenharmony_ci			mlog_errno(ret);
97762306a36Sopenharmony_ci			goto out;
97862306a36Sopenharmony_ci		}
97962306a36Sopenharmony_ci
98062306a36Sopenharmony_ci		brelse(dir_ent_bh);
98162306a36Sopenharmony_ci		dir_ent_bh = NULL;
98262306a36Sopenharmony_ci	}
98362306a36Sopenharmony_ci
98462306a36Sopenharmony_ci	if (found <= 0) {
98562306a36Sopenharmony_ci		ret = -ENOENT;
98662306a36Sopenharmony_ci		goto out;
98762306a36Sopenharmony_ci	}
98862306a36Sopenharmony_ci
98962306a36Sopenharmony_ci	res->dl_leaf_bh = dir_ent_bh;
99062306a36Sopenharmony_ci	res->dl_entry = dir_ent;
99162306a36Sopenharmony_ci	res->dl_dx_leaf_bh = dx_leaf_bh;
99262306a36Sopenharmony_ci	res->dl_dx_entry = dx_entry;
99362306a36Sopenharmony_ci
99462306a36Sopenharmony_ci	ret = 0;
99562306a36Sopenharmony_ciout:
99662306a36Sopenharmony_ci	if (ret) {
99762306a36Sopenharmony_ci		brelse(dx_leaf_bh);
99862306a36Sopenharmony_ci		brelse(dir_ent_bh);
99962306a36Sopenharmony_ci	}
100062306a36Sopenharmony_ci	return ret;
100162306a36Sopenharmony_ci}
100262306a36Sopenharmony_ci
100362306a36Sopenharmony_cistatic int ocfs2_find_entry_dx(const char *name, int namelen,
100462306a36Sopenharmony_ci			       struct inode *dir,
100562306a36Sopenharmony_ci			       struct ocfs2_dir_lookup_result *lookup)
100662306a36Sopenharmony_ci{
100762306a36Sopenharmony_ci	int ret;
100862306a36Sopenharmony_ci	struct buffer_head *di_bh = NULL;
100962306a36Sopenharmony_ci	struct ocfs2_dinode *di;
101062306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
101162306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
101262306a36Sopenharmony_ci
101362306a36Sopenharmony_ci	ret = ocfs2_read_inode_block(dir, &di_bh);
101462306a36Sopenharmony_ci	if (ret) {
101562306a36Sopenharmony_ci		mlog_errno(ret);
101662306a36Sopenharmony_ci		goto out;
101762306a36Sopenharmony_ci	}
101862306a36Sopenharmony_ci
101962306a36Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
102062306a36Sopenharmony_ci
102162306a36Sopenharmony_ci	ret = ocfs2_read_dx_root(dir, di, &dx_root_bh);
102262306a36Sopenharmony_ci	if (ret) {
102362306a36Sopenharmony_ci		mlog_errno(ret);
102462306a36Sopenharmony_ci		goto out;
102562306a36Sopenharmony_ci	}
102662306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
102762306a36Sopenharmony_ci
102862306a36Sopenharmony_ci	ret = ocfs2_dx_dir_search(name, namelen, dir, dx_root, lookup);
102962306a36Sopenharmony_ci	if (ret) {
103062306a36Sopenharmony_ci		if (ret != -ENOENT)
103162306a36Sopenharmony_ci			mlog_errno(ret);
103262306a36Sopenharmony_ci		goto out;
103362306a36Sopenharmony_ci	}
103462306a36Sopenharmony_ci
103562306a36Sopenharmony_ci	lookup->dl_dx_root_bh = dx_root_bh;
103662306a36Sopenharmony_ci	dx_root_bh = NULL;
103762306a36Sopenharmony_ciout:
103862306a36Sopenharmony_ci	brelse(di_bh);
103962306a36Sopenharmony_ci	brelse(dx_root_bh);
104062306a36Sopenharmony_ci	return ret;
104162306a36Sopenharmony_ci}
104262306a36Sopenharmony_ci
104362306a36Sopenharmony_ci/*
104462306a36Sopenharmony_ci * Try to find an entry of the provided name within 'dir'.
104562306a36Sopenharmony_ci *
104662306a36Sopenharmony_ci * If nothing was found, -ENOENT is returned. Otherwise, zero is
104762306a36Sopenharmony_ci * returned and the struct 'res' will contain information useful to
104862306a36Sopenharmony_ci * other directory manipulation functions.
104962306a36Sopenharmony_ci *
105062306a36Sopenharmony_ci * Caller can NOT assume anything about the contents of the
105162306a36Sopenharmony_ci * buffer_heads - they are passed back only so that it can be passed
105262306a36Sopenharmony_ci * into any one of the manipulation functions (add entry, delete
105362306a36Sopenharmony_ci * entry, etc). As an example, bh in the extent directory case is a
105462306a36Sopenharmony_ci * data block, in the inline-data case it actually points to an inode,
105562306a36Sopenharmony_ci * in the indexed directory case, multiple buffers are involved.
105662306a36Sopenharmony_ci */
105762306a36Sopenharmony_ciint ocfs2_find_entry(const char *name, int namelen,
105862306a36Sopenharmony_ci		     struct inode *dir, struct ocfs2_dir_lookup_result *lookup)
105962306a36Sopenharmony_ci{
106062306a36Sopenharmony_ci	struct buffer_head *bh;
106162306a36Sopenharmony_ci	struct ocfs2_dir_entry *res_dir = NULL;
106262306a36Sopenharmony_ci
106362306a36Sopenharmony_ci	if (ocfs2_dir_indexed(dir))
106462306a36Sopenharmony_ci		return ocfs2_find_entry_dx(name, namelen, dir, lookup);
106562306a36Sopenharmony_ci
106662306a36Sopenharmony_ci	/*
106762306a36Sopenharmony_ci	 * The unindexed dir code only uses part of the lookup
106862306a36Sopenharmony_ci	 * structure, so there's no reason to push it down further
106962306a36Sopenharmony_ci	 * than this.
107062306a36Sopenharmony_ci	 */
107162306a36Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
107262306a36Sopenharmony_ci		bh = ocfs2_find_entry_id(name, namelen, dir, &res_dir);
107362306a36Sopenharmony_ci	else
107462306a36Sopenharmony_ci		bh = ocfs2_find_entry_el(name, namelen, dir, &res_dir);
107562306a36Sopenharmony_ci
107662306a36Sopenharmony_ci	if (bh == NULL)
107762306a36Sopenharmony_ci		return -ENOENT;
107862306a36Sopenharmony_ci
107962306a36Sopenharmony_ci	lookup->dl_leaf_bh = bh;
108062306a36Sopenharmony_ci	lookup->dl_entry = res_dir;
108162306a36Sopenharmony_ci	return 0;
108262306a36Sopenharmony_ci}
108362306a36Sopenharmony_ci
108462306a36Sopenharmony_ci/*
108562306a36Sopenharmony_ci * Update inode number and type of a previously found directory entry.
108662306a36Sopenharmony_ci */
108762306a36Sopenharmony_ciint ocfs2_update_entry(struct inode *dir, handle_t *handle,
108862306a36Sopenharmony_ci		       struct ocfs2_dir_lookup_result *res,
108962306a36Sopenharmony_ci		       struct inode *new_entry_inode)
109062306a36Sopenharmony_ci{
109162306a36Sopenharmony_ci	int ret;
109262306a36Sopenharmony_ci	ocfs2_journal_access_func access = ocfs2_journal_access_db;
109362306a36Sopenharmony_ci	struct ocfs2_dir_entry *de = res->dl_entry;
109462306a36Sopenharmony_ci	struct buffer_head *de_bh = res->dl_leaf_bh;
109562306a36Sopenharmony_ci
109662306a36Sopenharmony_ci	/*
109762306a36Sopenharmony_ci	 * The same code works fine for both inline-data and extent
109862306a36Sopenharmony_ci	 * based directories, so no need to split this up.  The only
109962306a36Sopenharmony_ci	 * difference is the journal_access function.
110062306a36Sopenharmony_ci	 */
110162306a36Sopenharmony_ci
110262306a36Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
110362306a36Sopenharmony_ci		access = ocfs2_journal_access_di;
110462306a36Sopenharmony_ci
110562306a36Sopenharmony_ci	ret = access(handle, INODE_CACHE(dir), de_bh,
110662306a36Sopenharmony_ci		     OCFS2_JOURNAL_ACCESS_WRITE);
110762306a36Sopenharmony_ci	if (ret) {
110862306a36Sopenharmony_ci		mlog_errno(ret);
110962306a36Sopenharmony_ci		goto out;
111062306a36Sopenharmony_ci	}
111162306a36Sopenharmony_ci
111262306a36Sopenharmony_ci	de->inode = cpu_to_le64(OCFS2_I(new_entry_inode)->ip_blkno);
111362306a36Sopenharmony_ci	ocfs2_set_de_type(de, new_entry_inode->i_mode);
111462306a36Sopenharmony_ci
111562306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, de_bh);
111662306a36Sopenharmony_ci
111762306a36Sopenharmony_ciout:
111862306a36Sopenharmony_ci	return ret;
111962306a36Sopenharmony_ci}
112062306a36Sopenharmony_ci
112162306a36Sopenharmony_ci/*
112262306a36Sopenharmony_ci * __ocfs2_delete_entry deletes a directory entry by merging it with the
112362306a36Sopenharmony_ci * previous entry
112462306a36Sopenharmony_ci */
112562306a36Sopenharmony_cistatic int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
112662306a36Sopenharmony_ci				struct ocfs2_dir_entry *de_del,
112762306a36Sopenharmony_ci				struct buffer_head *bh, char *first_de,
112862306a36Sopenharmony_ci				unsigned int bytes)
112962306a36Sopenharmony_ci{
113062306a36Sopenharmony_ci	struct ocfs2_dir_entry *de, *pde;
113162306a36Sopenharmony_ci	int i, status = -ENOENT;
113262306a36Sopenharmony_ci	ocfs2_journal_access_func access = ocfs2_journal_access_db;
113362306a36Sopenharmony_ci
113462306a36Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
113562306a36Sopenharmony_ci		access = ocfs2_journal_access_di;
113662306a36Sopenharmony_ci
113762306a36Sopenharmony_ci	i = 0;
113862306a36Sopenharmony_ci	pde = NULL;
113962306a36Sopenharmony_ci	de = (struct ocfs2_dir_entry *) first_de;
114062306a36Sopenharmony_ci	while (i < bytes) {
114162306a36Sopenharmony_ci		if (!ocfs2_check_dir_entry(dir, de, bh, i)) {
114262306a36Sopenharmony_ci			status = -EIO;
114362306a36Sopenharmony_ci			mlog_errno(status);
114462306a36Sopenharmony_ci			goto bail;
114562306a36Sopenharmony_ci		}
114662306a36Sopenharmony_ci		if (de == de_del)  {
114762306a36Sopenharmony_ci			status = access(handle, INODE_CACHE(dir), bh,
114862306a36Sopenharmony_ci					OCFS2_JOURNAL_ACCESS_WRITE);
114962306a36Sopenharmony_ci			if (status < 0) {
115062306a36Sopenharmony_ci				status = -EIO;
115162306a36Sopenharmony_ci				mlog_errno(status);
115262306a36Sopenharmony_ci				goto bail;
115362306a36Sopenharmony_ci			}
115462306a36Sopenharmony_ci			if (pde)
115562306a36Sopenharmony_ci				le16_add_cpu(&pde->rec_len,
115662306a36Sopenharmony_ci						le16_to_cpu(de->rec_len));
115762306a36Sopenharmony_ci			de->inode = 0;
115862306a36Sopenharmony_ci			inode_inc_iversion(dir);
115962306a36Sopenharmony_ci			ocfs2_journal_dirty(handle, bh);
116062306a36Sopenharmony_ci			goto bail;
116162306a36Sopenharmony_ci		}
116262306a36Sopenharmony_ci		i += le16_to_cpu(de->rec_len);
116362306a36Sopenharmony_ci		pde = de;
116462306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len));
116562306a36Sopenharmony_ci	}
116662306a36Sopenharmony_cibail:
116762306a36Sopenharmony_ci	return status;
116862306a36Sopenharmony_ci}
116962306a36Sopenharmony_ci
117062306a36Sopenharmony_cistatic unsigned int ocfs2_figure_dirent_hole(struct ocfs2_dir_entry *de)
117162306a36Sopenharmony_ci{
117262306a36Sopenharmony_ci	unsigned int hole;
117362306a36Sopenharmony_ci
117462306a36Sopenharmony_ci	if (le64_to_cpu(de->inode) == 0)
117562306a36Sopenharmony_ci		hole = le16_to_cpu(de->rec_len);
117662306a36Sopenharmony_ci	else
117762306a36Sopenharmony_ci		hole = le16_to_cpu(de->rec_len) -
117862306a36Sopenharmony_ci			OCFS2_DIR_REC_LEN(de->name_len);
117962306a36Sopenharmony_ci
118062306a36Sopenharmony_ci	return hole;
118162306a36Sopenharmony_ci}
118262306a36Sopenharmony_ci
118362306a36Sopenharmony_cistatic int ocfs2_find_max_rec_len(struct super_block *sb,
118462306a36Sopenharmony_ci				  struct buffer_head *dirblock_bh)
118562306a36Sopenharmony_ci{
118662306a36Sopenharmony_ci	int size, this_hole, largest_hole = 0;
118762306a36Sopenharmony_ci	char *trailer, *de_buf, *limit, *start = dirblock_bh->b_data;
118862306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
118962306a36Sopenharmony_ci
119062306a36Sopenharmony_ci	trailer = (char *)ocfs2_trailer_from_bh(dirblock_bh, sb);
119162306a36Sopenharmony_ci	size = ocfs2_dir_trailer_blk_off(sb);
119262306a36Sopenharmony_ci	limit = start + size;
119362306a36Sopenharmony_ci	de_buf = start;
119462306a36Sopenharmony_ci	de = (struct ocfs2_dir_entry *)de_buf;
119562306a36Sopenharmony_ci	do {
119662306a36Sopenharmony_ci		if (de_buf != trailer) {
119762306a36Sopenharmony_ci			this_hole = ocfs2_figure_dirent_hole(de);
119862306a36Sopenharmony_ci			if (this_hole > largest_hole)
119962306a36Sopenharmony_ci				largest_hole = this_hole;
120062306a36Sopenharmony_ci		}
120162306a36Sopenharmony_ci
120262306a36Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
120362306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
120462306a36Sopenharmony_ci	} while (de_buf < limit);
120562306a36Sopenharmony_ci
120662306a36Sopenharmony_ci	if (largest_hole >= OCFS2_DIR_MIN_REC_LEN)
120762306a36Sopenharmony_ci		return largest_hole;
120862306a36Sopenharmony_ci	return 0;
120962306a36Sopenharmony_ci}
121062306a36Sopenharmony_ci
121162306a36Sopenharmony_cistatic void ocfs2_dx_list_remove_entry(struct ocfs2_dx_entry_list *entry_list,
121262306a36Sopenharmony_ci				       int index)
121362306a36Sopenharmony_ci{
121462306a36Sopenharmony_ci	int num_used = le16_to_cpu(entry_list->de_num_used);
121562306a36Sopenharmony_ci
121662306a36Sopenharmony_ci	if (num_used == 1 || index == (num_used - 1))
121762306a36Sopenharmony_ci		goto clear;
121862306a36Sopenharmony_ci
121962306a36Sopenharmony_ci	memmove(&entry_list->de_entries[index],
122062306a36Sopenharmony_ci		&entry_list->de_entries[index + 1],
122162306a36Sopenharmony_ci		(num_used - index - 1)*sizeof(struct ocfs2_dx_entry));
122262306a36Sopenharmony_ciclear:
122362306a36Sopenharmony_ci	num_used--;
122462306a36Sopenharmony_ci	memset(&entry_list->de_entries[num_used], 0,
122562306a36Sopenharmony_ci	       sizeof(struct ocfs2_dx_entry));
122662306a36Sopenharmony_ci	entry_list->de_num_used = cpu_to_le16(num_used);
122762306a36Sopenharmony_ci}
122862306a36Sopenharmony_ci
122962306a36Sopenharmony_cistatic int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
123062306a36Sopenharmony_ci				 struct ocfs2_dir_lookup_result *lookup)
123162306a36Sopenharmony_ci{
123262306a36Sopenharmony_ci	int ret, index, max_rec_len, add_to_free_list = 0;
123362306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
123462306a36Sopenharmony_ci	struct buffer_head *leaf_bh = lookup->dl_leaf_bh;
123562306a36Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
123662306a36Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry = lookup->dl_dx_entry;
123762306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
123862306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
123962306a36Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
124062306a36Sopenharmony_ci
124162306a36Sopenharmony_ci	/*
124262306a36Sopenharmony_ci	 * This function gets a bit messy because we might have to
124362306a36Sopenharmony_ci	 * modify the root block, regardless of whether the indexed
124462306a36Sopenharmony_ci	 * entries are stored inline.
124562306a36Sopenharmony_ci	 */
124662306a36Sopenharmony_ci
124762306a36Sopenharmony_ci	/*
124862306a36Sopenharmony_ci	 * *Only* set 'entry_list' here, based on where we're looking
124962306a36Sopenharmony_ci	 * for the indexed entries. Later, we might still want to
125062306a36Sopenharmony_ci	 * journal both blocks, based on free list state.
125162306a36Sopenharmony_ci	 */
125262306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
125362306a36Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root)) {
125462306a36Sopenharmony_ci		entry_list = &dx_root->dr_entries;
125562306a36Sopenharmony_ci	} else {
125662306a36Sopenharmony_ci		dx_leaf = (struct ocfs2_dx_leaf *) lookup->dl_dx_leaf_bh->b_data;
125762306a36Sopenharmony_ci		entry_list = &dx_leaf->dl_list;
125862306a36Sopenharmony_ci	}
125962306a36Sopenharmony_ci
126062306a36Sopenharmony_ci	/* Neither of these are a disk corruption - that should have
126162306a36Sopenharmony_ci	 * been caught by lookup, before we got here. */
126262306a36Sopenharmony_ci	BUG_ON(le16_to_cpu(entry_list->de_count) <= 0);
126362306a36Sopenharmony_ci	BUG_ON(le16_to_cpu(entry_list->de_num_used) <= 0);
126462306a36Sopenharmony_ci
126562306a36Sopenharmony_ci	index = (char *)dx_entry - (char *)entry_list->de_entries;
126662306a36Sopenharmony_ci	index /= sizeof(*dx_entry);
126762306a36Sopenharmony_ci
126862306a36Sopenharmony_ci	if (index >= le16_to_cpu(entry_list->de_num_used)) {
126962306a36Sopenharmony_ci		mlog(ML_ERROR, "Dir %llu: Bad dx_entry ptr idx %d, (%p, %p)\n",
127062306a36Sopenharmony_ci		     (unsigned long long)OCFS2_I(dir)->ip_blkno, index,
127162306a36Sopenharmony_ci		     entry_list, dx_entry);
127262306a36Sopenharmony_ci		return -EIO;
127362306a36Sopenharmony_ci	}
127462306a36Sopenharmony_ci
127562306a36Sopenharmony_ci	/*
127662306a36Sopenharmony_ci	 * We know that removal of this dirent will leave enough room
127762306a36Sopenharmony_ci	 * for a new one, so add this block to the free list if it
127862306a36Sopenharmony_ci	 * isn't already there.
127962306a36Sopenharmony_ci	 */
128062306a36Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(leaf_bh, dir->i_sb);
128162306a36Sopenharmony_ci	if (trailer->db_free_rec_len == 0)
128262306a36Sopenharmony_ci		add_to_free_list = 1;
128362306a36Sopenharmony_ci
128462306a36Sopenharmony_ci	/*
128562306a36Sopenharmony_ci	 * Add the block holding our index into the journal before
128662306a36Sopenharmony_ci	 * removing the unindexed entry. If we get an error return
128762306a36Sopenharmony_ci	 * from __ocfs2_delete_entry(), then it hasn't removed the
128862306a36Sopenharmony_ci	 * entry yet. Likewise, successful return means we *must*
128962306a36Sopenharmony_ci	 * remove the indexed entry.
129062306a36Sopenharmony_ci	 *
129162306a36Sopenharmony_ci	 * We're also careful to journal the root tree block here as
129262306a36Sopenharmony_ci	 * the entry count needs to be updated. Also, we might be
129362306a36Sopenharmony_ci	 * adding to the start of the free list.
129462306a36Sopenharmony_ci	 */
129562306a36Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
129662306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
129762306a36Sopenharmony_ci	if (ret) {
129862306a36Sopenharmony_ci		mlog_errno(ret);
129962306a36Sopenharmony_ci		goto out;
130062306a36Sopenharmony_ci	}
130162306a36Sopenharmony_ci
130262306a36Sopenharmony_ci	if (!ocfs2_dx_root_inline(dx_root)) {
130362306a36Sopenharmony_ci		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
130462306a36Sopenharmony_ci					      lookup->dl_dx_leaf_bh,
130562306a36Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_WRITE);
130662306a36Sopenharmony_ci		if (ret) {
130762306a36Sopenharmony_ci			mlog_errno(ret);
130862306a36Sopenharmony_ci			goto out;
130962306a36Sopenharmony_ci		}
131062306a36Sopenharmony_ci	}
131162306a36Sopenharmony_ci
131262306a36Sopenharmony_ci	trace_ocfs2_delete_entry_dx((unsigned long long)OCFS2_I(dir)->ip_blkno,
131362306a36Sopenharmony_ci				    index);
131462306a36Sopenharmony_ci
131562306a36Sopenharmony_ci	ret = __ocfs2_delete_entry(handle, dir, lookup->dl_entry,
131662306a36Sopenharmony_ci				   leaf_bh, leaf_bh->b_data, leaf_bh->b_size);
131762306a36Sopenharmony_ci	if (ret) {
131862306a36Sopenharmony_ci		mlog_errno(ret);
131962306a36Sopenharmony_ci		goto out;
132062306a36Sopenharmony_ci	}
132162306a36Sopenharmony_ci
132262306a36Sopenharmony_ci	max_rec_len = ocfs2_find_max_rec_len(dir->i_sb, leaf_bh);
132362306a36Sopenharmony_ci	trailer->db_free_rec_len = cpu_to_le16(max_rec_len);
132462306a36Sopenharmony_ci	if (add_to_free_list) {
132562306a36Sopenharmony_ci		trailer->db_free_next = dx_root->dr_free_blk;
132662306a36Sopenharmony_ci		dx_root->dr_free_blk = cpu_to_le64(leaf_bh->b_blocknr);
132762306a36Sopenharmony_ci		ocfs2_journal_dirty(handle, dx_root_bh);
132862306a36Sopenharmony_ci	}
132962306a36Sopenharmony_ci
133062306a36Sopenharmony_ci	/* leaf_bh was journal_accessed for us in __ocfs2_delete_entry */
133162306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, leaf_bh);
133262306a36Sopenharmony_ci
133362306a36Sopenharmony_ci	le32_add_cpu(&dx_root->dr_num_entries, -1);
133462306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
133562306a36Sopenharmony_ci
133662306a36Sopenharmony_ci	ocfs2_dx_list_remove_entry(entry_list, index);
133762306a36Sopenharmony_ci
133862306a36Sopenharmony_ci	if (!ocfs2_dx_root_inline(dx_root))
133962306a36Sopenharmony_ci		ocfs2_journal_dirty(handle, lookup->dl_dx_leaf_bh);
134062306a36Sopenharmony_ci
134162306a36Sopenharmony_ciout:
134262306a36Sopenharmony_ci	return ret;
134362306a36Sopenharmony_ci}
134462306a36Sopenharmony_ci
134562306a36Sopenharmony_cistatic inline int ocfs2_delete_entry_id(handle_t *handle,
134662306a36Sopenharmony_ci					struct inode *dir,
134762306a36Sopenharmony_ci					struct ocfs2_dir_entry *de_del,
134862306a36Sopenharmony_ci					struct buffer_head *bh)
134962306a36Sopenharmony_ci{
135062306a36Sopenharmony_ci	int ret;
135162306a36Sopenharmony_ci	struct buffer_head *di_bh = NULL;
135262306a36Sopenharmony_ci	struct ocfs2_dinode *di;
135362306a36Sopenharmony_ci	struct ocfs2_inline_data *data;
135462306a36Sopenharmony_ci
135562306a36Sopenharmony_ci	ret = ocfs2_read_inode_block(dir, &di_bh);
135662306a36Sopenharmony_ci	if (ret) {
135762306a36Sopenharmony_ci		mlog_errno(ret);
135862306a36Sopenharmony_ci		goto out;
135962306a36Sopenharmony_ci	}
136062306a36Sopenharmony_ci
136162306a36Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
136262306a36Sopenharmony_ci	data = &di->id2.i_data;
136362306a36Sopenharmony_ci
136462306a36Sopenharmony_ci	ret = __ocfs2_delete_entry(handle, dir, de_del, bh, data->id_data,
136562306a36Sopenharmony_ci				   i_size_read(dir));
136662306a36Sopenharmony_ci
136762306a36Sopenharmony_ci	brelse(di_bh);
136862306a36Sopenharmony_ciout:
136962306a36Sopenharmony_ci	return ret;
137062306a36Sopenharmony_ci}
137162306a36Sopenharmony_ci
137262306a36Sopenharmony_cistatic inline int ocfs2_delete_entry_el(handle_t *handle,
137362306a36Sopenharmony_ci					struct inode *dir,
137462306a36Sopenharmony_ci					struct ocfs2_dir_entry *de_del,
137562306a36Sopenharmony_ci					struct buffer_head *bh)
137662306a36Sopenharmony_ci{
137762306a36Sopenharmony_ci	return __ocfs2_delete_entry(handle, dir, de_del, bh, bh->b_data,
137862306a36Sopenharmony_ci				    bh->b_size);
137962306a36Sopenharmony_ci}
138062306a36Sopenharmony_ci
138162306a36Sopenharmony_ci/*
138262306a36Sopenharmony_ci * Delete a directory entry. Hide the details of directory
138362306a36Sopenharmony_ci * implementation from the caller.
138462306a36Sopenharmony_ci */
138562306a36Sopenharmony_ciint ocfs2_delete_entry(handle_t *handle,
138662306a36Sopenharmony_ci		       struct inode *dir,
138762306a36Sopenharmony_ci		       struct ocfs2_dir_lookup_result *res)
138862306a36Sopenharmony_ci{
138962306a36Sopenharmony_ci	if (ocfs2_dir_indexed(dir))
139062306a36Sopenharmony_ci		return ocfs2_delete_entry_dx(handle, dir, res);
139162306a36Sopenharmony_ci
139262306a36Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
139362306a36Sopenharmony_ci		return ocfs2_delete_entry_id(handle, dir, res->dl_entry,
139462306a36Sopenharmony_ci					     res->dl_leaf_bh);
139562306a36Sopenharmony_ci
139662306a36Sopenharmony_ci	return ocfs2_delete_entry_el(handle, dir, res->dl_entry,
139762306a36Sopenharmony_ci				     res->dl_leaf_bh);
139862306a36Sopenharmony_ci}
139962306a36Sopenharmony_ci
140062306a36Sopenharmony_ci/*
140162306a36Sopenharmony_ci * Check whether 'de' has enough room to hold an entry of
140262306a36Sopenharmony_ci * 'new_rec_len' bytes.
140362306a36Sopenharmony_ci */
140462306a36Sopenharmony_cistatic inline int ocfs2_dirent_would_fit(struct ocfs2_dir_entry *de,
140562306a36Sopenharmony_ci					 unsigned int new_rec_len)
140662306a36Sopenharmony_ci{
140762306a36Sopenharmony_ci	unsigned int de_really_used;
140862306a36Sopenharmony_ci
140962306a36Sopenharmony_ci	/* Check whether this is an empty record with enough space */
141062306a36Sopenharmony_ci	if (le64_to_cpu(de->inode) == 0 &&
141162306a36Sopenharmony_ci	    le16_to_cpu(de->rec_len) >= new_rec_len)
141262306a36Sopenharmony_ci		return 1;
141362306a36Sopenharmony_ci
141462306a36Sopenharmony_ci	/*
141562306a36Sopenharmony_ci	 * Record might have free space at the end which we can
141662306a36Sopenharmony_ci	 * use.
141762306a36Sopenharmony_ci	 */
141862306a36Sopenharmony_ci	de_really_used = OCFS2_DIR_REC_LEN(de->name_len);
141962306a36Sopenharmony_ci	if (le16_to_cpu(de->rec_len) >= (de_really_used + new_rec_len))
142062306a36Sopenharmony_ci	    return 1;
142162306a36Sopenharmony_ci
142262306a36Sopenharmony_ci	return 0;
142362306a36Sopenharmony_ci}
142462306a36Sopenharmony_ci
142562306a36Sopenharmony_cistatic void ocfs2_dx_dir_leaf_insert_tail(struct ocfs2_dx_leaf *dx_leaf,
142662306a36Sopenharmony_ci					  struct ocfs2_dx_entry *dx_new_entry)
142762306a36Sopenharmony_ci{
142862306a36Sopenharmony_ci	int i;
142962306a36Sopenharmony_ci
143062306a36Sopenharmony_ci	i = le16_to_cpu(dx_leaf->dl_list.de_num_used);
143162306a36Sopenharmony_ci	dx_leaf->dl_list.de_entries[i] = *dx_new_entry;
143262306a36Sopenharmony_ci
143362306a36Sopenharmony_ci	le16_add_cpu(&dx_leaf->dl_list.de_num_used, 1);
143462306a36Sopenharmony_ci}
143562306a36Sopenharmony_ci
143662306a36Sopenharmony_cistatic void ocfs2_dx_entry_list_insert(struct ocfs2_dx_entry_list *entry_list,
143762306a36Sopenharmony_ci				       struct ocfs2_dx_hinfo *hinfo,
143862306a36Sopenharmony_ci				       u64 dirent_blk)
143962306a36Sopenharmony_ci{
144062306a36Sopenharmony_ci	int i;
144162306a36Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry;
144262306a36Sopenharmony_ci
144362306a36Sopenharmony_ci	i = le16_to_cpu(entry_list->de_num_used);
144462306a36Sopenharmony_ci	dx_entry = &entry_list->de_entries[i];
144562306a36Sopenharmony_ci
144662306a36Sopenharmony_ci	memset(dx_entry, 0, sizeof(*dx_entry));
144762306a36Sopenharmony_ci	dx_entry->dx_major_hash = cpu_to_le32(hinfo->major_hash);
144862306a36Sopenharmony_ci	dx_entry->dx_minor_hash = cpu_to_le32(hinfo->minor_hash);
144962306a36Sopenharmony_ci	dx_entry->dx_dirent_blk = cpu_to_le64(dirent_blk);
145062306a36Sopenharmony_ci
145162306a36Sopenharmony_ci	le16_add_cpu(&entry_list->de_num_used, 1);
145262306a36Sopenharmony_ci}
145362306a36Sopenharmony_ci
145462306a36Sopenharmony_cistatic int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle,
145562306a36Sopenharmony_ci				      struct ocfs2_dx_hinfo *hinfo,
145662306a36Sopenharmony_ci				      u64 dirent_blk,
145762306a36Sopenharmony_ci				      struct buffer_head *dx_leaf_bh)
145862306a36Sopenharmony_ci{
145962306a36Sopenharmony_ci	int ret;
146062306a36Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
146162306a36Sopenharmony_ci
146262306a36Sopenharmony_ci	ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
146362306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
146462306a36Sopenharmony_ci	if (ret) {
146562306a36Sopenharmony_ci		mlog_errno(ret);
146662306a36Sopenharmony_ci		goto out;
146762306a36Sopenharmony_ci	}
146862306a36Sopenharmony_ci
146962306a36Sopenharmony_ci	dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_bh->b_data;
147062306a36Sopenharmony_ci	ocfs2_dx_entry_list_insert(&dx_leaf->dl_list, hinfo, dirent_blk);
147162306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_leaf_bh);
147262306a36Sopenharmony_ci
147362306a36Sopenharmony_ciout:
147462306a36Sopenharmony_ci	return ret;
147562306a36Sopenharmony_ci}
147662306a36Sopenharmony_ci
147762306a36Sopenharmony_cistatic void ocfs2_dx_inline_root_insert(struct inode *dir, handle_t *handle,
147862306a36Sopenharmony_ci					struct ocfs2_dx_hinfo *hinfo,
147962306a36Sopenharmony_ci					u64 dirent_blk,
148062306a36Sopenharmony_ci					struct ocfs2_dx_root_block *dx_root)
148162306a36Sopenharmony_ci{
148262306a36Sopenharmony_ci	ocfs2_dx_entry_list_insert(&dx_root->dr_entries, hinfo, dirent_blk);
148362306a36Sopenharmony_ci}
148462306a36Sopenharmony_ci
148562306a36Sopenharmony_cistatic int ocfs2_dx_dir_insert(struct inode *dir, handle_t *handle,
148662306a36Sopenharmony_ci			       struct ocfs2_dir_lookup_result *lookup)
148762306a36Sopenharmony_ci{
148862306a36Sopenharmony_ci	int ret = 0;
148962306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
149062306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
149162306a36Sopenharmony_ci
149262306a36Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
149362306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
149462306a36Sopenharmony_ci	if (ret) {
149562306a36Sopenharmony_ci		mlog_errno(ret);
149662306a36Sopenharmony_ci		goto out;
149762306a36Sopenharmony_ci	}
149862306a36Sopenharmony_ci
149962306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)lookup->dl_dx_root_bh->b_data;
150062306a36Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root)) {
150162306a36Sopenharmony_ci		ocfs2_dx_inline_root_insert(dir, handle,
150262306a36Sopenharmony_ci					    &lookup->dl_hinfo,
150362306a36Sopenharmony_ci					    lookup->dl_leaf_bh->b_blocknr,
150462306a36Sopenharmony_ci					    dx_root);
150562306a36Sopenharmony_ci	} else {
150662306a36Sopenharmony_ci		ret = __ocfs2_dx_dir_leaf_insert(dir, handle, &lookup->dl_hinfo,
150762306a36Sopenharmony_ci						 lookup->dl_leaf_bh->b_blocknr,
150862306a36Sopenharmony_ci						 lookup->dl_dx_leaf_bh);
150962306a36Sopenharmony_ci		if (ret)
151062306a36Sopenharmony_ci			goto out;
151162306a36Sopenharmony_ci	}
151262306a36Sopenharmony_ci
151362306a36Sopenharmony_ci	le32_add_cpu(&dx_root->dr_num_entries, 1);
151462306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
151562306a36Sopenharmony_ci
151662306a36Sopenharmony_ciout:
151762306a36Sopenharmony_ci	return ret;
151862306a36Sopenharmony_ci}
151962306a36Sopenharmony_ci
152062306a36Sopenharmony_cistatic void ocfs2_remove_block_from_free_list(struct inode *dir,
152162306a36Sopenharmony_ci				       handle_t *handle,
152262306a36Sopenharmony_ci				       struct ocfs2_dir_lookup_result *lookup)
152362306a36Sopenharmony_ci{
152462306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer, *prev;
152562306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
152662306a36Sopenharmony_ci	struct buffer_head *bh;
152762306a36Sopenharmony_ci
152862306a36Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(lookup->dl_leaf_bh, dir->i_sb);
152962306a36Sopenharmony_ci
153062306a36Sopenharmony_ci	if (ocfs2_free_list_at_root(lookup)) {
153162306a36Sopenharmony_ci		bh = lookup->dl_dx_root_bh;
153262306a36Sopenharmony_ci		dx_root = (struct ocfs2_dx_root_block *)bh->b_data;
153362306a36Sopenharmony_ci		dx_root->dr_free_blk = trailer->db_free_next;
153462306a36Sopenharmony_ci	} else {
153562306a36Sopenharmony_ci		bh = lookup->dl_prev_leaf_bh;
153662306a36Sopenharmony_ci		prev = ocfs2_trailer_from_bh(bh, dir->i_sb);
153762306a36Sopenharmony_ci		prev->db_free_next = trailer->db_free_next;
153862306a36Sopenharmony_ci	}
153962306a36Sopenharmony_ci
154062306a36Sopenharmony_ci	trailer->db_free_rec_len = cpu_to_le16(0);
154162306a36Sopenharmony_ci	trailer->db_free_next = cpu_to_le64(0);
154262306a36Sopenharmony_ci
154362306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, bh);
154462306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, lookup->dl_leaf_bh);
154562306a36Sopenharmony_ci}
154662306a36Sopenharmony_ci
154762306a36Sopenharmony_ci/*
154862306a36Sopenharmony_ci * This expects that a journal write has been reserved on
154962306a36Sopenharmony_ci * lookup->dl_prev_leaf_bh or lookup->dl_dx_root_bh
155062306a36Sopenharmony_ci */
155162306a36Sopenharmony_cistatic void ocfs2_recalc_free_list(struct inode *dir, handle_t *handle,
155262306a36Sopenharmony_ci				   struct ocfs2_dir_lookup_result *lookup)
155362306a36Sopenharmony_ci{
155462306a36Sopenharmony_ci	int max_rec_len;
155562306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
155662306a36Sopenharmony_ci
155762306a36Sopenharmony_ci	/* Walk dl_leaf_bh to figure out what the new free rec_len is. */
155862306a36Sopenharmony_ci	max_rec_len = ocfs2_find_max_rec_len(dir->i_sb, lookup->dl_leaf_bh);
155962306a36Sopenharmony_ci	if (max_rec_len) {
156062306a36Sopenharmony_ci		/*
156162306a36Sopenharmony_ci		 * There's still room in this block, so no need to remove it
156262306a36Sopenharmony_ci		 * from the free list. In this case, we just want to update
156362306a36Sopenharmony_ci		 * the rec len accounting.
156462306a36Sopenharmony_ci		 */
156562306a36Sopenharmony_ci		trailer = ocfs2_trailer_from_bh(lookup->dl_leaf_bh, dir->i_sb);
156662306a36Sopenharmony_ci		trailer->db_free_rec_len = cpu_to_le16(max_rec_len);
156762306a36Sopenharmony_ci		ocfs2_journal_dirty(handle, lookup->dl_leaf_bh);
156862306a36Sopenharmony_ci	} else {
156962306a36Sopenharmony_ci		ocfs2_remove_block_from_free_list(dir, handle, lookup);
157062306a36Sopenharmony_ci	}
157162306a36Sopenharmony_ci}
157262306a36Sopenharmony_ci
157362306a36Sopenharmony_ci/* we don't always have a dentry for what we want to add, so people
157462306a36Sopenharmony_ci * like orphan dir can call this instead.
157562306a36Sopenharmony_ci *
157662306a36Sopenharmony_ci * The lookup context must have been filled from
157762306a36Sopenharmony_ci * ocfs2_prepare_dir_for_insert.
157862306a36Sopenharmony_ci */
157962306a36Sopenharmony_ciint __ocfs2_add_entry(handle_t *handle,
158062306a36Sopenharmony_ci		      struct inode *dir,
158162306a36Sopenharmony_ci		      const char *name, int namelen,
158262306a36Sopenharmony_ci		      struct inode *inode, u64 blkno,
158362306a36Sopenharmony_ci		      struct buffer_head *parent_fe_bh,
158462306a36Sopenharmony_ci		      struct ocfs2_dir_lookup_result *lookup)
158562306a36Sopenharmony_ci{
158662306a36Sopenharmony_ci	unsigned long offset;
158762306a36Sopenharmony_ci	unsigned short rec_len;
158862306a36Sopenharmony_ci	struct ocfs2_dir_entry *de, *de1;
158962306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)parent_fe_bh->b_data;
159062306a36Sopenharmony_ci	struct super_block *sb = dir->i_sb;
159162306a36Sopenharmony_ci	int retval;
159262306a36Sopenharmony_ci	unsigned int size = sb->s_blocksize;
159362306a36Sopenharmony_ci	struct buffer_head *insert_bh = lookup->dl_leaf_bh;
159462306a36Sopenharmony_ci	char *data_start = insert_bh->b_data;
159562306a36Sopenharmony_ci
159662306a36Sopenharmony_ci	if (!namelen)
159762306a36Sopenharmony_ci		return -EINVAL;
159862306a36Sopenharmony_ci
159962306a36Sopenharmony_ci	if (ocfs2_dir_indexed(dir)) {
160062306a36Sopenharmony_ci		struct buffer_head *bh;
160162306a36Sopenharmony_ci
160262306a36Sopenharmony_ci		/*
160362306a36Sopenharmony_ci		 * An indexed dir may require that we update the free space
160462306a36Sopenharmony_ci		 * list. Reserve a write to the previous node in the list so
160562306a36Sopenharmony_ci		 * that we don't fail later.
160662306a36Sopenharmony_ci		 *
160762306a36Sopenharmony_ci		 * XXX: This can be either a dx_root_block, or an unindexed
160862306a36Sopenharmony_ci		 * directory tree leaf block.
160962306a36Sopenharmony_ci		 */
161062306a36Sopenharmony_ci		if (ocfs2_free_list_at_root(lookup)) {
161162306a36Sopenharmony_ci			bh = lookup->dl_dx_root_bh;
161262306a36Sopenharmony_ci			retval = ocfs2_journal_access_dr(handle,
161362306a36Sopenharmony_ci						 INODE_CACHE(dir), bh,
161462306a36Sopenharmony_ci						 OCFS2_JOURNAL_ACCESS_WRITE);
161562306a36Sopenharmony_ci		} else {
161662306a36Sopenharmony_ci			bh = lookup->dl_prev_leaf_bh;
161762306a36Sopenharmony_ci			retval = ocfs2_journal_access_db(handle,
161862306a36Sopenharmony_ci						 INODE_CACHE(dir), bh,
161962306a36Sopenharmony_ci						 OCFS2_JOURNAL_ACCESS_WRITE);
162062306a36Sopenharmony_ci		}
162162306a36Sopenharmony_ci		if (retval) {
162262306a36Sopenharmony_ci			mlog_errno(retval);
162362306a36Sopenharmony_ci			return retval;
162462306a36Sopenharmony_ci		}
162562306a36Sopenharmony_ci	} else if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
162662306a36Sopenharmony_ci		data_start = di->id2.i_data.id_data;
162762306a36Sopenharmony_ci		size = i_size_read(dir);
162862306a36Sopenharmony_ci
162962306a36Sopenharmony_ci		BUG_ON(insert_bh != parent_fe_bh);
163062306a36Sopenharmony_ci	}
163162306a36Sopenharmony_ci
163262306a36Sopenharmony_ci	rec_len = OCFS2_DIR_REC_LEN(namelen);
163362306a36Sopenharmony_ci	offset = 0;
163462306a36Sopenharmony_ci	de = (struct ocfs2_dir_entry *) data_start;
163562306a36Sopenharmony_ci	while (1) {
163662306a36Sopenharmony_ci		BUG_ON((char *)de >= (size + data_start));
163762306a36Sopenharmony_ci
163862306a36Sopenharmony_ci		/* These checks should've already been passed by the
163962306a36Sopenharmony_ci		 * prepare function, but I guess we can leave them
164062306a36Sopenharmony_ci		 * here anyway. */
164162306a36Sopenharmony_ci		if (!ocfs2_check_dir_entry(dir, de, insert_bh, offset)) {
164262306a36Sopenharmony_ci			retval = -ENOENT;
164362306a36Sopenharmony_ci			goto bail;
164462306a36Sopenharmony_ci		}
164562306a36Sopenharmony_ci		if (ocfs2_match(namelen, name, de)) {
164662306a36Sopenharmony_ci			retval = -EEXIST;
164762306a36Sopenharmony_ci			goto bail;
164862306a36Sopenharmony_ci		}
164962306a36Sopenharmony_ci
165062306a36Sopenharmony_ci		/* We're guaranteed that we should have space, so we
165162306a36Sopenharmony_ci		 * can't possibly have hit the trailer...right? */
165262306a36Sopenharmony_ci		mlog_bug_on_msg(ocfs2_skip_dir_trailer(dir, de, offset, size),
165362306a36Sopenharmony_ci				"Hit dir trailer trying to insert %.*s "
165462306a36Sopenharmony_ci			        "(namelen %d) into directory %llu.  "
165562306a36Sopenharmony_ci				"offset is %lu, trailer offset is %d\n",
165662306a36Sopenharmony_ci				namelen, name, namelen,
165762306a36Sopenharmony_ci				(unsigned long long)parent_fe_bh->b_blocknr,
165862306a36Sopenharmony_ci				offset, ocfs2_dir_trailer_blk_off(dir->i_sb));
165962306a36Sopenharmony_ci
166062306a36Sopenharmony_ci		if (ocfs2_dirent_would_fit(de, rec_len)) {
166162306a36Sopenharmony_ci			dir->i_mtime = inode_set_ctime_current(dir);
166262306a36Sopenharmony_ci			retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
166362306a36Sopenharmony_ci			if (retval < 0) {
166462306a36Sopenharmony_ci				mlog_errno(retval);
166562306a36Sopenharmony_ci				goto bail;
166662306a36Sopenharmony_ci			}
166762306a36Sopenharmony_ci
166862306a36Sopenharmony_ci			if (insert_bh == parent_fe_bh)
166962306a36Sopenharmony_ci				retval = ocfs2_journal_access_di(handle,
167062306a36Sopenharmony_ci								 INODE_CACHE(dir),
167162306a36Sopenharmony_ci								 insert_bh,
167262306a36Sopenharmony_ci								 OCFS2_JOURNAL_ACCESS_WRITE);
167362306a36Sopenharmony_ci			else {
167462306a36Sopenharmony_ci				retval = ocfs2_journal_access_db(handle,
167562306a36Sopenharmony_ci								 INODE_CACHE(dir),
167662306a36Sopenharmony_ci								 insert_bh,
167762306a36Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_WRITE);
167862306a36Sopenharmony_ci
167962306a36Sopenharmony_ci				if (!retval && ocfs2_dir_indexed(dir))
168062306a36Sopenharmony_ci					retval = ocfs2_dx_dir_insert(dir,
168162306a36Sopenharmony_ci								handle,
168262306a36Sopenharmony_ci								lookup);
168362306a36Sopenharmony_ci			}
168462306a36Sopenharmony_ci
168562306a36Sopenharmony_ci			if (retval) {
168662306a36Sopenharmony_ci				mlog_errno(retval);
168762306a36Sopenharmony_ci				goto bail;
168862306a36Sopenharmony_ci			}
168962306a36Sopenharmony_ci
169062306a36Sopenharmony_ci			/* By now the buffer is marked for journaling */
169162306a36Sopenharmony_ci			offset += le16_to_cpu(de->rec_len);
169262306a36Sopenharmony_ci			if (le64_to_cpu(de->inode)) {
169362306a36Sopenharmony_ci				de1 = (struct ocfs2_dir_entry *)((char *) de +
169462306a36Sopenharmony_ci					OCFS2_DIR_REC_LEN(de->name_len));
169562306a36Sopenharmony_ci				de1->rec_len =
169662306a36Sopenharmony_ci					cpu_to_le16(le16_to_cpu(de->rec_len) -
169762306a36Sopenharmony_ci					OCFS2_DIR_REC_LEN(de->name_len));
169862306a36Sopenharmony_ci				de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
169962306a36Sopenharmony_ci				de = de1;
170062306a36Sopenharmony_ci			}
170162306a36Sopenharmony_ci			de->file_type = FT_UNKNOWN;
170262306a36Sopenharmony_ci			if (blkno) {
170362306a36Sopenharmony_ci				de->inode = cpu_to_le64(blkno);
170462306a36Sopenharmony_ci				ocfs2_set_de_type(de, inode->i_mode);
170562306a36Sopenharmony_ci			} else
170662306a36Sopenharmony_ci				de->inode = 0;
170762306a36Sopenharmony_ci			de->name_len = namelen;
170862306a36Sopenharmony_ci			memcpy(de->name, name, namelen);
170962306a36Sopenharmony_ci
171062306a36Sopenharmony_ci			if (ocfs2_dir_indexed(dir))
171162306a36Sopenharmony_ci				ocfs2_recalc_free_list(dir, handle, lookup);
171262306a36Sopenharmony_ci
171362306a36Sopenharmony_ci			inode_inc_iversion(dir);
171462306a36Sopenharmony_ci			ocfs2_journal_dirty(handle, insert_bh);
171562306a36Sopenharmony_ci			retval = 0;
171662306a36Sopenharmony_ci			goto bail;
171762306a36Sopenharmony_ci		}
171862306a36Sopenharmony_ci
171962306a36Sopenharmony_ci		offset += le16_to_cpu(de->rec_len);
172062306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
172162306a36Sopenharmony_ci	}
172262306a36Sopenharmony_ci
172362306a36Sopenharmony_ci	/* when you think about it, the assert above should prevent us
172462306a36Sopenharmony_ci	 * from ever getting here. */
172562306a36Sopenharmony_ci	retval = -ENOSPC;
172662306a36Sopenharmony_cibail:
172762306a36Sopenharmony_ci	if (retval)
172862306a36Sopenharmony_ci		mlog_errno(retval);
172962306a36Sopenharmony_ci
173062306a36Sopenharmony_ci	return retval;
173162306a36Sopenharmony_ci}
173262306a36Sopenharmony_ci
173362306a36Sopenharmony_cistatic int ocfs2_dir_foreach_blk_id(struct inode *inode,
173462306a36Sopenharmony_ci				    u64 *f_version,
173562306a36Sopenharmony_ci				    struct dir_context *ctx)
173662306a36Sopenharmony_ci{
173762306a36Sopenharmony_ci	int ret, i;
173862306a36Sopenharmony_ci	unsigned long offset = ctx->pos;
173962306a36Sopenharmony_ci	struct buffer_head *di_bh = NULL;
174062306a36Sopenharmony_ci	struct ocfs2_dinode *di;
174162306a36Sopenharmony_ci	struct ocfs2_inline_data *data;
174262306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
174362306a36Sopenharmony_ci
174462306a36Sopenharmony_ci	ret = ocfs2_read_inode_block(inode, &di_bh);
174562306a36Sopenharmony_ci	if (ret) {
174662306a36Sopenharmony_ci		mlog(ML_ERROR, "Unable to read inode block for dir %llu\n",
174762306a36Sopenharmony_ci		     (unsigned long long)OCFS2_I(inode)->ip_blkno);
174862306a36Sopenharmony_ci		goto out;
174962306a36Sopenharmony_ci	}
175062306a36Sopenharmony_ci
175162306a36Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
175262306a36Sopenharmony_ci	data = &di->id2.i_data;
175362306a36Sopenharmony_ci
175462306a36Sopenharmony_ci	while (ctx->pos < i_size_read(inode)) {
175562306a36Sopenharmony_ci		/* If the dir block has changed since the last call to
175662306a36Sopenharmony_ci		 * readdir(2), then we might be pointing to an invalid
175762306a36Sopenharmony_ci		 * dirent right now.  Scan from the start of the block
175862306a36Sopenharmony_ci		 * to make sure. */
175962306a36Sopenharmony_ci		if (!inode_eq_iversion(inode, *f_version)) {
176062306a36Sopenharmony_ci			for (i = 0; i < i_size_read(inode) && i < offset; ) {
176162306a36Sopenharmony_ci				de = (struct ocfs2_dir_entry *)
176262306a36Sopenharmony_ci					(data->id_data + i);
176362306a36Sopenharmony_ci				/* It's too expensive to do a full
176462306a36Sopenharmony_ci				 * dirent test each time round this
176562306a36Sopenharmony_ci				 * loop, but we do have to test at
176662306a36Sopenharmony_ci				 * least that it is non-zero.  A
176762306a36Sopenharmony_ci				 * failure will be detected in the
176862306a36Sopenharmony_ci				 * dirent test below. */
176962306a36Sopenharmony_ci				if (le16_to_cpu(de->rec_len) <
177062306a36Sopenharmony_ci				    OCFS2_DIR_REC_LEN(1))
177162306a36Sopenharmony_ci					break;
177262306a36Sopenharmony_ci				i += le16_to_cpu(de->rec_len);
177362306a36Sopenharmony_ci			}
177462306a36Sopenharmony_ci			ctx->pos = offset = i;
177562306a36Sopenharmony_ci			*f_version = inode_query_iversion(inode);
177662306a36Sopenharmony_ci		}
177762306a36Sopenharmony_ci
177862306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *) (data->id_data + ctx->pos);
177962306a36Sopenharmony_ci		if (!ocfs2_check_dir_entry(inode, de, di_bh, ctx->pos)) {
178062306a36Sopenharmony_ci			/* On error, skip the f_pos to the end. */
178162306a36Sopenharmony_ci			ctx->pos = i_size_read(inode);
178262306a36Sopenharmony_ci			break;
178362306a36Sopenharmony_ci		}
178462306a36Sopenharmony_ci		offset += le16_to_cpu(de->rec_len);
178562306a36Sopenharmony_ci		if (le64_to_cpu(de->inode)) {
178662306a36Sopenharmony_ci			if (!dir_emit(ctx, de->name, de->name_len,
178762306a36Sopenharmony_ci				      le64_to_cpu(de->inode),
178862306a36Sopenharmony_ci				      fs_ftype_to_dtype(de->file_type)))
178962306a36Sopenharmony_ci				goto out;
179062306a36Sopenharmony_ci		}
179162306a36Sopenharmony_ci		ctx->pos += le16_to_cpu(de->rec_len);
179262306a36Sopenharmony_ci	}
179362306a36Sopenharmony_ciout:
179462306a36Sopenharmony_ci	brelse(di_bh);
179562306a36Sopenharmony_ci	return 0;
179662306a36Sopenharmony_ci}
179762306a36Sopenharmony_ci
179862306a36Sopenharmony_ci/*
179962306a36Sopenharmony_ci * NOTE: This function can be called against unindexed directories,
180062306a36Sopenharmony_ci * and indexed ones.
180162306a36Sopenharmony_ci */
180262306a36Sopenharmony_cistatic int ocfs2_dir_foreach_blk_el(struct inode *inode,
180362306a36Sopenharmony_ci				    u64 *f_version,
180462306a36Sopenharmony_ci				    struct dir_context *ctx,
180562306a36Sopenharmony_ci				    bool persist)
180662306a36Sopenharmony_ci{
180762306a36Sopenharmony_ci	unsigned long offset, blk, last_ra_blk = 0;
180862306a36Sopenharmony_ci	int i;
180962306a36Sopenharmony_ci	struct buffer_head * bh, * tmp;
181062306a36Sopenharmony_ci	struct ocfs2_dir_entry * de;
181162306a36Sopenharmony_ci	struct super_block * sb = inode->i_sb;
181262306a36Sopenharmony_ci	unsigned int ra_sectors = 16;
181362306a36Sopenharmony_ci	int stored = 0;
181462306a36Sopenharmony_ci
181562306a36Sopenharmony_ci	bh = NULL;
181662306a36Sopenharmony_ci
181762306a36Sopenharmony_ci	offset = ctx->pos & (sb->s_blocksize - 1);
181862306a36Sopenharmony_ci
181962306a36Sopenharmony_ci	while (ctx->pos < i_size_read(inode)) {
182062306a36Sopenharmony_ci		blk = ctx->pos >> sb->s_blocksize_bits;
182162306a36Sopenharmony_ci		if (ocfs2_read_dir_block(inode, blk, &bh, 0)) {
182262306a36Sopenharmony_ci			/* Skip the corrupt dirblock and keep trying */
182362306a36Sopenharmony_ci			ctx->pos += sb->s_blocksize - offset;
182462306a36Sopenharmony_ci			continue;
182562306a36Sopenharmony_ci		}
182662306a36Sopenharmony_ci
182762306a36Sopenharmony_ci		/* The idea here is to begin with 8k read-ahead and to stay
182862306a36Sopenharmony_ci		 * 4k ahead of our current position.
182962306a36Sopenharmony_ci		 *
183062306a36Sopenharmony_ci		 * TODO: Use the pagecache for this. We just need to
183162306a36Sopenharmony_ci		 * make sure it's cluster-safe... */
183262306a36Sopenharmony_ci		if (!last_ra_blk
183362306a36Sopenharmony_ci		    || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) {
183462306a36Sopenharmony_ci			for (i = ra_sectors >> (sb->s_blocksize_bits - 9);
183562306a36Sopenharmony_ci			     i > 0; i--) {
183662306a36Sopenharmony_ci				tmp = NULL;
183762306a36Sopenharmony_ci				if (!ocfs2_read_dir_block(inode, ++blk, &tmp,
183862306a36Sopenharmony_ci							  OCFS2_BH_READAHEAD))
183962306a36Sopenharmony_ci					brelse(tmp);
184062306a36Sopenharmony_ci			}
184162306a36Sopenharmony_ci			last_ra_blk = blk;
184262306a36Sopenharmony_ci			ra_sectors = 8;
184362306a36Sopenharmony_ci		}
184462306a36Sopenharmony_ci
184562306a36Sopenharmony_ci		/* If the dir block has changed since the last call to
184662306a36Sopenharmony_ci		 * readdir(2), then we might be pointing to an invalid
184762306a36Sopenharmony_ci		 * dirent right now.  Scan from the start of the block
184862306a36Sopenharmony_ci		 * to make sure. */
184962306a36Sopenharmony_ci		if (!inode_eq_iversion(inode, *f_version)) {
185062306a36Sopenharmony_ci			for (i = 0; i < sb->s_blocksize && i < offset; ) {
185162306a36Sopenharmony_ci				de = (struct ocfs2_dir_entry *) (bh->b_data + i);
185262306a36Sopenharmony_ci				/* It's too expensive to do a full
185362306a36Sopenharmony_ci				 * dirent test each time round this
185462306a36Sopenharmony_ci				 * loop, but we do have to test at
185562306a36Sopenharmony_ci				 * least that it is non-zero.  A
185662306a36Sopenharmony_ci				 * failure will be detected in the
185762306a36Sopenharmony_ci				 * dirent test below. */
185862306a36Sopenharmony_ci				if (le16_to_cpu(de->rec_len) <
185962306a36Sopenharmony_ci				    OCFS2_DIR_REC_LEN(1))
186062306a36Sopenharmony_ci					break;
186162306a36Sopenharmony_ci				i += le16_to_cpu(de->rec_len);
186262306a36Sopenharmony_ci			}
186362306a36Sopenharmony_ci			offset = i;
186462306a36Sopenharmony_ci			ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1))
186562306a36Sopenharmony_ci				| offset;
186662306a36Sopenharmony_ci			*f_version = inode_query_iversion(inode);
186762306a36Sopenharmony_ci		}
186862306a36Sopenharmony_ci
186962306a36Sopenharmony_ci		while (ctx->pos < i_size_read(inode)
187062306a36Sopenharmony_ci		       && offset < sb->s_blocksize) {
187162306a36Sopenharmony_ci			de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
187262306a36Sopenharmony_ci			if (!ocfs2_check_dir_entry(inode, de, bh, offset)) {
187362306a36Sopenharmony_ci				/* On error, skip the f_pos to the
187462306a36Sopenharmony_ci				   next block. */
187562306a36Sopenharmony_ci				ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1;
187662306a36Sopenharmony_ci				break;
187762306a36Sopenharmony_ci			}
187862306a36Sopenharmony_ci			if (le64_to_cpu(de->inode)) {
187962306a36Sopenharmony_ci				if (!dir_emit(ctx, de->name,
188062306a36Sopenharmony_ci						de->name_len,
188162306a36Sopenharmony_ci						le64_to_cpu(de->inode),
188262306a36Sopenharmony_ci					fs_ftype_to_dtype(de->file_type))) {
188362306a36Sopenharmony_ci					brelse(bh);
188462306a36Sopenharmony_ci					return 0;
188562306a36Sopenharmony_ci				}
188662306a36Sopenharmony_ci				stored++;
188762306a36Sopenharmony_ci			}
188862306a36Sopenharmony_ci			offset += le16_to_cpu(de->rec_len);
188962306a36Sopenharmony_ci			ctx->pos += le16_to_cpu(de->rec_len);
189062306a36Sopenharmony_ci		}
189162306a36Sopenharmony_ci		offset = 0;
189262306a36Sopenharmony_ci		brelse(bh);
189362306a36Sopenharmony_ci		bh = NULL;
189462306a36Sopenharmony_ci		if (!persist && stored)
189562306a36Sopenharmony_ci			break;
189662306a36Sopenharmony_ci	}
189762306a36Sopenharmony_ci	return 0;
189862306a36Sopenharmony_ci}
189962306a36Sopenharmony_ci
190062306a36Sopenharmony_cistatic int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version,
190162306a36Sopenharmony_ci				 struct dir_context *ctx,
190262306a36Sopenharmony_ci				 bool persist)
190362306a36Sopenharmony_ci{
190462306a36Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
190562306a36Sopenharmony_ci		return ocfs2_dir_foreach_blk_id(inode, f_version, ctx);
190662306a36Sopenharmony_ci	return ocfs2_dir_foreach_blk_el(inode, f_version, ctx, persist);
190762306a36Sopenharmony_ci}
190862306a36Sopenharmony_ci
190962306a36Sopenharmony_ci/*
191062306a36Sopenharmony_ci * This is intended to be called from inside other kernel functions,
191162306a36Sopenharmony_ci * so we fake some arguments.
191262306a36Sopenharmony_ci */
191362306a36Sopenharmony_ciint ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx)
191462306a36Sopenharmony_ci{
191562306a36Sopenharmony_ci	u64 version = inode_query_iversion(inode);
191662306a36Sopenharmony_ci	ocfs2_dir_foreach_blk(inode, &version, ctx, true);
191762306a36Sopenharmony_ci	return 0;
191862306a36Sopenharmony_ci}
191962306a36Sopenharmony_ci
192062306a36Sopenharmony_ci/*
192162306a36Sopenharmony_ci * ocfs2_readdir()
192262306a36Sopenharmony_ci *
192362306a36Sopenharmony_ci */
192462306a36Sopenharmony_ciint ocfs2_readdir(struct file *file, struct dir_context *ctx)
192562306a36Sopenharmony_ci{
192662306a36Sopenharmony_ci	int error = 0;
192762306a36Sopenharmony_ci	struct inode *inode = file_inode(file);
192862306a36Sopenharmony_ci	int lock_level = 0;
192962306a36Sopenharmony_ci
193062306a36Sopenharmony_ci	trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno);
193162306a36Sopenharmony_ci
193262306a36Sopenharmony_ci	error = ocfs2_inode_lock_atime(inode, file->f_path.mnt, &lock_level, 1);
193362306a36Sopenharmony_ci	if (lock_level && error >= 0) {
193462306a36Sopenharmony_ci		/* We release EX lock which used to update atime
193562306a36Sopenharmony_ci		 * and get PR lock again to reduce contention
193662306a36Sopenharmony_ci		 * on commonly accessed directories. */
193762306a36Sopenharmony_ci		ocfs2_inode_unlock(inode, 1);
193862306a36Sopenharmony_ci		lock_level = 0;
193962306a36Sopenharmony_ci		error = ocfs2_inode_lock(inode, NULL, 0);
194062306a36Sopenharmony_ci	}
194162306a36Sopenharmony_ci	if (error < 0) {
194262306a36Sopenharmony_ci		if (error != -ENOENT)
194362306a36Sopenharmony_ci			mlog_errno(error);
194462306a36Sopenharmony_ci		/* we haven't got any yet, so propagate the error. */
194562306a36Sopenharmony_ci		goto bail_nolock;
194662306a36Sopenharmony_ci	}
194762306a36Sopenharmony_ci
194862306a36Sopenharmony_ci	error = ocfs2_dir_foreach_blk(inode, &file->f_version, ctx, false);
194962306a36Sopenharmony_ci
195062306a36Sopenharmony_ci	ocfs2_inode_unlock(inode, lock_level);
195162306a36Sopenharmony_ci	if (error)
195262306a36Sopenharmony_ci		mlog_errno(error);
195362306a36Sopenharmony_ci
195462306a36Sopenharmony_cibail_nolock:
195562306a36Sopenharmony_ci
195662306a36Sopenharmony_ci	return error;
195762306a36Sopenharmony_ci}
195862306a36Sopenharmony_ci
195962306a36Sopenharmony_ci/*
196062306a36Sopenharmony_ci * NOTE: this should always be called with parent dir i_rwsem taken.
196162306a36Sopenharmony_ci */
196262306a36Sopenharmony_ciint ocfs2_find_files_on_disk(const char *name,
196362306a36Sopenharmony_ci			     int namelen,
196462306a36Sopenharmony_ci			     u64 *blkno,
196562306a36Sopenharmony_ci			     struct inode *inode,
196662306a36Sopenharmony_ci			     struct ocfs2_dir_lookup_result *lookup)
196762306a36Sopenharmony_ci{
196862306a36Sopenharmony_ci	int status = -ENOENT;
196962306a36Sopenharmony_ci
197062306a36Sopenharmony_ci	trace_ocfs2_find_files_on_disk(namelen, name, blkno,
197162306a36Sopenharmony_ci				(unsigned long long)OCFS2_I(inode)->ip_blkno);
197262306a36Sopenharmony_ci
197362306a36Sopenharmony_ci	status = ocfs2_find_entry(name, namelen, inode, lookup);
197462306a36Sopenharmony_ci	if (status)
197562306a36Sopenharmony_ci		goto leave;
197662306a36Sopenharmony_ci
197762306a36Sopenharmony_ci	*blkno = le64_to_cpu(lookup->dl_entry->inode);
197862306a36Sopenharmony_ci
197962306a36Sopenharmony_ci	status = 0;
198062306a36Sopenharmony_cileave:
198162306a36Sopenharmony_ci
198262306a36Sopenharmony_ci	return status;
198362306a36Sopenharmony_ci}
198462306a36Sopenharmony_ci
198562306a36Sopenharmony_ci/*
198662306a36Sopenharmony_ci * Convenience function for callers which just want the block number
198762306a36Sopenharmony_ci * mapped to a name and don't require the full dirent info, etc.
198862306a36Sopenharmony_ci */
198962306a36Sopenharmony_ciint ocfs2_lookup_ino_from_name(struct inode *dir, const char *name,
199062306a36Sopenharmony_ci			       int namelen, u64 *blkno)
199162306a36Sopenharmony_ci{
199262306a36Sopenharmony_ci	int ret;
199362306a36Sopenharmony_ci	struct ocfs2_dir_lookup_result lookup = { NULL, };
199462306a36Sopenharmony_ci
199562306a36Sopenharmony_ci	ret = ocfs2_find_files_on_disk(name, namelen, blkno, dir, &lookup);
199662306a36Sopenharmony_ci	ocfs2_free_dir_lookup_result(&lookup);
199762306a36Sopenharmony_ci
199862306a36Sopenharmony_ci	return ret;
199962306a36Sopenharmony_ci}
200062306a36Sopenharmony_ci
200162306a36Sopenharmony_ci/* Check for a name within a directory.
200262306a36Sopenharmony_ci *
200362306a36Sopenharmony_ci * Return 0 if the name does not exist
200462306a36Sopenharmony_ci * Return -EEXIST if the directory contains the name
200562306a36Sopenharmony_ci *
200662306a36Sopenharmony_ci * Callers should have i_rwsem + a cluster lock on dir
200762306a36Sopenharmony_ci */
200862306a36Sopenharmony_ciint ocfs2_check_dir_for_entry(struct inode *dir,
200962306a36Sopenharmony_ci			      const char *name,
201062306a36Sopenharmony_ci			      int namelen)
201162306a36Sopenharmony_ci{
201262306a36Sopenharmony_ci	int ret = 0;
201362306a36Sopenharmony_ci	struct ocfs2_dir_lookup_result lookup = { NULL, };
201462306a36Sopenharmony_ci
201562306a36Sopenharmony_ci	trace_ocfs2_check_dir_for_entry(
201662306a36Sopenharmony_ci		(unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name);
201762306a36Sopenharmony_ci
201862306a36Sopenharmony_ci	if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) {
201962306a36Sopenharmony_ci		ret = -EEXIST;
202062306a36Sopenharmony_ci		mlog_errno(ret);
202162306a36Sopenharmony_ci	}
202262306a36Sopenharmony_ci
202362306a36Sopenharmony_ci	ocfs2_free_dir_lookup_result(&lookup);
202462306a36Sopenharmony_ci
202562306a36Sopenharmony_ci	return ret;
202662306a36Sopenharmony_ci}
202762306a36Sopenharmony_ci
202862306a36Sopenharmony_cistruct ocfs2_empty_dir_priv {
202962306a36Sopenharmony_ci	struct dir_context ctx;
203062306a36Sopenharmony_ci	unsigned seen_dot;
203162306a36Sopenharmony_ci	unsigned seen_dot_dot;
203262306a36Sopenharmony_ci	unsigned seen_other;
203362306a36Sopenharmony_ci	unsigned dx_dir;
203462306a36Sopenharmony_ci};
203562306a36Sopenharmony_cistatic bool ocfs2_empty_dir_filldir(struct dir_context *ctx, const char *name,
203662306a36Sopenharmony_ci				   int name_len, loff_t pos, u64 ino,
203762306a36Sopenharmony_ci				   unsigned type)
203862306a36Sopenharmony_ci{
203962306a36Sopenharmony_ci	struct ocfs2_empty_dir_priv *p =
204062306a36Sopenharmony_ci		container_of(ctx, struct ocfs2_empty_dir_priv, ctx);
204162306a36Sopenharmony_ci
204262306a36Sopenharmony_ci	/*
204362306a36Sopenharmony_ci	 * Check the positions of "." and ".." records to be sure
204462306a36Sopenharmony_ci	 * they're in the correct place.
204562306a36Sopenharmony_ci	 *
204662306a36Sopenharmony_ci	 * Indexed directories don't need to proceed past the first
204762306a36Sopenharmony_ci	 * two entries, so we end the scan after seeing '..'. Despite
204862306a36Sopenharmony_ci	 * that, we allow the scan to proceed In the event that we
204962306a36Sopenharmony_ci	 * have a corrupted indexed directory (no dot or dot dot
205062306a36Sopenharmony_ci	 * entries). This allows us to double check for existing
205162306a36Sopenharmony_ci	 * entries which might not have been found in the index.
205262306a36Sopenharmony_ci	 */
205362306a36Sopenharmony_ci	if (name_len == 1 && !strncmp(".", name, 1) && pos == 0) {
205462306a36Sopenharmony_ci		p->seen_dot = 1;
205562306a36Sopenharmony_ci		return true;
205662306a36Sopenharmony_ci	}
205762306a36Sopenharmony_ci
205862306a36Sopenharmony_ci	if (name_len == 2 && !strncmp("..", name, 2) &&
205962306a36Sopenharmony_ci	    pos == OCFS2_DIR_REC_LEN(1)) {
206062306a36Sopenharmony_ci		p->seen_dot_dot = 1;
206162306a36Sopenharmony_ci
206262306a36Sopenharmony_ci		if (p->dx_dir && p->seen_dot)
206362306a36Sopenharmony_ci			return false;
206462306a36Sopenharmony_ci
206562306a36Sopenharmony_ci		return true;
206662306a36Sopenharmony_ci	}
206762306a36Sopenharmony_ci
206862306a36Sopenharmony_ci	p->seen_other = 1;
206962306a36Sopenharmony_ci	return false;
207062306a36Sopenharmony_ci}
207162306a36Sopenharmony_ci
207262306a36Sopenharmony_cistatic int ocfs2_empty_dir_dx(struct inode *inode,
207362306a36Sopenharmony_ci			      struct ocfs2_empty_dir_priv *priv)
207462306a36Sopenharmony_ci{
207562306a36Sopenharmony_ci	int ret;
207662306a36Sopenharmony_ci	struct buffer_head *di_bh = NULL;
207762306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
207862306a36Sopenharmony_ci	struct ocfs2_dinode *di;
207962306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
208062306a36Sopenharmony_ci
208162306a36Sopenharmony_ci	priv->dx_dir = 1;
208262306a36Sopenharmony_ci
208362306a36Sopenharmony_ci	ret = ocfs2_read_inode_block(inode, &di_bh);
208462306a36Sopenharmony_ci	if (ret) {
208562306a36Sopenharmony_ci		mlog_errno(ret);
208662306a36Sopenharmony_ci		goto out;
208762306a36Sopenharmony_ci	}
208862306a36Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
208962306a36Sopenharmony_ci
209062306a36Sopenharmony_ci	ret = ocfs2_read_dx_root(inode, di, &dx_root_bh);
209162306a36Sopenharmony_ci	if (ret) {
209262306a36Sopenharmony_ci		mlog_errno(ret);
209362306a36Sopenharmony_ci		goto out;
209462306a36Sopenharmony_ci	}
209562306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
209662306a36Sopenharmony_ci
209762306a36Sopenharmony_ci	if (le32_to_cpu(dx_root->dr_num_entries) != 2)
209862306a36Sopenharmony_ci		priv->seen_other = 1;
209962306a36Sopenharmony_ci
210062306a36Sopenharmony_ciout:
210162306a36Sopenharmony_ci	brelse(di_bh);
210262306a36Sopenharmony_ci	brelse(dx_root_bh);
210362306a36Sopenharmony_ci	return ret;
210462306a36Sopenharmony_ci}
210562306a36Sopenharmony_ci
210662306a36Sopenharmony_ci/*
210762306a36Sopenharmony_ci * routine to check that the specified directory is empty (for rmdir)
210862306a36Sopenharmony_ci *
210962306a36Sopenharmony_ci * Returns 1 if dir is empty, zero otherwise.
211062306a36Sopenharmony_ci *
211162306a36Sopenharmony_ci * XXX: This is a performance problem for unindexed directories.
211262306a36Sopenharmony_ci */
211362306a36Sopenharmony_ciint ocfs2_empty_dir(struct inode *inode)
211462306a36Sopenharmony_ci{
211562306a36Sopenharmony_ci	int ret;
211662306a36Sopenharmony_ci	struct ocfs2_empty_dir_priv priv = {
211762306a36Sopenharmony_ci		.ctx.actor = ocfs2_empty_dir_filldir,
211862306a36Sopenharmony_ci	};
211962306a36Sopenharmony_ci
212062306a36Sopenharmony_ci	if (ocfs2_dir_indexed(inode)) {
212162306a36Sopenharmony_ci		ret = ocfs2_empty_dir_dx(inode, &priv);
212262306a36Sopenharmony_ci		if (ret)
212362306a36Sopenharmony_ci			mlog_errno(ret);
212462306a36Sopenharmony_ci		/*
212562306a36Sopenharmony_ci		 * We still run ocfs2_dir_foreach to get the checks
212662306a36Sopenharmony_ci		 * for "." and "..".
212762306a36Sopenharmony_ci		 */
212862306a36Sopenharmony_ci	}
212962306a36Sopenharmony_ci
213062306a36Sopenharmony_ci	ret = ocfs2_dir_foreach(inode, &priv.ctx);
213162306a36Sopenharmony_ci	if (ret)
213262306a36Sopenharmony_ci		mlog_errno(ret);
213362306a36Sopenharmony_ci
213462306a36Sopenharmony_ci	if (!priv.seen_dot || !priv.seen_dot_dot) {
213562306a36Sopenharmony_ci		mlog(ML_ERROR, "bad directory (dir #%llu) - no `.' or `..'\n",
213662306a36Sopenharmony_ci		     (unsigned long long)OCFS2_I(inode)->ip_blkno);
213762306a36Sopenharmony_ci		/*
213862306a36Sopenharmony_ci		 * XXX: Is it really safe to allow an unlink to continue?
213962306a36Sopenharmony_ci		 */
214062306a36Sopenharmony_ci		return 1;
214162306a36Sopenharmony_ci	}
214262306a36Sopenharmony_ci
214362306a36Sopenharmony_ci	return !priv.seen_other;
214462306a36Sopenharmony_ci}
214562306a36Sopenharmony_ci
214662306a36Sopenharmony_ci/*
214762306a36Sopenharmony_ci * Fills "." and ".." dirents in a new directory block. Returns dirent for
214862306a36Sopenharmony_ci * "..", which might be used during creation of a directory with a trailing
214962306a36Sopenharmony_ci * header. It is otherwise safe to ignore the return code.
215062306a36Sopenharmony_ci */
215162306a36Sopenharmony_cistatic struct ocfs2_dir_entry *ocfs2_fill_initial_dirents(struct inode *inode,
215262306a36Sopenharmony_ci							  struct inode *parent,
215362306a36Sopenharmony_ci							  char *start,
215462306a36Sopenharmony_ci							  unsigned int size)
215562306a36Sopenharmony_ci{
215662306a36Sopenharmony_ci	struct ocfs2_dir_entry *de = (struct ocfs2_dir_entry *)start;
215762306a36Sopenharmony_ci
215862306a36Sopenharmony_ci	de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
215962306a36Sopenharmony_ci	de->name_len = 1;
216062306a36Sopenharmony_ci	de->rec_len =
216162306a36Sopenharmony_ci		cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
216262306a36Sopenharmony_ci	strcpy(de->name, ".");
216362306a36Sopenharmony_ci	ocfs2_set_de_type(de, S_IFDIR);
216462306a36Sopenharmony_ci
216562306a36Sopenharmony_ci	de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len));
216662306a36Sopenharmony_ci	de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno);
216762306a36Sopenharmony_ci	de->rec_len = cpu_to_le16(size - OCFS2_DIR_REC_LEN(1));
216862306a36Sopenharmony_ci	de->name_len = 2;
216962306a36Sopenharmony_ci	strcpy(de->name, "..");
217062306a36Sopenharmony_ci	ocfs2_set_de_type(de, S_IFDIR);
217162306a36Sopenharmony_ci
217262306a36Sopenharmony_ci	return de;
217362306a36Sopenharmony_ci}
217462306a36Sopenharmony_ci
217562306a36Sopenharmony_ci/*
217662306a36Sopenharmony_ci * This works together with code in ocfs2_mknod_locked() which sets
217762306a36Sopenharmony_ci * the inline-data flag and initializes the inline-data section.
217862306a36Sopenharmony_ci */
217962306a36Sopenharmony_cistatic int ocfs2_fill_new_dir_id(struct ocfs2_super *osb,
218062306a36Sopenharmony_ci				 handle_t *handle,
218162306a36Sopenharmony_ci				 struct inode *parent,
218262306a36Sopenharmony_ci				 struct inode *inode,
218362306a36Sopenharmony_ci				 struct buffer_head *di_bh)
218462306a36Sopenharmony_ci{
218562306a36Sopenharmony_ci	int ret;
218662306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
218762306a36Sopenharmony_ci	struct ocfs2_inline_data *data = &di->id2.i_data;
218862306a36Sopenharmony_ci	unsigned int size = le16_to_cpu(data->id_count);
218962306a36Sopenharmony_ci
219062306a36Sopenharmony_ci	ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
219162306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
219262306a36Sopenharmony_ci	if (ret) {
219362306a36Sopenharmony_ci		mlog_errno(ret);
219462306a36Sopenharmony_ci		goto out;
219562306a36Sopenharmony_ci	}
219662306a36Sopenharmony_ci
219762306a36Sopenharmony_ci	ocfs2_fill_initial_dirents(inode, parent, data->id_data, size);
219862306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
219962306a36Sopenharmony_ci
220062306a36Sopenharmony_ci	i_size_write(inode, size);
220162306a36Sopenharmony_ci	set_nlink(inode, 2);
220262306a36Sopenharmony_ci	inode->i_blocks = ocfs2_inode_sector_count(inode);
220362306a36Sopenharmony_ci
220462306a36Sopenharmony_ci	ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
220562306a36Sopenharmony_ci	if (ret < 0)
220662306a36Sopenharmony_ci		mlog_errno(ret);
220762306a36Sopenharmony_ci
220862306a36Sopenharmony_ciout:
220962306a36Sopenharmony_ci	return ret;
221062306a36Sopenharmony_ci}
221162306a36Sopenharmony_ci
221262306a36Sopenharmony_cistatic int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
221362306a36Sopenharmony_ci				 handle_t *handle,
221462306a36Sopenharmony_ci				 struct inode *parent,
221562306a36Sopenharmony_ci				 struct inode *inode,
221662306a36Sopenharmony_ci				 struct buffer_head *fe_bh,
221762306a36Sopenharmony_ci				 struct ocfs2_alloc_context *data_ac,
221862306a36Sopenharmony_ci				 struct buffer_head **ret_new_bh)
221962306a36Sopenharmony_ci{
222062306a36Sopenharmony_ci	int status;
222162306a36Sopenharmony_ci	unsigned int size = osb->sb->s_blocksize;
222262306a36Sopenharmony_ci	struct buffer_head *new_bh = NULL;
222362306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
222462306a36Sopenharmony_ci
222562306a36Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(inode))
222662306a36Sopenharmony_ci		size = ocfs2_dir_trailer_blk_off(parent->i_sb);
222762306a36Sopenharmony_ci
222862306a36Sopenharmony_ci	status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh,
222962306a36Sopenharmony_ci				     data_ac, NULL, &new_bh);
223062306a36Sopenharmony_ci	if (status < 0) {
223162306a36Sopenharmony_ci		mlog_errno(status);
223262306a36Sopenharmony_ci		goto bail;
223362306a36Sopenharmony_ci	}
223462306a36Sopenharmony_ci
223562306a36Sopenharmony_ci	ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), new_bh);
223662306a36Sopenharmony_ci
223762306a36Sopenharmony_ci	status = ocfs2_journal_access_db(handle, INODE_CACHE(inode), new_bh,
223862306a36Sopenharmony_ci					 OCFS2_JOURNAL_ACCESS_CREATE);
223962306a36Sopenharmony_ci	if (status < 0) {
224062306a36Sopenharmony_ci		mlog_errno(status);
224162306a36Sopenharmony_ci		goto bail;
224262306a36Sopenharmony_ci	}
224362306a36Sopenharmony_ci	memset(new_bh->b_data, 0, osb->sb->s_blocksize);
224462306a36Sopenharmony_ci
224562306a36Sopenharmony_ci	de = ocfs2_fill_initial_dirents(inode, parent, new_bh->b_data, size);
224662306a36Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(inode)) {
224762306a36Sopenharmony_ci		int size = le16_to_cpu(de->rec_len);
224862306a36Sopenharmony_ci
224962306a36Sopenharmony_ci		/*
225062306a36Sopenharmony_ci		 * Figure out the size of the hole left over after
225162306a36Sopenharmony_ci		 * insertion of '.' and '..'. The trailer wants this
225262306a36Sopenharmony_ci		 * information.
225362306a36Sopenharmony_ci		 */
225462306a36Sopenharmony_ci		size -= OCFS2_DIR_REC_LEN(2);
225562306a36Sopenharmony_ci		size -= sizeof(struct ocfs2_dir_block_trailer);
225662306a36Sopenharmony_ci
225762306a36Sopenharmony_ci		ocfs2_init_dir_trailer(inode, new_bh, size);
225862306a36Sopenharmony_ci	}
225962306a36Sopenharmony_ci
226062306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, new_bh);
226162306a36Sopenharmony_ci
226262306a36Sopenharmony_ci	i_size_write(inode, inode->i_sb->s_blocksize);
226362306a36Sopenharmony_ci	set_nlink(inode, 2);
226462306a36Sopenharmony_ci	inode->i_blocks = ocfs2_inode_sector_count(inode);
226562306a36Sopenharmony_ci	status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
226662306a36Sopenharmony_ci	if (status < 0) {
226762306a36Sopenharmony_ci		mlog_errno(status);
226862306a36Sopenharmony_ci		goto bail;
226962306a36Sopenharmony_ci	}
227062306a36Sopenharmony_ci
227162306a36Sopenharmony_ci	status = 0;
227262306a36Sopenharmony_ci	if (ret_new_bh) {
227362306a36Sopenharmony_ci		*ret_new_bh = new_bh;
227462306a36Sopenharmony_ci		new_bh = NULL;
227562306a36Sopenharmony_ci	}
227662306a36Sopenharmony_cibail:
227762306a36Sopenharmony_ci	brelse(new_bh);
227862306a36Sopenharmony_ci
227962306a36Sopenharmony_ci	return status;
228062306a36Sopenharmony_ci}
228162306a36Sopenharmony_ci
228262306a36Sopenharmony_cistatic int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
228362306a36Sopenharmony_ci				     handle_t *handle, struct inode *dir,
228462306a36Sopenharmony_ci				     struct buffer_head *di_bh,
228562306a36Sopenharmony_ci				     struct buffer_head *dirdata_bh,
228662306a36Sopenharmony_ci				     struct ocfs2_alloc_context *meta_ac,
228762306a36Sopenharmony_ci				     int dx_inline, u32 num_entries,
228862306a36Sopenharmony_ci				     struct buffer_head **ret_dx_root_bh)
228962306a36Sopenharmony_ci{
229062306a36Sopenharmony_ci	int ret;
229162306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
229262306a36Sopenharmony_ci	u16 dr_suballoc_bit;
229362306a36Sopenharmony_ci	u64 suballoc_loc, dr_blkno;
229462306a36Sopenharmony_ci	unsigned int num_bits;
229562306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
229662306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
229762306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer =
229862306a36Sopenharmony_ci		ocfs2_trailer_from_bh(dirdata_bh, dir->i_sb);
229962306a36Sopenharmony_ci
230062306a36Sopenharmony_ci	ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
230162306a36Sopenharmony_ci				   &dr_suballoc_bit, &num_bits, &dr_blkno);
230262306a36Sopenharmony_ci	if (ret) {
230362306a36Sopenharmony_ci		mlog_errno(ret);
230462306a36Sopenharmony_ci		goto out;
230562306a36Sopenharmony_ci	}
230662306a36Sopenharmony_ci
230762306a36Sopenharmony_ci	trace_ocfs2_dx_dir_attach_index(
230862306a36Sopenharmony_ci				(unsigned long long)OCFS2_I(dir)->ip_blkno,
230962306a36Sopenharmony_ci				(unsigned long long)dr_blkno);
231062306a36Sopenharmony_ci
231162306a36Sopenharmony_ci	dx_root_bh = sb_getblk(osb->sb, dr_blkno);
231262306a36Sopenharmony_ci	if (dx_root_bh == NULL) {
231362306a36Sopenharmony_ci		ret = -ENOMEM;
231462306a36Sopenharmony_ci		goto out;
231562306a36Sopenharmony_ci	}
231662306a36Sopenharmony_ci	ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dx_root_bh);
231762306a36Sopenharmony_ci
231862306a36Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
231962306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_CREATE);
232062306a36Sopenharmony_ci	if (ret < 0) {
232162306a36Sopenharmony_ci		mlog_errno(ret);
232262306a36Sopenharmony_ci		goto out;
232362306a36Sopenharmony_ci	}
232462306a36Sopenharmony_ci
232562306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
232662306a36Sopenharmony_ci	memset(dx_root, 0, osb->sb->s_blocksize);
232762306a36Sopenharmony_ci	strcpy(dx_root->dr_signature, OCFS2_DX_ROOT_SIGNATURE);
232862306a36Sopenharmony_ci	dx_root->dr_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
232962306a36Sopenharmony_ci	dx_root->dr_suballoc_loc = cpu_to_le64(suballoc_loc);
233062306a36Sopenharmony_ci	dx_root->dr_suballoc_bit = cpu_to_le16(dr_suballoc_bit);
233162306a36Sopenharmony_ci	dx_root->dr_fs_generation = cpu_to_le32(osb->fs_generation);
233262306a36Sopenharmony_ci	dx_root->dr_blkno = cpu_to_le64(dr_blkno);
233362306a36Sopenharmony_ci	dx_root->dr_dir_blkno = cpu_to_le64(OCFS2_I(dir)->ip_blkno);
233462306a36Sopenharmony_ci	dx_root->dr_num_entries = cpu_to_le32(num_entries);
233562306a36Sopenharmony_ci	if (le16_to_cpu(trailer->db_free_rec_len))
233662306a36Sopenharmony_ci		dx_root->dr_free_blk = cpu_to_le64(dirdata_bh->b_blocknr);
233762306a36Sopenharmony_ci	else
233862306a36Sopenharmony_ci		dx_root->dr_free_blk = cpu_to_le64(0);
233962306a36Sopenharmony_ci
234062306a36Sopenharmony_ci	if (dx_inline) {
234162306a36Sopenharmony_ci		dx_root->dr_flags |= OCFS2_DX_FLAG_INLINE;
234262306a36Sopenharmony_ci		dx_root->dr_entries.de_count =
234362306a36Sopenharmony_ci			cpu_to_le16(ocfs2_dx_entries_per_root(osb->sb));
234462306a36Sopenharmony_ci	} else {
234562306a36Sopenharmony_ci		dx_root->dr_list.l_count =
234662306a36Sopenharmony_ci			cpu_to_le16(ocfs2_extent_recs_per_dx_root(osb->sb));
234762306a36Sopenharmony_ci	}
234862306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
234962306a36Sopenharmony_ci
235062306a36Sopenharmony_ci	ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
235162306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_CREATE);
235262306a36Sopenharmony_ci	if (ret) {
235362306a36Sopenharmony_ci		mlog_errno(ret);
235462306a36Sopenharmony_ci		goto out;
235562306a36Sopenharmony_ci	}
235662306a36Sopenharmony_ci
235762306a36Sopenharmony_ci	di->i_dx_root = cpu_to_le64(dr_blkno);
235862306a36Sopenharmony_ci
235962306a36Sopenharmony_ci	spin_lock(&OCFS2_I(dir)->ip_lock);
236062306a36Sopenharmony_ci	OCFS2_I(dir)->ip_dyn_features |= OCFS2_INDEXED_DIR_FL;
236162306a36Sopenharmony_ci	di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
236262306a36Sopenharmony_ci	spin_unlock(&OCFS2_I(dir)->ip_lock);
236362306a36Sopenharmony_ci
236462306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
236562306a36Sopenharmony_ci
236662306a36Sopenharmony_ci	*ret_dx_root_bh = dx_root_bh;
236762306a36Sopenharmony_ci	dx_root_bh = NULL;
236862306a36Sopenharmony_ci
236962306a36Sopenharmony_ciout:
237062306a36Sopenharmony_ci	brelse(dx_root_bh);
237162306a36Sopenharmony_ci	return ret;
237262306a36Sopenharmony_ci}
237362306a36Sopenharmony_ci
237462306a36Sopenharmony_cistatic int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb,
237562306a36Sopenharmony_ci				       handle_t *handle, struct inode *dir,
237662306a36Sopenharmony_ci				       struct buffer_head **dx_leaves,
237762306a36Sopenharmony_ci				       int num_dx_leaves, u64 start_blk)
237862306a36Sopenharmony_ci{
237962306a36Sopenharmony_ci	int ret, i;
238062306a36Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
238162306a36Sopenharmony_ci	struct buffer_head *bh;
238262306a36Sopenharmony_ci
238362306a36Sopenharmony_ci	for (i = 0; i < num_dx_leaves; i++) {
238462306a36Sopenharmony_ci		bh = sb_getblk(osb->sb, start_blk + i);
238562306a36Sopenharmony_ci		if (bh == NULL) {
238662306a36Sopenharmony_ci			ret = -ENOMEM;
238762306a36Sopenharmony_ci			goto out;
238862306a36Sopenharmony_ci		}
238962306a36Sopenharmony_ci		dx_leaves[i] = bh;
239062306a36Sopenharmony_ci
239162306a36Sopenharmony_ci		ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), bh);
239262306a36Sopenharmony_ci
239362306a36Sopenharmony_ci		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), bh,
239462306a36Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_CREATE);
239562306a36Sopenharmony_ci		if (ret < 0) {
239662306a36Sopenharmony_ci			mlog_errno(ret);
239762306a36Sopenharmony_ci			goto out;
239862306a36Sopenharmony_ci		}
239962306a36Sopenharmony_ci
240062306a36Sopenharmony_ci		dx_leaf = (struct ocfs2_dx_leaf *) bh->b_data;
240162306a36Sopenharmony_ci
240262306a36Sopenharmony_ci		memset(dx_leaf, 0, osb->sb->s_blocksize);
240362306a36Sopenharmony_ci		strcpy(dx_leaf->dl_signature, OCFS2_DX_LEAF_SIGNATURE);
240462306a36Sopenharmony_ci		dx_leaf->dl_fs_generation = cpu_to_le32(osb->fs_generation);
240562306a36Sopenharmony_ci		dx_leaf->dl_blkno = cpu_to_le64(bh->b_blocknr);
240662306a36Sopenharmony_ci		dx_leaf->dl_list.de_count =
240762306a36Sopenharmony_ci			cpu_to_le16(ocfs2_dx_entries_per_leaf(osb->sb));
240862306a36Sopenharmony_ci
240962306a36Sopenharmony_ci		trace_ocfs2_dx_dir_format_cluster(
241062306a36Sopenharmony_ci				(unsigned long long)OCFS2_I(dir)->ip_blkno,
241162306a36Sopenharmony_ci				(unsigned long long)bh->b_blocknr,
241262306a36Sopenharmony_ci				le16_to_cpu(dx_leaf->dl_list.de_count));
241362306a36Sopenharmony_ci
241462306a36Sopenharmony_ci		ocfs2_journal_dirty(handle, bh);
241562306a36Sopenharmony_ci	}
241662306a36Sopenharmony_ci
241762306a36Sopenharmony_ci	ret = 0;
241862306a36Sopenharmony_ciout:
241962306a36Sopenharmony_ci	return ret;
242062306a36Sopenharmony_ci}
242162306a36Sopenharmony_ci
242262306a36Sopenharmony_ci/*
242362306a36Sopenharmony_ci * Allocates and formats a new cluster for use in an indexed dir
242462306a36Sopenharmony_ci * leaf. This version will not do the extent insert, so that it can be
242562306a36Sopenharmony_ci * used by operations which need careful ordering.
242662306a36Sopenharmony_ci */
242762306a36Sopenharmony_cistatic int __ocfs2_dx_dir_new_cluster(struct inode *dir,
242862306a36Sopenharmony_ci				      u32 cpos, handle_t *handle,
242962306a36Sopenharmony_ci				      struct ocfs2_alloc_context *data_ac,
243062306a36Sopenharmony_ci				      struct buffer_head **dx_leaves,
243162306a36Sopenharmony_ci				      int num_dx_leaves, u64 *ret_phys_blkno)
243262306a36Sopenharmony_ci{
243362306a36Sopenharmony_ci	int ret;
243462306a36Sopenharmony_ci	u32 phys, num;
243562306a36Sopenharmony_ci	u64 phys_blkno;
243662306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
243762306a36Sopenharmony_ci
243862306a36Sopenharmony_ci	/*
243962306a36Sopenharmony_ci	 * XXX: For create, this should claim cluster for the index
244062306a36Sopenharmony_ci	 * *before* the unindexed insert so that we have a better
244162306a36Sopenharmony_ci	 * chance of contiguousness as the directory grows in number
244262306a36Sopenharmony_ci	 * of entries.
244362306a36Sopenharmony_ci	 */
244462306a36Sopenharmony_ci	ret = __ocfs2_claim_clusters(handle, data_ac, 1, 1, &phys, &num);
244562306a36Sopenharmony_ci	if (ret) {
244662306a36Sopenharmony_ci		mlog_errno(ret);
244762306a36Sopenharmony_ci		goto out;
244862306a36Sopenharmony_ci	}
244962306a36Sopenharmony_ci
245062306a36Sopenharmony_ci	/*
245162306a36Sopenharmony_ci	 * Format the new cluster first. That way, we're inserting
245262306a36Sopenharmony_ci	 * valid data.
245362306a36Sopenharmony_ci	 */
245462306a36Sopenharmony_ci	phys_blkno = ocfs2_clusters_to_blocks(osb->sb, phys);
245562306a36Sopenharmony_ci	ret = ocfs2_dx_dir_format_cluster(osb, handle, dir, dx_leaves,
245662306a36Sopenharmony_ci					  num_dx_leaves, phys_blkno);
245762306a36Sopenharmony_ci	if (ret) {
245862306a36Sopenharmony_ci		mlog_errno(ret);
245962306a36Sopenharmony_ci		goto out;
246062306a36Sopenharmony_ci	}
246162306a36Sopenharmony_ci
246262306a36Sopenharmony_ci	*ret_phys_blkno = phys_blkno;
246362306a36Sopenharmony_ciout:
246462306a36Sopenharmony_ci	return ret;
246562306a36Sopenharmony_ci}
246662306a36Sopenharmony_ci
246762306a36Sopenharmony_cistatic int ocfs2_dx_dir_new_cluster(struct inode *dir,
246862306a36Sopenharmony_ci				    struct ocfs2_extent_tree *et,
246962306a36Sopenharmony_ci				    u32 cpos, handle_t *handle,
247062306a36Sopenharmony_ci				    struct ocfs2_alloc_context *data_ac,
247162306a36Sopenharmony_ci				    struct ocfs2_alloc_context *meta_ac,
247262306a36Sopenharmony_ci				    struct buffer_head **dx_leaves,
247362306a36Sopenharmony_ci				    int num_dx_leaves)
247462306a36Sopenharmony_ci{
247562306a36Sopenharmony_ci	int ret;
247662306a36Sopenharmony_ci	u64 phys_blkno;
247762306a36Sopenharmony_ci
247862306a36Sopenharmony_ci	ret = __ocfs2_dx_dir_new_cluster(dir, cpos, handle, data_ac, dx_leaves,
247962306a36Sopenharmony_ci					 num_dx_leaves, &phys_blkno);
248062306a36Sopenharmony_ci	if (ret) {
248162306a36Sopenharmony_ci		mlog_errno(ret);
248262306a36Sopenharmony_ci		goto out;
248362306a36Sopenharmony_ci	}
248462306a36Sopenharmony_ci
248562306a36Sopenharmony_ci	ret = ocfs2_insert_extent(handle, et, cpos, phys_blkno, 1, 0,
248662306a36Sopenharmony_ci				  meta_ac);
248762306a36Sopenharmony_ci	if (ret)
248862306a36Sopenharmony_ci		mlog_errno(ret);
248962306a36Sopenharmony_ciout:
249062306a36Sopenharmony_ci	return ret;
249162306a36Sopenharmony_ci}
249262306a36Sopenharmony_ci
249362306a36Sopenharmony_cistatic struct buffer_head **ocfs2_dx_dir_kmalloc_leaves(struct super_block *sb,
249462306a36Sopenharmony_ci							int *ret_num_leaves)
249562306a36Sopenharmony_ci{
249662306a36Sopenharmony_ci	int num_dx_leaves = ocfs2_clusters_to_blocks(sb, 1);
249762306a36Sopenharmony_ci	struct buffer_head **dx_leaves;
249862306a36Sopenharmony_ci
249962306a36Sopenharmony_ci	dx_leaves = kcalloc(num_dx_leaves, sizeof(struct buffer_head *),
250062306a36Sopenharmony_ci			    GFP_NOFS);
250162306a36Sopenharmony_ci	if (dx_leaves && ret_num_leaves)
250262306a36Sopenharmony_ci		*ret_num_leaves = num_dx_leaves;
250362306a36Sopenharmony_ci
250462306a36Sopenharmony_ci	return dx_leaves;
250562306a36Sopenharmony_ci}
250662306a36Sopenharmony_ci
250762306a36Sopenharmony_cistatic int ocfs2_fill_new_dir_dx(struct ocfs2_super *osb,
250862306a36Sopenharmony_ci				 handle_t *handle,
250962306a36Sopenharmony_ci				 struct inode *parent,
251062306a36Sopenharmony_ci				 struct inode *inode,
251162306a36Sopenharmony_ci				 struct buffer_head *di_bh,
251262306a36Sopenharmony_ci				 struct ocfs2_alloc_context *data_ac,
251362306a36Sopenharmony_ci				 struct ocfs2_alloc_context *meta_ac)
251462306a36Sopenharmony_ci{
251562306a36Sopenharmony_ci	int ret;
251662306a36Sopenharmony_ci	struct buffer_head *leaf_bh = NULL;
251762306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
251862306a36Sopenharmony_ci	struct ocfs2_dx_hinfo hinfo;
251962306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
252062306a36Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
252162306a36Sopenharmony_ci
252262306a36Sopenharmony_ci	/*
252362306a36Sopenharmony_ci	 * Our strategy is to create the directory as though it were
252462306a36Sopenharmony_ci	 * unindexed, then add the index block. This works with very
252562306a36Sopenharmony_ci	 * little complication since the state of a new directory is a
252662306a36Sopenharmony_ci	 * very well known quantity.
252762306a36Sopenharmony_ci	 *
252862306a36Sopenharmony_ci	 * Essentially, we have two dirents ("." and ".."), in the 1st
252962306a36Sopenharmony_ci	 * block which need indexing. These are easily inserted into
253062306a36Sopenharmony_ci	 * the index block.
253162306a36Sopenharmony_ci	 */
253262306a36Sopenharmony_ci
253362306a36Sopenharmony_ci	ret = ocfs2_fill_new_dir_el(osb, handle, parent, inode, di_bh,
253462306a36Sopenharmony_ci				    data_ac, &leaf_bh);
253562306a36Sopenharmony_ci	if (ret) {
253662306a36Sopenharmony_ci		mlog_errno(ret);
253762306a36Sopenharmony_ci		goto out;
253862306a36Sopenharmony_ci	}
253962306a36Sopenharmony_ci
254062306a36Sopenharmony_ci	ret = ocfs2_dx_dir_attach_index(osb, handle, inode, di_bh, leaf_bh,
254162306a36Sopenharmony_ci					meta_ac, 1, 2, &dx_root_bh);
254262306a36Sopenharmony_ci	if (ret) {
254362306a36Sopenharmony_ci		mlog_errno(ret);
254462306a36Sopenharmony_ci		goto out;
254562306a36Sopenharmony_ci	}
254662306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
254762306a36Sopenharmony_ci	entry_list = &dx_root->dr_entries;
254862306a36Sopenharmony_ci
254962306a36Sopenharmony_ci	/* Buffer has been journaled for us by ocfs2_dx_dir_attach_index */
255062306a36Sopenharmony_ci	ocfs2_dx_dir_name_hash(inode, ".", 1, &hinfo);
255162306a36Sopenharmony_ci	ocfs2_dx_entry_list_insert(entry_list, &hinfo, leaf_bh->b_blocknr);
255262306a36Sopenharmony_ci
255362306a36Sopenharmony_ci	ocfs2_dx_dir_name_hash(inode, "..", 2, &hinfo);
255462306a36Sopenharmony_ci	ocfs2_dx_entry_list_insert(entry_list, &hinfo, leaf_bh->b_blocknr);
255562306a36Sopenharmony_ci
255662306a36Sopenharmony_ciout:
255762306a36Sopenharmony_ci	brelse(dx_root_bh);
255862306a36Sopenharmony_ci	brelse(leaf_bh);
255962306a36Sopenharmony_ci	return ret;
256062306a36Sopenharmony_ci}
256162306a36Sopenharmony_ci
256262306a36Sopenharmony_ciint ocfs2_fill_new_dir(struct ocfs2_super *osb,
256362306a36Sopenharmony_ci		       handle_t *handle,
256462306a36Sopenharmony_ci		       struct inode *parent,
256562306a36Sopenharmony_ci		       struct inode *inode,
256662306a36Sopenharmony_ci		       struct buffer_head *fe_bh,
256762306a36Sopenharmony_ci		       struct ocfs2_alloc_context *data_ac,
256862306a36Sopenharmony_ci		       struct ocfs2_alloc_context *meta_ac)
256962306a36Sopenharmony_ci
257062306a36Sopenharmony_ci{
257162306a36Sopenharmony_ci	BUG_ON(!ocfs2_supports_inline_data(osb) && data_ac == NULL);
257262306a36Sopenharmony_ci
257362306a36Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
257462306a36Sopenharmony_ci		return ocfs2_fill_new_dir_id(osb, handle, parent, inode, fe_bh);
257562306a36Sopenharmony_ci
257662306a36Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb))
257762306a36Sopenharmony_ci		return ocfs2_fill_new_dir_dx(osb, handle, parent, inode, fe_bh,
257862306a36Sopenharmony_ci					     data_ac, meta_ac);
257962306a36Sopenharmony_ci
258062306a36Sopenharmony_ci	return ocfs2_fill_new_dir_el(osb, handle, parent, inode, fe_bh,
258162306a36Sopenharmony_ci				     data_ac, NULL);
258262306a36Sopenharmony_ci}
258362306a36Sopenharmony_ci
258462306a36Sopenharmony_cistatic int ocfs2_dx_dir_index_block(struct inode *dir,
258562306a36Sopenharmony_ci				    handle_t *handle,
258662306a36Sopenharmony_ci				    struct buffer_head **dx_leaves,
258762306a36Sopenharmony_ci				    int num_dx_leaves,
258862306a36Sopenharmony_ci				    u32 *num_dx_entries,
258962306a36Sopenharmony_ci				    struct buffer_head *dirent_bh)
259062306a36Sopenharmony_ci{
259162306a36Sopenharmony_ci	int ret = 0, namelen, i;
259262306a36Sopenharmony_ci	char *de_buf, *limit;
259362306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
259462306a36Sopenharmony_ci	struct buffer_head *dx_leaf_bh;
259562306a36Sopenharmony_ci	struct ocfs2_dx_hinfo hinfo;
259662306a36Sopenharmony_ci	u64 dirent_blk = dirent_bh->b_blocknr;
259762306a36Sopenharmony_ci
259862306a36Sopenharmony_ci	de_buf = dirent_bh->b_data;
259962306a36Sopenharmony_ci	limit = de_buf + dir->i_sb->s_blocksize;
260062306a36Sopenharmony_ci
260162306a36Sopenharmony_ci	while (de_buf < limit) {
260262306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
260362306a36Sopenharmony_ci
260462306a36Sopenharmony_ci		namelen = de->name_len;
260562306a36Sopenharmony_ci		if (!namelen || !de->inode)
260662306a36Sopenharmony_ci			goto inc;
260762306a36Sopenharmony_ci
260862306a36Sopenharmony_ci		ocfs2_dx_dir_name_hash(dir, de->name, namelen, &hinfo);
260962306a36Sopenharmony_ci
261062306a36Sopenharmony_ci		i = ocfs2_dx_dir_hash_idx(OCFS2_SB(dir->i_sb), &hinfo);
261162306a36Sopenharmony_ci		dx_leaf_bh = dx_leaves[i];
261262306a36Sopenharmony_ci
261362306a36Sopenharmony_ci		ret = __ocfs2_dx_dir_leaf_insert(dir, handle, &hinfo,
261462306a36Sopenharmony_ci						 dirent_blk, dx_leaf_bh);
261562306a36Sopenharmony_ci		if (ret) {
261662306a36Sopenharmony_ci			mlog_errno(ret);
261762306a36Sopenharmony_ci			goto out;
261862306a36Sopenharmony_ci		}
261962306a36Sopenharmony_ci
262062306a36Sopenharmony_ci		*num_dx_entries = *num_dx_entries + 1;
262162306a36Sopenharmony_ci
262262306a36Sopenharmony_ciinc:
262362306a36Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
262462306a36Sopenharmony_ci	}
262562306a36Sopenharmony_ci
262662306a36Sopenharmony_ciout:
262762306a36Sopenharmony_ci	return ret;
262862306a36Sopenharmony_ci}
262962306a36Sopenharmony_ci
263062306a36Sopenharmony_ci/*
263162306a36Sopenharmony_ci * XXX: This expects dx_root_bh to already be part of the transaction.
263262306a36Sopenharmony_ci */
263362306a36Sopenharmony_cistatic void ocfs2_dx_dir_index_root_block(struct inode *dir,
263462306a36Sopenharmony_ci					 struct buffer_head *dx_root_bh,
263562306a36Sopenharmony_ci					 struct buffer_head *dirent_bh)
263662306a36Sopenharmony_ci{
263762306a36Sopenharmony_ci	char *de_buf, *limit;
263862306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
263962306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
264062306a36Sopenharmony_ci	struct ocfs2_dx_hinfo hinfo;
264162306a36Sopenharmony_ci	u64 dirent_blk = dirent_bh->b_blocknr;
264262306a36Sopenharmony_ci
264362306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
264462306a36Sopenharmony_ci
264562306a36Sopenharmony_ci	de_buf = dirent_bh->b_data;
264662306a36Sopenharmony_ci	limit = de_buf + dir->i_sb->s_blocksize;
264762306a36Sopenharmony_ci
264862306a36Sopenharmony_ci	while (de_buf < limit) {
264962306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
265062306a36Sopenharmony_ci
265162306a36Sopenharmony_ci		if (!de->name_len || !de->inode)
265262306a36Sopenharmony_ci			goto inc;
265362306a36Sopenharmony_ci
265462306a36Sopenharmony_ci		ocfs2_dx_dir_name_hash(dir, de->name, de->name_len, &hinfo);
265562306a36Sopenharmony_ci
265662306a36Sopenharmony_ci		trace_ocfs2_dx_dir_index_root_block(
265762306a36Sopenharmony_ci				(unsigned long long)dir->i_ino,
265862306a36Sopenharmony_ci				hinfo.major_hash, hinfo.minor_hash,
265962306a36Sopenharmony_ci				de->name_len, de->name,
266062306a36Sopenharmony_ci				le16_to_cpu(dx_root->dr_entries.de_num_used));
266162306a36Sopenharmony_ci
266262306a36Sopenharmony_ci		ocfs2_dx_entry_list_insert(&dx_root->dr_entries, &hinfo,
266362306a36Sopenharmony_ci					   dirent_blk);
266462306a36Sopenharmony_ci
266562306a36Sopenharmony_ci		le32_add_cpu(&dx_root->dr_num_entries, 1);
266662306a36Sopenharmony_ciinc:
266762306a36Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
266862306a36Sopenharmony_ci	}
266962306a36Sopenharmony_ci}
267062306a36Sopenharmony_ci
267162306a36Sopenharmony_ci/*
267262306a36Sopenharmony_ci * Count the number of inline directory entries in di_bh and compare
267362306a36Sopenharmony_ci * them against the number of entries we can hold in an inline dx root
267462306a36Sopenharmony_ci * block.
267562306a36Sopenharmony_ci */
267662306a36Sopenharmony_cistatic int ocfs2_new_dx_should_be_inline(struct inode *dir,
267762306a36Sopenharmony_ci					 struct buffer_head *di_bh)
267862306a36Sopenharmony_ci{
267962306a36Sopenharmony_ci	int dirent_count = 0;
268062306a36Sopenharmony_ci	char *de_buf, *limit;
268162306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
268262306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
268362306a36Sopenharmony_ci
268462306a36Sopenharmony_ci	de_buf = di->id2.i_data.id_data;
268562306a36Sopenharmony_ci	limit = de_buf + i_size_read(dir);
268662306a36Sopenharmony_ci
268762306a36Sopenharmony_ci	while (de_buf < limit) {
268862306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
268962306a36Sopenharmony_ci
269062306a36Sopenharmony_ci		if (de->name_len && de->inode)
269162306a36Sopenharmony_ci			dirent_count++;
269262306a36Sopenharmony_ci
269362306a36Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
269462306a36Sopenharmony_ci	}
269562306a36Sopenharmony_ci
269662306a36Sopenharmony_ci	/* We are careful to leave room for one extra record. */
269762306a36Sopenharmony_ci	return dirent_count < ocfs2_dx_entries_per_root(dir->i_sb);
269862306a36Sopenharmony_ci}
269962306a36Sopenharmony_ci
270062306a36Sopenharmony_ci/*
270162306a36Sopenharmony_ci * Expand rec_len of the rightmost dirent in a directory block so that it
270262306a36Sopenharmony_ci * contains the end of our valid space for dirents. We do this during
270362306a36Sopenharmony_ci * expansion from an inline directory to one with extents. The first dir block
270462306a36Sopenharmony_ci * in that case is taken from the inline data portion of the inode block.
270562306a36Sopenharmony_ci *
270662306a36Sopenharmony_ci * This will also return the largest amount of contiguous space for a dirent
270762306a36Sopenharmony_ci * in the block. That value is *not* necessarily the last dirent, even after
270862306a36Sopenharmony_ci * expansion. The directory indexing code wants this value for free space
270962306a36Sopenharmony_ci * accounting. We do this here since we're already walking the entire dir
271062306a36Sopenharmony_ci * block.
271162306a36Sopenharmony_ci *
271262306a36Sopenharmony_ci * We add the dir trailer if this filesystem wants it.
271362306a36Sopenharmony_ci */
271462306a36Sopenharmony_cistatic unsigned int ocfs2_expand_last_dirent(char *start, unsigned int old_size,
271562306a36Sopenharmony_ci					     struct inode *dir)
271662306a36Sopenharmony_ci{
271762306a36Sopenharmony_ci	struct super_block *sb = dir->i_sb;
271862306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
271962306a36Sopenharmony_ci	struct ocfs2_dir_entry *prev_de;
272062306a36Sopenharmony_ci	char *de_buf, *limit;
272162306a36Sopenharmony_ci	unsigned int new_size = sb->s_blocksize;
272262306a36Sopenharmony_ci	unsigned int bytes, this_hole;
272362306a36Sopenharmony_ci	unsigned int largest_hole = 0;
272462306a36Sopenharmony_ci
272562306a36Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(dir))
272662306a36Sopenharmony_ci		new_size = ocfs2_dir_trailer_blk_off(sb);
272762306a36Sopenharmony_ci
272862306a36Sopenharmony_ci	bytes = new_size - old_size;
272962306a36Sopenharmony_ci
273062306a36Sopenharmony_ci	limit = start + old_size;
273162306a36Sopenharmony_ci	de_buf = start;
273262306a36Sopenharmony_ci	de = (struct ocfs2_dir_entry *)de_buf;
273362306a36Sopenharmony_ci	do {
273462306a36Sopenharmony_ci		this_hole = ocfs2_figure_dirent_hole(de);
273562306a36Sopenharmony_ci		if (this_hole > largest_hole)
273662306a36Sopenharmony_ci			largest_hole = this_hole;
273762306a36Sopenharmony_ci
273862306a36Sopenharmony_ci		prev_de = de;
273962306a36Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
274062306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
274162306a36Sopenharmony_ci	} while (de_buf < limit);
274262306a36Sopenharmony_ci
274362306a36Sopenharmony_ci	le16_add_cpu(&prev_de->rec_len, bytes);
274462306a36Sopenharmony_ci
274562306a36Sopenharmony_ci	/* We need to double check this after modification of the final
274662306a36Sopenharmony_ci	 * dirent. */
274762306a36Sopenharmony_ci	this_hole = ocfs2_figure_dirent_hole(prev_de);
274862306a36Sopenharmony_ci	if (this_hole > largest_hole)
274962306a36Sopenharmony_ci		largest_hole = this_hole;
275062306a36Sopenharmony_ci
275162306a36Sopenharmony_ci	if (largest_hole >= OCFS2_DIR_MIN_REC_LEN)
275262306a36Sopenharmony_ci		return largest_hole;
275362306a36Sopenharmony_ci	return 0;
275462306a36Sopenharmony_ci}
275562306a36Sopenharmony_ci
275662306a36Sopenharmony_ci/*
275762306a36Sopenharmony_ci * We allocate enough clusters to fulfill "blocks_wanted", but set
275862306a36Sopenharmony_ci * i_size to exactly one block. Ocfs2_extend_dir() will handle the
275962306a36Sopenharmony_ci * rest automatically for us.
276062306a36Sopenharmony_ci *
276162306a36Sopenharmony_ci * *first_block_bh is a pointer to the 1st data block allocated to the
276262306a36Sopenharmony_ci *  directory.
276362306a36Sopenharmony_ci */
276462306a36Sopenharmony_cistatic int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
276562306a36Sopenharmony_ci				   unsigned int blocks_wanted,
276662306a36Sopenharmony_ci				   struct ocfs2_dir_lookup_result *lookup,
276762306a36Sopenharmony_ci				   struct buffer_head **first_block_bh)
276862306a36Sopenharmony_ci{
276962306a36Sopenharmony_ci	u32 alloc, dx_alloc, bit_off, len, num_dx_entries = 0;
277062306a36Sopenharmony_ci	struct super_block *sb = dir->i_sb;
277162306a36Sopenharmony_ci	int ret, i, num_dx_leaves = 0, dx_inline = 0,
277262306a36Sopenharmony_ci		credits = ocfs2_inline_to_extents_credits(sb);
277362306a36Sopenharmony_ci	u64 dx_insert_blkno, blkno,
277462306a36Sopenharmony_ci		bytes = blocks_wanted << sb->s_blocksize_bits;
277562306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
277662306a36Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(dir);
277762306a36Sopenharmony_ci	struct ocfs2_alloc_context *data_ac = NULL;
277862306a36Sopenharmony_ci	struct ocfs2_alloc_context *meta_ac = NULL;
277962306a36Sopenharmony_ci	struct buffer_head *dirdata_bh = NULL;
278062306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
278162306a36Sopenharmony_ci	struct buffer_head **dx_leaves = NULL;
278262306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
278362306a36Sopenharmony_ci	handle_t *handle;
278462306a36Sopenharmony_ci	struct ocfs2_extent_tree et;
278562306a36Sopenharmony_ci	struct ocfs2_extent_tree dx_et;
278662306a36Sopenharmony_ci	int did_quota = 0, bytes_allocated = 0;
278762306a36Sopenharmony_ci
278862306a36Sopenharmony_ci	ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir), di_bh);
278962306a36Sopenharmony_ci
279062306a36Sopenharmony_ci	alloc = ocfs2_clusters_for_bytes(sb, bytes);
279162306a36Sopenharmony_ci	dx_alloc = 0;
279262306a36Sopenharmony_ci
279362306a36Sopenharmony_ci	down_write(&oi->ip_alloc_sem);
279462306a36Sopenharmony_ci
279562306a36Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb)) {
279662306a36Sopenharmony_ci		credits += ocfs2_add_dir_index_credits(sb);
279762306a36Sopenharmony_ci
279862306a36Sopenharmony_ci		dx_inline = ocfs2_new_dx_should_be_inline(dir, di_bh);
279962306a36Sopenharmony_ci		if (!dx_inline) {
280062306a36Sopenharmony_ci			/* Add one more cluster for an index leaf */
280162306a36Sopenharmony_ci			dx_alloc++;
280262306a36Sopenharmony_ci			dx_leaves = ocfs2_dx_dir_kmalloc_leaves(sb,
280362306a36Sopenharmony_ci								&num_dx_leaves);
280462306a36Sopenharmony_ci			if (!dx_leaves) {
280562306a36Sopenharmony_ci				ret = -ENOMEM;
280662306a36Sopenharmony_ci				mlog_errno(ret);
280762306a36Sopenharmony_ci				goto out;
280862306a36Sopenharmony_ci			}
280962306a36Sopenharmony_ci		}
281062306a36Sopenharmony_ci
281162306a36Sopenharmony_ci		/* This gets us the dx_root */
281262306a36Sopenharmony_ci		ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
281362306a36Sopenharmony_ci		if (ret) {
281462306a36Sopenharmony_ci			mlog_errno(ret);
281562306a36Sopenharmony_ci			goto out;
281662306a36Sopenharmony_ci		}
281762306a36Sopenharmony_ci	}
281862306a36Sopenharmony_ci
281962306a36Sopenharmony_ci	/*
282062306a36Sopenharmony_ci	 * We should never need more than 2 clusters for the unindexed
282162306a36Sopenharmony_ci	 * tree - maximum dirent size is far less than one block. In
282262306a36Sopenharmony_ci	 * fact, the only time we'd need more than one cluster is if
282362306a36Sopenharmony_ci	 * blocksize == clustersize and the dirent won't fit in the
282462306a36Sopenharmony_ci	 * extra space that the expansion to a single block gives. As
282562306a36Sopenharmony_ci	 * of today, that only happens on 4k/4k file systems.
282662306a36Sopenharmony_ci	 */
282762306a36Sopenharmony_ci	BUG_ON(alloc > 2);
282862306a36Sopenharmony_ci
282962306a36Sopenharmony_ci	ret = ocfs2_reserve_clusters(osb, alloc + dx_alloc, &data_ac);
283062306a36Sopenharmony_ci	if (ret) {
283162306a36Sopenharmony_ci		mlog_errno(ret);
283262306a36Sopenharmony_ci		goto out;
283362306a36Sopenharmony_ci	}
283462306a36Sopenharmony_ci
283562306a36Sopenharmony_ci	/*
283662306a36Sopenharmony_ci	 * Prepare for worst case allocation scenario of two separate
283762306a36Sopenharmony_ci	 * extents in the unindexed tree.
283862306a36Sopenharmony_ci	 */
283962306a36Sopenharmony_ci	if (alloc == 2)
284062306a36Sopenharmony_ci		credits += OCFS2_SUBALLOC_ALLOC;
284162306a36Sopenharmony_ci
284262306a36Sopenharmony_ci	handle = ocfs2_start_trans(osb, credits);
284362306a36Sopenharmony_ci	if (IS_ERR(handle)) {
284462306a36Sopenharmony_ci		ret = PTR_ERR(handle);
284562306a36Sopenharmony_ci		mlog_errno(ret);
284662306a36Sopenharmony_ci		goto out;
284762306a36Sopenharmony_ci	}
284862306a36Sopenharmony_ci
284962306a36Sopenharmony_ci	ret = dquot_alloc_space_nodirty(dir,
285062306a36Sopenharmony_ci		ocfs2_clusters_to_bytes(osb->sb, alloc + dx_alloc));
285162306a36Sopenharmony_ci	if (ret)
285262306a36Sopenharmony_ci		goto out_commit;
285362306a36Sopenharmony_ci	did_quota = 1;
285462306a36Sopenharmony_ci
285562306a36Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb) && !dx_inline) {
285662306a36Sopenharmony_ci		/*
285762306a36Sopenharmony_ci		 * Allocate our index cluster first, to maximize the
285862306a36Sopenharmony_ci		 * possibility that unindexed leaves grow
285962306a36Sopenharmony_ci		 * contiguously.
286062306a36Sopenharmony_ci		 */
286162306a36Sopenharmony_ci		ret = __ocfs2_dx_dir_new_cluster(dir, 0, handle, data_ac,
286262306a36Sopenharmony_ci						 dx_leaves, num_dx_leaves,
286362306a36Sopenharmony_ci						 &dx_insert_blkno);
286462306a36Sopenharmony_ci		if (ret) {
286562306a36Sopenharmony_ci			mlog_errno(ret);
286662306a36Sopenharmony_ci			goto out_commit;
286762306a36Sopenharmony_ci		}
286862306a36Sopenharmony_ci		bytes_allocated += ocfs2_clusters_to_bytes(dir->i_sb, 1);
286962306a36Sopenharmony_ci	}
287062306a36Sopenharmony_ci
287162306a36Sopenharmony_ci	/*
287262306a36Sopenharmony_ci	 * Try to claim as many clusters as the bitmap can give though
287362306a36Sopenharmony_ci	 * if we only get one now, that's enough to continue. The rest
287462306a36Sopenharmony_ci	 * will be claimed after the conversion to extents.
287562306a36Sopenharmony_ci	 */
287662306a36Sopenharmony_ci	if (ocfs2_dir_resv_allowed(osb))
287762306a36Sopenharmony_ci		data_ac->ac_resv = &oi->ip_la_data_resv;
287862306a36Sopenharmony_ci	ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off, &len);
287962306a36Sopenharmony_ci	if (ret) {
288062306a36Sopenharmony_ci		mlog_errno(ret);
288162306a36Sopenharmony_ci		goto out_commit;
288262306a36Sopenharmony_ci	}
288362306a36Sopenharmony_ci	bytes_allocated += ocfs2_clusters_to_bytes(dir->i_sb, 1);
288462306a36Sopenharmony_ci
288562306a36Sopenharmony_ci	/*
288662306a36Sopenharmony_ci	 * Operations are carefully ordered so that we set up the new
288762306a36Sopenharmony_ci	 * data block first. The conversion from inline data to
288862306a36Sopenharmony_ci	 * extents follows.
288962306a36Sopenharmony_ci	 */
289062306a36Sopenharmony_ci	blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
289162306a36Sopenharmony_ci	dirdata_bh = sb_getblk(sb, blkno);
289262306a36Sopenharmony_ci	if (!dirdata_bh) {
289362306a36Sopenharmony_ci		ret = -ENOMEM;
289462306a36Sopenharmony_ci		mlog_errno(ret);
289562306a36Sopenharmony_ci		goto out_commit;
289662306a36Sopenharmony_ci	}
289762306a36Sopenharmony_ci
289862306a36Sopenharmony_ci	ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dirdata_bh);
289962306a36Sopenharmony_ci
290062306a36Sopenharmony_ci	ret = ocfs2_journal_access_db(handle, INODE_CACHE(dir), dirdata_bh,
290162306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_CREATE);
290262306a36Sopenharmony_ci	if (ret) {
290362306a36Sopenharmony_ci		mlog_errno(ret);
290462306a36Sopenharmony_ci		goto out_commit;
290562306a36Sopenharmony_ci	}
290662306a36Sopenharmony_ci
290762306a36Sopenharmony_ci	memcpy(dirdata_bh->b_data, di->id2.i_data.id_data, i_size_read(dir));
290862306a36Sopenharmony_ci	memset(dirdata_bh->b_data + i_size_read(dir), 0,
290962306a36Sopenharmony_ci	       sb->s_blocksize - i_size_read(dir));
291062306a36Sopenharmony_ci	i = ocfs2_expand_last_dirent(dirdata_bh->b_data, i_size_read(dir), dir);
291162306a36Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(dir)) {
291262306a36Sopenharmony_ci		/*
291362306a36Sopenharmony_ci		 * Prepare the dir trailer up front. It will otherwise look
291462306a36Sopenharmony_ci		 * like a valid dirent. Even if inserting the index fails
291562306a36Sopenharmony_ci		 * (unlikely), then all we'll have done is given first dir
291662306a36Sopenharmony_ci		 * block a small amount of fragmentation.
291762306a36Sopenharmony_ci		 */
291862306a36Sopenharmony_ci		ocfs2_init_dir_trailer(dir, dirdata_bh, i);
291962306a36Sopenharmony_ci	}
292062306a36Sopenharmony_ci
292162306a36Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
292262306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, dirdata_bh);
292362306a36Sopenharmony_ci
292462306a36Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb) && !dx_inline) {
292562306a36Sopenharmony_ci		/*
292662306a36Sopenharmony_ci		 * Dx dirs with an external cluster need to do this up
292762306a36Sopenharmony_ci		 * front. Inline dx root's get handled later, after
292862306a36Sopenharmony_ci		 * we've allocated our root block. We get passed back
292962306a36Sopenharmony_ci		 * a total number of items so that dr_num_entries can
293062306a36Sopenharmony_ci		 * be correctly set once the dx_root has been
293162306a36Sopenharmony_ci		 * allocated.
293262306a36Sopenharmony_ci		 */
293362306a36Sopenharmony_ci		ret = ocfs2_dx_dir_index_block(dir, handle, dx_leaves,
293462306a36Sopenharmony_ci					       num_dx_leaves, &num_dx_entries,
293562306a36Sopenharmony_ci					       dirdata_bh);
293662306a36Sopenharmony_ci		if (ret) {
293762306a36Sopenharmony_ci			mlog_errno(ret);
293862306a36Sopenharmony_ci			goto out_commit;
293962306a36Sopenharmony_ci		}
294062306a36Sopenharmony_ci	}
294162306a36Sopenharmony_ci
294262306a36Sopenharmony_ci	/*
294362306a36Sopenharmony_ci	 * Set extent, i_size, etc on the directory. After this, the
294462306a36Sopenharmony_ci	 * inode should contain the same exact dirents as before and
294562306a36Sopenharmony_ci	 * be fully accessible from system calls.
294662306a36Sopenharmony_ci	 *
294762306a36Sopenharmony_ci	 * We let the later dirent insert modify c/mtime - to the user
294862306a36Sopenharmony_ci	 * the data hasn't changed.
294962306a36Sopenharmony_ci	 */
295062306a36Sopenharmony_ci	ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
295162306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_CREATE);
295262306a36Sopenharmony_ci	if (ret) {
295362306a36Sopenharmony_ci		mlog_errno(ret);
295462306a36Sopenharmony_ci		goto out_commit;
295562306a36Sopenharmony_ci	}
295662306a36Sopenharmony_ci
295762306a36Sopenharmony_ci	spin_lock(&oi->ip_lock);
295862306a36Sopenharmony_ci	oi->ip_dyn_features &= ~OCFS2_INLINE_DATA_FL;
295962306a36Sopenharmony_ci	di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
296062306a36Sopenharmony_ci	spin_unlock(&oi->ip_lock);
296162306a36Sopenharmony_ci
296262306a36Sopenharmony_ci	ocfs2_dinode_new_extent_list(dir, di);
296362306a36Sopenharmony_ci
296462306a36Sopenharmony_ci	i_size_write(dir, sb->s_blocksize);
296562306a36Sopenharmony_ci	dir->i_mtime = inode_set_ctime_current(dir);
296662306a36Sopenharmony_ci
296762306a36Sopenharmony_ci	di->i_size = cpu_to_le64(sb->s_blocksize);
296862306a36Sopenharmony_ci	di->i_ctime = di->i_mtime = cpu_to_le64(inode_get_ctime(dir).tv_sec);
296962306a36Sopenharmony_ci	di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(inode_get_ctime(dir).tv_nsec);
297062306a36Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
297162306a36Sopenharmony_ci
297262306a36Sopenharmony_ci	/*
297362306a36Sopenharmony_ci	 * This should never fail as our extent list is empty and all
297462306a36Sopenharmony_ci	 * related blocks have been journaled already.
297562306a36Sopenharmony_ci	 */
297662306a36Sopenharmony_ci	ret = ocfs2_insert_extent(handle, &et, 0, blkno, len,
297762306a36Sopenharmony_ci				  0, NULL);
297862306a36Sopenharmony_ci	if (ret) {
297962306a36Sopenharmony_ci		mlog_errno(ret);
298062306a36Sopenharmony_ci		goto out_commit;
298162306a36Sopenharmony_ci	}
298262306a36Sopenharmony_ci
298362306a36Sopenharmony_ci	/*
298462306a36Sopenharmony_ci	 * Set i_blocks after the extent insert for the most up to
298562306a36Sopenharmony_ci	 * date ip_clusters value.
298662306a36Sopenharmony_ci	 */
298762306a36Sopenharmony_ci	dir->i_blocks = ocfs2_inode_sector_count(dir);
298862306a36Sopenharmony_ci
298962306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
299062306a36Sopenharmony_ci
299162306a36Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb)) {
299262306a36Sopenharmony_ci		ret = ocfs2_dx_dir_attach_index(osb, handle, dir, di_bh,
299362306a36Sopenharmony_ci						dirdata_bh, meta_ac, dx_inline,
299462306a36Sopenharmony_ci						num_dx_entries, &dx_root_bh);
299562306a36Sopenharmony_ci		if (ret) {
299662306a36Sopenharmony_ci			mlog_errno(ret);
299762306a36Sopenharmony_ci			goto out_commit;
299862306a36Sopenharmony_ci		}
299962306a36Sopenharmony_ci
300062306a36Sopenharmony_ci		if (dx_inline) {
300162306a36Sopenharmony_ci			ocfs2_dx_dir_index_root_block(dir, dx_root_bh,
300262306a36Sopenharmony_ci						      dirdata_bh);
300362306a36Sopenharmony_ci		} else {
300462306a36Sopenharmony_ci			ocfs2_init_dx_root_extent_tree(&dx_et,
300562306a36Sopenharmony_ci						       INODE_CACHE(dir),
300662306a36Sopenharmony_ci						       dx_root_bh);
300762306a36Sopenharmony_ci			ret = ocfs2_insert_extent(handle, &dx_et, 0,
300862306a36Sopenharmony_ci						  dx_insert_blkno, 1, 0, NULL);
300962306a36Sopenharmony_ci			if (ret)
301062306a36Sopenharmony_ci				mlog_errno(ret);
301162306a36Sopenharmony_ci		}
301262306a36Sopenharmony_ci	}
301362306a36Sopenharmony_ci
301462306a36Sopenharmony_ci	/*
301562306a36Sopenharmony_ci	 * We asked for two clusters, but only got one in the 1st
301662306a36Sopenharmony_ci	 * pass. Claim the 2nd cluster as a separate extent.
301762306a36Sopenharmony_ci	 */
301862306a36Sopenharmony_ci	if (alloc > len) {
301962306a36Sopenharmony_ci		ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off,
302062306a36Sopenharmony_ci					   &len);
302162306a36Sopenharmony_ci		if (ret) {
302262306a36Sopenharmony_ci			mlog_errno(ret);
302362306a36Sopenharmony_ci			goto out_commit;
302462306a36Sopenharmony_ci		}
302562306a36Sopenharmony_ci		blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
302662306a36Sopenharmony_ci
302762306a36Sopenharmony_ci		ret = ocfs2_insert_extent(handle, &et, 1,
302862306a36Sopenharmony_ci					  blkno, len, 0, NULL);
302962306a36Sopenharmony_ci		if (ret) {
303062306a36Sopenharmony_ci			mlog_errno(ret);
303162306a36Sopenharmony_ci			goto out_commit;
303262306a36Sopenharmony_ci		}
303362306a36Sopenharmony_ci		bytes_allocated += ocfs2_clusters_to_bytes(dir->i_sb, 1);
303462306a36Sopenharmony_ci	}
303562306a36Sopenharmony_ci
303662306a36Sopenharmony_ci	*first_block_bh = dirdata_bh;
303762306a36Sopenharmony_ci	dirdata_bh = NULL;
303862306a36Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb)) {
303962306a36Sopenharmony_ci		unsigned int off;
304062306a36Sopenharmony_ci
304162306a36Sopenharmony_ci		if (!dx_inline) {
304262306a36Sopenharmony_ci			/*
304362306a36Sopenharmony_ci			 * We need to return the correct block within the
304462306a36Sopenharmony_ci			 * cluster which should hold our entry.
304562306a36Sopenharmony_ci			 */
304662306a36Sopenharmony_ci			off = ocfs2_dx_dir_hash_idx(osb,
304762306a36Sopenharmony_ci						    &lookup->dl_hinfo);
304862306a36Sopenharmony_ci			get_bh(dx_leaves[off]);
304962306a36Sopenharmony_ci			lookup->dl_dx_leaf_bh = dx_leaves[off];
305062306a36Sopenharmony_ci		}
305162306a36Sopenharmony_ci		lookup->dl_dx_root_bh = dx_root_bh;
305262306a36Sopenharmony_ci		dx_root_bh = NULL;
305362306a36Sopenharmony_ci	}
305462306a36Sopenharmony_ci
305562306a36Sopenharmony_ciout_commit:
305662306a36Sopenharmony_ci	if (ret < 0 && did_quota)
305762306a36Sopenharmony_ci		dquot_free_space_nodirty(dir, bytes_allocated);
305862306a36Sopenharmony_ci
305962306a36Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
306062306a36Sopenharmony_ci
306162306a36Sopenharmony_ciout:
306262306a36Sopenharmony_ci	up_write(&oi->ip_alloc_sem);
306362306a36Sopenharmony_ci	if (data_ac)
306462306a36Sopenharmony_ci		ocfs2_free_alloc_context(data_ac);
306562306a36Sopenharmony_ci	if (meta_ac)
306662306a36Sopenharmony_ci		ocfs2_free_alloc_context(meta_ac);
306762306a36Sopenharmony_ci
306862306a36Sopenharmony_ci	if (dx_leaves) {
306962306a36Sopenharmony_ci		for (i = 0; i < num_dx_leaves; i++)
307062306a36Sopenharmony_ci			brelse(dx_leaves[i]);
307162306a36Sopenharmony_ci		kfree(dx_leaves);
307262306a36Sopenharmony_ci	}
307362306a36Sopenharmony_ci
307462306a36Sopenharmony_ci	brelse(dirdata_bh);
307562306a36Sopenharmony_ci	brelse(dx_root_bh);
307662306a36Sopenharmony_ci
307762306a36Sopenharmony_ci	return ret;
307862306a36Sopenharmony_ci}
307962306a36Sopenharmony_ci
308062306a36Sopenharmony_ci/* returns a bh of the 1st new block in the allocation. */
308162306a36Sopenharmony_cistatic int ocfs2_do_extend_dir(struct super_block *sb,
308262306a36Sopenharmony_ci			       handle_t *handle,
308362306a36Sopenharmony_ci			       struct inode *dir,
308462306a36Sopenharmony_ci			       struct buffer_head *parent_fe_bh,
308562306a36Sopenharmony_ci			       struct ocfs2_alloc_context *data_ac,
308662306a36Sopenharmony_ci			       struct ocfs2_alloc_context *meta_ac,
308762306a36Sopenharmony_ci			       struct buffer_head **new_bh)
308862306a36Sopenharmony_ci{
308962306a36Sopenharmony_ci	int status;
309062306a36Sopenharmony_ci	int extend, did_quota = 0;
309162306a36Sopenharmony_ci	u64 p_blkno, v_blkno;
309262306a36Sopenharmony_ci
309362306a36Sopenharmony_ci	spin_lock(&OCFS2_I(dir)->ip_lock);
309462306a36Sopenharmony_ci	extend = (i_size_read(dir) == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters));
309562306a36Sopenharmony_ci	spin_unlock(&OCFS2_I(dir)->ip_lock);
309662306a36Sopenharmony_ci
309762306a36Sopenharmony_ci	if (extend) {
309862306a36Sopenharmony_ci		u32 offset = OCFS2_I(dir)->ip_clusters;
309962306a36Sopenharmony_ci
310062306a36Sopenharmony_ci		status = dquot_alloc_space_nodirty(dir,
310162306a36Sopenharmony_ci					ocfs2_clusters_to_bytes(sb, 1));
310262306a36Sopenharmony_ci		if (status)
310362306a36Sopenharmony_ci			goto bail;
310462306a36Sopenharmony_ci		did_quota = 1;
310562306a36Sopenharmony_ci
310662306a36Sopenharmony_ci		status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
310762306a36Sopenharmony_ci					      1, 0, parent_fe_bh, handle,
310862306a36Sopenharmony_ci					      data_ac, meta_ac, NULL);
310962306a36Sopenharmony_ci		BUG_ON(status == -EAGAIN);
311062306a36Sopenharmony_ci		if (status < 0) {
311162306a36Sopenharmony_ci			mlog_errno(status);
311262306a36Sopenharmony_ci			goto bail;
311362306a36Sopenharmony_ci		}
311462306a36Sopenharmony_ci	}
311562306a36Sopenharmony_ci
311662306a36Sopenharmony_ci	v_blkno = ocfs2_blocks_for_bytes(sb, i_size_read(dir));
311762306a36Sopenharmony_ci	status = ocfs2_extent_map_get_blocks(dir, v_blkno, &p_blkno, NULL, NULL);
311862306a36Sopenharmony_ci	if (status < 0) {
311962306a36Sopenharmony_ci		mlog_errno(status);
312062306a36Sopenharmony_ci		goto bail;
312162306a36Sopenharmony_ci	}
312262306a36Sopenharmony_ci
312362306a36Sopenharmony_ci	*new_bh = sb_getblk(sb, p_blkno);
312462306a36Sopenharmony_ci	if (!*new_bh) {
312562306a36Sopenharmony_ci		status = -ENOMEM;
312662306a36Sopenharmony_ci		mlog_errno(status);
312762306a36Sopenharmony_ci		goto bail;
312862306a36Sopenharmony_ci	}
312962306a36Sopenharmony_ci	status = 0;
313062306a36Sopenharmony_cibail:
313162306a36Sopenharmony_ci	if (did_quota && status < 0)
313262306a36Sopenharmony_ci		dquot_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
313362306a36Sopenharmony_ci	return status;
313462306a36Sopenharmony_ci}
313562306a36Sopenharmony_ci
313662306a36Sopenharmony_ci/*
313762306a36Sopenharmony_ci * Assumes you already have a cluster lock on the directory.
313862306a36Sopenharmony_ci *
313962306a36Sopenharmony_ci * 'blocks_wanted' is only used if we have an inline directory which
314062306a36Sopenharmony_ci * is to be turned into an extent based one. The size of the dirent to
314162306a36Sopenharmony_ci * insert might be larger than the space gained by growing to just one
314262306a36Sopenharmony_ci * block, so we may have to grow the inode by two blocks in that case.
314362306a36Sopenharmony_ci *
314462306a36Sopenharmony_ci * If the directory is already indexed, dx_root_bh must be provided.
314562306a36Sopenharmony_ci */
314662306a36Sopenharmony_cistatic int ocfs2_extend_dir(struct ocfs2_super *osb,
314762306a36Sopenharmony_ci			    struct inode *dir,
314862306a36Sopenharmony_ci			    struct buffer_head *parent_fe_bh,
314962306a36Sopenharmony_ci			    unsigned int blocks_wanted,
315062306a36Sopenharmony_ci			    struct ocfs2_dir_lookup_result *lookup,
315162306a36Sopenharmony_ci			    struct buffer_head **new_de_bh)
315262306a36Sopenharmony_ci{
315362306a36Sopenharmony_ci	int status = 0;
315462306a36Sopenharmony_ci	int credits, num_free_extents, drop_alloc_sem = 0;
315562306a36Sopenharmony_ci	loff_t dir_i_size;
315662306a36Sopenharmony_ci	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
315762306a36Sopenharmony_ci	struct ocfs2_extent_list *el = &fe->id2.i_list;
315862306a36Sopenharmony_ci	struct ocfs2_alloc_context *data_ac = NULL;
315962306a36Sopenharmony_ci	struct ocfs2_alloc_context *meta_ac = NULL;
316062306a36Sopenharmony_ci	handle_t *handle = NULL;
316162306a36Sopenharmony_ci	struct buffer_head *new_bh = NULL;
316262306a36Sopenharmony_ci	struct ocfs2_dir_entry * de;
316362306a36Sopenharmony_ci	struct super_block *sb = osb->sb;
316462306a36Sopenharmony_ci	struct ocfs2_extent_tree et;
316562306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
316662306a36Sopenharmony_ci
316762306a36Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
316862306a36Sopenharmony_ci		/*
316962306a36Sopenharmony_ci		 * This would be a code error as an inline directory should
317062306a36Sopenharmony_ci		 * never have an index root.
317162306a36Sopenharmony_ci		 */
317262306a36Sopenharmony_ci		BUG_ON(dx_root_bh);
317362306a36Sopenharmony_ci
317462306a36Sopenharmony_ci		status = ocfs2_expand_inline_dir(dir, parent_fe_bh,
317562306a36Sopenharmony_ci						 blocks_wanted, lookup,
317662306a36Sopenharmony_ci						 &new_bh);
317762306a36Sopenharmony_ci		if (status) {
317862306a36Sopenharmony_ci			mlog_errno(status);
317962306a36Sopenharmony_ci			goto bail;
318062306a36Sopenharmony_ci		}
318162306a36Sopenharmony_ci
318262306a36Sopenharmony_ci		/* Expansion from inline to an indexed directory will
318362306a36Sopenharmony_ci		 * have given us this. */
318462306a36Sopenharmony_ci		dx_root_bh = lookup->dl_dx_root_bh;
318562306a36Sopenharmony_ci
318662306a36Sopenharmony_ci		if (blocks_wanted == 1) {
318762306a36Sopenharmony_ci			/*
318862306a36Sopenharmony_ci			 * If the new dirent will fit inside the space
318962306a36Sopenharmony_ci			 * created by pushing out to one block, then
319062306a36Sopenharmony_ci			 * we can complete the operation
319162306a36Sopenharmony_ci			 * here. Otherwise we have to expand i_size
319262306a36Sopenharmony_ci			 * and format the 2nd block below.
319362306a36Sopenharmony_ci			 */
319462306a36Sopenharmony_ci			BUG_ON(new_bh == NULL);
319562306a36Sopenharmony_ci			goto bail_bh;
319662306a36Sopenharmony_ci		}
319762306a36Sopenharmony_ci
319862306a36Sopenharmony_ci		/*
319962306a36Sopenharmony_ci		 * Get rid of 'new_bh' - we want to format the 2nd
320062306a36Sopenharmony_ci		 * data block and return that instead.
320162306a36Sopenharmony_ci		 */
320262306a36Sopenharmony_ci		brelse(new_bh);
320362306a36Sopenharmony_ci		new_bh = NULL;
320462306a36Sopenharmony_ci
320562306a36Sopenharmony_ci		down_write(&OCFS2_I(dir)->ip_alloc_sem);
320662306a36Sopenharmony_ci		drop_alloc_sem = 1;
320762306a36Sopenharmony_ci		dir_i_size = i_size_read(dir);
320862306a36Sopenharmony_ci		credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
320962306a36Sopenharmony_ci		goto do_extend;
321062306a36Sopenharmony_ci	}
321162306a36Sopenharmony_ci
321262306a36Sopenharmony_ci	down_write(&OCFS2_I(dir)->ip_alloc_sem);
321362306a36Sopenharmony_ci	drop_alloc_sem = 1;
321462306a36Sopenharmony_ci	dir_i_size = i_size_read(dir);
321562306a36Sopenharmony_ci	trace_ocfs2_extend_dir((unsigned long long)OCFS2_I(dir)->ip_blkno,
321662306a36Sopenharmony_ci			       dir_i_size);
321762306a36Sopenharmony_ci
321862306a36Sopenharmony_ci	/* dir->i_size is always block aligned. */
321962306a36Sopenharmony_ci	spin_lock(&OCFS2_I(dir)->ip_lock);
322062306a36Sopenharmony_ci	if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
322162306a36Sopenharmony_ci		spin_unlock(&OCFS2_I(dir)->ip_lock);
322262306a36Sopenharmony_ci		ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir),
322362306a36Sopenharmony_ci					      parent_fe_bh);
322462306a36Sopenharmony_ci		num_free_extents = ocfs2_num_free_extents(&et);
322562306a36Sopenharmony_ci		if (num_free_extents < 0) {
322662306a36Sopenharmony_ci			status = num_free_extents;
322762306a36Sopenharmony_ci			mlog_errno(status);
322862306a36Sopenharmony_ci			goto bail;
322962306a36Sopenharmony_ci		}
323062306a36Sopenharmony_ci
323162306a36Sopenharmony_ci		if (!num_free_extents) {
323262306a36Sopenharmony_ci			status = ocfs2_reserve_new_metadata(osb, el, &meta_ac);
323362306a36Sopenharmony_ci			if (status < 0) {
323462306a36Sopenharmony_ci				if (status != -ENOSPC)
323562306a36Sopenharmony_ci					mlog_errno(status);
323662306a36Sopenharmony_ci				goto bail;
323762306a36Sopenharmony_ci			}
323862306a36Sopenharmony_ci		}
323962306a36Sopenharmony_ci
324062306a36Sopenharmony_ci		status = ocfs2_reserve_clusters(osb, 1, &data_ac);
324162306a36Sopenharmony_ci		if (status < 0) {
324262306a36Sopenharmony_ci			if (status != -ENOSPC)
324362306a36Sopenharmony_ci				mlog_errno(status);
324462306a36Sopenharmony_ci			goto bail;
324562306a36Sopenharmony_ci		}
324662306a36Sopenharmony_ci
324762306a36Sopenharmony_ci		if (ocfs2_dir_resv_allowed(osb))
324862306a36Sopenharmony_ci			data_ac->ac_resv = &OCFS2_I(dir)->ip_la_data_resv;
324962306a36Sopenharmony_ci
325062306a36Sopenharmony_ci		credits = ocfs2_calc_extend_credits(sb, el);
325162306a36Sopenharmony_ci	} else {
325262306a36Sopenharmony_ci		spin_unlock(&OCFS2_I(dir)->ip_lock);
325362306a36Sopenharmony_ci		credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
325462306a36Sopenharmony_ci	}
325562306a36Sopenharmony_ci
325662306a36Sopenharmony_cido_extend:
325762306a36Sopenharmony_ci	if (ocfs2_dir_indexed(dir))
325862306a36Sopenharmony_ci		credits++; /* For attaching the new dirent block to the
325962306a36Sopenharmony_ci			    * dx_root */
326062306a36Sopenharmony_ci
326162306a36Sopenharmony_ci	handle = ocfs2_start_trans(osb, credits);
326262306a36Sopenharmony_ci	if (IS_ERR(handle)) {
326362306a36Sopenharmony_ci		status = PTR_ERR(handle);
326462306a36Sopenharmony_ci		handle = NULL;
326562306a36Sopenharmony_ci		mlog_errno(status);
326662306a36Sopenharmony_ci		goto bail;
326762306a36Sopenharmony_ci	}
326862306a36Sopenharmony_ci
326962306a36Sopenharmony_ci	status = ocfs2_do_extend_dir(osb->sb, handle, dir, parent_fe_bh,
327062306a36Sopenharmony_ci				     data_ac, meta_ac, &new_bh);
327162306a36Sopenharmony_ci	if (status < 0) {
327262306a36Sopenharmony_ci		mlog_errno(status);
327362306a36Sopenharmony_ci		goto bail;
327462306a36Sopenharmony_ci	}
327562306a36Sopenharmony_ci
327662306a36Sopenharmony_ci	ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), new_bh);
327762306a36Sopenharmony_ci
327862306a36Sopenharmony_ci	status = ocfs2_journal_access_db(handle, INODE_CACHE(dir), new_bh,
327962306a36Sopenharmony_ci					 OCFS2_JOURNAL_ACCESS_CREATE);
328062306a36Sopenharmony_ci	if (status < 0) {
328162306a36Sopenharmony_ci		mlog_errno(status);
328262306a36Sopenharmony_ci		goto bail;
328362306a36Sopenharmony_ci	}
328462306a36Sopenharmony_ci	memset(new_bh->b_data, 0, sb->s_blocksize);
328562306a36Sopenharmony_ci
328662306a36Sopenharmony_ci	de = (struct ocfs2_dir_entry *) new_bh->b_data;
328762306a36Sopenharmony_ci	de->inode = 0;
328862306a36Sopenharmony_ci	if (ocfs2_supports_dir_trailer(dir)) {
328962306a36Sopenharmony_ci		de->rec_len = cpu_to_le16(ocfs2_dir_trailer_blk_off(sb));
329062306a36Sopenharmony_ci
329162306a36Sopenharmony_ci		ocfs2_init_dir_trailer(dir, new_bh, le16_to_cpu(de->rec_len));
329262306a36Sopenharmony_ci
329362306a36Sopenharmony_ci		if (ocfs2_dir_indexed(dir)) {
329462306a36Sopenharmony_ci			status = ocfs2_dx_dir_link_trailer(dir, handle,
329562306a36Sopenharmony_ci							   dx_root_bh, new_bh);
329662306a36Sopenharmony_ci			if (status) {
329762306a36Sopenharmony_ci				mlog_errno(status);
329862306a36Sopenharmony_ci				goto bail;
329962306a36Sopenharmony_ci			}
330062306a36Sopenharmony_ci		}
330162306a36Sopenharmony_ci	} else {
330262306a36Sopenharmony_ci		de->rec_len = cpu_to_le16(sb->s_blocksize);
330362306a36Sopenharmony_ci	}
330462306a36Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
330562306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, new_bh);
330662306a36Sopenharmony_ci
330762306a36Sopenharmony_ci	dir_i_size += dir->i_sb->s_blocksize;
330862306a36Sopenharmony_ci	i_size_write(dir, dir_i_size);
330962306a36Sopenharmony_ci	dir->i_blocks = ocfs2_inode_sector_count(dir);
331062306a36Sopenharmony_ci	status = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
331162306a36Sopenharmony_ci	if (status < 0) {
331262306a36Sopenharmony_ci		mlog_errno(status);
331362306a36Sopenharmony_ci		goto bail;
331462306a36Sopenharmony_ci	}
331562306a36Sopenharmony_ci
331662306a36Sopenharmony_cibail_bh:
331762306a36Sopenharmony_ci	*new_de_bh = new_bh;
331862306a36Sopenharmony_ci	get_bh(*new_de_bh);
331962306a36Sopenharmony_cibail:
332062306a36Sopenharmony_ci	if (handle)
332162306a36Sopenharmony_ci		ocfs2_commit_trans(osb, handle);
332262306a36Sopenharmony_ci	if (drop_alloc_sem)
332362306a36Sopenharmony_ci		up_write(&OCFS2_I(dir)->ip_alloc_sem);
332462306a36Sopenharmony_ci
332562306a36Sopenharmony_ci	if (data_ac)
332662306a36Sopenharmony_ci		ocfs2_free_alloc_context(data_ac);
332762306a36Sopenharmony_ci	if (meta_ac)
332862306a36Sopenharmony_ci		ocfs2_free_alloc_context(meta_ac);
332962306a36Sopenharmony_ci
333062306a36Sopenharmony_ci	brelse(new_bh);
333162306a36Sopenharmony_ci
333262306a36Sopenharmony_ci	return status;
333362306a36Sopenharmony_ci}
333462306a36Sopenharmony_ci
333562306a36Sopenharmony_cistatic int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh,
333662306a36Sopenharmony_ci				   const char *name, int namelen,
333762306a36Sopenharmony_ci				   struct buffer_head **ret_de_bh,
333862306a36Sopenharmony_ci				   unsigned int *blocks_wanted)
333962306a36Sopenharmony_ci{
334062306a36Sopenharmony_ci	int ret;
334162306a36Sopenharmony_ci	struct super_block *sb = dir->i_sb;
334262306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
334362306a36Sopenharmony_ci	struct ocfs2_dir_entry *de, *last_de = NULL;
334462306a36Sopenharmony_ci	char *de_buf, *limit;
334562306a36Sopenharmony_ci	unsigned long offset = 0;
334662306a36Sopenharmony_ci	unsigned int rec_len, new_rec_len, free_space;
334762306a36Sopenharmony_ci
334862306a36Sopenharmony_ci	/*
334962306a36Sopenharmony_ci	 * This calculates how many free bytes we'd have in block zero, should
335062306a36Sopenharmony_ci	 * this function force expansion to an extent tree.
335162306a36Sopenharmony_ci	 */
335262306a36Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(dir))
335362306a36Sopenharmony_ci		free_space = ocfs2_dir_trailer_blk_off(sb) - i_size_read(dir);
335462306a36Sopenharmony_ci	else
335562306a36Sopenharmony_ci		free_space = dir->i_sb->s_blocksize - i_size_read(dir);
335662306a36Sopenharmony_ci
335762306a36Sopenharmony_ci	de_buf = di->id2.i_data.id_data;
335862306a36Sopenharmony_ci	limit = de_buf + i_size_read(dir);
335962306a36Sopenharmony_ci	rec_len = OCFS2_DIR_REC_LEN(namelen);
336062306a36Sopenharmony_ci
336162306a36Sopenharmony_ci	while (de_buf < limit) {
336262306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
336362306a36Sopenharmony_ci
336462306a36Sopenharmony_ci		if (!ocfs2_check_dir_entry(dir, de, di_bh, offset)) {
336562306a36Sopenharmony_ci			ret = -ENOENT;
336662306a36Sopenharmony_ci			goto out;
336762306a36Sopenharmony_ci		}
336862306a36Sopenharmony_ci		if (ocfs2_match(namelen, name, de)) {
336962306a36Sopenharmony_ci			ret = -EEXIST;
337062306a36Sopenharmony_ci			goto out;
337162306a36Sopenharmony_ci		}
337262306a36Sopenharmony_ci		/*
337362306a36Sopenharmony_ci		 * No need to check for a trailing dirent record here as
337462306a36Sopenharmony_ci		 * they're not used for inline dirs.
337562306a36Sopenharmony_ci		 */
337662306a36Sopenharmony_ci
337762306a36Sopenharmony_ci		if (ocfs2_dirent_would_fit(de, rec_len)) {
337862306a36Sopenharmony_ci			/* Ok, we found a spot. Return this bh and let
337962306a36Sopenharmony_ci			 * the caller actually fill it in. */
338062306a36Sopenharmony_ci			*ret_de_bh = di_bh;
338162306a36Sopenharmony_ci			get_bh(*ret_de_bh);
338262306a36Sopenharmony_ci			ret = 0;
338362306a36Sopenharmony_ci			goto out;
338462306a36Sopenharmony_ci		}
338562306a36Sopenharmony_ci
338662306a36Sopenharmony_ci		last_de = de;
338762306a36Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
338862306a36Sopenharmony_ci		offset += le16_to_cpu(de->rec_len);
338962306a36Sopenharmony_ci	}
339062306a36Sopenharmony_ci
339162306a36Sopenharmony_ci	/*
339262306a36Sopenharmony_ci	 * We're going to require expansion of the directory - figure
339362306a36Sopenharmony_ci	 * out how many blocks we'll need so that a place for the
339462306a36Sopenharmony_ci	 * dirent can be found.
339562306a36Sopenharmony_ci	 */
339662306a36Sopenharmony_ci	*blocks_wanted = 1;
339762306a36Sopenharmony_ci	new_rec_len = le16_to_cpu(last_de->rec_len) + free_space;
339862306a36Sopenharmony_ci	if (new_rec_len < (rec_len + OCFS2_DIR_REC_LEN(last_de->name_len)))
339962306a36Sopenharmony_ci		*blocks_wanted = 2;
340062306a36Sopenharmony_ci
340162306a36Sopenharmony_ci	ret = -ENOSPC;
340262306a36Sopenharmony_ciout:
340362306a36Sopenharmony_ci	return ret;
340462306a36Sopenharmony_ci}
340562306a36Sopenharmony_ci
340662306a36Sopenharmony_cistatic int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
340762306a36Sopenharmony_ci				   int namelen, struct buffer_head **ret_de_bh)
340862306a36Sopenharmony_ci{
340962306a36Sopenharmony_ci	unsigned long offset;
341062306a36Sopenharmony_ci	struct buffer_head *bh = NULL;
341162306a36Sopenharmony_ci	unsigned short rec_len;
341262306a36Sopenharmony_ci	struct ocfs2_dir_entry *de;
341362306a36Sopenharmony_ci	struct super_block *sb = dir->i_sb;
341462306a36Sopenharmony_ci	int status;
341562306a36Sopenharmony_ci	int blocksize = dir->i_sb->s_blocksize;
341662306a36Sopenharmony_ci
341762306a36Sopenharmony_ci	status = ocfs2_read_dir_block(dir, 0, &bh, 0);
341862306a36Sopenharmony_ci	if (status)
341962306a36Sopenharmony_ci		goto bail;
342062306a36Sopenharmony_ci
342162306a36Sopenharmony_ci	rec_len = OCFS2_DIR_REC_LEN(namelen);
342262306a36Sopenharmony_ci	offset = 0;
342362306a36Sopenharmony_ci	de = (struct ocfs2_dir_entry *) bh->b_data;
342462306a36Sopenharmony_ci	while (1) {
342562306a36Sopenharmony_ci		if ((char *)de >= sb->s_blocksize + bh->b_data) {
342662306a36Sopenharmony_ci			brelse(bh);
342762306a36Sopenharmony_ci			bh = NULL;
342862306a36Sopenharmony_ci
342962306a36Sopenharmony_ci			if (i_size_read(dir) <= offset) {
343062306a36Sopenharmony_ci				/*
343162306a36Sopenharmony_ci				 * Caller will have to expand this
343262306a36Sopenharmony_ci				 * directory.
343362306a36Sopenharmony_ci				 */
343462306a36Sopenharmony_ci				status = -ENOSPC;
343562306a36Sopenharmony_ci				goto bail;
343662306a36Sopenharmony_ci			}
343762306a36Sopenharmony_ci			status = ocfs2_read_dir_block(dir,
343862306a36Sopenharmony_ci					     offset >> sb->s_blocksize_bits,
343962306a36Sopenharmony_ci					     &bh, 0);
344062306a36Sopenharmony_ci			if (status)
344162306a36Sopenharmony_ci				goto bail;
344262306a36Sopenharmony_ci
344362306a36Sopenharmony_ci			/* move to next block */
344462306a36Sopenharmony_ci			de = (struct ocfs2_dir_entry *) bh->b_data;
344562306a36Sopenharmony_ci		}
344662306a36Sopenharmony_ci		if (!ocfs2_check_dir_entry(dir, de, bh, offset)) {
344762306a36Sopenharmony_ci			status = -ENOENT;
344862306a36Sopenharmony_ci			goto bail;
344962306a36Sopenharmony_ci		}
345062306a36Sopenharmony_ci		if (ocfs2_match(namelen, name, de)) {
345162306a36Sopenharmony_ci			status = -EEXIST;
345262306a36Sopenharmony_ci			goto bail;
345362306a36Sopenharmony_ci		}
345462306a36Sopenharmony_ci
345562306a36Sopenharmony_ci		if (ocfs2_skip_dir_trailer(dir, de, offset % blocksize,
345662306a36Sopenharmony_ci					   blocksize))
345762306a36Sopenharmony_ci			goto next;
345862306a36Sopenharmony_ci
345962306a36Sopenharmony_ci		if (ocfs2_dirent_would_fit(de, rec_len)) {
346062306a36Sopenharmony_ci			/* Ok, we found a spot. Return this bh and let
346162306a36Sopenharmony_ci			 * the caller actually fill it in. */
346262306a36Sopenharmony_ci			*ret_de_bh = bh;
346362306a36Sopenharmony_ci			get_bh(*ret_de_bh);
346462306a36Sopenharmony_ci			status = 0;
346562306a36Sopenharmony_ci			goto bail;
346662306a36Sopenharmony_ci		}
346762306a36Sopenharmony_cinext:
346862306a36Sopenharmony_ci		offset += le16_to_cpu(de->rec_len);
346962306a36Sopenharmony_ci		de = (struct ocfs2_dir_entry *)((char *) de + le16_to_cpu(de->rec_len));
347062306a36Sopenharmony_ci	}
347162306a36Sopenharmony_ci
347262306a36Sopenharmony_cibail:
347362306a36Sopenharmony_ci	brelse(bh);
347462306a36Sopenharmony_ci	if (status)
347562306a36Sopenharmony_ci		mlog_errno(status);
347662306a36Sopenharmony_ci
347762306a36Sopenharmony_ci	return status;
347862306a36Sopenharmony_ci}
347962306a36Sopenharmony_ci
348062306a36Sopenharmony_cistatic int dx_leaf_sort_cmp(const void *a, const void *b)
348162306a36Sopenharmony_ci{
348262306a36Sopenharmony_ci	const struct ocfs2_dx_entry *entry1 = a;
348362306a36Sopenharmony_ci	const struct ocfs2_dx_entry *entry2 = b;
348462306a36Sopenharmony_ci	u32 major_hash1 = le32_to_cpu(entry1->dx_major_hash);
348562306a36Sopenharmony_ci	u32 major_hash2 = le32_to_cpu(entry2->dx_major_hash);
348662306a36Sopenharmony_ci	u32 minor_hash1 = le32_to_cpu(entry1->dx_minor_hash);
348762306a36Sopenharmony_ci	u32 minor_hash2 = le32_to_cpu(entry2->dx_minor_hash);
348862306a36Sopenharmony_ci
348962306a36Sopenharmony_ci	if (major_hash1 > major_hash2)
349062306a36Sopenharmony_ci		return 1;
349162306a36Sopenharmony_ci	if (major_hash1 < major_hash2)
349262306a36Sopenharmony_ci		return -1;
349362306a36Sopenharmony_ci
349462306a36Sopenharmony_ci	/*
349562306a36Sopenharmony_ci	 * It is not strictly necessary to sort by minor
349662306a36Sopenharmony_ci	 */
349762306a36Sopenharmony_ci	if (minor_hash1 > minor_hash2)
349862306a36Sopenharmony_ci		return 1;
349962306a36Sopenharmony_ci	if (minor_hash1 < minor_hash2)
350062306a36Sopenharmony_ci		return -1;
350162306a36Sopenharmony_ci	return 0;
350262306a36Sopenharmony_ci}
350362306a36Sopenharmony_ci
350462306a36Sopenharmony_cistatic void dx_leaf_sort_swap(void *a, void *b, int size)
350562306a36Sopenharmony_ci{
350662306a36Sopenharmony_ci	struct ocfs2_dx_entry *entry1 = a;
350762306a36Sopenharmony_ci	struct ocfs2_dx_entry *entry2 = b;
350862306a36Sopenharmony_ci
350962306a36Sopenharmony_ci	BUG_ON(size != sizeof(*entry1));
351062306a36Sopenharmony_ci
351162306a36Sopenharmony_ci	swap(*entry1, *entry2);
351262306a36Sopenharmony_ci}
351362306a36Sopenharmony_ci
351462306a36Sopenharmony_cistatic int ocfs2_dx_leaf_same_major(struct ocfs2_dx_leaf *dx_leaf)
351562306a36Sopenharmony_ci{
351662306a36Sopenharmony_ci	struct ocfs2_dx_entry_list *dl_list = &dx_leaf->dl_list;
351762306a36Sopenharmony_ci	int i, num = le16_to_cpu(dl_list->de_num_used);
351862306a36Sopenharmony_ci
351962306a36Sopenharmony_ci	for (i = 0; i < (num - 1); i++) {
352062306a36Sopenharmony_ci		if (le32_to_cpu(dl_list->de_entries[i].dx_major_hash) !=
352162306a36Sopenharmony_ci		    le32_to_cpu(dl_list->de_entries[i + 1].dx_major_hash))
352262306a36Sopenharmony_ci			return 0;
352362306a36Sopenharmony_ci	}
352462306a36Sopenharmony_ci
352562306a36Sopenharmony_ci	return 1;
352662306a36Sopenharmony_ci}
352762306a36Sopenharmony_ci
352862306a36Sopenharmony_ci/*
352962306a36Sopenharmony_ci * Find the optimal value to split this leaf on. This expects the leaf
353062306a36Sopenharmony_ci * entries to be in sorted order.
353162306a36Sopenharmony_ci *
353262306a36Sopenharmony_ci * leaf_cpos is the cpos of the leaf we're splitting. insert_hash is
353362306a36Sopenharmony_ci * the hash we want to insert.
353462306a36Sopenharmony_ci *
353562306a36Sopenharmony_ci * This function is only concerned with the major hash - that which
353662306a36Sopenharmony_ci * determines which cluster an item belongs to.
353762306a36Sopenharmony_ci */
353862306a36Sopenharmony_cistatic int ocfs2_dx_dir_find_leaf_split(struct ocfs2_dx_leaf *dx_leaf,
353962306a36Sopenharmony_ci					u32 leaf_cpos, u32 insert_hash,
354062306a36Sopenharmony_ci					u32 *split_hash)
354162306a36Sopenharmony_ci{
354262306a36Sopenharmony_ci	struct ocfs2_dx_entry_list *dl_list = &dx_leaf->dl_list;
354362306a36Sopenharmony_ci	int i, num_used = le16_to_cpu(dl_list->de_num_used);
354462306a36Sopenharmony_ci	int allsame;
354562306a36Sopenharmony_ci
354662306a36Sopenharmony_ci	/*
354762306a36Sopenharmony_ci	 * There's a couple rare, but nasty corner cases we have to
354862306a36Sopenharmony_ci	 * check for here. All of them involve a leaf where all value
354962306a36Sopenharmony_ci	 * have the same hash, which is what we look for first.
355062306a36Sopenharmony_ci	 *
355162306a36Sopenharmony_ci	 * Most of the time, all of the above is false, and we simply
355262306a36Sopenharmony_ci	 * pick the median value for a split.
355362306a36Sopenharmony_ci	 */
355462306a36Sopenharmony_ci	allsame = ocfs2_dx_leaf_same_major(dx_leaf);
355562306a36Sopenharmony_ci	if (allsame) {
355662306a36Sopenharmony_ci		u32 val = le32_to_cpu(dl_list->de_entries[0].dx_major_hash);
355762306a36Sopenharmony_ci
355862306a36Sopenharmony_ci		if (val == insert_hash) {
355962306a36Sopenharmony_ci			/*
356062306a36Sopenharmony_ci			 * No matter where we would choose to split,
356162306a36Sopenharmony_ci			 * the new entry would want to occupy the same
356262306a36Sopenharmony_ci			 * block as these. Since there's no space left
356362306a36Sopenharmony_ci			 * in their existing block, we know there
356462306a36Sopenharmony_ci			 * won't be space after the split.
356562306a36Sopenharmony_ci			 */
356662306a36Sopenharmony_ci			return -ENOSPC;
356762306a36Sopenharmony_ci		}
356862306a36Sopenharmony_ci
356962306a36Sopenharmony_ci		if (val == leaf_cpos) {
357062306a36Sopenharmony_ci			/*
357162306a36Sopenharmony_ci			 * Because val is the same as leaf_cpos (which
357262306a36Sopenharmony_ci			 * is the smallest value this leaf can have),
357362306a36Sopenharmony_ci			 * yet is not equal to insert_hash, then we
357462306a36Sopenharmony_ci			 * know that insert_hash *must* be larger than
357562306a36Sopenharmony_ci			 * val (and leaf_cpos). At least cpos+1 in value.
357662306a36Sopenharmony_ci			 *
357762306a36Sopenharmony_ci			 * We also know then, that there cannot be an
357862306a36Sopenharmony_ci			 * adjacent extent (otherwise we'd be looking
357962306a36Sopenharmony_ci			 * at it). Choosing this value gives us a
358062306a36Sopenharmony_ci			 * chance to get some contiguousness.
358162306a36Sopenharmony_ci			 */
358262306a36Sopenharmony_ci			*split_hash = leaf_cpos + 1;
358362306a36Sopenharmony_ci			return 0;
358462306a36Sopenharmony_ci		}
358562306a36Sopenharmony_ci
358662306a36Sopenharmony_ci		if (val > insert_hash) {
358762306a36Sopenharmony_ci			/*
358862306a36Sopenharmony_ci			 * val can not be the same as insert hash, and
358962306a36Sopenharmony_ci			 * also must be larger than leaf_cpos. Also,
359062306a36Sopenharmony_ci			 * we know that there can't be a leaf between
359162306a36Sopenharmony_ci			 * cpos and val, otherwise the entries with
359262306a36Sopenharmony_ci			 * hash 'val' would be there.
359362306a36Sopenharmony_ci			 */
359462306a36Sopenharmony_ci			*split_hash = val;
359562306a36Sopenharmony_ci			return 0;
359662306a36Sopenharmony_ci		}
359762306a36Sopenharmony_ci
359862306a36Sopenharmony_ci		*split_hash = insert_hash;
359962306a36Sopenharmony_ci		return 0;
360062306a36Sopenharmony_ci	}
360162306a36Sopenharmony_ci
360262306a36Sopenharmony_ci	/*
360362306a36Sopenharmony_ci	 * Since the records are sorted and the checks above
360462306a36Sopenharmony_ci	 * guaranteed that not all records in this block are the same,
360562306a36Sopenharmony_ci	 * we simple travel forward, from the median, and pick the 1st
360662306a36Sopenharmony_ci	 * record whose value is larger than leaf_cpos.
360762306a36Sopenharmony_ci	 */
360862306a36Sopenharmony_ci	for (i = (num_used / 2); i < num_used; i++)
360962306a36Sopenharmony_ci		if (le32_to_cpu(dl_list->de_entries[i].dx_major_hash) >
361062306a36Sopenharmony_ci		    leaf_cpos)
361162306a36Sopenharmony_ci			break;
361262306a36Sopenharmony_ci
361362306a36Sopenharmony_ci	BUG_ON(i == num_used); /* Should be impossible */
361462306a36Sopenharmony_ci	*split_hash = le32_to_cpu(dl_list->de_entries[i].dx_major_hash);
361562306a36Sopenharmony_ci	return 0;
361662306a36Sopenharmony_ci}
361762306a36Sopenharmony_ci
361862306a36Sopenharmony_ci/*
361962306a36Sopenharmony_ci * Transfer all entries in orig_dx_leaves whose major hash is equal to or
362062306a36Sopenharmony_ci * larger than split_hash into new_dx_leaves. We use a temporary
362162306a36Sopenharmony_ci * buffer (tmp_dx_leaf) to make the changes to the original leaf blocks.
362262306a36Sopenharmony_ci *
362362306a36Sopenharmony_ci * Since the block offset inside a leaf (cluster) is a constant mask
362462306a36Sopenharmony_ci * of minor_hash, we can optimize - an item at block offset X within
362562306a36Sopenharmony_ci * the original cluster, will be at offset X within the new cluster.
362662306a36Sopenharmony_ci */
362762306a36Sopenharmony_cistatic void ocfs2_dx_dir_transfer_leaf(struct inode *dir, u32 split_hash,
362862306a36Sopenharmony_ci				       handle_t *handle,
362962306a36Sopenharmony_ci				       struct ocfs2_dx_leaf *tmp_dx_leaf,
363062306a36Sopenharmony_ci				       struct buffer_head **orig_dx_leaves,
363162306a36Sopenharmony_ci				       struct buffer_head **new_dx_leaves,
363262306a36Sopenharmony_ci				       int num_dx_leaves)
363362306a36Sopenharmony_ci{
363462306a36Sopenharmony_ci	int i, j, num_used;
363562306a36Sopenharmony_ci	u32 major_hash;
363662306a36Sopenharmony_ci	struct ocfs2_dx_leaf *orig_dx_leaf, *new_dx_leaf;
363762306a36Sopenharmony_ci	struct ocfs2_dx_entry_list *orig_list, *tmp_list;
363862306a36Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry;
363962306a36Sopenharmony_ci
364062306a36Sopenharmony_ci	tmp_list = &tmp_dx_leaf->dl_list;
364162306a36Sopenharmony_ci
364262306a36Sopenharmony_ci	for (i = 0; i < num_dx_leaves; i++) {
364362306a36Sopenharmony_ci		orig_dx_leaf = (struct ocfs2_dx_leaf *) orig_dx_leaves[i]->b_data;
364462306a36Sopenharmony_ci		orig_list = &orig_dx_leaf->dl_list;
364562306a36Sopenharmony_ci		new_dx_leaf = (struct ocfs2_dx_leaf *) new_dx_leaves[i]->b_data;
364662306a36Sopenharmony_ci
364762306a36Sopenharmony_ci		num_used = le16_to_cpu(orig_list->de_num_used);
364862306a36Sopenharmony_ci
364962306a36Sopenharmony_ci		memcpy(tmp_dx_leaf, orig_dx_leaf, dir->i_sb->s_blocksize);
365062306a36Sopenharmony_ci		tmp_list->de_num_used = cpu_to_le16(0);
365162306a36Sopenharmony_ci		memset(&tmp_list->de_entries, 0, sizeof(*dx_entry)*num_used);
365262306a36Sopenharmony_ci
365362306a36Sopenharmony_ci		for (j = 0; j < num_used; j++) {
365462306a36Sopenharmony_ci			dx_entry = &orig_list->de_entries[j];
365562306a36Sopenharmony_ci			major_hash = le32_to_cpu(dx_entry->dx_major_hash);
365662306a36Sopenharmony_ci			if (major_hash >= split_hash)
365762306a36Sopenharmony_ci				ocfs2_dx_dir_leaf_insert_tail(new_dx_leaf,
365862306a36Sopenharmony_ci							      dx_entry);
365962306a36Sopenharmony_ci			else
366062306a36Sopenharmony_ci				ocfs2_dx_dir_leaf_insert_tail(tmp_dx_leaf,
366162306a36Sopenharmony_ci							      dx_entry);
366262306a36Sopenharmony_ci		}
366362306a36Sopenharmony_ci		memcpy(orig_dx_leaf, tmp_dx_leaf, dir->i_sb->s_blocksize);
366462306a36Sopenharmony_ci
366562306a36Sopenharmony_ci		ocfs2_journal_dirty(handle, orig_dx_leaves[i]);
366662306a36Sopenharmony_ci		ocfs2_journal_dirty(handle, new_dx_leaves[i]);
366762306a36Sopenharmony_ci	}
366862306a36Sopenharmony_ci}
366962306a36Sopenharmony_ci
367062306a36Sopenharmony_cistatic int ocfs2_dx_dir_rebalance_credits(struct ocfs2_super *osb,
367162306a36Sopenharmony_ci					  struct ocfs2_dx_root_block *dx_root)
367262306a36Sopenharmony_ci{
367362306a36Sopenharmony_ci	int credits = ocfs2_clusters_to_blocks(osb->sb, 3);
367462306a36Sopenharmony_ci
367562306a36Sopenharmony_ci	credits += ocfs2_calc_extend_credits(osb->sb, &dx_root->dr_list);
367662306a36Sopenharmony_ci	credits += ocfs2_quota_trans_credits(osb->sb);
367762306a36Sopenharmony_ci	return credits;
367862306a36Sopenharmony_ci}
367962306a36Sopenharmony_ci
368062306a36Sopenharmony_ci/*
368162306a36Sopenharmony_ci * Find the median value in dx_leaf_bh and allocate a new leaf to move
368262306a36Sopenharmony_ci * half our entries into.
368362306a36Sopenharmony_ci */
368462306a36Sopenharmony_cistatic int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
368562306a36Sopenharmony_ci				  struct buffer_head *dx_root_bh,
368662306a36Sopenharmony_ci				  struct buffer_head *dx_leaf_bh,
368762306a36Sopenharmony_ci				  struct ocfs2_dx_hinfo *hinfo, u32 leaf_cpos,
368862306a36Sopenharmony_ci				  u64 leaf_blkno)
368962306a36Sopenharmony_ci{
369062306a36Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_bh->b_data;
369162306a36Sopenharmony_ci	int credits, ret, i, num_used, did_quota = 0;
369262306a36Sopenharmony_ci	u32 cpos, split_hash, insert_hash = hinfo->major_hash;
369362306a36Sopenharmony_ci	u64 orig_leaves_start;
369462306a36Sopenharmony_ci	int num_dx_leaves;
369562306a36Sopenharmony_ci	struct buffer_head **orig_dx_leaves = NULL;
369662306a36Sopenharmony_ci	struct buffer_head **new_dx_leaves = NULL;
369762306a36Sopenharmony_ci	struct ocfs2_alloc_context *data_ac = NULL, *meta_ac = NULL;
369862306a36Sopenharmony_ci	struct ocfs2_extent_tree et;
369962306a36Sopenharmony_ci	handle_t *handle = NULL;
370062306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
370162306a36Sopenharmony_ci	struct ocfs2_dx_leaf *tmp_dx_leaf = NULL;
370262306a36Sopenharmony_ci
370362306a36Sopenharmony_ci	trace_ocfs2_dx_dir_rebalance((unsigned long long)OCFS2_I(dir)->ip_blkno,
370462306a36Sopenharmony_ci				     (unsigned long long)leaf_blkno,
370562306a36Sopenharmony_ci				     insert_hash);
370662306a36Sopenharmony_ci
370762306a36Sopenharmony_ci	ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
370862306a36Sopenharmony_ci
370962306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
371062306a36Sopenharmony_ci	/*
371162306a36Sopenharmony_ci	 * XXX: This is a rather large limit. We should use a more
371262306a36Sopenharmony_ci	 * realistic value.
371362306a36Sopenharmony_ci	 */
371462306a36Sopenharmony_ci	if (le32_to_cpu(dx_root->dr_clusters) == UINT_MAX)
371562306a36Sopenharmony_ci		return -ENOSPC;
371662306a36Sopenharmony_ci
371762306a36Sopenharmony_ci	num_used = le16_to_cpu(dx_leaf->dl_list.de_num_used);
371862306a36Sopenharmony_ci	if (num_used < le16_to_cpu(dx_leaf->dl_list.de_count)) {
371962306a36Sopenharmony_ci		mlog(ML_ERROR, "DX Dir: %llu, Asked to rebalance empty leaf: "
372062306a36Sopenharmony_ci		     "%llu, %d\n", (unsigned long long)OCFS2_I(dir)->ip_blkno,
372162306a36Sopenharmony_ci		     (unsigned long long)leaf_blkno, num_used);
372262306a36Sopenharmony_ci		ret = -EIO;
372362306a36Sopenharmony_ci		goto out;
372462306a36Sopenharmony_ci	}
372562306a36Sopenharmony_ci
372662306a36Sopenharmony_ci	orig_dx_leaves = ocfs2_dx_dir_kmalloc_leaves(osb->sb, &num_dx_leaves);
372762306a36Sopenharmony_ci	if (!orig_dx_leaves) {
372862306a36Sopenharmony_ci		ret = -ENOMEM;
372962306a36Sopenharmony_ci		mlog_errno(ret);
373062306a36Sopenharmony_ci		goto out;
373162306a36Sopenharmony_ci	}
373262306a36Sopenharmony_ci
373362306a36Sopenharmony_ci	new_dx_leaves = ocfs2_dx_dir_kmalloc_leaves(osb->sb, NULL);
373462306a36Sopenharmony_ci	if (!new_dx_leaves) {
373562306a36Sopenharmony_ci		ret = -ENOMEM;
373662306a36Sopenharmony_ci		mlog_errno(ret);
373762306a36Sopenharmony_ci		goto out;
373862306a36Sopenharmony_ci	}
373962306a36Sopenharmony_ci
374062306a36Sopenharmony_ci	ret = ocfs2_lock_allocators(dir, &et, 1, 0, &data_ac, &meta_ac);
374162306a36Sopenharmony_ci	if (ret) {
374262306a36Sopenharmony_ci		if (ret != -ENOSPC)
374362306a36Sopenharmony_ci			mlog_errno(ret);
374462306a36Sopenharmony_ci		goto out;
374562306a36Sopenharmony_ci	}
374662306a36Sopenharmony_ci
374762306a36Sopenharmony_ci	credits = ocfs2_dx_dir_rebalance_credits(osb, dx_root);
374862306a36Sopenharmony_ci	handle = ocfs2_start_trans(osb, credits);
374962306a36Sopenharmony_ci	if (IS_ERR(handle)) {
375062306a36Sopenharmony_ci		ret = PTR_ERR(handle);
375162306a36Sopenharmony_ci		handle = NULL;
375262306a36Sopenharmony_ci		mlog_errno(ret);
375362306a36Sopenharmony_ci		goto out;
375462306a36Sopenharmony_ci	}
375562306a36Sopenharmony_ci
375662306a36Sopenharmony_ci	ret = dquot_alloc_space_nodirty(dir,
375762306a36Sopenharmony_ci				       ocfs2_clusters_to_bytes(dir->i_sb, 1));
375862306a36Sopenharmony_ci	if (ret)
375962306a36Sopenharmony_ci		goto out_commit;
376062306a36Sopenharmony_ci	did_quota = 1;
376162306a36Sopenharmony_ci
376262306a36Sopenharmony_ci	ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
376362306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
376462306a36Sopenharmony_ci	if (ret) {
376562306a36Sopenharmony_ci		mlog_errno(ret);
376662306a36Sopenharmony_ci		goto out_commit;
376762306a36Sopenharmony_ci	}
376862306a36Sopenharmony_ci
376962306a36Sopenharmony_ci	/*
377062306a36Sopenharmony_ci	 * This block is changing anyway, so we can sort it in place.
377162306a36Sopenharmony_ci	 */
377262306a36Sopenharmony_ci	sort(dx_leaf->dl_list.de_entries, num_used,
377362306a36Sopenharmony_ci	     sizeof(struct ocfs2_dx_entry), dx_leaf_sort_cmp,
377462306a36Sopenharmony_ci	     dx_leaf_sort_swap);
377562306a36Sopenharmony_ci
377662306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_leaf_bh);
377762306a36Sopenharmony_ci
377862306a36Sopenharmony_ci	ret = ocfs2_dx_dir_find_leaf_split(dx_leaf, leaf_cpos, insert_hash,
377962306a36Sopenharmony_ci					   &split_hash);
378062306a36Sopenharmony_ci	if (ret) {
378162306a36Sopenharmony_ci		mlog_errno(ret);
378262306a36Sopenharmony_ci		goto  out_commit;
378362306a36Sopenharmony_ci	}
378462306a36Sopenharmony_ci
378562306a36Sopenharmony_ci	trace_ocfs2_dx_dir_rebalance_split(leaf_cpos, split_hash, insert_hash);
378662306a36Sopenharmony_ci
378762306a36Sopenharmony_ci	/*
378862306a36Sopenharmony_ci	 * We have to carefully order operations here. There are items
378962306a36Sopenharmony_ci	 * which want to be in the new cluster before insert, but in
379062306a36Sopenharmony_ci	 * order to put those items in the new cluster, we alter the
379162306a36Sopenharmony_ci	 * old cluster. A failure to insert gets nasty.
379262306a36Sopenharmony_ci	 *
379362306a36Sopenharmony_ci	 * So, start by reserving writes to the old
379462306a36Sopenharmony_ci	 * cluster. ocfs2_dx_dir_new_cluster will reserve writes on
379562306a36Sopenharmony_ci	 * the new cluster for us, before inserting it. The insert
379662306a36Sopenharmony_ci	 * won't happen if there's an error before that. Once the
379762306a36Sopenharmony_ci	 * insert is done then, we can transfer from one leaf into the
379862306a36Sopenharmony_ci	 * other without fear of hitting any error.
379962306a36Sopenharmony_ci	 */
380062306a36Sopenharmony_ci
380162306a36Sopenharmony_ci	/*
380262306a36Sopenharmony_ci	 * The leaf transfer wants some scratch space so that we don't
380362306a36Sopenharmony_ci	 * wind up doing a bunch of expensive memmove().
380462306a36Sopenharmony_ci	 */
380562306a36Sopenharmony_ci	tmp_dx_leaf = kmalloc(osb->sb->s_blocksize, GFP_NOFS);
380662306a36Sopenharmony_ci	if (!tmp_dx_leaf) {
380762306a36Sopenharmony_ci		ret = -ENOMEM;
380862306a36Sopenharmony_ci		mlog_errno(ret);
380962306a36Sopenharmony_ci		goto out_commit;
381062306a36Sopenharmony_ci	}
381162306a36Sopenharmony_ci
381262306a36Sopenharmony_ci	orig_leaves_start = ocfs2_block_to_cluster_start(dir->i_sb, leaf_blkno);
381362306a36Sopenharmony_ci	ret = ocfs2_read_dx_leaves(dir, orig_leaves_start, num_dx_leaves,
381462306a36Sopenharmony_ci				   orig_dx_leaves);
381562306a36Sopenharmony_ci	if (ret) {
381662306a36Sopenharmony_ci		mlog_errno(ret);
381762306a36Sopenharmony_ci		goto out_commit;
381862306a36Sopenharmony_ci	}
381962306a36Sopenharmony_ci
382062306a36Sopenharmony_ci	cpos = split_hash;
382162306a36Sopenharmony_ci	ret = ocfs2_dx_dir_new_cluster(dir, &et, cpos, handle,
382262306a36Sopenharmony_ci				       data_ac, meta_ac, new_dx_leaves,
382362306a36Sopenharmony_ci				       num_dx_leaves);
382462306a36Sopenharmony_ci	if (ret) {
382562306a36Sopenharmony_ci		mlog_errno(ret);
382662306a36Sopenharmony_ci		goto out_commit;
382762306a36Sopenharmony_ci	}
382862306a36Sopenharmony_ci
382962306a36Sopenharmony_ci	for (i = 0; i < num_dx_leaves; i++) {
383062306a36Sopenharmony_ci		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
383162306a36Sopenharmony_ci					      orig_dx_leaves[i],
383262306a36Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_WRITE);
383362306a36Sopenharmony_ci		if (ret) {
383462306a36Sopenharmony_ci			mlog_errno(ret);
383562306a36Sopenharmony_ci			goto out_commit;
383662306a36Sopenharmony_ci		}
383762306a36Sopenharmony_ci
383862306a36Sopenharmony_ci		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
383962306a36Sopenharmony_ci					      new_dx_leaves[i],
384062306a36Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_WRITE);
384162306a36Sopenharmony_ci		if (ret) {
384262306a36Sopenharmony_ci			mlog_errno(ret);
384362306a36Sopenharmony_ci			goto out_commit;
384462306a36Sopenharmony_ci		}
384562306a36Sopenharmony_ci	}
384662306a36Sopenharmony_ci
384762306a36Sopenharmony_ci	ocfs2_dx_dir_transfer_leaf(dir, split_hash, handle, tmp_dx_leaf,
384862306a36Sopenharmony_ci				   orig_dx_leaves, new_dx_leaves, num_dx_leaves);
384962306a36Sopenharmony_ci
385062306a36Sopenharmony_ciout_commit:
385162306a36Sopenharmony_ci	if (ret < 0 && did_quota)
385262306a36Sopenharmony_ci		dquot_free_space_nodirty(dir,
385362306a36Sopenharmony_ci				ocfs2_clusters_to_bytes(dir->i_sb, 1));
385462306a36Sopenharmony_ci
385562306a36Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
385662306a36Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
385762306a36Sopenharmony_ci
385862306a36Sopenharmony_ciout:
385962306a36Sopenharmony_ci	if (orig_dx_leaves || new_dx_leaves) {
386062306a36Sopenharmony_ci		for (i = 0; i < num_dx_leaves; i++) {
386162306a36Sopenharmony_ci			if (orig_dx_leaves)
386262306a36Sopenharmony_ci				brelse(orig_dx_leaves[i]);
386362306a36Sopenharmony_ci			if (new_dx_leaves)
386462306a36Sopenharmony_ci				brelse(new_dx_leaves[i]);
386562306a36Sopenharmony_ci		}
386662306a36Sopenharmony_ci		kfree(orig_dx_leaves);
386762306a36Sopenharmony_ci		kfree(new_dx_leaves);
386862306a36Sopenharmony_ci	}
386962306a36Sopenharmony_ci
387062306a36Sopenharmony_ci	if (meta_ac)
387162306a36Sopenharmony_ci		ocfs2_free_alloc_context(meta_ac);
387262306a36Sopenharmony_ci	if (data_ac)
387362306a36Sopenharmony_ci		ocfs2_free_alloc_context(data_ac);
387462306a36Sopenharmony_ci
387562306a36Sopenharmony_ci	kfree(tmp_dx_leaf);
387662306a36Sopenharmony_ci	return ret;
387762306a36Sopenharmony_ci}
387862306a36Sopenharmony_ci
387962306a36Sopenharmony_cistatic int ocfs2_find_dir_space_dx(struct ocfs2_super *osb, struct inode *dir,
388062306a36Sopenharmony_ci				   struct buffer_head *di_bh,
388162306a36Sopenharmony_ci				   struct buffer_head *dx_root_bh,
388262306a36Sopenharmony_ci				   const char *name, int namelen,
388362306a36Sopenharmony_ci				   struct ocfs2_dir_lookup_result *lookup)
388462306a36Sopenharmony_ci{
388562306a36Sopenharmony_ci	int ret, rebalanced = 0;
388662306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
388762306a36Sopenharmony_ci	struct buffer_head *dx_leaf_bh = NULL;
388862306a36Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
388962306a36Sopenharmony_ci	u64 blkno;
389062306a36Sopenharmony_ci	u32 leaf_cpos;
389162306a36Sopenharmony_ci
389262306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
389362306a36Sopenharmony_ci
389462306a36Sopenharmony_cirestart_search:
389562306a36Sopenharmony_ci	ret = ocfs2_dx_dir_lookup(dir, &dx_root->dr_list, &lookup->dl_hinfo,
389662306a36Sopenharmony_ci				  &leaf_cpos, &blkno);
389762306a36Sopenharmony_ci	if (ret) {
389862306a36Sopenharmony_ci		mlog_errno(ret);
389962306a36Sopenharmony_ci		goto out;
390062306a36Sopenharmony_ci	}
390162306a36Sopenharmony_ci
390262306a36Sopenharmony_ci	ret = ocfs2_read_dx_leaf(dir, blkno, &dx_leaf_bh);
390362306a36Sopenharmony_ci	if (ret) {
390462306a36Sopenharmony_ci		mlog_errno(ret);
390562306a36Sopenharmony_ci		goto out;
390662306a36Sopenharmony_ci	}
390762306a36Sopenharmony_ci
390862306a36Sopenharmony_ci	dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_bh->b_data;
390962306a36Sopenharmony_ci
391062306a36Sopenharmony_ci	if (le16_to_cpu(dx_leaf->dl_list.de_num_used) >=
391162306a36Sopenharmony_ci	    le16_to_cpu(dx_leaf->dl_list.de_count)) {
391262306a36Sopenharmony_ci		if (rebalanced) {
391362306a36Sopenharmony_ci			/*
391462306a36Sopenharmony_ci			 * Rebalancing should have provided us with
391562306a36Sopenharmony_ci			 * space in an appropriate leaf.
391662306a36Sopenharmony_ci			 *
391762306a36Sopenharmony_ci			 * XXX: Is this an abnormal condition then?
391862306a36Sopenharmony_ci			 * Should we print a message here?
391962306a36Sopenharmony_ci			 */
392062306a36Sopenharmony_ci			ret = -ENOSPC;
392162306a36Sopenharmony_ci			goto out;
392262306a36Sopenharmony_ci		}
392362306a36Sopenharmony_ci
392462306a36Sopenharmony_ci		ret = ocfs2_dx_dir_rebalance(osb, dir, dx_root_bh, dx_leaf_bh,
392562306a36Sopenharmony_ci					     &lookup->dl_hinfo, leaf_cpos,
392662306a36Sopenharmony_ci					     blkno);
392762306a36Sopenharmony_ci		if (ret) {
392862306a36Sopenharmony_ci			if (ret != -ENOSPC)
392962306a36Sopenharmony_ci				mlog_errno(ret);
393062306a36Sopenharmony_ci			goto out;
393162306a36Sopenharmony_ci		}
393262306a36Sopenharmony_ci
393362306a36Sopenharmony_ci		/*
393462306a36Sopenharmony_ci		 * Restart the lookup. The rebalance might have
393562306a36Sopenharmony_ci		 * changed which block our item fits into. Mark our
393662306a36Sopenharmony_ci		 * progress, so we only execute this once.
393762306a36Sopenharmony_ci		 */
393862306a36Sopenharmony_ci		brelse(dx_leaf_bh);
393962306a36Sopenharmony_ci		dx_leaf_bh = NULL;
394062306a36Sopenharmony_ci		rebalanced = 1;
394162306a36Sopenharmony_ci		goto restart_search;
394262306a36Sopenharmony_ci	}
394362306a36Sopenharmony_ci
394462306a36Sopenharmony_ci	lookup->dl_dx_leaf_bh = dx_leaf_bh;
394562306a36Sopenharmony_ci	dx_leaf_bh = NULL;
394662306a36Sopenharmony_ci
394762306a36Sopenharmony_ciout:
394862306a36Sopenharmony_ci	brelse(dx_leaf_bh);
394962306a36Sopenharmony_ci	return ret;
395062306a36Sopenharmony_ci}
395162306a36Sopenharmony_ci
395262306a36Sopenharmony_cistatic int ocfs2_search_dx_free_list(struct inode *dir,
395362306a36Sopenharmony_ci				     struct buffer_head *dx_root_bh,
395462306a36Sopenharmony_ci				     int namelen,
395562306a36Sopenharmony_ci				     struct ocfs2_dir_lookup_result *lookup)
395662306a36Sopenharmony_ci{
395762306a36Sopenharmony_ci	int ret = -ENOSPC;
395862306a36Sopenharmony_ci	struct buffer_head *leaf_bh = NULL, *prev_leaf_bh = NULL;
395962306a36Sopenharmony_ci	struct ocfs2_dir_block_trailer *db;
396062306a36Sopenharmony_ci	u64 next_block;
396162306a36Sopenharmony_ci	int rec_len = OCFS2_DIR_REC_LEN(namelen);
396262306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
396362306a36Sopenharmony_ci
396462306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
396562306a36Sopenharmony_ci	next_block = le64_to_cpu(dx_root->dr_free_blk);
396662306a36Sopenharmony_ci
396762306a36Sopenharmony_ci	while (next_block) {
396862306a36Sopenharmony_ci		brelse(prev_leaf_bh);
396962306a36Sopenharmony_ci		prev_leaf_bh = leaf_bh;
397062306a36Sopenharmony_ci		leaf_bh = NULL;
397162306a36Sopenharmony_ci
397262306a36Sopenharmony_ci		ret = ocfs2_read_dir_block_direct(dir, next_block, &leaf_bh);
397362306a36Sopenharmony_ci		if (ret) {
397462306a36Sopenharmony_ci			mlog_errno(ret);
397562306a36Sopenharmony_ci			goto out;
397662306a36Sopenharmony_ci		}
397762306a36Sopenharmony_ci
397862306a36Sopenharmony_ci		db = ocfs2_trailer_from_bh(leaf_bh, dir->i_sb);
397962306a36Sopenharmony_ci		if (rec_len <= le16_to_cpu(db->db_free_rec_len)) {
398062306a36Sopenharmony_ci			lookup->dl_leaf_bh = leaf_bh;
398162306a36Sopenharmony_ci			lookup->dl_prev_leaf_bh = prev_leaf_bh;
398262306a36Sopenharmony_ci			leaf_bh = NULL;
398362306a36Sopenharmony_ci			prev_leaf_bh = NULL;
398462306a36Sopenharmony_ci			break;
398562306a36Sopenharmony_ci		}
398662306a36Sopenharmony_ci
398762306a36Sopenharmony_ci		next_block = le64_to_cpu(db->db_free_next);
398862306a36Sopenharmony_ci	}
398962306a36Sopenharmony_ci
399062306a36Sopenharmony_ci	if (!next_block)
399162306a36Sopenharmony_ci		ret = -ENOSPC;
399262306a36Sopenharmony_ci
399362306a36Sopenharmony_ciout:
399462306a36Sopenharmony_ci
399562306a36Sopenharmony_ci	brelse(leaf_bh);
399662306a36Sopenharmony_ci	brelse(prev_leaf_bh);
399762306a36Sopenharmony_ci	return ret;
399862306a36Sopenharmony_ci}
399962306a36Sopenharmony_ci
400062306a36Sopenharmony_cistatic int ocfs2_expand_inline_dx_root(struct inode *dir,
400162306a36Sopenharmony_ci				       struct buffer_head *dx_root_bh)
400262306a36Sopenharmony_ci{
400362306a36Sopenharmony_ci	int ret, num_dx_leaves, i, j, did_quota = 0;
400462306a36Sopenharmony_ci	struct buffer_head **dx_leaves = NULL;
400562306a36Sopenharmony_ci	struct ocfs2_extent_tree et;
400662306a36Sopenharmony_ci	u64 insert_blkno;
400762306a36Sopenharmony_ci	struct ocfs2_alloc_context *data_ac = NULL;
400862306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
400962306a36Sopenharmony_ci	handle_t *handle = NULL;
401062306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
401162306a36Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
401262306a36Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry;
401362306a36Sopenharmony_ci	struct ocfs2_dx_leaf *target_leaf;
401462306a36Sopenharmony_ci
401562306a36Sopenharmony_ci	ret = ocfs2_reserve_clusters(osb, 1, &data_ac);
401662306a36Sopenharmony_ci	if (ret) {
401762306a36Sopenharmony_ci		mlog_errno(ret);
401862306a36Sopenharmony_ci		goto out;
401962306a36Sopenharmony_ci	}
402062306a36Sopenharmony_ci
402162306a36Sopenharmony_ci	dx_leaves = ocfs2_dx_dir_kmalloc_leaves(osb->sb, &num_dx_leaves);
402262306a36Sopenharmony_ci	if (!dx_leaves) {
402362306a36Sopenharmony_ci		ret = -ENOMEM;
402462306a36Sopenharmony_ci		mlog_errno(ret);
402562306a36Sopenharmony_ci		goto out;
402662306a36Sopenharmony_ci	}
402762306a36Sopenharmony_ci
402862306a36Sopenharmony_ci	handle = ocfs2_start_trans(osb, ocfs2_calc_dxi_expand_credits(osb->sb));
402962306a36Sopenharmony_ci	if (IS_ERR(handle)) {
403062306a36Sopenharmony_ci		ret = PTR_ERR(handle);
403162306a36Sopenharmony_ci		mlog_errno(ret);
403262306a36Sopenharmony_ci		goto out;
403362306a36Sopenharmony_ci	}
403462306a36Sopenharmony_ci
403562306a36Sopenharmony_ci	ret = dquot_alloc_space_nodirty(dir,
403662306a36Sopenharmony_ci				       ocfs2_clusters_to_bytes(osb->sb, 1));
403762306a36Sopenharmony_ci	if (ret)
403862306a36Sopenharmony_ci		goto out_commit;
403962306a36Sopenharmony_ci	did_quota = 1;
404062306a36Sopenharmony_ci
404162306a36Sopenharmony_ci	/*
404262306a36Sopenharmony_ci	 * We do this up front, before the allocation, so that a
404362306a36Sopenharmony_ci	 * failure to add the dx_root_bh to the journal won't result
404462306a36Sopenharmony_ci	 * us losing clusters.
404562306a36Sopenharmony_ci	 */
404662306a36Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
404762306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
404862306a36Sopenharmony_ci	if (ret) {
404962306a36Sopenharmony_ci		mlog_errno(ret);
405062306a36Sopenharmony_ci		goto out_commit;
405162306a36Sopenharmony_ci	}
405262306a36Sopenharmony_ci
405362306a36Sopenharmony_ci	ret = __ocfs2_dx_dir_new_cluster(dir, 0, handle, data_ac, dx_leaves,
405462306a36Sopenharmony_ci					 num_dx_leaves, &insert_blkno);
405562306a36Sopenharmony_ci	if (ret) {
405662306a36Sopenharmony_ci		mlog_errno(ret);
405762306a36Sopenharmony_ci		goto out_commit;
405862306a36Sopenharmony_ci	}
405962306a36Sopenharmony_ci
406062306a36Sopenharmony_ci	/*
406162306a36Sopenharmony_ci	 * Transfer the entries from our dx_root into the appropriate
406262306a36Sopenharmony_ci	 * block
406362306a36Sopenharmony_ci	 */
406462306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
406562306a36Sopenharmony_ci	entry_list = &dx_root->dr_entries;
406662306a36Sopenharmony_ci
406762306a36Sopenharmony_ci	for (i = 0; i < le16_to_cpu(entry_list->de_num_used); i++) {
406862306a36Sopenharmony_ci		dx_entry = &entry_list->de_entries[i];
406962306a36Sopenharmony_ci
407062306a36Sopenharmony_ci		j = __ocfs2_dx_dir_hash_idx(osb,
407162306a36Sopenharmony_ci					    le32_to_cpu(dx_entry->dx_minor_hash));
407262306a36Sopenharmony_ci		target_leaf = (struct ocfs2_dx_leaf *)dx_leaves[j]->b_data;
407362306a36Sopenharmony_ci
407462306a36Sopenharmony_ci		ocfs2_dx_dir_leaf_insert_tail(target_leaf, dx_entry);
407562306a36Sopenharmony_ci
407662306a36Sopenharmony_ci		/* Each leaf has been passed to the journal already
407762306a36Sopenharmony_ci		 * via __ocfs2_dx_dir_new_cluster() */
407862306a36Sopenharmony_ci	}
407962306a36Sopenharmony_ci
408062306a36Sopenharmony_ci	dx_root->dr_flags &= ~OCFS2_DX_FLAG_INLINE;
408162306a36Sopenharmony_ci	memset(&dx_root->dr_list, 0, osb->sb->s_blocksize -
408262306a36Sopenharmony_ci	       offsetof(struct ocfs2_dx_root_block, dr_list));
408362306a36Sopenharmony_ci	dx_root->dr_list.l_count =
408462306a36Sopenharmony_ci		cpu_to_le16(ocfs2_extent_recs_per_dx_root(osb->sb));
408562306a36Sopenharmony_ci
408662306a36Sopenharmony_ci	/* This should never fail considering we start with an empty
408762306a36Sopenharmony_ci	 * dx_root. */
408862306a36Sopenharmony_ci	ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
408962306a36Sopenharmony_ci	ret = ocfs2_insert_extent(handle, &et, 0, insert_blkno, 1, 0, NULL);
409062306a36Sopenharmony_ci	if (ret)
409162306a36Sopenharmony_ci		mlog_errno(ret);
409262306a36Sopenharmony_ci	did_quota = 0;
409362306a36Sopenharmony_ci
409462306a36Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
409562306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
409662306a36Sopenharmony_ci
409762306a36Sopenharmony_ciout_commit:
409862306a36Sopenharmony_ci	if (ret < 0 && did_quota)
409962306a36Sopenharmony_ci		dquot_free_space_nodirty(dir,
410062306a36Sopenharmony_ci					  ocfs2_clusters_to_bytes(dir->i_sb, 1));
410162306a36Sopenharmony_ci
410262306a36Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
410362306a36Sopenharmony_ci
410462306a36Sopenharmony_ciout:
410562306a36Sopenharmony_ci	if (data_ac)
410662306a36Sopenharmony_ci		ocfs2_free_alloc_context(data_ac);
410762306a36Sopenharmony_ci
410862306a36Sopenharmony_ci	if (dx_leaves) {
410962306a36Sopenharmony_ci		for (i = 0; i < num_dx_leaves; i++)
411062306a36Sopenharmony_ci			brelse(dx_leaves[i]);
411162306a36Sopenharmony_ci		kfree(dx_leaves);
411262306a36Sopenharmony_ci	}
411362306a36Sopenharmony_ci	return ret;
411462306a36Sopenharmony_ci}
411562306a36Sopenharmony_ci
411662306a36Sopenharmony_cistatic int ocfs2_inline_dx_has_space(struct buffer_head *dx_root_bh)
411762306a36Sopenharmony_ci{
411862306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
411962306a36Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
412062306a36Sopenharmony_ci
412162306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
412262306a36Sopenharmony_ci	entry_list = &dx_root->dr_entries;
412362306a36Sopenharmony_ci
412462306a36Sopenharmony_ci	if (le16_to_cpu(entry_list->de_num_used) >=
412562306a36Sopenharmony_ci	    le16_to_cpu(entry_list->de_count))
412662306a36Sopenharmony_ci		return -ENOSPC;
412762306a36Sopenharmony_ci
412862306a36Sopenharmony_ci	return 0;
412962306a36Sopenharmony_ci}
413062306a36Sopenharmony_ci
413162306a36Sopenharmony_cistatic int ocfs2_prepare_dx_dir_for_insert(struct inode *dir,
413262306a36Sopenharmony_ci					   struct buffer_head *di_bh,
413362306a36Sopenharmony_ci					   const char *name,
413462306a36Sopenharmony_ci					   int namelen,
413562306a36Sopenharmony_ci					   struct ocfs2_dir_lookup_result *lookup)
413662306a36Sopenharmony_ci{
413762306a36Sopenharmony_ci	int ret, free_dx_root = 1;
413862306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
413962306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
414062306a36Sopenharmony_ci	struct buffer_head *leaf_bh = NULL;
414162306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
414262306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
414362306a36Sopenharmony_ci
414462306a36Sopenharmony_ci	ret = ocfs2_read_dx_root(dir, di, &dx_root_bh);
414562306a36Sopenharmony_ci	if (ret) {
414662306a36Sopenharmony_ci		mlog_errno(ret);
414762306a36Sopenharmony_ci		goto out;
414862306a36Sopenharmony_ci	}
414962306a36Sopenharmony_ci
415062306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
415162306a36Sopenharmony_ci	if (le32_to_cpu(dx_root->dr_num_entries) == OCFS2_DX_ENTRIES_MAX) {
415262306a36Sopenharmony_ci		ret = -ENOSPC;
415362306a36Sopenharmony_ci		mlog_errno(ret);
415462306a36Sopenharmony_ci		goto out;
415562306a36Sopenharmony_ci	}
415662306a36Sopenharmony_ci
415762306a36Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root)) {
415862306a36Sopenharmony_ci		ret = ocfs2_inline_dx_has_space(dx_root_bh);
415962306a36Sopenharmony_ci
416062306a36Sopenharmony_ci		if (ret == 0)
416162306a36Sopenharmony_ci			goto search_el;
416262306a36Sopenharmony_ci
416362306a36Sopenharmony_ci		/*
416462306a36Sopenharmony_ci		 * We ran out of room in the root block. Expand it to
416562306a36Sopenharmony_ci		 * an extent, then allow ocfs2_find_dir_space_dx to do
416662306a36Sopenharmony_ci		 * the rest.
416762306a36Sopenharmony_ci		 */
416862306a36Sopenharmony_ci		ret = ocfs2_expand_inline_dx_root(dir, dx_root_bh);
416962306a36Sopenharmony_ci		if (ret) {
417062306a36Sopenharmony_ci			mlog_errno(ret);
417162306a36Sopenharmony_ci			goto out;
417262306a36Sopenharmony_ci		}
417362306a36Sopenharmony_ci	}
417462306a36Sopenharmony_ci
417562306a36Sopenharmony_ci	/*
417662306a36Sopenharmony_ci	 * Insert preparation for an indexed directory is split into two
417762306a36Sopenharmony_ci	 * steps. The call to find_dir_space_dx reserves room in the index for
417862306a36Sopenharmony_ci	 * an additional item. If we run out of space there, it's a real error
417962306a36Sopenharmony_ci	 * we can't continue on.
418062306a36Sopenharmony_ci	 */
418162306a36Sopenharmony_ci	ret = ocfs2_find_dir_space_dx(osb, dir, di_bh, dx_root_bh, name,
418262306a36Sopenharmony_ci				      namelen, lookup);
418362306a36Sopenharmony_ci	if (ret) {
418462306a36Sopenharmony_ci		mlog_errno(ret);
418562306a36Sopenharmony_ci		goto out;
418662306a36Sopenharmony_ci	}
418762306a36Sopenharmony_ci
418862306a36Sopenharmony_cisearch_el:
418962306a36Sopenharmony_ci	/*
419062306a36Sopenharmony_ci	 * Next, we need to find space in the unindexed tree. This call
419162306a36Sopenharmony_ci	 * searches using the free space linked list. If the unindexed tree
419262306a36Sopenharmony_ci	 * lacks sufficient space, we'll expand it below. The expansion code
419362306a36Sopenharmony_ci	 * is smart enough to add any new blocks to the free space list.
419462306a36Sopenharmony_ci	 */
419562306a36Sopenharmony_ci	ret = ocfs2_search_dx_free_list(dir, dx_root_bh, namelen, lookup);
419662306a36Sopenharmony_ci	if (ret && ret != -ENOSPC) {
419762306a36Sopenharmony_ci		mlog_errno(ret);
419862306a36Sopenharmony_ci		goto out;
419962306a36Sopenharmony_ci	}
420062306a36Sopenharmony_ci
420162306a36Sopenharmony_ci	/* Do this up here - ocfs2_extend_dir might need the dx_root */
420262306a36Sopenharmony_ci	lookup->dl_dx_root_bh = dx_root_bh;
420362306a36Sopenharmony_ci	free_dx_root = 0;
420462306a36Sopenharmony_ci
420562306a36Sopenharmony_ci	if (ret == -ENOSPC) {
420662306a36Sopenharmony_ci		ret = ocfs2_extend_dir(osb, dir, di_bh, 1, lookup, &leaf_bh);
420762306a36Sopenharmony_ci
420862306a36Sopenharmony_ci		if (ret) {
420962306a36Sopenharmony_ci			mlog_errno(ret);
421062306a36Sopenharmony_ci			goto out;
421162306a36Sopenharmony_ci		}
421262306a36Sopenharmony_ci
421362306a36Sopenharmony_ci		/*
421462306a36Sopenharmony_ci		 * We make the assumption here that new leaf blocks are added
421562306a36Sopenharmony_ci		 * to the front of our free list.
421662306a36Sopenharmony_ci		 */
421762306a36Sopenharmony_ci		lookup->dl_prev_leaf_bh = NULL;
421862306a36Sopenharmony_ci		lookup->dl_leaf_bh = leaf_bh;
421962306a36Sopenharmony_ci	}
422062306a36Sopenharmony_ci
422162306a36Sopenharmony_ciout:
422262306a36Sopenharmony_ci	if (free_dx_root)
422362306a36Sopenharmony_ci		brelse(dx_root_bh);
422462306a36Sopenharmony_ci	return ret;
422562306a36Sopenharmony_ci}
422662306a36Sopenharmony_ci
422762306a36Sopenharmony_ci/*
422862306a36Sopenharmony_ci * Get a directory ready for insert. Any directory allocation required
422962306a36Sopenharmony_ci * happens here. Success returns zero, and enough context in the dir
423062306a36Sopenharmony_ci * lookup result that ocfs2_add_entry() will be able complete the task
423162306a36Sopenharmony_ci * with minimal performance impact.
423262306a36Sopenharmony_ci */
423362306a36Sopenharmony_ciint ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
423462306a36Sopenharmony_ci				 struct inode *dir,
423562306a36Sopenharmony_ci				 struct buffer_head *parent_fe_bh,
423662306a36Sopenharmony_ci				 const char *name,
423762306a36Sopenharmony_ci				 int namelen,
423862306a36Sopenharmony_ci				 struct ocfs2_dir_lookup_result *lookup)
423962306a36Sopenharmony_ci{
424062306a36Sopenharmony_ci	int ret;
424162306a36Sopenharmony_ci	unsigned int blocks_wanted = 1;
424262306a36Sopenharmony_ci	struct buffer_head *bh = NULL;
424362306a36Sopenharmony_ci
424462306a36Sopenharmony_ci	trace_ocfs2_prepare_dir_for_insert(
424562306a36Sopenharmony_ci		(unsigned long long)OCFS2_I(dir)->ip_blkno, namelen);
424662306a36Sopenharmony_ci
424762306a36Sopenharmony_ci	if (!namelen) {
424862306a36Sopenharmony_ci		ret = -EINVAL;
424962306a36Sopenharmony_ci		mlog_errno(ret);
425062306a36Sopenharmony_ci		goto out;
425162306a36Sopenharmony_ci	}
425262306a36Sopenharmony_ci
425362306a36Sopenharmony_ci	/*
425462306a36Sopenharmony_ci	 * Do this up front to reduce confusion.
425562306a36Sopenharmony_ci	 *
425662306a36Sopenharmony_ci	 * The directory might start inline, then be turned into an
425762306a36Sopenharmony_ci	 * indexed one, in which case we'd need to hash deep inside
425862306a36Sopenharmony_ci	 * ocfs2_find_dir_space_id(). Since
425962306a36Sopenharmony_ci	 * ocfs2_prepare_dx_dir_for_insert() also needs this hash
426062306a36Sopenharmony_ci	 * done, there seems no point in spreading out the calls. We
426162306a36Sopenharmony_ci	 * can optimize away the case where the file system doesn't
426262306a36Sopenharmony_ci	 * support indexing.
426362306a36Sopenharmony_ci	 */
426462306a36Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb))
426562306a36Sopenharmony_ci		ocfs2_dx_dir_name_hash(dir, name, namelen, &lookup->dl_hinfo);
426662306a36Sopenharmony_ci
426762306a36Sopenharmony_ci	if (ocfs2_dir_indexed(dir)) {
426862306a36Sopenharmony_ci		ret = ocfs2_prepare_dx_dir_for_insert(dir, parent_fe_bh,
426962306a36Sopenharmony_ci						      name, namelen, lookup);
427062306a36Sopenharmony_ci		if (ret)
427162306a36Sopenharmony_ci			mlog_errno(ret);
427262306a36Sopenharmony_ci		goto out;
427362306a36Sopenharmony_ci	}
427462306a36Sopenharmony_ci
427562306a36Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
427662306a36Sopenharmony_ci		ret = ocfs2_find_dir_space_id(dir, parent_fe_bh, name,
427762306a36Sopenharmony_ci					      namelen, &bh, &blocks_wanted);
427862306a36Sopenharmony_ci	} else
427962306a36Sopenharmony_ci		ret = ocfs2_find_dir_space_el(dir, name, namelen, &bh);
428062306a36Sopenharmony_ci
428162306a36Sopenharmony_ci	if (ret && ret != -ENOSPC) {
428262306a36Sopenharmony_ci		mlog_errno(ret);
428362306a36Sopenharmony_ci		goto out;
428462306a36Sopenharmony_ci	}
428562306a36Sopenharmony_ci
428662306a36Sopenharmony_ci	if (ret == -ENOSPC) {
428762306a36Sopenharmony_ci		/*
428862306a36Sopenharmony_ci		 * We have to expand the directory to add this name.
428962306a36Sopenharmony_ci		 */
429062306a36Sopenharmony_ci		BUG_ON(bh);
429162306a36Sopenharmony_ci
429262306a36Sopenharmony_ci		ret = ocfs2_extend_dir(osb, dir, parent_fe_bh, blocks_wanted,
429362306a36Sopenharmony_ci				       lookup, &bh);
429462306a36Sopenharmony_ci		if (ret) {
429562306a36Sopenharmony_ci			if (ret != -ENOSPC)
429662306a36Sopenharmony_ci				mlog_errno(ret);
429762306a36Sopenharmony_ci			goto out;
429862306a36Sopenharmony_ci		}
429962306a36Sopenharmony_ci
430062306a36Sopenharmony_ci		BUG_ON(!bh);
430162306a36Sopenharmony_ci	}
430262306a36Sopenharmony_ci
430362306a36Sopenharmony_ci	lookup->dl_leaf_bh = bh;
430462306a36Sopenharmony_ci	bh = NULL;
430562306a36Sopenharmony_ciout:
430662306a36Sopenharmony_ci	brelse(bh);
430762306a36Sopenharmony_ci	return ret;
430862306a36Sopenharmony_ci}
430962306a36Sopenharmony_ci
431062306a36Sopenharmony_cistatic int ocfs2_dx_dir_remove_index(struct inode *dir,
431162306a36Sopenharmony_ci				     struct buffer_head *di_bh,
431262306a36Sopenharmony_ci				     struct buffer_head *dx_root_bh)
431362306a36Sopenharmony_ci{
431462306a36Sopenharmony_ci	int ret;
431562306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
431662306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
431762306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
431862306a36Sopenharmony_ci	struct inode *dx_alloc_inode = NULL;
431962306a36Sopenharmony_ci	struct buffer_head *dx_alloc_bh = NULL;
432062306a36Sopenharmony_ci	handle_t *handle;
432162306a36Sopenharmony_ci	u64 blk;
432262306a36Sopenharmony_ci	u16 bit;
432362306a36Sopenharmony_ci	u64 bg_blkno;
432462306a36Sopenharmony_ci
432562306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
432662306a36Sopenharmony_ci
432762306a36Sopenharmony_ci	dx_alloc_inode = ocfs2_get_system_file_inode(osb,
432862306a36Sopenharmony_ci					EXTENT_ALLOC_SYSTEM_INODE,
432962306a36Sopenharmony_ci					le16_to_cpu(dx_root->dr_suballoc_slot));
433062306a36Sopenharmony_ci	if (!dx_alloc_inode) {
433162306a36Sopenharmony_ci		ret = -ENOMEM;
433262306a36Sopenharmony_ci		mlog_errno(ret);
433362306a36Sopenharmony_ci		goto out;
433462306a36Sopenharmony_ci	}
433562306a36Sopenharmony_ci	inode_lock(dx_alloc_inode);
433662306a36Sopenharmony_ci
433762306a36Sopenharmony_ci	ret = ocfs2_inode_lock(dx_alloc_inode, &dx_alloc_bh, 1);
433862306a36Sopenharmony_ci	if (ret) {
433962306a36Sopenharmony_ci		mlog_errno(ret);
434062306a36Sopenharmony_ci		goto out_mutex;
434162306a36Sopenharmony_ci	}
434262306a36Sopenharmony_ci
434362306a36Sopenharmony_ci	handle = ocfs2_start_trans(osb, OCFS2_DX_ROOT_REMOVE_CREDITS);
434462306a36Sopenharmony_ci	if (IS_ERR(handle)) {
434562306a36Sopenharmony_ci		ret = PTR_ERR(handle);
434662306a36Sopenharmony_ci		mlog_errno(ret);
434762306a36Sopenharmony_ci		goto out_unlock;
434862306a36Sopenharmony_ci	}
434962306a36Sopenharmony_ci
435062306a36Sopenharmony_ci	ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
435162306a36Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
435262306a36Sopenharmony_ci	if (ret) {
435362306a36Sopenharmony_ci		mlog_errno(ret);
435462306a36Sopenharmony_ci		goto out_commit;
435562306a36Sopenharmony_ci	}
435662306a36Sopenharmony_ci
435762306a36Sopenharmony_ci	spin_lock(&OCFS2_I(dir)->ip_lock);
435862306a36Sopenharmony_ci	OCFS2_I(dir)->ip_dyn_features &= ~OCFS2_INDEXED_DIR_FL;
435962306a36Sopenharmony_ci	di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
436062306a36Sopenharmony_ci	spin_unlock(&OCFS2_I(dir)->ip_lock);
436162306a36Sopenharmony_ci	di->i_dx_root = cpu_to_le64(0ULL);
436262306a36Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
436362306a36Sopenharmony_ci
436462306a36Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
436562306a36Sopenharmony_ci
436662306a36Sopenharmony_ci	blk = le64_to_cpu(dx_root->dr_blkno);
436762306a36Sopenharmony_ci	bit = le16_to_cpu(dx_root->dr_suballoc_bit);
436862306a36Sopenharmony_ci	if (dx_root->dr_suballoc_loc)
436962306a36Sopenharmony_ci		bg_blkno = le64_to_cpu(dx_root->dr_suballoc_loc);
437062306a36Sopenharmony_ci	else
437162306a36Sopenharmony_ci		bg_blkno = ocfs2_which_suballoc_group(blk, bit);
437262306a36Sopenharmony_ci	ret = ocfs2_free_suballoc_bits(handle, dx_alloc_inode, dx_alloc_bh,
437362306a36Sopenharmony_ci				       bit, bg_blkno, 1);
437462306a36Sopenharmony_ci	if (ret)
437562306a36Sopenharmony_ci		mlog_errno(ret);
437662306a36Sopenharmony_ci
437762306a36Sopenharmony_ciout_commit:
437862306a36Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
437962306a36Sopenharmony_ci
438062306a36Sopenharmony_ciout_unlock:
438162306a36Sopenharmony_ci	ocfs2_inode_unlock(dx_alloc_inode, 1);
438262306a36Sopenharmony_ci
438362306a36Sopenharmony_ciout_mutex:
438462306a36Sopenharmony_ci	inode_unlock(dx_alloc_inode);
438562306a36Sopenharmony_ci	brelse(dx_alloc_bh);
438662306a36Sopenharmony_ciout:
438762306a36Sopenharmony_ci	iput(dx_alloc_inode);
438862306a36Sopenharmony_ci	return ret;
438962306a36Sopenharmony_ci}
439062306a36Sopenharmony_ci
439162306a36Sopenharmony_ciint ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh)
439262306a36Sopenharmony_ci{
439362306a36Sopenharmony_ci	int ret;
439462306a36Sopenharmony_ci	unsigned int clen;
439562306a36Sopenharmony_ci	u32 major_hash = UINT_MAX, p_cpos, cpos;
439662306a36Sopenharmony_ci	u64 blkno;
439762306a36Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
439862306a36Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
439962306a36Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
440062306a36Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
440162306a36Sopenharmony_ci	struct ocfs2_cached_dealloc_ctxt dealloc;
440262306a36Sopenharmony_ci	struct ocfs2_extent_tree et;
440362306a36Sopenharmony_ci
440462306a36Sopenharmony_ci	ocfs2_init_dealloc_ctxt(&dealloc);
440562306a36Sopenharmony_ci
440662306a36Sopenharmony_ci	if (!ocfs2_dir_indexed(dir))
440762306a36Sopenharmony_ci		return 0;
440862306a36Sopenharmony_ci
440962306a36Sopenharmony_ci	ret = ocfs2_read_dx_root(dir, di, &dx_root_bh);
441062306a36Sopenharmony_ci	if (ret) {
441162306a36Sopenharmony_ci		mlog_errno(ret);
441262306a36Sopenharmony_ci		goto out;
441362306a36Sopenharmony_ci	}
441462306a36Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
441562306a36Sopenharmony_ci
441662306a36Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root))
441762306a36Sopenharmony_ci		goto remove_index;
441862306a36Sopenharmony_ci
441962306a36Sopenharmony_ci	ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
442062306a36Sopenharmony_ci
442162306a36Sopenharmony_ci	/* XXX: What if dr_clusters is too large? */
442262306a36Sopenharmony_ci	while (le32_to_cpu(dx_root->dr_clusters)) {
442362306a36Sopenharmony_ci		ret = ocfs2_dx_dir_lookup_rec(dir, &dx_root->dr_list,
442462306a36Sopenharmony_ci					      major_hash, &cpos, &blkno, &clen);
442562306a36Sopenharmony_ci		if (ret) {
442662306a36Sopenharmony_ci			mlog_errno(ret);
442762306a36Sopenharmony_ci			goto out;
442862306a36Sopenharmony_ci		}
442962306a36Sopenharmony_ci
443062306a36Sopenharmony_ci		p_cpos = ocfs2_blocks_to_clusters(dir->i_sb, blkno);
443162306a36Sopenharmony_ci
443262306a36Sopenharmony_ci		ret = ocfs2_remove_btree_range(dir, &et, cpos, p_cpos, clen, 0,
443362306a36Sopenharmony_ci					       &dealloc, 0, false);
443462306a36Sopenharmony_ci		if (ret) {
443562306a36Sopenharmony_ci			mlog_errno(ret);
443662306a36Sopenharmony_ci			goto out;
443762306a36Sopenharmony_ci		}
443862306a36Sopenharmony_ci
443962306a36Sopenharmony_ci		if (cpos == 0)
444062306a36Sopenharmony_ci			break;
444162306a36Sopenharmony_ci
444262306a36Sopenharmony_ci		major_hash = cpos - 1;
444362306a36Sopenharmony_ci	}
444462306a36Sopenharmony_ci
444562306a36Sopenharmony_ciremove_index:
444662306a36Sopenharmony_ci	ret = ocfs2_dx_dir_remove_index(dir, di_bh, dx_root_bh);
444762306a36Sopenharmony_ci	if (ret) {
444862306a36Sopenharmony_ci		mlog_errno(ret);
444962306a36Sopenharmony_ci		goto out;
445062306a36Sopenharmony_ci	}
445162306a36Sopenharmony_ci
445262306a36Sopenharmony_ci	ocfs2_remove_from_cache(INODE_CACHE(dir), dx_root_bh);
445362306a36Sopenharmony_ciout:
445462306a36Sopenharmony_ci	ocfs2_schedule_truncate_log_flush(osb, 1);
445562306a36Sopenharmony_ci	ocfs2_run_deallocs(osb, &dealloc);
445662306a36Sopenharmony_ci
445762306a36Sopenharmony_ci	brelse(dx_root_bh);
445862306a36Sopenharmony_ci	return ret;
445962306a36Sopenharmony_ci}
4460