18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/* -*- mode: c; c-basic-offset: 8; -*-
38c2ecf20Sopenharmony_ci * vim: noexpandtab sw=8 ts=8 sts=0:
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * dir.c
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * Creates, reads, walks and deletes directory-nodes
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright (C) 2002, 2004 Oracle.  All rights reserved.
108c2ecf20Sopenharmony_ci *
118c2ecf20Sopenharmony_ci *  Portions of this code from linux/fs/ext3/dir.c
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci *  Copyright (C) 1992, 1993, 1994, 1995
148c2ecf20Sopenharmony_ci *  Remy Card (card@masi.ibp.fr)
158c2ecf20Sopenharmony_ci *  Laboratoire MASI - Institut Blaise pascal
168c2ecf20Sopenharmony_ci *  Universite Pierre et Marie Curie (Paris VI)
178c2ecf20Sopenharmony_ci *
188c2ecf20Sopenharmony_ci *   from
198c2ecf20Sopenharmony_ci *
208c2ecf20Sopenharmony_ci *   linux/fs/minix/dir.c
218c2ecf20Sopenharmony_ci *
228c2ecf20Sopenharmony_ci *   Copyright (C) 1991, 1992 Linus Torvalds
238c2ecf20Sopenharmony_ci */
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci#include <linux/fs.h>
268c2ecf20Sopenharmony_ci#include <linux/types.h>
278c2ecf20Sopenharmony_ci#include <linux/slab.h>
288c2ecf20Sopenharmony_ci#include <linux/highmem.h>
298c2ecf20Sopenharmony_ci#include <linux/quotaops.h>
308c2ecf20Sopenharmony_ci#include <linux/sort.h>
318c2ecf20Sopenharmony_ci#include <linux/iversion.h>
328c2ecf20Sopenharmony_ci
338c2ecf20Sopenharmony_ci#include <cluster/masklog.h>
348c2ecf20Sopenharmony_ci
358c2ecf20Sopenharmony_ci#include "ocfs2.h"
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#include "alloc.h"
388c2ecf20Sopenharmony_ci#include "blockcheck.h"
398c2ecf20Sopenharmony_ci#include "dir.h"
408c2ecf20Sopenharmony_ci#include "dlmglue.h"
418c2ecf20Sopenharmony_ci#include "extent_map.h"
428c2ecf20Sopenharmony_ci#include "file.h"
438c2ecf20Sopenharmony_ci#include "inode.h"
448c2ecf20Sopenharmony_ci#include "journal.h"
458c2ecf20Sopenharmony_ci#include "namei.h"
468c2ecf20Sopenharmony_ci#include "suballoc.h"
478c2ecf20Sopenharmony_ci#include "super.h"
488c2ecf20Sopenharmony_ci#include "sysfile.h"
498c2ecf20Sopenharmony_ci#include "uptodate.h"
508c2ecf20Sopenharmony_ci#include "ocfs2_trace.h"
518c2ecf20Sopenharmony_ci
528c2ecf20Sopenharmony_ci#include "buffer_head_io.h"
538c2ecf20Sopenharmony_ci
548c2ecf20Sopenharmony_ci#define NAMEI_RA_CHUNKS  2
558c2ecf20Sopenharmony_ci#define NAMEI_RA_BLOCKS  4
568c2ecf20Sopenharmony_ci#define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_cistatic int ocfs2_do_extend_dir(struct super_block *sb,
598c2ecf20Sopenharmony_ci			       handle_t *handle,
608c2ecf20Sopenharmony_ci			       struct inode *dir,
618c2ecf20Sopenharmony_ci			       struct buffer_head *parent_fe_bh,
628c2ecf20Sopenharmony_ci			       struct ocfs2_alloc_context *data_ac,
638c2ecf20Sopenharmony_ci			       struct ocfs2_alloc_context *meta_ac,
648c2ecf20Sopenharmony_ci			       struct buffer_head **new_bh);
658c2ecf20Sopenharmony_cistatic int ocfs2_dir_indexed(struct inode *inode);
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/*
688c2ecf20Sopenharmony_ci * These are distinct checks because future versions of the file system will
698c2ecf20Sopenharmony_ci * want to have a trailing dirent structure independent of indexing.
708c2ecf20Sopenharmony_ci */
718c2ecf20Sopenharmony_cistatic int ocfs2_supports_dir_trailer(struct inode *dir)
728c2ecf20Sopenharmony_ci{
738c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
768c2ecf20Sopenharmony_ci		return 0;
778c2ecf20Sopenharmony_ci
788c2ecf20Sopenharmony_ci	return ocfs2_meta_ecc(osb) || ocfs2_dir_indexed(dir);
798c2ecf20Sopenharmony_ci}
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci/*
828c2ecf20Sopenharmony_ci * "new' here refers to the point at which we're creating a new
838c2ecf20Sopenharmony_ci * directory via "mkdir()", but also when we're expanding an inline
848c2ecf20Sopenharmony_ci * directory. In either case, we don't yet have the indexing bit set
858c2ecf20Sopenharmony_ci * on the directory, so the standard checks will fail in when metaecc
868c2ecf20Sopenharmony_ci * is turned off. Only directory-initialization type functions should
878c2ecf20Sopenharmony_ci * use this then. Everything else wants ocfs2_supports_dir_trailer()
888c2ecf20Sopenharmony_ci */
898c2ecf20Sopenharmony_cistatic int ocfs2_new_dir_wants_trailer(struct inode *dir)
908c2ecf20Sopenharmony_ci{
918c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci	return ocfs2_meta_ecc(osb) ||
948c2ecf20Sopenharmony_ci		ocfs2_supports_indexed_dirs(osb);
958c2ecf20Sopenharmony_ci}
968c2ecf20Sopenharmony_ci
978c2ecf20Sopenharmony_cistatic inline unsigned int ocfs2_dir_trailer_blk_off(struct super_block *sb)
988c2ecf20Sopenharmony_ci{
998c2ecf20Sopenharmony_ci	return sb->s_blocksize - sizeof(struct ocfs2_dir_block_trailer);
1008c2ecf20Sopenharmony_ci}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci#define ocfs2_trailer_from_bh(_bh, _sb) ((struct ocfs2_dir_block_trailer *) ((_bh)->b_data + ocfs2_dir_trailer_blk_off((_sb))))
1038c2ecf20Sopenharmony_ci
1048c2ecf20Sopenharmony_ci/* XXX ocfs2_block_dqtrailer() is similar but not quite - can we make
1058c2ecf20Sopenharmony_ci * them more consistent? */
1068c2ecf20Sopenharmony_cistruct ocfs2_dir_block_trailer *ocfs2_dir_trailer_from_size(int blocksize,
1078c2ecf20Sopenharmony_ci							    void *data)
1088c2ecf20Sopenharmony_ci{
1098c2ecf20Sopenharmony_ci	char *p = data;
1108c2ecf20Sopenharmony_ci
1118c2ecf20Sopenharmony_ci	p += blocksize - sizeof(struct ocfs2_dir_block_trailer);
1128c2ecf20Sopenharmony_ci	return (struct ocfs2_dir_block_trailer *)p;
1138c2ecf20Sopenharmony_ci}
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_ci/*
1168c2ecf20Sopenharmony_ci * XXX: This is executed once on every dirent. We should consider optimizing
1178c2ecf20Sopenharmony_ci * it.
1188c2ecf20Sopenharmony_ci */
1198c2ecf20Sopenharmony_cistatic int ocfs2_skip_dir_trailer(struct inode *dir,
1208c2ecf20Sopenharmony_ci				  struct ocfs2_dir_entry *de,
1218c2ecf20Sopenharmony_ci				  unsigned long offset,
1228c2ecf20Sopenharmony_ci				  unsigned long blklen)
1238c2ecf20Sopenharmony_ci{
1248c2ecf20Sopenharmony_ci	unsigned long toff = blklen - sizeof(struct ocfs2_dir_block_trailer);
1258c2ecf20Sopenharmony_ci
1268c2ecf20Sopenharmony_ci	if (!ocfs2_supports_dir_trailer(dir))
1278c2ecf20Sopenharmony_ci		return 0;
1288c2ecf20Sopenharmony_ci
1298c2ecf20Sopenharmony_ci	if (offset != toff)
1308c2ecf20Sopenharmony_ci		return 0;
1318c2ecf20Sopenharmony_ci
1328c2ecf20Sopenharmony_ci	return 1;
1338c2ecf20Sopenharmony_ci}
1348c2ecf20Sopenharmony_ci
1358c2ecf20Sopenharmony_cistatic void ocfs2_init_dir_trailer(struct inode *inode,
1368c2ecf20Sopenharmony_ci				   struct buffer_head *bh, u16 rec_len)
1378c2ecf20Sopenharmony_ci{
1388c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
1398c2ecf20Sopenharmony_ci
1408c2ecf20Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(bh, inode->i_sb);
1418c2ecf20Sopenharmony_ci	strcpy(trailer->db_signature, OCFS2_DIR_TRAILER_SIGNATURE);
1428c2ecf20Sopenharmony_ci	trailer->db_compat_rec_len =
1438c2ecf20Sopenharmony_ci			cpu_to_le16(sizeof(struct ocfs2_dir_block_trailer));
1448c2ecf20Sopenharmony_ci	trailer->db_parent_dinode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
1458c2ecf20Sopenharmony_ci	trailer->db_blkno = cpu_to_le64(bh->b_blocknr);
1468c2ecf20Sopenharmony_ci	trailer->db_free_rec_len = cpu_to_le16(rec_len);
1478c2ecf20Sopenharmony_ci}
1488c2ecf20Sopenharmony_ci/*
1498c2ecf20Sopenharmony_ci * Link an unindexed block with a dir trailer structure into the index free
1508c2ecf20Sopenharmony_ci * list. This function will modify dirdata_bh, but assumes you've already
1518c2ecf20Sopenharmony_ci * passed it to the journal.
1528c2ecf20Sopenharmony_ci */
1538c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_link_trailer(struct inode *dir, handle_t *handle,
1548c2ecf20Sopenharmony_ci				     struct buffer_head *dx_root_bh,
1558c2ecf20Sopenharmony_ci				     struct buffer_head *dirdata_bh)
1568c2ecf20Sopenharmony_ci{
1578c2ecf20Sopenharmony_ci	int ret;
1588c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
1598c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
1608c2ecf20Sopenharmony_ci
1618c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
1628c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
1638c2ecf20Sopenharmony_ci	if (ret) {
1648c2ecf20Sopenharmony_ci		mlog_errno(ret);
1658c2ecf20Sopenharmony_ci		goto out;
1668c2ecf20Sopenharmony_ci	}
1678c2ecf20Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(dirdata_bh, dir->i_sb);
1688c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
1698c2ecf20Sopenharmony_ci
1708c2ecf20Sopenharmony_ci	trailer->db_free_next = dx_root->dr_free_blk;
1718c2ecf20Sopenharmony_ci	dx_root->dr_free_blk = cpu_to_le64(dirdata_bh->b_blocknr);
1728c2ecf20Sopenharmony_ci
1738c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ciout:
1768c2ecf20Sopenharmony_ci	return ret;
1778c2ecf20Sopenharmony_ci}
1788c2ecf20Sopenharmony_ci
1798c2ecf20Sopenharmony_cistatic int ocfs2_free_list_at_root(struct ocfs2_dir_lookup_result *res)
1808c2ecf20Sopenharmony_ci{
1818c2ecf20Sopenharmony_ci	return res->dl_prev_leaf_bh == NULL;
1828c2ecf20Sopenharmony_ci}
1838c2ecf20Sopenharmony_ci
1848c2ecf20Sopenharmony_civoid ocfs2_free_dir_lookup_result(struct ocfs2_dir_lookup_result *res)
1858c2ecf20Sopenharmony_ci{
1868c2ecf20Sopenharmony_ci	brelse(res->dl_dx_root_bh);
1878c2ecf20Sopenharmony_ci	brelse(res->dl_leaf_bh);
1888c2ecf20Sopenharmony_ci	brelse(res->dl_dx_leaf_bh);
1898c2ecf20Sopenharmony_ci	brelse(res->dl_prev_leaf_bh);
1908c2ecf20Sopenharmony_ci}
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistatic int ocfs2_dir_indexed(struct inode *inode)
1938c2ecf20Sopenharmony_ci{
1948c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INDEXED_DIR_FL)
1958c2ecf20Sopenharmony_ci		return 1;
1968c2ecf20Sopenharmony_ci	return 0;
1978c2ecf20Sopenharmony_ci}
1988c2ecf20Sopenharmony_ci
1998c2ecf20Sopenharmony_cistatic inline int ocfs2_dx_root_inline(struct ocfs2_dx_root_block *dx_root)
2008c2ecf20Sopenharmony_ci{
2018c2ecf20Sopenharmony_ci	return dx_root->dr_flags & OCFS2_DX_FLAG_INLINE;
2028c2ecf20Sopenharmony_ci}
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_ci/*
2058c2ecf20Sopenharmony_ci * Hashing code adapted from ext3
2068c2ecf20Sopenharmony_ci */
2078c2ecf20Sopenharmony_ci#define DELTA 0x9E3779B9
2088c2ecf20Sopenharmony_ci
2098c2ecf20Sopenharmony_cistatic void TEA_transform(__u32 buf[4], __u32 const in[])
2108c2ecf20Sopenharmony_ci{
2118c2ecf20Sopenharmony_ci	__u32	sum = 0;
2128c2ecf20Sopenharmony_ci	__u32	b0 = buf[0], b1 = buf[1];
2138c2ecf20Sopenharmony_ci	__u32	a = in[0], b = in[1], c = in[2], d = in[3];
2148c2ecf20Sopenharmony_ci	int	n = 16;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci	do {
2178c2ecf20Sopenharmony_ci		sum += DELTA;
2188c2ecf20Sopenharmony_ci		b0 += ((b1 << 4)+a) ^ (b1+sum) ^ ((b1 >> 5)+b);
2198c2ecf20Sopenharmony_ci		b1 += ((b0 << 4)+c) ^ (b0+sum) ^ ((b0 >> 5)+d);
2208c2ecf20Sopenharmony_ci	} while (--n);
2218c2ecf20Sopenharmony_ci
2228c2ecf20Sopenharmony_ci	buf[0] += b0;
2238c2ecf20Sopenharmony_ci	buf[1] += b1;
2248c2ecf20Sopenharmony_ci}
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_cistatic void str2hashbuf(const char *msg, int len, __u32 *buf, int num)
2278c2ecf20Sopenharmony_ci{
2288c2ecf20Sopenharmony_ci	__u32	pad, val;
2298c2ecf20Sopenharmony_ci	int	i;
2308c2ecf20Sopenharmony_ci
2318c2ecf20Sopenharmony_ci	pad = (__u32)len | ((__u32)len << 8);
2328c2ecf20Sopenharmony_ci	pad |= pad << 16;
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_ci	val = pad;
2358c2ecf20Sopenharmony_ci	if (len > num*4)
2368c2ecf20Sopenharmony_ci		len = num * 4;
2378c2ecf20Sopenharmony_ci	for (i = 0; i < len; i++) {
2388c2ecf20Sopenharmony_ci		if ((i % 4) == 0)
2398c2ecf20Sopenharmony_ci			val = pad;
2408c2ecf20Sopenharmony_ci		val = msg[i] + (val << 8);
2418c2ecf20Sopenharmony_ci		if ((i % 4) == 3) {
2428c2ecf20Sopenharmony_ci			*buf++ = val;
2438c2ecf20Sopenharmony_ci			val = pad;
2448c2ecf20Sopenharmony_ci			num--;
2458c2ecf20Sopenharmony_ci		}
2468c2ecf20Sopenharmony_ci	}
2478c2ecf20Sopenharmony_ci	if (--num >= 0)
2488c2ecf20Sopenharmony_ci		*buf++ = val;
2498c2ecf20Sopenharmony_ci	while (--num >= 0)
2508c2ecf20Sopenharmony_ci		*buf++ = pad;
2518c2ecf20Sopenharmony_ci}
2528c2ecf20Sopenharmony_ci
2538c2ecf20Sopenharmony_cistatic void ocfs2_dx_dir_name_hash(struct inode *dir, const char *name, int len,
2548c2ecf20Sopenharmony_ci				   struct ocfs2_dx_hinfo *hinfo)
2558c2ecf20Sopenharmony_ci{
2568c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
2578c2ecf20Sopenharmony_ci	const char	*p;
2588c2ecf20Sopenharmony_ci	__u32		in[8], buf[4];
2598c2ecf20Sopenharmony_ci
2608c2ecf20Sopenharmony_ci	/*
2618c2ecf20Sopenharmony_ci	 * XXX: Is this really necessary, if the index is never looked
2628c2ecf20Sopenharmony_ci	 * at by readdir? Is a hash value of '0' a bad idea?
2638c2ecf20Sopenharmony_ci	 */
2648c2ecf20Sopenharmony_ci	if ((len == 1 && !strncmp(".", name, 1)) ||
2658c2ecf20Sopenharmony_ci	    (len == 2 && !strncmp("..", name, 2))) {
2668c2ecf20Sopenharmony_ci		buf[0] = buf[1] = 0;
2678c2ecf20Sopenharmony_ci		goto out;
2688c2ecf20Sopenharmony_ci	}
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci#ifdef OCFS2_DEBUG_DX_DIRS
2718c2ecf20Sopenharmony_ci	/*
2728c2ecf20Sopenharmony_ci	 * This makes it very easy to debug indexing problems. We
2738c2ecf20Sopenharmony_ci	 * should never allow this to be selected without hand editing
2748c2ecf20Sopenharmony_ci	 * this file though.
2758c2ecf20Sopenharmony_ci	 */
2768c2ecf20Sopenharmony_ci	buf[0] = buf[1] = len;
2778c2ecf20Sopenharmony_ci	goto out;
2788c2ecf20Sopenharmony_ci#endif
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	memcpy(buf, osb->osb_dx_seed, sizeof(buf));
2818c2ecf20Sopenharmony_ci
2828c2ecf20Sopenharmony_ci	p = name;
2838c2ecf20Sopenharmony_ci	while (len > 0) {
2848c2ecf20Sopenharmony_ci		str2hashbuf(p, len, in, 4);
2858c2ecf20Sopenharmony_ci		TEA_transform(buf, in);
2868c2ecf20Sopenharmony_ci		len -= 16;
2878c2ecf20Sopenharmony_ci		p += 16;
2888c2ecf20Sopenharmony_ci	}
2898c2ecf20Sopenharmony_ci
2908c2ecf20Sopenharmony_ciout:
2918c2ecf20Sopenharmony_ci	hinfo->major_hash = buf[0];
2928c2ecf20Sopenharmony_ci	hinfo->minor_hash = buf[1];
2938c2ecf20Sopenharmony_ci}
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci/*
2968c2ecf20Sopenharmony_ci * bh passed here can be an inode block or a dir data block, depending
2978c2ecf20Sopenharmony_ci * on the inode inline data flag.
2988c2ecf20Sopenharmony_ci */
2998c2ecf20Sopenharmony_cistatic int ocfs2_check_dir_entry(struct inode *dir,
3008c2ecf20Sopenharmony_ci				 struct ocfs2_dir_entry *de,
3018c2ecf20Sopenharmony_ci				 struct buffer_head *bh,
3028c2ecf20Sopenharmony_ci				 char *buf,
3038c2ecf20Sopenharmony_ci				 unsigned int size,
3048c2ecf20Sopenharmony_ci				 unsigned long offset)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	const char *error_msg = NULL;
3078c2ecf20Sopenharmony_ci	const int rlen = le16_to_cpu(de->rec_len);
3088c2ecf20Sopenharmony_ci	const unsigned long next_offset = ((char *) de - buf) + rlen;
3098c2ecf20Sopenharmony_ci
3108c2ecf20Sopenharmony_ci	if (unlikely(rlen < OCFS2_DIR_REC_LEN(1)))
3118c2ecf20Sopenharmony_ci		error_msg = "rec_len is smaller than minimal";
3128c2ecf20Sopenharmony_ci	else if (unlikely(rlen % 4 != 0))
3138c2ecf20Sopenharmony_ci		error_msg = "rec_len % 4 != 0";
3148c2ecf20Sopenharmony_ci	else if (unlikely(rlen < OCFS2_DIR_REC_LEN(de->name_len)))
3158c2ecf20Sopenharmony_ci		error_msg = "rec_len is too small for name_len";
3168c2ecf20Sopenharmony_ci	else if (unlikely(next_offset > size))
3178c2ecf20Sopenharmony_ci		error_msg = "directory entry overrun";
3188c2ecf20Sopenharmony_ci	else if (unlikely(next_offset > size - OCFS2_DIR_REC_LEN(1)) &&
3198c2ecf20Sopenharmony_ci		 next_offset != size)
3208c2ecf20Sopenharmony_ci		error_msg = "directory entry too close to end";
3218c2ecf20Sopenharmony_ci
3228c2ecf20Sopenharmony_ci	if (unlikely(error_msg != NULL))
3238c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "bad entry in directory #%llu: %s - "
3248c2ecf20Sopenharmony_ci		     "offset=%lu, inode=%llu, rec_len=%d, name_len=%d\n",
3258c2ecf20Sopenharmony_ci		     (unsigned long long)OCFS2_I(dir)->ip_blkno, error_msg,
3268c2ecf20Sopenharmony_ci		     offset, (unsigned long long)le64_to_cpu(de->inode), rlen,
3278c2ecf20Sopenharmony_ci		     de->name_len);
3288c2ecf20Sopenharmony_ci
3298c2ecf20Sopenharmony_ci	return error_msg == NULL ? 1 : 0;
3308c2ecf20Sopenharmony_ci}
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_cistatic inline int ocfs2_match(int len,
3338c2ecf20Sopenharmony_ci			      const char * const name,
3348c2ecf20Sopenharmony_ci			      struct ocfs2_dir_entry *de)
3358c2ecf20Sopenharmony_ci{
3368c2ecf20Sopenharmony_ci	if (len != de->name_len)
3378c2ecf20Sopenharmony_ci		return 0;
3388c2ecf20Sopenharmony_ci	if (!de->inode)
3398c2ecf20Sopenharmony_ci		return 0;
3408c2ecf20Sopenharmony_ci	return !memcmp(name, de->name, len);
3418c2ecf20Sopenharmony_ci}
3428c2ecf20Sopenharmony_ci
3438c2ecf20Sopenharmony_ci/*
3448c2ecf20Sopenharmony_ci * Returns 0 if not found, -1 on failure, and 1 on success
3458c2ecf20Sopenharmony_ci */
3468c2ecf20Sopenharmony_cistatic inline int ocfs2_search_dirblock(struct buffer_head *bh,
3478c2ecf20Sopenharmony_ci					struct inode *dir,
3488c2ecf20Sopenharmony_ci					const char *name, int namelen,
3498c2ecf20Sopenharmony_ci					unsigned long offset,
3508c2ecf20Sopenharmony_ci					char *first_de,
3518c2ecf20Sopenharmony_ci					unsigned int bytes,
3528c2ecf20Sopenharmony_ci					struct ocfs2_dir_entry **res_dir)
3538c2ecf20Sopenharmony_ci{
3548c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
3558c2ecf20Sopenharmony_ci	char *dlimit, *de_buf;
3568c2ecf20Sopenharmony_ci	int de_len;
3578c2ecf20Sopenharmony_ci	int ret = 0;
3588c2ecf20Sopenharmony_ci
3598c2ecf20Sopenharmony_ci	de_buf = first_de;
3608c2ecf20Sopenharmony_ci	dlimit = de_buf + bytes;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	while (de_buf < dlimit - OCFS2_DIR_MEMBER_LEN) {
3638c2ecf20Sopenharmony_ci		/* this code is executed quadratically often */
3648c2ecf20Sopenharmony_ci		/* do minimal checking `by hand' */
3658c2ecf20Sopenharmony_ci
3668c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *) de_buf;
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci		if (de->name + namelen <= dlimit &&
3698c2ecf20Sopenharmony_ci		    ocfs2_match(namelen, name, de)) {
3708c2ecf20Sopenharmony_ci			/* found a match - just to be sure, do a full check */
3718c2ecf20Sopenharmony_ci			if (!ocfs2_check_dir_entry(dir, de, bh, first_de,
3728c2ecf20Sopenharmony_ci						   bytes, offset)) {
3738c2ecf20Sopenharmony_ci				ret = -1;
3748c2ecf20Sopenharmony_ci				goto bail;
3758c2ecf20Sopenharmony_ci			}
3768c2ecf20Sopenharmony_ci			*res_dir = de;
3778c2ecf20Sopenharmony_ci			ret = 1;
3788c2ecf20Sopenharmony_ci			goto bail;
3798c2ecf20Sopenharmony_ci		}
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci		/* prevent looping on a bad block */
3828c2ecf20Sopenharmony_ci		de_len = le16_to_cpu(de->rec_len);
3838c2ecf20Sopenharmony_ci		if (de_len <= 0) {
3848c2ecf20Sopenharmony_ci			ret = -1;
3858c2ecf20Sopenharmony_ci			goto bail;
3868c2ecf20Sopenharmony_ci		}
3878c2ecf20Sopenharmony_ci
3888c2ecf20Sopenharmony_ci		de_buf += de_len;
3898c2ecf20Sopenharmony_ci		offset += de_len;
3908c2ecf20Sopenharmony_ci	}
3918c2ecf20Sopenharmony_ci
3928c2ecf20Sopenharmony_cibail:
3938c2ecf20Sopenharmony_ci	trace_ocfs2_search_dirblock(ret);
3948c2ecf20Sopenharmony_ci	return ret;
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_cistatic struct buffer_head *ocfs2_find_entry_id(const char *name,
3988c2ecf20Sopenharmony_ci					       int namelen,
3998c2ecf20Sopenharmony_ci					       struct inode *dir,
4008c2ecf20Sopenharmony_ci					       struct ocfs2_dir_entry **res_dir)
4018c2ecf20Sopenharmony_ci{
4028c2ecf20Sopenharmony_ci	int ret, found;
4038c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
4048c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di;
4058c2ecf20Sopenharmony_ci	struct ocfs2_inline_data *data;
4068c2ecf20Sopenharmony_ci
4078c2ecf20Sopenharmony_ci	ret = ocfs2_read_inode_block(dir, &di_bh);
4088c2ecf20Sopenharmony_ci	if (ret) {
4098c2ecf20Sopenharmony_ci		mlog_errno(ret);
4108c2ecf20Sopenharmony_ci		goto out;
4118c2ecf20Sopenharmony_ci	}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
4148c2ecf20Sopenharmony_ci	data = &di->id2.i_data;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	found = ocfs2_search_dirblock(di_bh, dir, name, namelen, 0,
4178c2ecf20Sopenharmony_ci				      data->id_data, i_size_read(dir), res_dir);
4188c2ecf20Sopenharmony_ci	if (found == 1)
4198c2ecf20Sopenharmony_ci		return di_bh;
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci	brelse(di_bh);
4228c2ecf20Sopenharmony_ciout:
4238c2ecf20Sopenharmony_ci	return NULL;
4248c2ecf20Sopenharmony_ci}
4258c2ecf20Sopenharmony_ci
4268c2ecf20Sopenharmony_cistatic int ocfs2_validate_dir_block(struct super_block *sb,
4278c2ecf20Sopenharmony_ci				    struct buffer_head *bh)
4288c2ecf20Sopenharmony_ci{
4298c2ecf20Sopenharmony_ci	int rc;
4308c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer =
4318c2ecf20Sopenharmony_ci		ocfs2_trailer_from_bh(bh, sb);
4328c2ecf20Sopenharmony_ci
4338c2ecf20Sopenharmony_ci
4348c2ecf20Sopenharmony_ci	/*
4358c2ecf20Sopenharmony_ci	 * We don't validate dirents here, that's handled
4368c2ecf20Sopenharmony_ci	 * in-place when the code walks them.
4378c2ecf20Sopenharmony_ci	 */
4388c2ecf20Sopenharmony_ci	trace_ocfs2_validate_dir_block((unsigned long long)bh->b_blocknr);
4398c2ecf20Sopenharmony_ci
4408c2ecf20Sopenharmony_ci	BUG_ON(!buffer_uptodate(bh));
4418c2ecf20Sopenharmony_ci
4428c2ecf20Sopenharmony_ci	/*
4438c2ecf20Sopenharmony_ci	 * If the ecc fails, we return the error but otherwise
4448c2ecf20Sopenharmony_ci	 * leave the filesystem running.  We know any error is
4458c2ecf20Sopenharmony_ci	 * local to this block.
4468c2ecf20Sopenharmony_ci	 *
4478c2ecf20Sopenharmony_ci	 * Note that we are safe to call this even if the directory
4488c2ecf20Sopenharmony_ci	 * doesn't have a trailer.  Filesystems without metaecc will do
4498c2ecf20Sopenharmony_ci	 * nothing, and filesystems with it will have one.
4508c2ecf20Sopenharmony_ci	 */
4518c2ecf20Sopenharmony_ci	rc = ocfs2_validate_meta_ecc(sb, bh->b_data, &trailer->db_check);
4528c2ecf20Sopenharmony_ci	if (rc)
4538c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "Checksum failed for dinode %llu\n",
4548c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
4558c2ecf20Sopenharmony_ci
4568c2ecf20Sopenharmony_ci	return rc;
4578c2ecf20Sopenharmony_ci}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci/*
4608c2ecf20Sopenharmony_ci * Validate a directory trailer.
4618c2ecf20Sopenharmony_ci *
4628c2ecf20Sopenharmony_ci * We check the trailer here rather than in ocfs2_validate_dir_block()
4638c2ecf20Sopenharmony_ci * because that function doesn't have the inode to test.
4648c2ecf20Sopenharmony_ci */
4658c2ecf20Sopenharmony_cistatic int ocfs2_check_dir_trailer(struct inode *dir, struct buffer_head *bh)
4668c2ecf20Sopenharmony_ci{
4678c2ecf20Sopenharmony_ci	int rc = 0;
4688c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
4698c2ecf20Sopenharmony_ci
4708c2ecf20Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(bh, dir->i_sb);
4718c2ecf20Sopenharmony_ci	if (!OCFS2_IS_VALID_DIR_TRAILER(trailer)) {
4728c2ecf20Sopenharmony_ci		rc = ocfs2_error(dir->i_sb,
4738c2ecf20Sopenharmony_ci				 "Invalid dirblock #%llu: signature = %.*s\n",
4748c2ecf20Sopenharmony_ci				 (unsigned long long)bh->b_blocknr, 7,
4758c2ecf20Sopenharmony_ci				 trailer->db_signature);
4768c2ecf20Sopenharmony_ci		goto out;
4778c2ecf20Sopenharmony_ci	}
4788c2ecf20Sopenharmony_ci	if (le64_to_cpu(trailer->db_blkno) != bh->b_blocknr) {
4798c2ecf20Sopenharmony_ci		rc = ocfs2_error(dir->i_sb,
4808c2ecf20Sopenharmony_ci				 "Directory block #%llu has an invalid db_blkno of %llu\n",
4818c2ecf20Sopenharmony_ci				 (unsigned long long)bh->b_blocknr,
4828c2ecf20Sopenharmony_ci				 (unsigned long long)le64_to_cpu(trailer->db_blkno));
4838c2ecf20Sopenharmony_ci		goto out;
4848c2ecf20Sopenharmony_ci	}
4858c2ecf20Sopenharmony_ci	if (le64_to_cpu(trailer->db_parent_dinode) !=
4868c2ecf20Sopenharmony_ci	    OCFS2_I(dir)->ip_blkno) {
4878c2ecf20Sopenharmony_ci		rc = ocfs2_error(dir->i_sb,
4888c2ecf20Sopenharmony_ci				 "Directory block #%llu on dinode #%llu has an invalid parent_dinode of %llu\n",
4898c2ecf20Sopenharmony_ci				 (unsigned long long)bh->b_blocknr,
4908c2ecf20Sopenharmony_ci				 (unsigned long long)OCFS2_I(dir)->ip_blkno,
4918c2ecf20Sopenharmony_ci				 (unsigned long long)le64_to_cpu(trailer->db_blkno));
4928c2ecf20Sopenharmony_ci		goto out;
4938c2ecf20Sopenharmony_ci	}
4948c2ecf20Sopenharmony_ciout:
4958c2ecf20Sopenharmony_ci	return rc;
4968c2ecf20Sopenharmony_ci}
4978c2ecf20Sopenharmony_ci
4988c2ecf20Sopenharmony_ci/*
4998c2ecf20Sopenharmony_ci * This function forces all errors to -EIO for consistency with its
5008c2ecf20Sopenharmony_ci * predecessor, ocfs2_bread().  We haven't audited what returning the
5018c2ecf20Sopenharmony_ci * real error codes would do to callers.  We log the real codes with
5028c2ecf20Sopenharmony_ci * mlog_errno() before we squash them.
5038c2ecf20Sopenharmony_ci */
5048c2ecf20Sopenharmony_cistatic int ocfs2_read_dir_block(struct inode *inode, u64 v_block,
5058c2ecf20Sopenharmony_ci				struct buffer_head **bh, int flags)
5068c2ecf20Sopenharmony_ci{
5078c2ecf20Sopenharmony_ci	int rc = 0;
5088c2ecf20Sopenharmony_ci	struct buffer_head *tmp = *bh;
5098c2ecf20Sopenharmony_ci
5108c2ecf20Sopenharmony_ci	rc = ocfs2_read_virt_blocks(inode, v_block, 1, &tmp, flags,
5118c2ecf20Sopenharmony_ci				    ocfs2_validate_dir_block);
5128c2ecf20Sopenharmony_ci	if (rc) {
5138c2ecf20Sopenharmony_ci		mlog_errno(rc);
5148c2ecf20Sopenharmony_ci		goto out;
5158c2ecf20Sopenharmony_ci	}
5168c2ecf20Sopenharmony_ci
5178c2ecf20Sopenharmony_ci	if (!(flags & OCFS2_BH_READAHEAD) &&
5188c2ecf20Sopenharmony_ci	    ocfs2_supports_dir_trailer(inode)) {
5198c2ecf20Sopenharmony_ci		rc = ocfs2_check_dir_trailer(inode, tmp);
5208c2ecf20Sopenharmony_ci		if (rc) {
5218c2ecf20Sopenharmony_ci			if (!*bh)
5228c2ecf20Sopenharmony_ci				brelse(tmp);
5238c2ecf20Sopenharmony_ci			mlog_errno(rc);
5248c2ecf20Sopenharmony_ci			goto out;
5258c2ecf20Sopenharmony_ci		}
5268c2ecf20Sopenharmony_ci	}
5278c2ecf20Sopenharmony_ci
5288c2ecf20Sopenharmony_ci	/* If ocfs2_read_virt_blocks() got us a new bh, pass it up. */
5298c2ecf20Sopenharmony_ci	if (!*bh)
5308c2ecf20Sopenharmony_ci		*bh = tmp;
5318c2ecf20Sopenharmony_ci
5328c2ecf20Sopenharmony_ciout:
5338c2ecf20Sopenharmony_ci	return rc ? -EIO : 0;
5348c2ecf20Sopenharmony_ci}
5358c2ecf20Sopenharmony_ci
5368c2ecf20Sopenharmony_ci/*
5378c2ecf20Sopenharmony_ci * Read the block at 'phys' which belongs to this directory
5388c2ecf20Sopenharmony_ci * inode. This function does no virtual->physical block translation -
5398c2ecf20Sopenharmony_ci * what's passed in is assumed to be a valid directory block.
5408c2ecf20Sopenharmony_ci */
5418c2ecf20Sopenharmony_cistatic int ocfs2_read_dir_block_direct(struct inode *dir, u64 phys,
5428c2ecf20Sopenharmony_ci				       struct buffer_head **bh)
5438c2ecf20Sopenharmony_ci{
5448c2ecf20Sopenharmony_ci	int ret;
5458c2ecf20Sopenharmony_ci	struct buffer_head *tmp = *bh;
5468c2ecf20Sopenharmony_ci
5478c2ecf20Sopenharmony_ci	ret = ocfs2_read_block(INODE_CACHE(dir), phys, &tmp,
5488c2ecf20Sopenharmony_ci			       ocfs2_validate_dir_block);
5498c2ecf20Sopenharmony_ci	if (ret) {
5508c2ecf20Sopenharmony_ci		mlog_errno(ret);
5518c2ecf20Sopenharmony_ci		goto out;
5528c2ecf20Sopenharmony_ci	}
5538c2ecf20Sopenharmony_ci
5548c2ecf20Sopenharmony_ci	if (ocfs2_supports_dir_trailer(dir)) {
5558c2ecf20Sopenharmony_ci		ret = ocfs2_check_dir_trailer(dir, tmp);
5568c2ecf20Sopenharmony_ci		if (ret) {
5578c2ecf20Sopenharmony_ci			if (!*bh)
5588c2ecf20Sopenharmony_ci				brelse(tmp);
5598c2ecf20Sopenharmony_ci			mlog_errno(ret);
5608c2ecf20Sopenharmony_ci			goto out;
5618c2ecf20Sopenharmony_ci		}
5628c2ecf20Sopenharmony_ci	}
5638c2ecf20Sopenharmony_ci
5648c2ecf20Sopenharmony_ci	if (!ret && !*bh)
5658c2ecf20Sopenharmony_ci		*bh = tmp;
5668c2ecf20Sopenharmony_ciout:
5678c2ecf20Sopenharmony_ci	return ret;
5688c2ecf20Sopenharmony_ci}
5698c2ecf20Sopenharmony_ci
5708c2ecf20Sopenharmony_cistatic int ocfs2_validate_dx_root(struct super_block *sb,
5718c2ecf20Sopenharmony_ci				  struct buffer_head *bh)
5728c2ecf20Sopenharmony_ci{
5738c2ecf20Sopenharmony_ci	int ret;
5748c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci	BUG_ON(!buffer_uptodate(bh));
5778c2ecf20Sopenharmony_ci
5788c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) bh->b_data;
5798c2ecf20Sopenharmony_ci
5808c2ecf20Sopenharmony_ci	ret = ocfs2_validate_meta_ecc(sb, bh->b_data, &dx_root->dr_check);
5818c2ecf20Sopenharmony_ci	if (ret) {
5828c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
5838c2ecf20Sopenharmony_ci		     "Checksum failed for dir index root block %llu\n",
5848c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
5858c2ecf20Sopenharmony_ci		return ret;
5868c2ecf20Sopenharmony_ci	}
5878c2ecf20Sopenharmony_ci
5888c2ecf20Sopenharmony_ci	if (!OCFS2_IS_VALID_DX_ROOT(dx_root)) {
5898c2ecf20Sopenharmony_ci		ret = ocfs2_error(sb,
5908c2ecf20Sopenharmony_ci				  "Dir Index Root # %llu has bad signature %.*s\n",
5918c2ecf20Sopenharmony_ci				  (unsigned long long)le64_to_cpu(dx_root->dr_blkno),
5928c2ecf20Sopenharmony_ci				  7, dx_root->dr_signature);
5938c2ecf20Sopenharmony_ci	}
5948c2ecf20Sopenharmony_ci
5958c2ecf20Sopenharmony_ci	return ret;
5968c2ecf20Sopenharmony_ci}
5978c2ecf20Sopenharmony_ci
5988c2ecf20Sopenharmony_cistatic int ocfs2_read_dx_root(struct inode *dir, struct ocfs2_dinode *di,
5998c2ecf20Sopenharmony_ci			      struct buffer_head **dx_root_bh)
6008c2ecf20Sopenharmony_ci{
6018c2ecf20Sopenharmony_ci	int ret;
6028c2ecf20Sopenharmony_ci	u64 blkno = le64_to_cpu(di->i_dx_root);
6038c2ecf20Sopenharmony_ci	struct buffer_head *tmp = *dx_root_bh;
6048c2ecf20Sopenharmony_ci
6058c2ecf20Sopenharmony_ci	ret = ocfs2_read_block(INODE_CACHE(dir), blkno, &tmp,
6068c2ecf20Sopenharmony_ci			       ocfs2_validate_dx_root);
6078c2ecf20Sopenharmony_ci
6088c2ecf20Sopenharmony_ci	/* If ocfs2_read_block() got us a new bh, pass it up. */
6098c2ecf20Sopenharmony_ci	if (!ret && !*dx_root_bh)
6108c2ecf20Sopenharmony_ci		*dx_root_bh = tmp;
6118c2ecf20Sopenharmony_ci
6128c2ecf20Sopenharmony_ci	return ret;
6138c2ecf20Sopenharmony_ci}
6148c2ecf20Sopenharmony_ci
6158c2ecf20Sopenharmony_cistatic int ocfs2_validate_dx_leaf(struct super_block *sb,
6168c2ecf20Sopenharmony_ci				  struct buffer_head *bh)
6178c2ecf20Sopenharmony_ci{
6188c2ecf20Sopenharmony_ci	int ret;
6198c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf = (struct ocfs2_dx_leaf *)bh->b_data;
6208c2ecf20Sopenharmony_ci
6218c2ecf20Sopenharmony_ci	BUG_ON(!buffer_uptodate(bh));
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	ret = ocfs2_validate_meta_ecc(sb, bh->b_data, &dx_leaf->dl_check);
6248c2ecf20Sopenharmony_ci	if (ret) {
6258c2ecf20Sopenharmony_ci		mlog(ML_ERROR,
6268c2ecf20Sopenharmony_ci		     "Checksum failed for dir index leaf block %llu\n",
6278c2ecf20Sopenharmony_ci		     (unsigned long long)bh->b_blocknr);
6288c2ecf20Sopenharmony_ci		return ret;
6298c2ecf20Sopenharmony_ci	}
6308c2ecf20Sopenharmony_ci
6318c2ecf20Sopenharmony_ci	if (!OCFS2_IS_VALID_DX_LEAF(dx_leaf)) {
6328c2ecf20Sopenharmony_ci		ret = ocfs2_error(sb, "Dir Index Leaf has bad signature %.*s\n",
6338c2ecf20Sopenharmony_ci				  7, dx_leaf->dl_signature);
6348c2ecf20Sopenharmony_ci	}
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	return ret;
6378c2ecf20Sopenharmony_ci}
6388c2ecf20Sopenharmony_ci
6398c2ecf20Sopenharmony_cistatic int ocfs2_read_dx_leaf(struct inode *dir, u64 blkno,
6408c2ecf20Sopenharmony_ci			      struct buffer_head **dx_leaf_bh)
6418c2ecf20Sopenharmony_ci{
6428c2ecf20Sopenharmony_ci	int ret;
6438c2ecf20Sopenharmony_ci	struct buffer_head *tmp = *dx_leaf_bh;
6448c2ecf20Sopenharmony_ci
6458c2ecf20Sopenharmony_ci	ret = ocfs2_read_block(INODE_CACHE(dir), blkno, &tmp,
6468c2ecf20Sopenharmony_ci			       ocfs2_validate_dx_leaf);
6478c2ecf20Sopenharmony_ci
6488c2ecf20Sopenharmony_ci	/* If ocfs2_read_block() got us a new bh, pass it up. */
6498c2ecf20Sopenharmony_ci	if (!ret && !*dx_leaf_bh)
6508c2ecf20Sopenharmony_ci		*dx_leaf_bh = tmp;
6518c2ecf20Sopenharmony_ci
6528c2ecf20Sopenharmony_ci	return ret;
6538c2ecf20Sopenharmony_ci}
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci/*
6568c2ecf20Sopenharmony_ci * Read a series of dx_leaf blocks. This expects all buffer_head
6578c2ecf20Sopenharmony_ci * pointers to be NULL on function entry.
6588c2ecf20Sopenharmony_ci */
6598c2ecf20Sopenharmony_cistatic int ocfs2_read_dx_leaves(struct inode *dir, u64 start, int num,
6608c2ecf20Sopenharmony_ci				struct buffer_head **dx_leaf_bhs)
6618c2ecf20Sopenharmony_ci{
6628c2ecf20Sopenharmony_ci	int ret;
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	ret = ocfs2_read_blocks(INODE_CACHE(dir), start, num, dx_leaf_bhs, 0,
6658c2ecf20Sopenharmony_ci				ocfs2_validate_dx_leaf);
6668c2ecf20Sopenharmony_ci	if (ret)
6678c2ecf20Sopenharmony_ci		mlog_errno(ret);
6688c2ecf20Sopenharmony_ci
6698c2ecf20Sopenharmony_ci	return ret;
6708c2ecf20Sopenharmony_ci}
6718c2ecf20Sopenharmony_ci
6728c2ecf20Sopenharmony_cistatic struct buffer_head *ocfs2_find_entry_el(const char *name, int namelen,
6738c2ecf20Sopenharmony_ci					       struct inode *dir,
6748c2ecf20Sopenharmony_ci					       struct ocfs2_dir_entry **res_dir)
6758c2ecf20Sopenharmony_ci{
6768c2ecf20Sopenharmony_ci	struct super_block *sb;
6778c2ecf20Sopenharmony_ci	struct buffer_head *bh_use[NAMEI_RA_SIZE];
6788c2ecf20Sopenharmony_ci	struct buffer_head *bh, *ret = NULL;
6798c2ecf20Sopenharmony_ci	unsigned long start, block, b;
6808c2ecf20Sopenharmony_ci	int ra_max = 0;		/* Number of bh's in the readahead
6818c2ecf20Sopenharmony_ci				   buffer, bh_use[] */
6828c2ecf20Sopenharmony_ci	int ra_ptr = 0;		/* Current index into readahead
6838c2ecf20Sopenharmony_ci				   buffer */
6848c2ecf20Sopenharmony_ci	int num = 0;
6858c2ecf20Sopenharmony_ci	int nblocks, i;
6868c2ecf20Sopenharmony_ci
6878c2ecf20Sopenharmony_ci	sb = dir->i_sb;
6888c2ecf20Sopenharmony_ci
6898c2ecf20Sopenharmony_ci	nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
6908c2ecf20Sopenharmony_ci	start = OCFS2_I(dir)->ip_dir_start_lookup;
6918c2ecf20Sopenharmony_ci	if (start >= nblocks)
6928c2ecf20Sopenharmony_ci		start = 0;
6938c2ecf20Sopenharmony_ci	block = start;
6948c2ecf20Sopenharmony_ci
6958c2ecf20Sopenharmony_cirestart:
6968c2ecf20Sopenharmony_ci	do {
6978c2ecf20Sopenharmony_ci		/*
6988c2ecf20Sopenharmony_ci		 * We deal with the read-ahead logic here.
6998c2ecf20Sopenharmony_ci		 */
7008c2ecf20Sopenharmony_ci		if (ra_ptr >= ra_max) {
7018c2ecf20Sopenharmony_ci			/* Refill the readahead buffer */
7028c2ecf20Sopenharmony_ci			ra_ptr = 0;
7038c2ecf20Sopenharmony_ci			b = block;
7048c2ecf20Sopenharmony_ci			for (ra_max = 0; ra_max < NAMEI_RA_SIZE; ra_max++) {
7058c2ecf20Sopenharmony_ci				/*
7068c2ecf20Sopenharmony_ci				 * Terminate if we reach the end of the
7078c2ecf20Sopenharmony_ci				 * directory and must wrap, or if our
7088c2ecf20Sopenharmony_ci				 * search has finished at this block.
7098c2ecf20Sopenharmony_ci				 */
7108c2ecf20Sopenharmony_ci				if (b >= nblocks || (num && block == start)) {
7118c2ecf20Sopenharmony_ci					bh_use[ra_max] = NULL;
7128c2ecf20Sopenharmony_ci					break;
7138c2ecf20Sopenharmony_ci				}
7148c2ecf20Sopenharmony_ci				num++;
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci				bh = NULL;
7178c2ecf20Sopenharmony_ci				ocfs2_read_dir_block(dir, b++, &bh,
7188c2ecf20Sopenharmony_ci							   OCFS2_BH_READAHEAD);
7198c2ecf20Sopenharmony_ci				bh_use[ra_max] = bh;
7208c2ecf20Sopenharmony_ci			}
7218c2ecf20Sopenharmony_ci		}
7228c2ecf20Sopenharmony_ci		if ((bh = bh_use[ra_ptr++]) == NULL)
7238c2ecf20Sopenharmony_ci			goto next;
7248c2ecf20Sopenharmony_ci		if (ocfs2_read_dir_block(dir, block, &bh, 0)) {
7258c2ecf20Sopenharmony_ci			/* read error, skip block & hope for the best.
7268c2ecf20Sopenharmony_ci			 * ocfs2_read_dir_block() has released the bh. */
7278c2ecf20Sopenharmony_ci			mlog(ML_ERROR, "reading directory %llu, "
7288c2ecf20Sopenharmony_ci				    "offset %lu\n",
7298c2ecf20Sopenharmony_ci				    (unsigned long long)OCFS2_I(dir)->ip_blkno,
7308c2ecf20Sopenharmony_ci				    block);
7318c2ecf20Sopenharmony_ci			goto next;
7328c2ecf20Sopenharmony_ci		}
7338c2ecf20Sopenharmony_ci		i = ocfs2_search_dirblock(bh, dir, name, namelen,
7348c2ecf20Sopenharmony_ci					  block << sb->s_blocksize_bits,
7358c2ecf20Sopenharmony_ci					  bh->b_data, sb->s_blocksize,
7368c2ecf20Sopenharmony_ci					  res_dir);
7378c2ecf20Sopenharmony_ci		if (i == 1) {
7388c2ecf20Sopenharmony_ci			OCFS2_I(dir)->ip_dir_start_lookup = block;
7398c2ecf20Sopenharmony_ci			ret = bh;
7408c2ecf20Sopenharmony_ci			goto cleanup_and_exit;
7418c2ecf20Sopenharmony_ci		} else {
7428c2ecf20Sopenharmony_ci			brelse(bh);
7438c2ecf20Sopenharmony_ci			if (i < 0)
7448c2ecf20Sopenharmony_ci				goto cleanup_and_exit;
7458c2ecf20Sopenharmony_ci		}
7468c2ecf20Sopenharmony_ci	next:
7478c2ecf20Sopenharmony_ci		if (++block >= nblocks)
7488c2ecf20Sopenharmony_ci			block = 0;
7498c2ecf20Sopenharmony_ci	} while (block != start);
7508c2ecf20Sopenharmony_ci
7518c2ecf20Sopenharmony_ci	/*
7528c2ecf20Sopenharmony_ci	 * If the directory has grown while we were searching, then
7538c2ecf20Sopenharmony_ci	 * search the last part of the directory before giving up.
7548c2ecf20Sopenharmony_ci	 */
7558c2ecf20Sopenharmony_ci	block = nblocks;
7568c2ecf20Sopenharmony_ci	nblocks = i_size_read(dir) >> sb->s_blocksize_bits;
7578c2ecf20Sopenharmony_ci	if (block < nblocks) {
7588c2ecf20Sopenharmony_ci		start = 0;
7598c2ecf20Sopenharmony_ci		goto restart;
7608c2ecf20Sopenharmony_ci	}
7618c2ecf20Sopenharmony_ci
7628c2ecf20Sopenharmony_cicleanup_and_exit:
7638c2ecf20Sopenharmony_ci	/* Clean up the read-ahead blocks */
7648c2ecf20Sopenharmony_ci	for (; ra_ptr < ra_max; ra_ptr++)
7658c2ecf20Sopenharmony_ci		brelse(bh_use[ra_ptr]);
7668c2ecf20Sopenharmony_ci
7678c2ecf20Sopenharmony_ci	trace_ocfs2_find_entry_el(ret);
7688c2ecf20Sopenharmony_ci	return ret;
7698c2ecf20Sopenharmony_ci}
7708c2ecf20Sopenharmony_ci
7718c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_lookup_rec(struct inode *inode,
7728c2ecf20Sopenharmony_ci				   struct ocfs2_extent_list *el,
7738c2ecf20Sopenharmony_ci				   u32 major_hash,
7748c2ecf20Sopenharmony_ci				   u32 *ret_cpos,
7758c2ecf20Sopenharmony_ci				   u64 *ret_phys_blkno,
7768c2ecf20Sopenharmony_ci				   unsigned int *ret_clen)
7778c2ecf20Sopenharmony_ci{
7788c2ecf20Sopenharmony_ci	int ret = 0, i, found;
7798c2ecf20Sopenharmony_ci	struct buffer_head *eb_bh = NULL;
7808c2ecf20Sopenharmony_ci	struct ocfs2_extent_block *eb;
7818c2ecf20Sopenharmony_ci	struct ocfs2_extent_rec *rec = NULL;
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_ci	if (el->l_tree_depth) {
7848c2ecf20Sopenharmony_ci		ret = ocfs2_find_leaf(INODE_CACHE(inode), el, major_hash,
7858c2ecf20Sopenharmony_ci				      &eb_bh);
7868c2ecf20Sopenharmony_ci		if (ret) {
7878c2ecf20Sopenharmony_ci			mlog_errno(ret);
7888c2ecf20Sopenharmony_ci			goto out;
7898c2ecf20Sopenharmony_ci		}
7908c2ecf20Sopenharmony_ci
7918c2ecf20Sopenharmony_ci		eb = (struct ocfs2_extent_block *) eb_bh->b_data;
7928c2ecf20Sopenharmony_ci		el = &eb->h_list;
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci		if (el->l_tree_depth) {
7958c2ecf20Sopenharmony_ci			ret = ocfs2_error(inode->i_sb,
7968c2ecf20Sopenharmony_ci					  "Inode %lu has non zero tree depth in btree tree block %llu\n",
7978c2ecf20Sopenharmony_ci					  inode->i_ino,
7988c2ecf20Sopenharmony_ci					  (unsigned long long)eb_bh->b_blocknr);
7998c2ecf20Sopenharmony_ci			goto out;
8008c2ecf20Sopenharmony_ci		}
8018c2ecf20Sopenharmony_ci	}
8028c2ecf20Sopenharmony_ci
8038c2ecf20Sopenharmony_ci	found = 0;
8048c2ecf20Sopenharmony_ci	for (i = le16_to_cpu(el->l_next_free_rec) - 1; i >= 0; i--) {
8058c2ecf20Sopenharmony_ci		rec = &el->l_recs[i];
8068c2ecf20Sopenharmony_ci
8078c2ecf20Sopenharmony_ci		if (le32_to_cpu(rec->e_cpos) <= major_hash) {
8088c2ecf20Sopenharmony_ci			found = 1;
8098c2ecf20Sopenharmony_ci			break;
8108c2ecf20Sopenharmony_ci		}
8118c2ecf20Sopenharmony_ci	}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	if (!found) {
8148c2ecf20Sopenharmony_ci		ret = ocfs2_error(inode->i_sb,
8158c2ecf20Sopenharmony_ci				  "Inode %lu has bad extent record (%u, %u, 0) in btree\n",
8168c2ecf20Sopenharmony_ci				  inode->i_ino,
8178c2ecf20Sopenharmony_ci				  le32_to_cpu(rec->e_cpos),
8188c2ecf20Sopenharmony_ci				  ocfs2_rec_clusters(el, rec));
8198c2ecf20Sopenharmony_ci		goto out;
8208c2ecf20Sopenharmony_ci	}
8218c2ecf20Sopenharmony_ci
8228c2ecf20Sopenharmony_ci	if (ret_phys_blkno)
8238c2ecf20Sopenharmony_ci		*ret_phys_blkno = le64_to_cpu(rec->e_blkno);
8248c2ecf20Sopenharmony_ci	if (ret_cpos)
8258c2ecf20Sopenharmony_ci		*ret_cpos = le32_to_cpu(rec->e_cpos);
8268c2ecf20Sopenharmony_ci	if (ret_clen)
8278c2ecf20Sopenharmony_ci		*ret_clen = le16_to_cpu(rec->e_leaf_clusters);
8288c2ecf20Sopenharmony_ci
8298c2ecf20Sopenharmony_ciout:
8308c2ecf20Sopenharmony_ci	brelse(eb_bh);
8318c2ecf20Sopenharmony_ci	return ret;
8328c2ecf20Sopenharmony_ci}
8338c2ecf20Sopenharmony_ci
8348c2ecf20Sopenharmony_ci/*
8358c2ecf20Sopenharmony_ci * Returns the block index, from the start of the cluster which this
8368c2ecf20Sopenharmony_ci * hash belongs too.
8378c2ecf20Sopenharmony_ci */
8388c2ecf20Sopenharmony_cistatic inline unsigned int __ocfs2_dx_dir_hash_idx(struct ocfs2_super *osb,
8398c2ecf20Sopenharmony_ci						   u32 minor_hash)
8408c2ecf20Sopenharmony_ci{
8418c2ecf20Sopenharmony_ci	return minor_hash & osb->osb_dx_mask;
8428c2ecf20Sopenharmony_ci}
8438c2ecf20Sopenharmony_ci
8448c2ecf20Sopenharmony_cistatic inline unsigned int ocfs2_dx_dir_hash_idx(struct ocfs2_super *osb,
8458c2ecf20Sopenharmony_ci					  struct ocfs2_dx_hinfo *hinfo)
8468c2ecf20Sopenharmony_ci{
8478c2ecf20Sopenharmony_ci	return __ocfs2_dx_dir_hash_idx(osb, hinfo->minor_hash);
8488c2ecf20Sopenharmony_ci}
8498c2ecf20Sopenharmony_ci
8508c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_lookup(struct inode *inode,
8518c2ecf20Sopenharmony_ci			       struct ocfs2_extent_list *el,
8528c2ecf20Sopenharmony_ci			       struct ocfs2_dx_hinfo *hinfo,
8538c2ecf20Sopenharmony_ci			       u32 *ret_cpos,
8548c2ecf20Sopenharmony_ci			       u64 *ret_phys_blkno)
8558c2ecf20Sopenharmony_ci{
8568c2ecf20Sopenharmony_ci	int ret = 0;
8578c2ecf20Sopenharmony_ci	unsigned int cend, clen;
8588c2ecf20Sopenharmony_ci	u32 cpos;
8598c2ecf20Sopenharmony_ci	u64 blkno;
8608c2ecf20Sopenharmony_ci	u32 name_hash = hinfo->major_hash;
8618c2ecf20Sopenharmony_ci
8628c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_lookup_rec(inode, el, name_hash, &cpos, &blkno,
8638c2ecf20Sopenharmony_ci				      &clen);
8648c2ecf20Sopenharmony_ci	if (ret) {
8658c2ecf20Sopenharmony_ci		mlog_errno(ret);
8668c2ecf20Sopenharmony_ci		goto out;
8678c2ecf20Sopenharmony_ci	}
8688c2ecf20Sopenharmony_ci
8698c2ecf20Sopenharmony_ci	cend = cpos + clen;
8708c2ecf20Sopenharmony_ci	if (name_hash >= cend) {
8718c2ecf20Sopenharmony_ci		/* We want the last cluster */
8728c2ecf20Sopenharmony_ci		blkno += ocfs2_clusters_to_blocks(inode->i_sb, clen - 1);
8738c2ecf20Sopenharmony_ci		cpos += clen - 1;
8748c2ecf20Sopenharmony_ci	} else {
8758c2ecf20Sopenharmony_ci		blkno += ocfs2_clusters_to_blocks(inode->i_sb,
8768c2ecf20Sopenharmony_ci						  name_hash - cpos);
8778c2ecf20Sopenharmony_ci		cpos = name_hash;
8788c2ecf20Sopenharmony_ci	}
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci	/*
8818c2ecf20Sopenharmony_ci	 * We now have the cluster which should hold our entry. To
8828c2ecf20Sopenharmony_ci	 * find the exact block from the start of the cluster to
8838c2ecf20Sopenharmony_ci	 * search, we take the lower bits of the hash.
8848c2ecf20Sopenharmony_ci	 */
8858c2ecf20Sopenharmony_ci	blkno += ocfs2_dx_dir_hash_idx(OCFS2_SB(inode->i_sb), hinfo);
8868c2ecf20Sopenharmony_ci
8878c2ecf20Sopenharmony_ci	if (ret_phys_blkno)
8888c2ecf20Sopenharmony_ci		*ret_phys_blkno = blkno;
8898c2ecf20Sopenharmony_ci	if (ret_cpos)
8908c2ecf20Sopenharmony_ci		*ret_cpos = cpos;
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ciout:
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci	return ret;
8958c2ecf20Sopenharmony_ci}
8968c2ecf20Sopenharmony_ci
8978c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_search(const char *name, int namelen,
8988c2ecf20Sopenharmony_ci			       struct inode *dir,
8998c2ecf20Sopenharmony_ci			       struct ocfs2_dx_root_block *dx_root,
9008c2ecf20Sopenharmony_ci			       struct ocfs2_dir_lookup_result *res)
9018c2ecf20Sopenharmony_ci{
9028c2ecf20Sopenharmony_ci	int ret, i, found;
9038c2ecf20Sopenharmony_ci	u64 phys;
9048c2ecf20Sopenharmony_ci	struct buffer_head *dx_leaf_bh = NULL;
9058c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
9068c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry = NULL;
9078c2ecf20Sopenharmony_ci	struct buffer_head *dir_ent_bh = NULL;
9088c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *dir_ent = NULL;
9098c2ecf20Sopenharmony_ci	struct ocfs2_dx_hinfo *hinfo = &res->dl_hinfo;
9108c2ecf20Sopenharmony_ci	struct ocfs2_extent_list *dr_el;
9118c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	ocfs2_dx_dir_name_hash(dir, name, namelen, &res->dl_hinfo);
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root)) {
9168c2ecf20Sopenharmony_ci		entry_list = &dx_root->dr_entries;
9178c2ecf20Sopenharmony_ci		goto search;
9188c2ecf20Sopenharmony_ci	}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	dr_el = &dx_root->dr_list;
9218c2ecf20Sopenharmony_ci
9228c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_lookup(dir, dr_el, hinfo, NULL, &phys);
9238c2ecf20Sopenharmony_ci	if (ret) {
9248c2ecf20Sopenharmony_ci		mlog_errno(ret);
9258c2ecf20Sopenharmony_ci		goto out;
9268c2ecf20Sopenharmony_ci	}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_ci	trace_ocfs2_dx_dir_search((unsigned long long)OCFS2_I(dir)->ip_blkno,
9298c2ecf20Sopenharmony_ci				  namelen, name, hinfo->major_hash,
9308c2ecf20Sopenharmony_ci				  hinfo->minor_hash, (unsigned long long)phys);
9318c2ecf20Sopenharmony_ci
9328c2ecf20Sopenharmony_ci	ret = ocfs2_read_dx_leaf(dir, phys, &dx_leaf_bh);
9338c2ecf20Sopenharmony_ci	if (ret) {
9348c2ecf20Sopenharmony_ci		mlog_errno(ret);
9358c2ecf20Sopenharmony_ci		goto out;
9368c2ecf20Sopenharmony_ci	}
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	dx_leaf = (struct ocfs2_dx_leaf *) dx_leaf_bh->b_data;
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_ci	trace_ocfs2_dx_dir_search_leaf_info(
9418c2ecf20Sopenharmony_ci			le16_to_cpu(dx_leaf->dl_list.de_num_used),
9428c2ecf20Sopenharmony_ci			le16_to_cpu(dx_leaf->dl_list.de_count));
9438c2ecf20Sopenharmony_ci
9448c2ecf20Sopenharmony_ci	entry_list = &dx_leaf->dl_list;
9458c2ecf20Sopenharmony_ci
9468c2ecf20Sopenharmony_cisearch:
9478c2ecf20Sopenharmony_ci	/*
9488c2ecf20Sopenharmony_ci	 * Empty leaf is legal, so no need to check for that.
9498c2ecf20Sopenharmony_ci	 */
9508c2ecf20Sopenharmony_ci	found = 0;
9518c2ecf20Sopenharmony_ci	for (i = 0; i < le16_to_cpu(entry_list->de_num_used); i++) {
9528c2ecf20Sopenharmony_ci		dx_entry = &entry_list->de_entries[i];
9538c2ecf20Sopenharmony_ci
9548c2ecf20Sopenharmony_ci		if (hinfo->major_hash != le32_to_cpu(dx_entry->dx_major_hash)
9558c2ecf20Sopenharmony_ci		    || hinfo->minor_hash != le32_to_cpu(dx_entry->dx_minor_hash))
9568c2ecf20Sopenharmony_ci			continue;
9578c2ecf20Sopenharmony_ci
9588c2ecf20Sopenharmony_ci		/*
9598c2ecf20Sopenharmony_ci		 * Search unindexed leaf block now. We're not
9608c2ecf20Sopenharmony_ci		 * guaranteed to find anything.
9618c2ecf20Sopenharmony_ci		 */
9628c2ecf20Sopenharmony_ci		ret = ocfs2_read_dir_block_direct(dir,
9638c2ecf20Sopenharmony_ci					  le64_to_cpu(dx_entry->dx_dirent_blk),
9648c2ecf20Sopenharmony_ci					  &dir_ent_bh);
9658c2ecf20Sopenharmony_ci		if (ret) {
9668c2ecf20Sopenharmony_ci			mlog_errno(ret);
9678c2ecf20Sopenharmony_ci			goto out;
9688c2ecf20Sopenharmony_ci		}
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_ci		/*
9718c2ecf20Sopenharmony_ci		 * XXX: We should check the unindexed block here,
9728c2ecf20Sopenharmony_ci		 * before using it.
9738c2ecf20Sopenharmony_ci		 */
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_ci		found = ocfs2_search_dirblock(dir_ent_bh, dir, name, namelen,
9768c2ecf20Sopenharmony_ci					      0, dir_ent_bh->b_data,
9778c2ecf20Sopenharmony_ci					      dir->i_sb->s_blocksize, &dir_ent);
9788c2ecf20Sopenharmony_ci		if (found == 1)
9798c2ecf20Sopenharmony_ci			break;
9808c2ecf20Sopenharmony_ci
9818c2ecf20Sopenharmony_ci		if (found == -1) {
9828c2ecf20Sopenharmony_ci			/* This means we found a bad directory entry. */
9838c2ecf20Sopenharmony_ci			ret = -EIO;
9848c2ecf20Sopenharmony_ci			mlog_errno(ret);
9858c2ecf20Sopenharmony_ci			goto out;
9868c2ecf20Sopenharmony_ci		}
9878c2ecf20Sopenharmony_ci
9888c2ecf20Sopenharmony_ci		brelse(dir_ent_bh);
9898c2ecf20Sopenharmony_ci		dir_ent_bh = NULL;
9908c2ecf20Sopenharmony_ci	}
9918c2ecf20Sopenharmony_ci
9928c2ecf20Sopenharmony_ci	if (found <= 0) {
9938c2ecf20Sopenharmony_ci		ret = -ENOENT;
9948c2ecf20Sopenharmony_ci		goto out;
9958c2ecf20Sopenharmony_ci	}
9968c2ecf20Sopenharmony_ci
9978c2ecf20Sopenharmony_ci	res->dl_leaf_bh = dir_ent_bh;
9988c2ecf20Sopenharmony_ci	res->dl_entry = dir_ent;
9998c2ecf20Sopenharmony_ci	res->dl_dx_leaf_bh = dx_leaf_bh;
10008c2ecf20Sopenharmony_ci	res->dl_dx_entry = dx_entry;
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	ret = 0;
10038c2ecf20Sopenharmony_ciout:
10048c2ecf20Sopenharmony_ci	if (ret) {
10058c2ecf20Sopenharmony_ci		brelse(dx_leaf_bh);
10068c2ecf20Sopenharmony_ci		brelse(dir_ent_bh);
10078c2ecf20Sopenharmony_ci	}
10088c2ecf20Sopenharmony_ci	return ret;
10098c2ecf20Sopenharmony_ci}
10108c2ecf20Sopenharmony_ci
10118c2ecf20Sopenharmony_cistatic int ocfs2_find_entry_dx(const char *name, int namelen,
10128c2ecf20Sopenharmony_ci			       struct inode *dir,
10138c2ecf20Sopenharmony_ci			       struct ocfs2_dir_lookup_result *lookup)
10148c2ecf20Sopenharmony_ci{
10158c2ecf20Sopenharmony_ci	int ret;
10168c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
10178c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di;
10188c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
10198c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
10208c2ecf20Sopenharmony_ci
10218c2ecf20Sopenharmony_ci	ret = ocfs2_read_inode_block(dir, &di_bh);
10228c2ecf20Sopenharmony_ci	if (ret) {
10238c2ecf20Sopenharmony_ci		mlog_errno(ret);
10248c2ecf20Sopenharmony_ci		goto out;
10258c2ecf20Sopenharmony_ci	}
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
10288c2ecf20Sopenharmony_ci
10298c2ecf20Sopenharmony_ci	ret = ocfs2_read_dx_root(dir, di, &dx_root_bh);
10308c2ecf20Sopenharmony_ci	if (ret) {
10318c2ecf20Sopenharmony_ci		mlog_errno(ret);
10328c2ecf20Sopenharmony_ci		goto out;
10338c2ecf20Sopenharmony_ci	}
10348c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
10358c2ecf20Sopenharmony_ci
10368c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_search(name, namelen, dir, dx_root, lookup);
10378c2ecf20Sopenharmony_ci	if (ret) {
10388c2ecf20Sopenharmony_ci		if (ret != -ENOENT)
10398c2ecf20Sopenharmony_ci			mlog_errno(ret);
10408c2ecf20Sopenharmony_ci		goto out;
10418c2ecf20Sopenharmony_ci	}
10428c2ecf20Sopenharmony_ci
10438c2ecf20Sopenharmony_ci	lookup->dl_dx_root_bh = dx_root_bh;
10448c2ecf20Sopenharmony_ci	dx_root_bh = NULL;
10458c2ecf20Sopenharmony_ciout:
10468c2ecf20Sopenharmony_ci	brelse(di_bh);
10478c2ecf20Sopenharmony_ci	brelse(dx_root_bh);
10488c2ecf20Sopenharmony_ci	return ret;
10498c2ecf20Sopenharmony_ci}
10508c2ecf20Sopenharmony_ci
10518c2ecf20Sopenharmony_ci/*
10528c2ecf20Sopenharmony_ci * Try to find an entry of the provided name within 'dir'.
10538c2ecf20Sopenharmony_ci *
10548c2ecf20Sopenharmony_ci * If nothing was found, -ENOENT is returned. Otherwise, zero is
10558c2ecf20Sopenharmony_ci * returned and the struct 'res' will contain information useful to
10568c2ecf20Sopenharmony_ci * other directory manipulation functions.
10578c2ecf20Sopenharmony_ci *
10588c2ecf20Sopenharmony_ci * Caller can NOT assume anything about the contents of the
10598c2ecf20Sopenharmony_ci * buffer_heads - they are passed back only so that it can be passed
10608c2ecf20Sopenharmony_ci * into any one of the manipulation functions (add entry, delete
10618c2ecf20Sopenharmony_ci * entry, etc). As an example, bh in the extent directory case is a
10628c2ecf20Sopenharmony_ci * data block, in the inline-data case it actually points to an inode,
10638c2ecf20Sopenharmony_ci * in the indexed directory case, multiple buffers are involved.
10648c2ecf20Sopenharmony_ci */
10658c2ecf20Sopenharmony_ciint ocfs2_find_entry(const char *name, int namelen,
10668c2ecf20Sopenharmony_ci		     struct inode *dir, struct ocfs2_dir_lookup_result *lookup)
10678c2ecf20Sopenharmony_ci{
10688c2ecf20Sopenharmony_ci	struct buffer_head *bh;
10698c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *res_dir = NULL;
10708c2ecf20Sopenharmony_ci
10718c2ecf20Sopenharmony_ci	if (ocfs2_dir_indexed(dir))
10728c2ecf20Sopenharmony_ci		return ocfs2_find_entry_dx(name, namelen, dir, lookup);
10738c2ecf20Sopenharmony_ci
10748c2ecf20Sopenharmony_ci	/*
10758c2ecf20Sopenharmony_ci	 * The unindexed dir code only uses part of the lookup
10768c2ecf20Sopenharmony_ci	 * structure, so there's no reason to push it down further
10778c2ecf20Sopenharmony_ci	 * than this.
10788c2ecf20Sopenharmony_ci	 */
10798c2ecf20Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
10808c2ecf20Sopenharmony_ci		bh = ocfs2_find_entry_id(name, namelen, dir, &res_dir);
10818c2ecf20Sopenharmony_ci	else
10828c2ecf20Sopenharmony_ci		bh = ocfs2_find_entry_el(name, namelen, dir, &res_dir);
10838c2ecf20Sopenharmony_ci
10848c2ecf20Sopenharmony_ci	if (bh == NULL)
10858c2ecf20Sopenharmony_ci		return -ENOENT;
10868c2ecf20Sopenharmony_ci
10878c2ecf20Sopenharmony_ci	lookup->dl_leaf_bh = bh;
10888c2ecf20Sopenharmony_ci	lookup->dl_entry = res_dir;
10898c2ecf20Sopenharmony_ci	return 0;
10908c2ecf20Sopenharmony_ci}
10918c2ecf20Sopenharmony_ci
10928c2ecf20Sopenharmony_ci/*
10938c2ecf20Sopenharmony_ci * Update inode number and type of a previously found directory entry.
10948c2ecf20Sopenharmony_ci */
10958c2ecf20Sopenharmony_ciint ocfs2_update_entry(struct inode *dir, handle_t *handle,
10968c2ecf20Sopenharmony_ci		       struct ocfs2_dir_lookup_result *res,
10978c2ecf20Sopenharmony_ci		       struct inode *new_entry_inode)
10988c2ecf20Sopenharmony_ci{
10998c2ecf20Sopenharmony_ci	int ret;
11008c2ecf20Sopenharmony_ci	ocfs2_journal_access_func access = ocfs2_journal_access_db;
11018c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de = res->dl_entry;
11028c2ecf20Sopenharmony_ci	struct buffer_head *de_bh = res->dl_leaf_bh;
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	/*
11058c2ecf20Sopenharmony_ci	 * The same code works fine for both inline-data and extent
11068c2ecf20Sopenharmony_ci	 * based directories, so no need to split this up.  The only
11078c2ecf20Sopenharmony_ci	 * difference is the journal_access function.
11088c2ecf20Sopenharmony_ci	 */
11098c2ecf20Sopenharmony_ci
11108c2ecf20Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
11118c2ecf20Sopenharmony_ci		access = ocfs2_journal_access_di;
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	ret = access(handle, INODE_CACHE(dir), de_bh,
11148c2ecf20Sopenharmony_ci		     OCFS2_JOURNAL_ACCESS_WRITE);
11158c2ecf20Sopenharmony_ci	if (ret) {
11168c2ecf20Sopenharmony_ci		mlog_errno(ret);
11178c2ecf20Sopenharmony_ci		goto out;
11188c2ecf20Sopenharmony_ci	}
11198c2ecf20Sopenharmony_ci
11208c2ecf20Sopenharmony_ci	de->inode = cpu_to_le64(OCFS2_I(new_entry_inode)->ip_blkno);
11218c2ecf20Sopenharmony_ci	ocfs2_set_de_type(de, new_entry_inode->i_mode);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, de_bh);
11248c2ecf20Sopenharmony_ci
11258c2ecf20Sopenharmony_ciout:
11268c2ecf20Sopenharmony_ci	return ret;
11278c2ecf20Sopenharmony_ci}
11288c2ecf20Sopenharmony_ci
11298c2ecf20Sopenharmony_ci/*
11308c2ecf20Sopenharmony_ci * __ocfs2_delete_entry deletes a directory entry by merging it with the
11318c2ecf20Sopenharmony_ci * previous entry
11328c2ecf20Sopenharmony_ci */
11338c2ecf20Sopenharmony_cistatic int __ocfs2_delete_entry(handle_t *handle, struct inode *dir,
11348c2ecf20Sopenharmony_ci				struct ocfs2_dir_entry *de_del,
11358c2ecf20Sopenharmony_ci				struct buffer_head *bh, char *first_de,
11368c2ecf20Sopenharmony_ci				unsigned int bytes)
11378c2ecf20Sopenharmony_ci{
11388c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de, *pde;
11398c2ecf20Sopenharmony_ci	int i, status = -ENOENT;
11408c2ecf20Sopenharmony_ci	ocfs2_journal_access_func access = ocfs2_journal_access_db;
11418c2ecf20Sopenharmony_ci
11428c2ecf20Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
11438c2ecf20Sopenharmony_ci		access = ocfs2_journal_access_di;
11448c2ecf20Sopenharmony_ci
11458c2ecf20Sopenharmony_ci	i = 0;
11468c2ecf20Sopenharmony_ci	pde = NULL;
11478c2ecf20Sopenharmony_ci	de = (struct ocfs2_dir_entry *) first_de;
11488c2ecf20Sopenharmony_ci	while (i < bytes) {
11498c2ecf20Sopenharmony_ci		if (!ocfs2_check_dir_entry(dir, de, bh, first_de, bytes, i)) {
11508c2ecf20Sopenharmony_ci			status = -EIO;
11518c2ecf20Sopenharmony_ci			mlog_errno(status);
11528c2ecf20Sopenharmony_ci			goto bail;
11538c2ecf20Sopenharmony_ci		}
11548c2ecf20Sopenharmony_ci		if (de == de_del)  {
11558c2ecf20Sopenharmony_ci			status = access(handle, INODE_CACHE(dir), bh,
11568c2ecf20Sopenharmony_ci					OCFS2_JOURNAL_ACCESS_WRITE);
11578c2ecf20Sopenharmony_ci			if (status < 0) {
11588c2ecf20Sopenharmony_ci				status = -EIO;
11598c2ecf20Sopenharmony_ci				mlog_errno(status);
11608c2ecf20Sopenharmony_ci				goto bail;
11618c2ecf20Sopenharmony_ci			}
11628c2ecf20Sopenharmony_ci			if (pde)
11638c2ecf20Sopenharmony_ci				le16_add_cpu(&pde->rec_len,
11648c2ecf20Sopenharmony_ci						le16_to_cpu(de->rec_len));
11658c2ecf20Sopenharmony_ci			de->inode = 0;
11668c2ecf20Sopenharmony_ci			inode_inc_iversion(dir);
11678c2ecf20Sopenharmony_ci			ocfs2_journal_dirty(handle, bh);
11688c2ecf20Sopenharmony_ci			goto bail;
11698c2ecf20Sopenharmony_ci		}
11708c2ecf20Sopenharmony_ci		i += le16_to_cpu(de->rec_len);
11718c2ecf20Sopenharmony_ci		pde = de;
11728c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *)((char *)de + le16_to_cpu(de->rec_len));
11738c2ecf20Sopenharmony_ci	}
11748c2ecf20Sopenharmony_cibail:
11758c2ecf20Sopenharmony_ci	return status;
11768c2ecf20Sopenharmony_ci}
11778c2ecf20Sopenharmony_ci
11788c2ecf20Sopenharmony_cistatic unsigned int ocfs2_figure_dirent_hole(struct ocfs2_dir_entry *de)
11798c2ecf20Sopenharmony_ci{
11808c2ecf20Sopenharmony_ci	unsigned int hole;
11818c2ecf20Sopenharmony_ci
11828c2ecf20Sopenharmony_ci	if (le64_to_cpu(de->inode) == 0)
11838c2ecf20Sopenharmony_ci		hole = le16_to_cpu(de->rec_len);
11848c2ecf20Sopenharmony_ci	else
11858c2ecf20Sopenharmony_ci		hole = le16_to_cpu(de->rec_len) -
11868c2ecf20Sopenharmony_ci			OCFS2_DIR_REC_LEN(de->name_len);
11878c2ecf20Sopenharmony_ci
11888c2ecf20Sopenharmony_ci	return hole;
11898c2ecf20Sopenharmony_ci}
11908c2ecf20Sopenharmony_ci
11918c2ecf20Sopenharmony_cistatic int ocfs2_find_max_rec_len(struct super_block *sb,
11928c2ecf20Sopenharmony_ci				  struct buffer_head *dirblock_bh)
11938c2ecf20Sopenharmony_ci{
11948c2ecf20Sopenharmony_ci	int size, this_hole, largest_hole = 0;
11958c2ecf20Sopenharmony_ci	char *trailer, *de_buf, *limit, *start = dirblock_bh->b_data;
11968c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
11978c2ecf20Sopenharmony_ci
11988c2ecf20Sopenharmony_ci	trailer = (char *)ocfs2_trailer_from_bh(dirblock_bh, sb);
11998c2ecf20Sopenharmony_ci	size = ocfs2_dir_trailer_blk_off(sb);
12008c2ecf20Sopenharmony_ci	limit = start + size;
12018c2ecf20Sopenharmony_ci	de_buf = start;
12028c2ecf20Sopenharmony_ci	de = (struct ocfs2_dir_entry *)de_buf;
12038c2ecf20Sopenharmony_ci	do {
12048c2ecf20Sopenharmony_ci		if (de_buf != trailer) {
12058c2ecf20Sopenharmony_ci			this_hole = ocfs2_figure_dirent_hole(de);
12068c2ecf20Sopenharmony_ci			if (this_hole > largest_hole)
12078c2ecf20Sopenharmony_ci				largest_hole = this_hole;
12088c2ecf20Sopenharmony_ci		}
12098c2ecf20Sopenharmony_ci
12108c2ecf20Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
12118c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
12128c2ecf20Sopenharmony_ci	} while (de_buf < limit);
12138c2ecf20Sopenharmony_ci
12148c2ecf20Sopenharmony_ci	if (largest_hole >= OCFS2_DIR_MIN_REC_LEN)
12158c2ecf20Sopenharmony_ci		return largest_hole;
12168c2ecf20Sopenharmony_ci	return 0;
12178c2ecf20Sopenharmony_ci}
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_cistatic void ocfs2_dx_list_remove_entry(struct ocfs2_dx_entry_list *entry_list,
12208c2ecf20Sopenharmony_ci				       int index)
12218c2ecf20Sopenharmony_ci{
12228c2ecf20Sopenharmony_ci	int num_used = le16_to_cpu(entry_list->de_num_used);
12238c2ecf20Sopenharmony_ci
12248c2ecf20Sopenharmony_ci	if (num_used == 1 || index == (num_used - 1))
12258c2ecf20Sopenharmony_ci		goto clear;
12268c2ecf20Sopenharmony_ci
12278c2ecf20Sopenharmony_ci	memmove(&entry_list->de_entries[index],
12288c2ecf20Sopenharmony_ci		&entry_list->de_entries[index + 1],
12298c2ecf20Sopenharmony_ci		(num_used - index - 1)*sizeof(struct ocfs2_dx_entry));
12308c2ecf20Sopenharmony_ciclear:
12318c2ecf20Sopenharmony_ci	num_used--;
12328c2ecf20Sopenharmony_ci	memset(&entry_list->de_entries[num_used], 0,
12338c2ecf20Sopenharmony_ci	       sizeof(struct ocfs2_dx_entry));
12348c2ecf20Sopenharmony_ci	entry_list->de_num_used = cpu_to_le16(num_used);
12358c2ecf20Sopenharmony_ci}
12368c2ecf20Sopenharmony_ci
12378c2ecf20Sopenharmony_cistatic int ocfs2_delete_entry_dx(handle_t *handle, struct inode *dir,
12388c2ecf20Sopenharmony_ci				 struct ocfs2_dir_lookup_result *lookup)
12398c2ecf20Sopenharmony_ci{
12408c2ecf20Sopenharmony_ci	int ret, index, max_rec_len, add_to_free_list = 0;
12418c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
12428c2ecf20Sopenharmony_ci	struct buffer_head *leaf_bh = lookup->dl_leaf_bh;
12438c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
12448c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry = lookup->dl_dx_entry;
12458c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
12468c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
12478c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	/*
12508c2ecf20Sopenharmony_ci	 * This function gets a bit messy because we might have to
12518c2ecf20Sopenharmony_ci	 * modify the root block, regardless of whether the indexed
12528c2ecf20Sopenharmony_ci	 * entries are stored inline.
12538c2ecf20Sopenharmony_ci	 */
12548c2ecf20Sopenharmony_ci
12558c2ecf20Sopenharmony_ci	/*
12568c2ecf20Sopenharmony_ci	 * *Only* set 'entry_list' here, based on where we're looking
12578c2ecf20Sopenharmony_ci	 * for the indexed entries. Later, we might still want to
12588c2ecf20Sopenharmony_ci	 * journal both blocks, based on free list state.
12598c2ecf20Sopenharmony_ci	 */
12608c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
12618c2ecf20Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root)) {
12628c2ecf20Sopenharmony_ci		entry_list = &dx_root->dr_entries;
12638c2ecf20Sopenharmony_ci	} else {
12648c2ecf20Sopenharmony_ci		dx_leaf = (struct ocfs2_dx_leaf *) lookup->dl_dx_leaf_bh->b_data;
12658c2ecf20Sopenharmony_ci		entry_list = &dx_leaf->dl_list;
12668c2ecf20Sopenharmony_ci	}
12678c2ecf20Sopenharmony_ci
12688c2ecf20Sopenharmony_ci	/* Neither of these are a disk corruption - that should have
12698c2ecf20Sopenharmony_ci	 * been caught by lookup, before we got here. */
12708c2ecf20Sopenharmony_ci	BUG_ON(le16_to_cpu(entry_list->de_count) <= 0);
12718c2ecf20Sopenharmony_ci	BUG_ON(le16_to_cpu(entry_list->de_num_used) <= 0);
12728c2ecf20Sopenharmony_ci
12738c2ecf20Sopenharmony_ci	index = (char *)dx_entry - (char *)entry_list->de_entries;
12748c2ecf20Sopenharmony_ci	index /= sizeof(*dx_entry);
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci	if (index >= le16_to_cpu(entry_list->de_num_used)) {
12778c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "Dir %llu: Bad dx_entry ptr idx %d, (%p, %p)\n",
12788c2ecf20Sopenharmony_ci		     (unsigned long long)OCFS2_I(dir)->ip_blkno, index,
12798c2ecf20Sopenharmony_ci		     entry_list, dx_entry);
12808c2ecf20Sopenharmony_ci		return -EIO;
12818c2ecf20Sopenharmony_ci	}
12828c2ecf20Sopenharmony_ci
12838c2ecf20Sopenharmony_ci	/*
12848c2ecf20Sopenharmony_ci	 * We know that removal of this dirent will leave enough room
12858c2ecf20Sopenharmony_ci	 * for a new one, so add this block to the free list if it
12868c2ecf20Sopenharmony_ci	 * isn't already there.
12878c2ecf20Sopenharmony_ci	 */
12888c2ecf20Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(leaf_bh, dir->i_sb);
12898c2ecf20Sopenharmony_ci	if (trailer->db_free_rec_len == 0)
12908c2ecf20Sopenharmony_ci		add_to_free_list = 1;
12918c2ecf20Sopenharmony_ci
12928c2ecf20Sopenharmony_ci	/*
12938c2ecf20Sopenharmony_ci	 * Add the block holding our index into the journal before
12948c2ecf20Sopenharmony_ci	 * removing the unindexed entry. If we get an error return
12958c2ecf20Sopenharmony_ci	 * from __ocfs2_delete_entry(), then it hasn't removed the
12968c2ecf20Sopenharmony_ci	 * entry yet. Likewise, successful return means we *must*
12978c2ecf20Sopenharmony_ci	 * remove the indexed entry.
12988c2ecf20Sopenharmony_ci	 *
12998c2ecf20Sopenharmony_ci	 * We're also careful to journal the root tree block here as
13008c2ecf20Sopenharmony_ci	 * the entry count needs to be updated. Also, we might be
13018c2ecf20Sopenharmony_ci	 * adding to the start of the free list.
13028c2ecf20Sopenharmony_ci	 */
13038c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
13048c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
13058c2ecf20Sopenharmony_ci	if (ret) {
13068c2ecf20Sopenharmony_ci		mlog_errno(ret);
13078c2ecf20Sopenharmony_ci		goto out;
13088c2ecf20Sopenharmony_ci	}
13098c2ecf20Sopenharmony_ci
13108c2ecf20Sopenharmony_ci	if (!ocfs2_dx_root_inline(dx_root)) {
13118c2ecf20Sopenharmony_ci		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
13128c2ecf20Sopenharmony_ci					      lookup->dl_dx_leaf_bh,
13138c2ecf20Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_WRITE);
13148c2ecf20Sopenharmony_ci		if (ret) {
13158c2ecf20Sopenharmony_ci			mlog_errno(ret);
13168c2ecf20Sopenharmony_ci			goto out;
13178c2ecf20Sopenharmony_ci		}
13188c2ecf20Sopenharmony_ci	}
13198c2ecf20Sopenharmony_ci
13208c2ecf20Sopenharmony_ci	trace_ocfs2_delete_entry_dx((unsigned long long)OCFS2_I(dir)->ip_blkno,
13218c2ecf20Sopenharmony_ci				    index);
13228c2ecf20Sopenharmony_ci
13238c2ecf20Sopenharmony_ci	ret = __ocfs2_delete_entry(handle, dir, lookup->dl_entry,
13248c2ecf20Sopenharmony_ci				   leaf_bh, leaf_bh->b_data, leaf_bh->b_size);
13258c2ecf20Sopenharmony_ci	if (ret) {
13268c2ecf20Sopenharmony_ci		mlog_errno(ret);
13278c2ecf20Sopenharmony_ci		goto out;
13288c2ecf20Sopenharmony_ci	}
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	max_rec_len = ocfs2_find_max_rec_len(dir->i_sb, leaf_bh);
13318c2ecf20Sopenharmony_ci	trailer->db_free_rec_len = cpu_to_le16(max_rec_len);
13328c2ecf20Sopenharmony_ci	if (add_to_free_list) {
13338c2ecf20Sopenharmony_ci		trailer->db_free_next = dx_root->dr_free_blk;
13348c2ecf20Sopenharmony_ci		dx_root->dr_free_blk = cpu_to_le64(leaf_bh->b_blocknr);
13358c2ecf20Sopenharmony_ci		ocfs2_journal_dirty(handle, dx_root_bh);
13368c2ecf20Sopenharmony_ci	}
13378c2ecf20Sopenharmony_ci
13388c2ecf20Sopenharmony_ci	/* leaf_bh was journal_accessed for us in __ocfs2_delete_entry */
13398c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, leaf_bh);
13408c2ecf20Sopenharmony_ci
13418c2ecf20Sopenharmony_ci	le32_add_cpu(&dx_root->dr_num_entries, -1);
13428c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
13438c2ecf20Sopenharmony_ci
13448c2ecf20Sopenharmony_ci	ocfs2_dx_list_remove_entry(entry_list, index);
13458c2ecf20Sopenharmony_ci
13468c2ecf20Sopenharmony_ci	if (!ocfs2_dx_root_inline(dx_root))
13478c2ecf20Sopenharmony_ci		ocfs2_journal_dirty(handle, lookup->dl_dx_leaf_bh);
13488c2ecf20Sopenharmony_ci
13498c2ecf20Sopenharmony_ciout:
13508c2ecf20Sopenharmony_ci	return ret;
13518c2ecf20Sopenharmony_ci}
13528c2ecf20Sopenharmony_ci
13538c2ecf20Sopenharmony_cistatic inline int ocfs2_delete_entry_id(handle_t *handle,
13548c2ecf20Sopenharmony_ci					struct inode *dir,
13558c2ecf20Sopenharmony_ci					struct ocfs2_dir_entry *de_del,
13568c2ecf20Sopenharmony_ci					struct buffer_head *bh)
13578c2ecf20Sopenharmony_ci{
13588c2ecf20Sopenharmony_ci	int ret;
13598c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
13608c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di;
13618c2ecf20Sopenharmony_ci	struct ocfs2_inline_data *data;
13628c2ecf20Sopenharmony_ci
13638c2ecf20Sopenharmony_ci	ret = ocfs2_read_inode_block(dir, &di_bh);
13648c2ecf20Sopenharmony_ci	if (ret) {
13658c2ecf20Sopenharmony_ci		mlog_errno(ret);
13668c2ecf20Sopenharmony_ci		goto out;
13678c2ecf20Sopenharmony_ci	}
13688c2ecf20Sopenharmony_ci
13698c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
13708c2ecf20Sopenharmony_ci	data = &di->id2.i_data;
13718c2ecf20Sopenharmony_ci
13728c2ecf20Sopenharmony_ci	ret = __ocfs2_delete_entry(handle, dir, de_del, bh, data->id_data,
13738c2ecf20Sopenharmony_ci				   i_size_read(dir));
13748c2ecf20Sopenharmony_ci
13758c2ecf20Sopenharmony_ci	brelse(di_bh);
13768c2ecf20Sopenharmony_ciout:
13778c2ecf20Sopenharmony_ci	return ret;
13788c2ecf20Sopenharmony_ci}
13798c2ecf20Sopenharmony_ci
13808c2ecf20Sopenharmony_cistatic inline int ocfs2_delete_entry_el(handle_t *handle,
13818c2ecf20Sopenharmony_ci					struct inode *dir,
13828c2ecf20Sopenharmony_ci					struct ocfs2_dir_entry *de_del,
13838c2ecf20Sopenharmony_ci					struct buffer_head *bh)
13848c2ecf20Sopenharmony_ci{
13858c2ecf20Sopenharmony_ci	return __ocfs2_delete_entry(handle, dir, de_del, bh, bh->b_data,
13868c2ecf20Sopenharmony_ci				    bh->b_size);
13878c2ecf20Sopenharmony_ci}
13888c2ecf20Sopenharmony_ci
13898c2ecf20Sopenharmony_ci/*
13908c2ecf20Sopenharmony_ci * Delete a directory entry. Hide the details of directory
13918c2ecf20Sopenharmony_ci * implementation from the caller.
13928c2ecf20Sopenharmony_ci */
13938c2ecf20Sopenharmony_ciint ocfs2_delete_entry(handle_t *handle,
13948c2ecf20Sopenharmony_ci		       struct inode *dir,
13958c2ecf20Sopenharmony_ci		       struct ocfs2_dir_lookup_result *res)
13968c2ecf20Sopenharmony_ci{
13978c2ecf20Sopenharmony_ci	if (ocfs2_dir_indexed(dir))
13988c2ecf20Sopenharmony_ci		return ocfs2_delete_entry_dx(handle, dir, res);
13998c2ecf20Sopenharmony_ci
14008c2ecf20Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
14018c2ecf20Sopenharmony_ci		return ocfs2_delete_entry_id(handle, dir, res->dl_entry,
14028c2ecf20Sopenharmony_ci					     res->dl_leaf_bh);
14038c2ecf20Sopenharmony_ci
14048c2ecf20Sopenharmony_ci	return ocfs2_delete_entry_el(handle, dir, res->dl_entry,
14058c2ecf20Sopenharmony_ci				     res->dl_leaf_bh);
14068c2ecf20Sopenharmony_ci}
14078c2ecf20Sopenharmony_ci
14088c2ecf20Sopenharmony_ci/*
14098c2ecf20Sopenharmony_ci * Check whether 'de' has enough room to hold an entry of
14108c2ecf20Sopenharmony_ci * 'new_rec_len' bytes.
14118c2ecf20Sopenharmony_ci */
14128c2ecf20Sopenharmony_cistatic inline int ocfs2_dirent_would_fit(struct ocfs2_dir_entry *de,
14138c2ecf20Sopenharmony_ci					 unsigned int new_rec_len)
14148c2ecf20Sopenharmony_ci{
14158c2ecf20Sopenharmony_ci	unsigned int de_really_used;
14168c2ecf20Sopenharmony_ci
14178c2ecf20Sopenharmony_ci	/* Check whether this is an empty record with enough space */
14188c2ecf20Sopenharmony_ci	if (le64_to_cpu(de->inode) == 0 &&
14198c2ecf20Sopenharmony_ci	    le16_to_cpu(de->rec_len) >= new_rec_len)
14208c2ecf20Sopenharmony_ci		return 1;
14218c2ecf20Sopenharmony_ci
14228c2ecf20Sopenharmony_ci	/*
14238c2ecf20Sopenharmony_ci	 * Record might have free space at the end which we can
14248c2ecf20Sopenharmony_ci	 * use.
14258c2ecf20Sopenharmony_ci	 */
14268c2ecf20Sopenharmony_ci	de_really_used = OCFS2_DIR_REC_LEN(de->name_len);
14278c2ecf20Sopenharmony_ci	if (le16_to_cpu(de->rec_len) >= (de_really_used + new_rec_len))
14288c2ecf20Sopenharmony_ci	    return 1;
14298c2ecf20Sopenharmony_ci
14308c2ecf20Sopenharmony_ci	return 0;
14318c2ecf20Sopenharmony_ci}
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_cistatic void ocfs2_dx_dir_leaf_insert_tail(struct ocfs2_dx_leaf *dx_leaf,
14348c2ecf20Sopenharmony_ci					  struct ocfs2_dx_entry *dx_new_entry)
14358c2ecf20Sopenharmony_ci{
14368c2ecf20Sopenharmony_ci	int i;
14378c2ecf20Sopenharmony_ci
14388c2ecf20Sopenharmony_ci	i = le16_to_cpu(dx_leaf->dl_list.de_num_used);
14398c2ecf20Sopenharmony_ci	dx_leaf->dl_list.de_entries[i] = *dx_new_entry;
14408c2ecf20Sopenharmony_ci
14418c2ecf20Sopenharmony_ci	le16_add_cpu(&dx_leaf->dl_list.de_num_used, 1);
14428c2ecf20Sopenharmony_ci}
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_cistatic void ocfs2_dx_entry_list_insert(struct ocfs2_dx_entry_list *entry_list,
14458c2ecf20Sopenharmony_ci				       struct ocfs2_dx_hinfo *hinfo,
14468c2ecf20Sopenharmony_ci				       u64 dirent_blk)
14478c2ecf20Sopenharmony_ci{
14488c2ecf20Sopenharmony_ci	int i;
14498c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry;
14508c2ecf20Sopenharmony_ci
14518c2ecf20Sopenharmony_ci	i = le16_to_cpu(entry_list->de_num_used);
14528c2ecf20Sopenharmony_ci	dx_entry = &entry_list->de_entries[i];
14538c2ecf20Sopenharmony_ci
14548c2ecf20Sopenharmony_ci	memset(dx_entry, 0, sizeof(*dx_entry));
14558c2ecf20Sopenharmony_ci	dx_entry->dx_major_hash = cpu_to_le32(hinfo->major_hash);
14568c2ecf20Sopenharmony_ci	dx_entry->dx_minor_hash = cpu_to_le32(hinfo->minor_hash);
14578c2ecf20Sopenharmony_ci	dx_entry->dx_dirent_blk = cpu_to_le64(dirent_blk);
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci	le16_add_cpu(&entry_list->de_num_used, 1);
14608c2ecf20Sopenharmony_ci}
14618c2ecf20Sopenharmony_ci
14628c2ecf20Sopenharmony_cistatic int __ocfs2_dx_dir_leaf_insert(struct inode *dir, handle_t *handle,
14638c2ecf20Sopenharmony_ci				      struct ocfs2_dx_hinfo *hinfo,
14648c2ecf20Sopenharmony_ci				      u64 dirent_blk,
14658c2ecf20Sopenharmony_ci				      struct buffer_head *dx_leaf_bh)
14668c2ecf20Sopenharmony_ci{
14678c2ecf20Sopenharmony_ci	int ret;
14688c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
14698c2ecf20Sopenharmony_ci
14708c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
14718c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
14728c2ecf20Sopenharmony_ci	if (ret) {
14738c2ecf20Sopenharmony_ci		mlog_errno(ret);
14748c2ecf20Sopenharmony_ci		goto out;
14758c2ecf20Sopenharmony_ci	}
14768c2ecf20Sopenharmony_ci
14778c2ecf20Sopenharmony_ci	dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_bh->b_data;
14788c2ecf20Sopenharmony_ci	ocfs2_dx_entry_list_insert(&dx_leaf->dl_list, hinfo, dirent_blk);
14798c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_leaf_bh);
14808c2ecf20Sopenharmony_ci
14818c2ecf20Sopenharmony_ciout:
14828c2ecf20Sopenharmony_ci	return ret;
14838c2ecf20Sopenharmony_ci}
14848c2ecf20Sopenharmony_ci
14858c2ecf20Sopenharmony_cistatic void ocfs2_dx_inline_root_insert(struct inode *dir, handle_t *handle,
14868c2ecf20Sopenharmony_ci					struct ocfs2_dx_hinfo *hinfo,
14878c2ecf20Sopenharmony_ci					u64 dirent_blk,
14888c2ecf20Sopenharmony_ci					struct ocfs2_dx_root_block *dx_root)
14898c2ecf20Sopenharmony_ci{
14908c2ecf20Sopenharmony_ci	ocfs2_dx_entry_list_insert(&dx_root->dr_entries, hinfo, dirent_blk);
14918c2ecf20Sopenharmony_ci}
14928c2ecf20Sopenharmony_ci
14938c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_insert(struct inode *dir, handle_t *handle,
14948c2ecf20Sopenharmony_ci			       struct ocfs2_dir_lookup_result *lookup)
14958c2ecf20Sopenharmony_ci{
14968c2ecf20Sopenharmony_ci	int ret = 0;
14978c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
14988c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
14998c2ecf20Sopenharmony_ci
15008c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
15018c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
15028c2ecf20Sopenharmony_ci	if (ret) {
15038c2ecf20Sopenharmony_ci		mlog_errno(ret);
15048c2ecf20Sopenharmony_ci		goto out;
15058c2ecf20Sopenharmony_ci	}
15068c2ecf20Sopenharmony_ci
15078c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)lookup->dl_dx_root_bh->b_data;
15088c2ecf20Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root)) {
15098c2ecf20Sopenharmony_ci		ocfs2_dx_inline_root_insert(dir, handle,
15108c2ecf20Sopenharmony_ci					    &lookup->dl_hinfo,
15118c2ecf20Sopenharmony_ci					    lookup->dl_leaf_bh->b_blocknr,
15128c2ecf20Sopenharmony_ci					    dx_root);
15138c2ecf20Sopenharmony_ci	} else {
15148c2ecf20Sopenharmony_ci		ret = __ocfs2_dx_dir_leaf_insert(dir, handle, &lookup->dl_hinfo,
15158c2ecf20Sopenharmony_ci						 lookup->dl_leaf_bh->b_blocknr,
15168c2ecf20Sopenharmony_ci						 lookup->dl_dx_leaf_bh);
15178c2ecf20Sopenharmony_ci		if (ret)
15188c2ecf20Sopenharmony_ci			goto out;
15198c2ecf20Sopenharmony_ci	}
15208c2ecf20Sopenharmony_ci
15218c2ecf20Sopenharmony_ci	le32_add_cpu(&dx_root->dr_num_entries, 1);
15228c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
15238c2ecf20Sopenharmony_ci
15248c2ecf20Sopenharmony_ciout:
15258c2ecf20Sopenharmony_ci	return ret;
15268c2ecf20Sopenharmony_ci}
15278c2ecf20Sopenharmony_ci
15288c2ecf20Sopenharmony_cistatic void ocfs2_remove_block_from_free_list(struct inode *dir,
15298c2ecf20Sopenharmony_ci				       handle_t *handle,
15308c2ecf20Sopenharmony_ci				       struct ocfs2_dir_lookup_result *lookup)
15318c2ecf20Sopenharmony_ci{
15328c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer, *prev;
15338c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
15348c2ecf20Sopenharmony_ci	struct buffer_head *bh;
15358c2ecf20Sopenharmony_ci
15368c2ecf20Sopenharmony_ci	trailer = ocfs2_trailer_from_bh(lookup->dl_leaf_bh, dir->i_sb);
15378c2ecf20Sopenharmony_ci
15388c2ecf20Sopenharmony_ci	if (ocfs2_free_list_at_root(lookup)) {
15398c2ecf20Sopenharmony_ci		bh = lookup->dl_dx_root_bh;
15408c2ecf20Sopenharmony_ci		dx_root = (struct ocfs2_dx_root_block *)bh->b_data;
15418c2ecf20Sopenharmony_ci		dx_root->dr_free_blk = trailer->db_free_next;
15428c2ecf20Sopenharmony_ci	} else {
15438c2ecf20Sopenharmony_ci		bh = lookup->dl_prev_leaf_bh;
15448c2ecf20Sopenharmony_ci		prev = ocfs2_trailer_from_bh(bh, dir->i_sb);
15458c2ecf20Sopenharmony_ci		prev->db_free_next = trailer->db_free_next;
15468c2ecf20Sopenharmony_ci	}
15478c2ecf20Sopenharmony_ci
15488c2ecf20Sopenharmony_ci	trailer->db_free_rec_len = cpu_to_le16(0);
15498c2ecf20Sopenharmony_ci	trailer->db_free_next = cpu_to_le64(0);
15508c2ecf20Sopenharmony_ci
15518c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, bh);
15528c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, lookup->dl_leaf_bh);
15538c2ecf20Sopenharmony_ci}
15548c2ecf20Sopenharmony_ci
15558c2ecf20Sopenharmony_ci/*
15568c2ecf20Sopenharmony_ci * This expects that a journal write has been reserved on
15578c2ecf20Sopenharmony_ci * lookup->dl_prev_leaf_bh or lookup->dl_dx_root_bh
15588c2ecf20Sopenharmony_ci */
15598c2ecf20Sopenharmony_cistatic void ocfs2_recalc_free_list(struct inode *dir, handle_t *handle,
15608c2ecf20Sopenharmony_ci				   struct ocfs2_dir_lookup_result *lookup)
15618c2ecf20Sopenharmony_ci{
15628c2ecf20Sopenharmony_ci	int max_rec_len;
15638c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer;
15648c2ecf20Sopenharmony_ci
15658c2ecf20Sopenharmony_ci	/* Walk dl_leaf_bh to figure out what the new free rec_len is. */
15668c2ecf20Sopenharmony_ci	max_rec_len = ocfs2_find_max_rec_len(dir->i_sb, lookup->dl_leaf_bh);
15678c2ecf20Sopenharmony_ci	if (max_rec_len) {
15688c2ecf20Sopenharmony_ci		/*
15698c2ecf20Sopenharmony_ci		 * There's still room in this block, so no need to remove it
15708c2ecf20Sopenharmony_ci		 * from the free list. In this case, we just want to update
15718c2ecf20Sopenharmony_ci		 * the rec len accounting.
15728c2ecf20Sopenharmony_ci		 */
15738c2ecf20Sopenharmony_ci		trailer = ocfs2_trailer_from_bh(lookup->dl_leaf_bh, dir->i_sb);
15748c2ecf20Sopenharmony_ci		trailer->db_free_rec_len = cpu_to_le16(max_rec_len);
15758c2ecf20Sopenharmony_ci		ocfs2_journal_dirty(handle, lookup->dl_leaf_bh);
15768c2ecf20Sopenharmony_ci	} else {
15778c2ecf20Sopenharmony_ci		ocfs2_remove_block_from_free_list(dir, handle, lookup);
15788c2ecf20Sopenharmony_ci	}
15798c2ecf20Sopenharmony_ci}
15808c2ecf20Sopenharmony_ci
15818c2ecf20Sopenharmony_ci/* we don't always have a dentry for what we want to add, so people
15828c2ecf20Sopenharmony_ci * like orphan dir can call this instead.
15838c2ecf20Sopenharmony_ci *
15848c2ecf20Sopenharmony_ci * The lookup context must have been filled from
15858c2ecf20Sopenharmony_ci * ocfs2_prepare_dir_for_insert.
15868c2ecf20Sopenharmony_ci */
15878c2ecf20Sopenharmony_ciint __ocfs2_add_entry(handle_t *handle,
15888c2ecf20Sopenharmony_ci		      struct inode *dir,
15898c2ecf20Sopenharmony_ci		      const char *name, int namelen,
15908c2ecf20Sopenharmony_ci		      struct inode *inode, u64 blkno,
15918c2ecf20Sopenharmony_ci		      struct buffer_head *parent_fe_bh,
15928c2ecf20Sopenharmony_ci		      struct ocfs2_dir_lookup_result *lookup)
15938c2ecf20Sopenharmony_ci{
15948c2ecf20Sopenharmony_ci	unsigned long offset;
15958c2ecf20Sopenharmony_ci	unsigned short rec_len;
15968c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de, *de1;
15978c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)parent_fe_bh->b_data;
15988c2ecf20Sopenharmony_ci	struct super_block *sb = dir->i_sb;
15998c2ecf20Sopenharmony_ci	int retval;
16008c2ecf20Sopenharmony_ci	unsigned int size = sb->s_blocksize;
16018c2ecf20Sopenharmony_ci	struct buffer_head *insert_bh = lookup->dl_leaf_bh;
16028c2ecf20Sopenharmony_ci	char *data_start = insert_bh->b_data;
16038c2ecf20Sopenharmony_ci
16048c2ecf20Sopenharmony_ci	if (!namelen)
16058c2ecf20Sopenharmony_ci		return -EINVAL;
16068c2ecf20Sopenharmony_ci
16078c2ecf20Sopenharmony_ci	if (ocfs2_dir_indexed(dir)) {
16088c2ecf20Sopenharmony_ci		struct buffer_head *bh;
16098c2ecf20Sopenharmony_ci
16108c2ecf20Sopenharmony_ci		/*
16118c2ecf20Sopenharmony_ci		 * An indexed dir may require that we update the free space
16128c2ecf20Sopenharmony_ci		 * list. Reserve a write to the previous node in the list so
16138c2ecf20Sopenharmony_ci		 * that we don't fail later.
16148c2ecf20Sopenharmony_ci		 *
16158c2ecf20Sopenharmony_ci		 * XXX: This can be either a dx_root_block, or an unindexed
16168c2ecf20Sopenharmony_ci		 * directory tree leaf block.
16178c2ecf20Sopenharmony_ci		 */
16188c2ecf20Sopenharmony_ci		if (ocfs2_free_list_at_root(lookup)) {
16198c2ecf20Sopenharmony_ci			bh = lookup->dl_dx_root_bh;
16208c2ecf20Sopenharmony_ci			retval = ocfs2_journal_access_dr(handle,
16218c2ecf20Sopenharmony_ci						 INODE_CACHE(dir), bh,
16228c2ecf20Sopenharmony_ci						 OCFS2_JOURNAL_ACCESS_WRITE);
16238c2ecf20Sopenharmony_ci		} else {
16248c2ecf20Sopenharmony_ci			bh = lookup->dl_prev_leaf_bh;
16258c2ecf20Sopenharmony_ci			retval = ocfs2_journal_access_db(handle,
16268c2ecf20Sopenharmony_ci						 INODE_CACHE(dir), bh,
16278c2ecf20Sopenharmony_ci						 OCFS2_JOURNAL_ACCESS_WRITE);
16288c2ecf20Sopenharmony_ci		}
16298c2ecf20Sopenharmony_ci		if (retval) {
16308c2ecf20Sopenharmony_ci			mlog_errno(retval);
16318c2ecf20Sopenharmony_ci			return retval;
16328c2ecf20Sopenharmony_ci		}
16338c2ecf20Sopenharmony_ci	} else if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
16348c2ecf20Sopenharmony_ci		data_start = di->id2.i_data.id_data;
16358c2ecf20Sopenharmony_ci		size = i_size_read(dir);
16368c2ecf20Sopenharmony_ci
16378c2ecf20Sopenharmony_ci		BUG_ON(insert_bh != parent_fe_bh);
16388c2ecf20Sopenharmony_ci	}
16398c2ecf20Sopenharmony_ci
16408c2ecf20Sopenharmony_ci	rec_len = OCFS2_DIR_REC_LEN(namelen);
16418c2ecf20Sopenharmony_ci	offset = 0;
16428c2ecf20Sopenharmony_ci	de = (struct ocfs2_dir_entry *) data_start;
16438c2ecf20Sopenharmony_ci	while (1) {
16448c2ecf20Sopenharmony_ci		BUG_ON((char *)de >= (size + data_start));
16458c2ecf20Sopenharmony_ci
16468c2ecf20Sopenharmony_ci		/* These checks should've already been passed by the
16478c2ecf20Sopenharmony_ci		 * prepare function, but I guess we can leave them
16488c2ecf20Sopenharmony_ci		 * here anyway. */
16498c2ecf20Sopenharmony_ci		if (!ocfs2_check_dir_entry(dir, de, insert_bh, data_start,
16508c2ecf20Sopenharmony_ci					   size, offset)) {
16518c2ecf20Sopenharmony_ci			retval = -ENOENT;
16528c2ecf20Sopenharmony_ci			goto bail;
16538c2ecf20Sopenharmony_ci		}
16548c2ecf20Sopenharmony_ci		if (ocfs2_match(namelen, name, de)) {
16558c2ecf20Sopenharmony_ci			retval = -EEXIST;
16568c2ecf20Sopenharmony_ci			goto bail;
16578c2ecf20Sopenharmony_ci		}
16588c2ecf20Sopenharmony_ci
16598c2ecf20Sopenharmony_ci		/* We're guaranteed that we should have space, so we
16608c2ecf20Sopenharmony_ci		 * can't possibly have hit the trailer...right? */
16618c2ecf20Sopenharmony_ci		mlog_bug_on_msg(ocfs2_skip_dir_trailer(dir, de, offset, size),
16628c2ecf20Sopenharmony_ci				"Hit dir trailer trying to insert %.*s "
16638c2ecf20Sopenharmony_ci			        "(namelen %d) into directory %llu.  "
16648c2ecf20Sopenharmony_ci				"offset is %lu, trailer offset is %d\n",
16658c2ecf20Sopenharmony_ci				namelen, name, namelen,
16668c2ecf20Sopenharmony_ci				(unsigned long long)parent_fe_bh->b_blocknr,
16678c2ecf20Sopenharmony_ci				offset, ocfs2_dir_trailer_blk_off(dir->i_sb));
16688c2ecf20Sopenharmony_ci
16698c2ecf20Sopenharmony_ci		if (ocfs2_dirent_would_fit(de, rec_len)) {
16708c2ecf20Sopenharmony_ci			dir->i_mtime = dir->i_ctime = current_time(dir);
16718c2ecf20Sopenharmony_ci			retval = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
16728c2ecf20Sopenharmony_ci			if (retval < 0) {
16738c2ecf20Sopenharmony_ci				mlog_errno(retval);
16748c2ecf20Sopenharmony_ci				goto bail;
16758c2ecf20Sopenharmony_ci			}
16768c2ecf20Sopenharmony_ci
16778c2ecf20Sopenharmony_ci			if (insert_bh == parent_fe_bh)
16788c2ecf20Sopenharmony_ci				retval = ocfs2_journal_access_di(handle,
16798c2ecf20Sopenharmony_ci								 INODE_CACHE(dir),
16808c2ecf20Sopenharmony_ci								 insert_bh,
16818c2ecf20Sopenharmony_ci								 OCFS2_JOURNAL_ACCESS_WRITE);
16828c2ecf20Sopenharmony_ci			else {
16838c2ecf20Sopenharmony_ci				retval = ocfs2_journal_access_db(handle,
16848c2ecf20Sopenharmony_ci								 INODE_CACHE(dir),
16858c2ecf20Sopenharmony_ci								 insert_bh,
16868c2ecf20Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_WRITE);
16878c2ecf20Sopenharmony_ci
16888c2ecf20Sopenharmony_ci				if (!retval && ocfs2_dir_indexed(dir))
16898c2ecf20Sopenharmony_ci					retval = ocfs2_dx_dir_insert(dir,
16908c2ecf20Sopenharmony_ci								handle,
16918c2ecf20Sopenharmony_ci								lookup);
16928c2ecf20Sopenharmony_ci			}
16938c2ecf20Sopenharmony_ci
16948c2ecf20Sopenharmony_ci			if (retval) {
16958c2ecf20Sopenharmony_ci				mlog_errno(retval);
16968c2ecf20Sopenharmony_ci				goto bail;
16978c2ecf20Sopenharmony_ci			}
16988c2ecf20Sopenharmony_ci
16998c2ecf20Sopenharmony_ci			/* By now the buffer is marked for journaling */
17008c2ecf20Sopenharmony_ci			offset += le16_to_cpu(de->rec_len);
17018c2ecf20Sopenharmony_ci			if (le64_to_cpu(de->inode)) {
17028c2ecf20Sopenharmony_ci				de1 = (struct ocfs2_dir_entry *)((char *) de +
17038c2ecf20Sopenharmony_ci					OCFS2_DIR_REC_LEN(de->name_len));
17048c2ecf20Sopenharmony_ci				de1->rec_len =
17058c2ecf20Sopenharmony_ci					cpu_to_le16(le16_to_cpu(de->rec_len) -
17068c2ecf20Sopenharmony_ci					OCFS2_DIR_REC_LEN(de->name_len));
17078c2ecf20Sopenharmony_ci				de->rec_len = cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
17088c2ecf20Sopenharmony_ci				de = de1;
17098c2ecf20Sopenharmony_ci			}
17108c2ecf20Sopenharmony_ci			de->file_type = FT_UNKNOWN;
17118c2ecf20Sopenharmony_ci			if (blkno) {
17128c2ecf20Sopenharmony_ci				de->inode = cpu_to_le64(blkno);
17138c2ecf20Sopenharmony_ci				ocfs2_set_de_type(de, inode->i_mode);
17148c2ecf20Sopenharmony_ci			} else
17158c2ecf20Sopenharmony_ci				de->inode = 0;
17168c2ecf20Sopenharmony_ci			de->name_len = namelen;
17178c2ecf20Sopenharmony_ci			memcpy(de->name, name, namelen);
17188c2ecf20Sopenharmony_ci
17198c2ecf20Sopenharmony_ci			if (ocfs2_dir_indexed(dir))
17208c2ecf20Sopenharmony_ci				ocfs2_recalc_free_list(dir, handle, lookup);
17218c2ecf20Sopenharmony_ci
17228c2ecf20Sopenharmony_ci			inode_inc_iversion(dir);
17238c2ecf20Sopenharmony_ci			ocfs2_journal_dirty(handle, insert_bh);
17248c2ecf20Sopenharmony_ci			retval = 0;
17258c2ecf20Sopenharmony_ci			goto bail;
17268c2ecf20Sopenharmony_ci		}
17278c2ecf20Sopenharmony_ci
17288c2ecf20Sopenharmony_ci		offset += le16_to_cpu(de->rec_len);
17298c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *) ((char *) de + le16_to_cpu(de->rec_len));
17308c2ecf20Sopenharmony_ci	}
17318c2ecf20Sopenharmony_ci
17328c2ecf20Sopenharmony_ci	/* when you think about it, the assert above should prevent us
17338c2ecf20Sopenharmony_ci	 * from ever getting here. */
17348c2ecf20Sopenharmony_ci	retval = -ENOSPC;
17358c2ecf20Sopenharmony_cibail:
17368c2ecf20Sopenharmony_ci	if (retval)
17378c2ecf20Sopenharmony_ci		mlog_errno(retval);
17388c2ecf20Sopenharmony_ci
17398c2ecf20Sopenharmony_ci	return retval;
17408c2ecf20Sopenharmony_ci}
17418c2ecf20Sopenharmony_ci
17428c2ecf20Sopenharmony_cistatic int ocfs2_dir_foreach_blk_id(struct inode *inode,
17438c2ecf20Sopenharmony_ci				    u64 *f_version,
17448c2ecf20Sopenharmony_ci				    struct dir_context *ctx)
17458c2ecf20Sopenharmony_ci{
17468c2ecf20Sopenharmony_ci	int ret, i;
17478c2ecf20Sopenharmony_ci	unsigned long offset = ctx->pos;
17488c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
17498c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di;
17508c2ecf20Sopenharmony_ci	struct ocfs2_inline_data *data;
17518c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
17528c2ecf20Sopenharmony_ci
17538c2ecf20Sopenharmony_ci	ret = ocfs2_read_inode_block(inode, &di_bh);
17548c2ecf20Sopenharmony_ci	if (ret) {
17558c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "Unable to read inode block for dir %llu\n",
17568c2ecf20Sopenharmony_ci		     (unsigned long long)OCFS2_I(inode)->ip_blkno);
17578c2ecf20Sopenharmony_ci		goto out;
17588c2ecf20Sopenharmony_ci	}
17598c2ecf20Sopenharmony_ci
17608c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
17618c2ecf20Sopenharmony_ci	data = &di->id2.i_data;
17628c2ecf20Sopenharmony_ci
17638c2ecf20Sopenharmony_ci	while (ctx->pos < i_size_read(inode)) {
17648c2ecf20Sopenharmony_ci		/* If the dir block has changed since the last call to
17658c2ecf20Sopenharmony_ci		 * readdir(2), then we might be pointing to an invalid
17668c2ecf20Sopenharmony_ci		 * dirent right now.  Scan from the start of the block
17678c2ecf20Sopenharmony_ci		 * to make sure. */
17688c2ecf20Sopenharmony_ci		if (!inode_eq_iversion(inode, *f_version)) {
17698c2ecf20Sopenharmony_ci			for (i = 0; i < i_size_read(inode) && i < offset; ) {
17708c2ecf20Sopenharmony_ci				de = (struct ocfs2_dir_entry *)
17718c2ecf20Sopenharmony_ci					(data->id_data + i);
17728c2ecf20Sopenharmony_ci				/* It's too expensive to do a full
17738c2ecf20Sopenharmony_ci				 * dirent test each time round this
17748c2ecf20Sopenharmony_ci				 * loop, but we do have to test at
17758c2ecf20Sopenharmony_ci				 * least that it is non-zero.  A
17768c2ecf20Sopenharmony_ci				 * failure will be detected in the
17778c2ecf20Sopenharmony_ci				 * dirent test below. */
17788c2ecf20Sopenharmony_ci				if (le16_to_cpu(de->rec_len) <
17798c2ecf20Sopenharmony_ci				    OCFS2_DIR_REC_LEN(1))
17808c2ecf20Sopenharmony_ci					break;
17818c2ecf20Sopenharmony_ci				i += le16_to_cpu(de->rec_len);
17828c2ecf20Sopenharmony_ci			}
17838c2ecf20Sopenharmony_ci			ctx->pos = offset = i;
17848c2ecf20Sopenharmony_ci			*f_version = inode_query_iversion(inode);
17858c2ecf20Sopenharmony_ci		}
17868c2ecf20Sopenharmony_ci
17878c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *) (data->id_data + ctx->pos);
17888c2ecf20Sopenharmony_ci		if (!ocfs2_check_dir_entry(inode, de, di_bh, (char *)data->id_data,
17898c2ecf20Sopenharmony_ci					   i_size_read(inode), ctx->pos)) {
17908c2ecf20Sopenharmony_ci			/* On error, skip the f_pos to the end. */
17918c2ecf20Sopenharmony_ci			ctx->pos = i_size_read(inode);
17928c2ecf20Sopenharmony_ci			break;
17938c2ecf20Sopenharmony_ci		}
17948c2ecf20Sopenharmony_ci		offset += le16_to_cpu(de->rec_len);
17958c2ecf20Sopenharmony_ci		if (le64_to_cpu(de->inode)) {
17968c2ecf20Sopenharmony_ci			if (!dir_emit(ctx, de->name, de->name_len,
17978c2ecf20Sopenharmony_ci				      le64_to_cpu(de->inode),
17988c2ecf20Sopenharmony_ci				      fs_ftype_to_dtype(de->file_type)))
17998c2ecf20Sopenharmony_ci				goto out;
18008c2ecf20Sopenharmony_ci		}
18018c2ecf20Sopenharmony_ci		ctx->pos += le16_to_cpu(de->rec_len);
18028c2ecf20Sopenharmony_ci	}
18038c2ecf20Sopenharmony_ciout:
18048c2ecf20Sopenharmony_ci	brelse(di_bh);
18058c2ecf20Sopenharmony_ci	return 0;
18068c2ecf20Sopenharmony_ci}
18078c2ecf20Sopenharmony_ci
18088c2ecf20Sopenharmony_ci/*
18098c2ecf20Sopenharmony_ci * NOTE: This function can be called against unindexed directories,
18108c2ecf20Sopenharmony_ci * and indexed ones.
18118c2ecf20Sopenharmony_ci */
18128c2ecf20Sopenharmony_cistatic int ocfs2_dir_foreach_blk_el(struct inode *inode,
18138c2ecf20Sopenharmony_ci				    u64 *f_version,
18148c2ecf20Sopenharmony_ci				    struct dir_context *ctx,
18158c2ecf20Sopenharmony_ci				    bool persist)
18168c2ecf20Sopenharmony_ci{
18178c2ecf20Sopenharmony_ci	unsigned long offset, blk, last_ra_blk = 0;
18188c2ecf20Sopenharmony_ci	int i;
18198c2ecf20Sopenharmony_ci	struct buffer_head * bh, * tmp;
18208c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry * de;
18218c2ecf20Sopenharmony_ci	struct super_block * sb = inode->i_sb;
18228c2ecf20Sopenharmony_ci	unsigned int ra_sectors = 16;
18238c2ecf20Sopenharmony_ci	int stored = 0;
18248c2ecf20Sopenharmony_ci
18258c2ecf20Sopenharmony_ci	bh = NULL;
18268c2ecf20Sopenharmony_ci
18278c2ecf20Sopenharmony_ci	offset = ctx->pos & (sb->s_blocksize - 1);
18288c2ecf20Sopenharmony_ci
18298c2ecf20Sopenharmony_ci	while (ctx->pos < i_size_read(inode)) {
18308c2ecf20Sopenharmony_ci		blk = ctx->pos >> sb->s_blocksize_bits;
18318c2ecf20Sopenharmony_ci		if (ocfs2_read_dir_block(inode, blk, &bh, 0)) {
18328c2ecf20Sopenharmony_ci			/* Skip the corrupt dirblock and keep trying */
18338c2ecf20Sopenharmony_ci			ctx->pos += sb->s_blocksize - offset;
18348c2ecf20Sopenharmony_ci			continue;
18358c2ecf20Sopenharmony_ci		}
18368c2ecf20Sopenharmony_ci
18378c2ecf20Sopenharmony_ci		/* The idea here is to begin with 8k read-ahead and to stay
18388c2ecf20Sopenharmony_ci		 * 4k ahead of our current position.
18398c2ecf20Sopenharmony_ci		 *
18408c2ecf20Sopenharmony_ci		 * TODO: Use the pagecache for this. We just need to
18418c2ecf20Sopenharmony_ci		 * make sure it's cluster-safe... */
18428c2ecf20Sopenharmony_ci		if (!last_ra_blk
18438c2ecf20Sopenharmony_ci		    || (((last_ra_blk - blk) << 9) <= (ra_sectors / 2))) {
18448c2ecf20Sopenharmony_ci			for (i = ra_sectors >> (sb->s_blocksize_bits - 9);
18458c2ecf20Sopenharmony_ci			     i > 0; i--) {
18468c2ecf20Sopenharmony_ci				tmp = NULL;
18478c2ecf20Sopenharmony_ci				if (!ocfs2_read_dir_block(inode, ++blk, &tmp,
18488c2ecf20Sopenharmony_ci							  OCFS2_BH_READAHEAD))
18498c2ecf20Sopenharmony_ci					brelse(tmp);
18508c2ecf20Sopenharmony_ci			}
18518c2ecf20Sopenharmony_ci			last_ra_blk = blk;
18528c2ecf20Sopenharmony_ci			ra_sectors = 8;
18538c2ecf20Sopenharmony_ci		}
18548c2ecf20Sopenharmony_ci
18558c2ecf20Sopenharmony_ci		/* If the dir block has changed since the last call to
18568c2ecf20Sopenharmony_ci		 * readdir(2), then we might be pointing to an invalid
18578c2ecf20Sopenharmony_ci		 * dirent right now.  Scan from the start of the block
18588c2ecf20Sopenharmony_ci		 * to make sure. */
18598c2ecf20Sopenharmony_ci		if (!inode_eq_iversion(inode, *f_version)) {
18608c2ecf20Sopenharmony_ci			for (i = 0; i < sb->s_blocksize && i < offset; ) {
18618c2ecf20Sopenharmony_ci				de = (struct ocfs2_dir_entry *) (bh->b_data + i);
18628c2ecf20Sopenharmony_ci				/* It's too expensive to do a full
18638c2ecf20Sopenharmony_ci				 * dirent test each time round this
18648c2ecf20Sopenharmony_ci				 * loop, but we do have to test at
18658c2ecf20Sopenharmony_ci				 * least that it is non-zero.  A
18668c2ecf20Sopenharmony_ci				 * failure will be detected in the
18678c2ecf20Sopenharmony_ci				 * dirent test below. */
18688c2ecf20Sopenharmony_ci				if (le16_to_cpu(de->rec_len) <
18698c2ecf20Sopenharmony_ci				    OCFS2_DIR_REC_LEN(1))
18708c2ecf20Sopenharmony_ci					break;
18718c2ecf20Sopenharmony_ci				i += le16_to_cpu(de->rec_len);
18728c2ecf20Sopenharmony_ci			}
18738c2ecf20Sopenharmony_ci			offset = i;
18748c2ecf20Sopenharmony_ci			ctx->pos = (ctx->pos & ~(sb->s_blocksize - 1))
18758c2ecf20Sopenharmony_ci				| offset;
18768c2ecf20Sopenharmony_ci			*f_version = inode_query_iversion(inode);
18778c2ecf20Sopenharmony_ci		}
18788c2ecf20Sopenharmony_ci
18798c2ecf20Sopenharmony_ci		while (ctx->pos < i_size_read(inode)
18808c2ecf20Sopenharmony_ci		       && offset < sb->s_blocksize) {
18818c2ecf20Sopenharmony_ci			de = (struct ocfs2_dir_entry *) (bh->b_data + offset);
18828c2ecf20Sopenharmony_ci			if (!ocfs2_check_dir_entry(inode, de, bh, bh->b_data,
18838c2ecf20Sopenharmony_ci						   sb->s_blocksize, offset)) {
18848c2ecf20Sopenharmony_ci				/* On error, skip the f_pos to the
18858c2ecf20Sopenharmony_ci				   next block. */
18868c2ecf20Sopenharmony_ci				ctx->pos = (ctx->pos | (sb->s_blocksize - 1)) + 1;
18878c2ecf20Sopenharmony_ci				break;
18888c2ecf20Sopenharmony_ci			}
18898c2ecf20Sopenharmony_ci			if (le64_to_cpu(de->inode)) {
18908c2ecf20Sopenharmony_ci				if (!dir_emit(ctx, de->name,
18918c2ecf20Sopenharmony_ci						de->name_len,
18928c2ecf20Sopenharmony_ci						le64_to_cpu(de->inode),
18938c2ecf20Sopenharmony_ci					fs_ftype_to_dtype(de->file_type))) {
18948c2ecf20Sopenharmony_ci					brelse(bh);
18958c2ecf20Sopenharmony_ci					return 0;
18968c2ecf20Sopenharmony_ci				}
18978c2ecf20Sopenharmony_ci				stored++;
18988c2ecf20Sopenharmony_ci			}
18998c2ecf20Sopenharmony_ci			offset += le16_to_cpu(de->rec_len);
19008c2ecf20Sopenharmony_ci			ctx->pos += le16_to_cpu(de->rec_len);
19018c2ecf20Sopenharmony_ci		}
19028c2ecf20Sopenharmony_ci		offset = 0;
19038c2ecf20Sopenharmony_ci		brelse(bh);
19048c2ecf20Sopenharmony_ci		bh = NULL;
19058c2ecf20Sopenharmony_ci		if (!persist && stored)
19068c2ecf20Sopenharmony_ci			break;
19078c2ecf20Sopenharmony_ci	}
19088c2ecf20Sopenharmony_ci	return 0;
19098c2ecf20Sopenharmony_ci}
19108c2ecf20Sopenharmony_ci
19118c2ecf20Sopenharmony_cistatic int ocfs2_dir_foreach_blk(struct inode *inode, u64 *f_version,
19128c2ecf20Sopenharmony_ci				 struct dir_context *ctx,
19138c2ecf20Sopenharmony_ci				 bool persist)
19148c2ecf20Sopenharmony_ci{
19158c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
19168c2ecf20Sopenharmony_ci		return ocfs2_dir_foreach_blk_id(inode, f_version, ctx);
19178c2ecf20Sopenharmony_ci	return ocfs2_dir_foreach_blk_el(inode, f_version, ctx, persist);
19188c2ecf20Sopenharmony_ci}
19198c2ecf20Sopenharmony_ci
19208c2ecf20Sopenharmony_ci/*
19218c2ecf20Sopenharmony_ci * This is intended to be called from inside other kernel functions,
19228c2ecf20Sopenharmony_ci * so we fake some arguments.
19238c2ecf20Sopenharmony_ci */
19248c2ecf20Sopenharmony_ciint ocfs2_dir_foreach(struct inode *inode, struct dir_context *ctx)
19258c2ecf20Sopenharmony_ci{
19268c2ecf20Sopenharmony_ci	u64 version = inode_query_iversion(inode);
19278c2ecf20Sopenharmony_ci	ocfs2_dir_foreach_blk(inode, &version, ctx, true);
19288c2ecf20Sopenharmony_ci	return 0;
19298c2ecf20Sopenharmony_ci}
19308c2ecf20Sopenharmony_ci
19318c2ecf20Sopenharmony_ci/*
19328c2ecf20Sopenharmony_ci * ocfs2_readdir()
19338c2ecf20Sopenharmony_ci *
19348c2ecf20Sopenharmony_ci */
19358c2ecf20Sopenharmony_ciint ocfs2_readdir(struct file *file, struct dir_context *ctx)
19368c2ecf20Sopenharmony_ci{
19378c2ecf20Sopenharmony_ci	int error = 0;
19388c2ecf20Sopenharmony_ci	struct inode *inode = file_inode(file);
19398c2ecf20Sopenharmony_ci	int lock_level = 0;
19408c2ecf20Sopenharmony_ci
19418c2ecf20Sopenharmony_ci	trace_ocfs2_readdir((unsigned long long)OCFS2_I(inode)->ip_blkno);
19428c2ecf20Sopenharmony_ci
19438c2ecf20Sopenharmony_ci	error = ocfs2_inode_lock_atime(inode, file->f_path.mnt, &lock_level, 1);
19448c2ecf20Sopenharmony_ci	if (lock_level && error >= 0) {
19458c2ecf20Sopenharmony_ci		/* We release EX lock which used to update atime
19468c2ecf20Sopenharmony_ci		 * and get PR lock again to reduce contention
19478c2ecf20Sopenharmony_ci		 * on commonly accessed directories. */
19488c2ecf20Sopenharmony_ci		ocfs2_inode_unlock(inode, 1);
19498c2ecf20Sopenharmony_ci		lock_level = 0;
19508c2ecf20Sopenharmony_ci		error = ocfs2_inode_lock(inode, NULL, 0);
19518c2ecf20Sopenharmony_ci	}
19528c2ecf20Sopenharmony_ci	if (error < 0) {
19538c2ecf20Sopenharmony_ci		if (error != -ENOENT)
19548c2ecf20Sopenharmony_ci			mlog_errno(error);
19558c2ecf20Sopenharmony_ci		/* we haven't got any yet, so propagate the error. */
19568c2ecf20Sopenharmony_ci		goto bail_nolock;
19578c2ecf20Sopenharmony_ci	}
19588c2ecf20Sopenharmony_ci
19598c2ecf20Sopenharmony_ci	error = ocfs2_dir_foreach_blk(inode, &file->f_version, ctx, false);
19608c2ecf20Sopenharmony_ci
19618c2ecf20Sopenharmony_ci	ocfs2_inode_unlock(inode, lock_level);
19628c2ecf20Sopenharmony_ci	if (error)
19638c2ecf20Sopenharmony_ci		mlog_errno(error);
19648c2ecf20Sopenharmony_ci
19658c2ecf20Sopenharmony_cibail_nolock:
19668c2ecf20Sopenharmony_ci
19678c2ecf20Sopenharmony_ci	return error;
19688c2ecf20Sopenharmony_ci}
19698c2ecf20Sopenharmony_ci
19708c2ecf20Sopenharmony_ci/*
19718c2ecf20Sopenharmony_ci * NOTE: this should always be called with parent dir i_mutex taken.
19728c2ecf20Sopenharmony_ci */
19738c2ecf20Sopenharmony_ciint ocfs2_find_files_on_disk(const char *name,
19748c2ecf20Sopenharmony_ci			     int namelen,
19758c2ecf20Sopenharmony_ci			     u64 *blkno,
19768c2ecf20Sopenharmony_ci			     struct inode *inode,
19778c2ecf20Sopenharmony_ci			     struct ocfs2_dir_lookup_result *lookup)
19788c2ecf20Sopenharmony_ci{
19798c2ecf20Sopenharmony_ci	int status = -ENOENT;
19808c2ecf20Sopenharmony_ci
19818c2ecf20Sopenharmony_ci	trace_ocfs2_find_files_on_disk(namelen, name, blkno,
19828c2ecf20Sopenharmony_ci				(unsigned long long)OCFS2_I(inode)->ip_blkno);
19838c2ecf20Sopenharmony_ci
19848c2ecf20Sopenharmony_ci	status = ocfs2_find_entry(name, namelen, inode, lookup);
19858c2ecf20Sopenharmony_ci	if (status)
19868c2ecf20Sopenharmony_ci		goto leave;
19878c2ecf20Sopenharmony_ci
19888c2ecf20Sopenharmony_ci	*blkno = le64_to_cpu(lookup->dl_entry->inode);
19898c2ecf20Sopenharmony_ci
19908c2ecf20Sopenharmony_ci	status = 0;
19918c2ecf20Sopenharmony_cileave:
19928c2ecf20Sopenharmony_ci
19938c2ecf20Sopenharmony_ci	return status;
19948c2ecf20Sopenharmony_ci}
19958c2ecf20Sopenharmony_ci
19968c2ecf20Sopenharmony_ci/*
19978c2ecf20Sopenharmony_ci * Convenience function for callers which just want the block number
19988c2ecf20Sopenharmony_ci * mapped to a name and don't require the full dirent info, etc.
19998c2ecf20Sopenharmony_ci */
20008c2ecf20Sopenharmony_ciint ocfs2_lookup_ino_from_name(struct inode *dir, const char *name,
20018c2ecf20Sopenharmony_ci			       int namelen, u64 *blkno)
20028c2ecf20Sopenharmony_ci{
20038c2ecf20Sopenharmony_ci	int ret;
20048c2ecf20Sopenharmony_ci	struct ocfs2_dir_lookup_result lookup = { NULL, };
20058c2ecf20Sopenharmony_ci
20068c2ecf20Sopenharmony_ci	ret = ocfs2_find_files_on_disk(name, namelen, blkno, dir, &lookup);
20078c2ecf20Sopenharmony_ci	ocfs2_free_dir_lookup_result(&lookup);
20088c2ecf20Sopenharmony_ci
20098c2ecf20Sopenharmony_ci	return ret;
20108c2ecf20Sopenharmony_ci}
20118c2ecf20Sopenharmony_ci
20128c2ecf20Sopenharmony_ci/* Check for a name within a directory.
20138c2ecf20Sopenharmony_ci *
20148c2ecf20Sopenharmony_ci * Return 0 if the name does not exist
20158c2ecf20Sopenharmony_ci * Return -EEXIST if the directory contains the name
20168c2ecf20Sopenharmony_ci *
20178c2ecf20Sopenharmony_ci * Callers should have i_mutex + a cluster lock on dir
20188c2ecf20Sopenharmony_ci */
20198c2ecf20Sopenharmony_ciint ocfs2_check_dir_for_entry(struct inode *dir,
20208c2ecf20Sopenharmony_ci			      const char *name,
20218c2ecf20Sopenharmony_ci			      int namelen)
20228c2ecf20Sopenharmony_ci{
20238c2ecf20Sopenharmony_ci	int ret = 0;
20248c2ecf20Sopenharmony_ci	struct ocfs2_dir_lookup_result lookup = { NULL, };
20258c2ecf20Sopenharmony_ci
20268c2ecf20Sopenharmony_ci	trace_ocfs2_check_dir_for_entry(
20278c2ecf20Sopenharmony_ci		(unsigned long long)OCFS2_I(dir)->ip_blkno, namelen, name);
20288c2ecf20Sopenharmony_ci
20298c2ecf20Sopenharmony_ci	if (ocfs2_find_entry(name, namelen, dir, &lookup) == 0) {
20308c2ecf20Sopenharmony_ci		ret = -EEXIST;
20318c2ecf20Sopenharmony_ci		mlog_errno(ret);
20328c2ecf20Sopenharmony_ci	}
20338c2ecf20Sopenharmony_ci
20348c2ecf20Sopenharmony_ci	ocfs2_free_dir_lookup_result(&lookup);
20358c2ecf20Sopenharmony_ci
20368c2ecf20Sopenharmony_ci	return ret;
20378c2ecf20Sopenharmony_ci}
20388c2ecf20Sopenharmony_ci
20398c2ecf20Sopenharmony_cistruct ocfs2_empty_dir_priv {
20408c2ecf20Sopenharmony_ci	struct dir_context ctx;
20418c2ecf20Sopenharmony_ci	unsigned seen_dot;
20428c2ecf20Sopenharmony_ci	unsigned seen_dot_dot;
20438c2ecf20Sopenharmony_ci	unsigned seen_other;
20448c2ecf20Sopenharmony_ci	unsigned dx_dir;
20458c2ecf20Sopenharmony_ci};
20468c2ecf20Sopenharmony_cistatic int ocfs2_empty_dir_filldir(struct dir_context *ctx, const char *name,
20478c2ecf20Sopenharmony_ci				   int name_len, loff_t pos, u64 ino,
20488c2ecf20Sopenharmony_ci				   unsigned type)
20498c2ecf20Sopenharmony_ci{
20508c2ecf20Sopenharmony_ci	struct ocfs2_empty_dir_priv *p =
20518c2ecf20Sopenharmony_ci		container_of(ctx, struct ocfs2_empty_dir_priv, ctx);
20528c2ecf20Sopenharmony_ci
20538c2ecf20Sopenharmony_ci	/*
20548c2ecf20Sopenharmony_ci	 * Check the positions of "." and ".." records to be sure
20558c2ecf20Sopenharmony_ci	 * they're in the correct place.
20568c2ecf20Sopenharmony_ci	 *
20578c2ecf20Sopenharmony_ci	 * Indexed directories don't need to proceed past the first
20588c2ecf20Sopenharmony_ci	 * two entries, so we end the scan after seeing '..'. Despite
20598c2ecf20Sopenharmony_ci	 * that, we allow the scan to proceed In the event that we
20608c2ecf20Sopenharmony_ci	 * have a corrupted indexed directory (no dot or dot dot
20618c2ecf20Sopenharmony_ci	 * entries). This allows us to double check for existing
20628c2ecf20Sopenharmony_ci	 * entries which might not have been found in the index.
20638c2ecf20Sopenharmony_ci	 */
20648c2ecf20Sopenharmony_ci	if (name_len == 1 && !strncmp(".", name, 1) && pos == 0) {
20658c2ecf20Sopenharmony_ci		p->seen_dot = 1;
20668c2ecf20Sopenharmony_ci		return 0;
20678c2ecf20Sopenharmony_ci	}
20688c2ecf20Sopenharmony_ci
20698c2ecf20Sopenharmony_ci	if (name_len == 2 && !strncmp("..", name, 2) &&
20708c2ecf20Sopenharmony_ci	    pos == OCFS2_DIR_REC_LEN(1)) {
20718c2ecf20Sopenharmony_ci		p->seen_dot_dot = 1;
20728c2ecf20Sopenharmony_ci
20738c2ecf20Sopenharmony_ci		if (p->dx_dir && p->seen_dot)
20748c2ecf20Sopenharmony_ci			return 1;
20758c2ecf20Sopenharmony_ci
20768c2ecf20Sopenharmony_ci		return 0;
20778c2ecf20Sopenharmony_ci	}
20788c2ecf20Sopenharmony_ci
20798c2ecf20Sopenharmony_ci	p->seen_other = 1;
20808c2ecf20Sopenharmony_ci	return 1;
20818c2ecf20Sopenharmony_ci}
20828c2ecf20Sopenharmony_ci
20838c2ecf20Sopenharmony_cistatic int ocfs2_empty_dir_dx(struct inode *inode,
20848c2ecf20Sopenharmony_ci			      struct ocfs2_empty_dir_priv *priv)
20858c2ecf20Sopenharmony_ci{
20868c2ecf20Sopenharmony_ci	int ret;
20878c2ecf20Sopenharmony_ci	struct buffer_head *di_bh = NULL;
20888c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
20898c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di;
20908c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
20918c2ecf20Sopenharmony_ci
20928c2ecf20Sopenharmony_ci	priv->dx_dir = 1;
20938c2ecf20Sopenharmony_ci
20948c2ecf20Sopenharmony_ci	ret = ocfs2_read_inode_block(inode, &di_bh);
20958c2ecf20Sopenharmony_ci	if (ret) {
20968c2ecf20Sopenharmony_ci		mlog_errno(ret);
20978c2ecf20Sopenharmony_ci		goto out;
20988c2ecf20Sopenharmony_ci	}
20998c2ecf20Sopenharmony_ci	di = (struct ocfs2_dinode *)di_bh->b_data;
21008c2ecf20Sopenharmony_ci
21018c2ecf20Sopenharmony_ci	ret = ocfs2_read_dx_root(inode, di, &dx_root_bh);
21028c2ecf20Sopenharmony_ci	if (ret) {
21038c2ecf20Sopenharmony_ci		mlog_errno(ret);
21048c2ecf20Sopenharmony_ci		goto out;
21058c2ecf20Sopenharmony_ci	}
21068c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
21078c2ecf20Sopenharmony_ci
21088c2ecf20Sopenharmony_ci	if (le32_to_cpu(dx_root->dr_num_entries) != 2)
21098c2ecf20Sopenharmony_ci		priv->seen_other = 1;
21108c2ecf20Sopenharmony_ci
21118c2ecf20Sopenharmony_ciout:
21128c2ecf20Sopenharmony_ci	brelse(di_bh);
21138c2ecf20Sopenharmony_ci	brelse(dx_root_bh);
21148c2ecf20Sopenharmony_ci	return ret;
21158c2ecf20Sopenharmony_ci}
21168c2ecf20Sopenharmony_ci
21178c2ecf20Sopenharmony_ci/*
21188c2ecf20Sopenharmony_ci * routine to check that the specified directory is empty (for rmdir)
21198c2ecf20Sopenharmony_ci *
21208c2ecf20Sopenharmony_ci * Returns 1 if dir is empty, zero otherwise.
21218c2ecf20Sopenharmony_ci *
21228c2ecf20Sopenharmony_ci * XXX: This is a performance problem for unindexed directories.
21238c2ecf20Sopenharmony_ci */
21248c2ecf20Sopenharmony_ciint ocfs2_empty_dir(struct inode *inode)
21258c2ecf20Sopenharmony_ci{
21268c2ecf20Sopenharmony_ci	int ret;
21278c2ecf20Sopenharmony_ci	struct ocfs2_empty_dir_priv priv = {
21288c2ecf20Sopenharmony_ci		.ctx.actor = ocfs2_empty_dir_filldir,
21298c2ecf20Sopenharmony_ci	};
21308c2ecf20Sopenharmony_ci
21318c2ecf20Sopenharmony_ci	if (ocfs2_dir_indexed(inode)) {
21328c2ecf20Sopenharmony_ci		ret = ocfs2_empty_dir_dx(inode, &priv);
21338c2ecf20Sopenharmony_ci		if (ret)
21348c2ecf20Sopenharmony_ci			mlog_errno(ret);
21358c2ecf20Sopenharmony_ci		/*
21368c2ecf20Sopenharmony_ci		 * We still run ocfs2_dir_foreach to get the checks
21378c2ecf20Sopenharmony_ci		 * for "." and "..".
21388c2ecf20Sopenharmony_ci		 */
21398c2ecf20Sopenharmony_ci	}
21408c2ecf20Sopenharmony_ci
21418c2ecf20Sopenharmony_ci	ret = ocfs2_dir_foreach(inode, &priv.ctx);
21428c2ecf20Sopenharmony_ci	if (ret)
21438c2ecf20Sopenharmony_ci		mlog_errno(ret);
21448c2ecf20Sopenharmony_ci
21458c2ecf20Sopenharmony_ci	if (!priv.seen_dot || !priv.seen_dot_dot) {
21468c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "bad directory (dir #%llu) - no `.' or `..'\n",
21478c2ecf20Sopenharmony_ci		     (unsigned long long)OCFS2_I(inode)->ip_blkno);
21488c2ecf20Sopenharmony_ci		/*
21498c2ecf20Sopenharmony_ci		 * XXX: Is it really safe to allow an unlink to continue?
21508c2ecf20Sopenharmony_ci		 */
21518c2ecf20Sopenharmony_ci		return 1;
21528c2ecf20Sopenharmony_ci	}
21538c2ecf20Sopenharmony_ci
21548c2ecf20Sopenharmony_ci	return !priv.seen_other;
21558c2ecf20Sopenharmony_ci}
21568c2ecf20Sopenharmony_ci
21578c2ecf20Sopenharmony_ci/*
21588c2ecf20Sopenharmony_ci * Fills "." and ".." dirents in a new directory block. Returns dirent for
21598c2ecf20Sopenharmony_ci * "..", which might be used during creation of a directory with a trailing
21608c2ecf20Sopenharmony_ci * header. It is otherwise safe to ignore the return code.
21618c2ecf20Sopenharmony_ci */
21628c2ecf20Sopenharmony_cistatic struct ocfs2_dir_entry *ocfs2_fill_initial_dirents(struct inode *inode,
21638c2ecf20Sopenharmony_ci							  struct inode *parent,
21648c2ecf20Sopenharmony_ci							  char *start,
21658c2ecf20Sopenharmony_ci							  unsigned int size)
21668c2ecf20Sopenharmony_ci{
21678c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de = (struct ocfs2_dir_entry *)start;
21688c2ecf20Sopenharmony_ci
21698c2ecf20Sopenharmony_ci	de->inode = cpu_to_le64(OCFS2_I(inode)->ip_blkno);
21708c2ecf20Sopenharmony_ci	de->name_len = 1;
21718c2ecf20Sopenharmony_ci	de->rec_len =
21728c2ecf20Sopenharmony_ci		cpu_to_le16(OCFS2_DIR_REC_LEN(de->name_len));
21738c2ecf20Sopenharmony_ci	strcpy(de->name, ".");
21748c2ecf20Sopenharmony_ci	ocfs2_set_de_type(de, S_IFDIR);
21758c2ecf20Sopenharmony_ci
21768c2ecf20Sopenharmony_ci	de = (struct ocfs2_dir_entry *) ((char *)de + le16_to_cpu(de->rec_len));
21778c2ecf20Sopenharmony_ci	de->inode = cpu_to_le64(OCFS2_I(parent)->ip_blkno);
21788c2ecf20Sopenharmony_ci	de->rec_len = cpu_to_le16(size - OCFS2_DIR_REC_LEN(1));
21798c2ecf20Sopenharmony_ci	de->name_len = 2;
21808c2ecf20Sopenharmony_ci	strcpy(de->name, "..");
21818c2ecf20Sopenharmony_ci	ocfs2_set_de_type(de, S_IFDIR);
21828c2ecf20Sopenharmony_ci
21838c2ecf20Sopenharmony_ci	return de;
21848c2ecf20Sopenharmony_ci}
21858c2ecf20Sopenharmony_ci
21868c2ecf20Sopenharmony_ci/*
21878c2ecf20Sopenharmony_ci * This works together with code in ocfs2_mknod_locked() which sets
21888c2ecf20Sopenharmony_ci * the inline-data flag and initializes the inline-data section.
21898c2ecf20Sopenharmony_ci */
21908c2ecf20Sopenharmony_cistatic int ocfs2_fill_new_dir_id(struct ocfs2_super *osb,
21918c2ecf20Sopenharmony_ci				 handle_t *handle,
21928c2ecf20Sopenharmony_ci				 struct inode *parent,
21938c2ecf20Sopenharmony_ci				 struct inode *inode,
21948c2ecf20Sopenharmony_ci				 struct buffer_head *di_bh)
21958c2ecf20Sopenharmony_ci{
21968c2ecf20Sopenharmony_ci	int ret;
21978c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
21988c2ecf20Sopenharmony_ci	struct ocfs2_inline_data *data = &di->id2.i_data;
21998c2ecf20Sopenharmony_ci	unsigned int size = le16_to_cpu(data->id_count);
22008c2ecf20Sopenharmony_ci
22018c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_di(handle, INODE_CACHE(inode), di_bh,
22028c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
22038c2ecf20Sopenharmony_ci	if (ret) {
22048c2ecf20Sopenharmony_ci		mlog_errno(ret);
22058c2ecf20Sopenharmony_ci		goto out;
22068c2ecf20Sopenharmony_ci	}
22078c2ecf20Sopenharmony_ci
22088c2ecf20Sopenharmony_ci	ocfs2_fill_initial_dirents(inode, parent, data->id_data, size);
22098c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
22108c2ecf20Sopenharmony_ci
22118c2ecf20Sopenharmony_ci	i_size_write(inode, size);
22128c2ecf20Sopenharmony_ci	set_nlink(inode, 2);
22138c2ecf20Sopenharmony_ci	inode->i_blocks = ocfs2_inode_sector_count(inode);
22148c2ecf20Sopenharmony_ci
22158c2ecf20Sopenharmony_ci	ret = ocfs2_mark_inode_dirty(handle, inode, di_bh);
22168c2ecf20Sopenharmony_ci	if (ret < 0)
22178c2ecf20Sopenharmony_ci		mlog_errno(ret);
22188c2ecf20Sopenharmony_ci
22198c2ecf20Sopenharmony_ciout:
22208c2ecf20Sopenharmony_ci	return ret;
22218c2ecf20Sopenharmony_ci}
22228c2ecf20Sopenharmony_ci
22238c2ecf20Sopenharmony_cistatic int ocfs2_fill_new_dir_el(struct ocfs2_super *osb,
22248c2ecf20Sopenharmony_ci				 handle_t *handle,
22258c2ecf20Sopenharmony_ci				 struct inode *parent,
22268c2ecf20Sopenharmony_ci				 struct inode *inode,
22278c2ecf20Sopenharmony_ci				 struct buffer_head *fe_bh,
22288c2ecf20Sopenharmony_ci				 struct ocfs2_alloc_context *data_ac,
22298c2ecf20Sopenharmony_ci				 struct buffer_head **ret_new_bh)
22308c2ecf20Sopenharmony_ci{
22318c2ecf20Sopenharmony_ci	int status;
22328c2ecf20Sopenharmony_ci	unsigned int size = osb->sb->s_blocksize;
22338c2ecf20Sopenharmony_ci	struct buffer_head *new_bh = NULL;
22348c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
22358c2ecf20Sopenharmony_ci
22368c2ecf20Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(inode))
22378c2ecf20Sopenharmony_ci		size = ocfs2_dir_trailer_blk_off(parent->i_sb);
22388c2ecf20Sopenharmony_ci
22398c2ecf20Sopenharmony_ci	status = ocfs2_do_extend_dir(osb->sb, handle, inode, fe_bh,
22408c2ecf20Sopenharmony_ci				     data_ac, NULL, &new_bh);
22418c2ecf20Sopenharmony_ci	if (status < 0) {
22428c2ecf20Sopenharmony_ci		mlog_errno(status);
22438c2ecf20Sopenharmony_ci		goto bail;
22448c2ecf20Sopenharmony_ci	}
22458c2ecf20Sopenharmony_ci
22468c2ecf20Sopenharmony_ci	ocfs2_set_new_buffer_uptodate(INODE_CACHE(inode), new_bh);
22478c2ecf20Sopenharmony_ci
22488c2ecf20Sopenharmony_ci	status = ocfs2_journal_access_db(handle, INODE_CACHE(inode), new_bh,
22498c2ecf20Sopenharmony_ci					 OCFS2_JOURNAL_ACCESS_CREATE);
22508c2ecf20Sopenharmony_ci	if (status < 0) {
22518c2ecf20Sopenharmony_ci		mlog_errno(status);
22528c2ecf20Sopenharmony_ci		goto bail;
22538c2ecf20Sopenharmony_ci	}
22548c2ecf20Sopenharmony_ci	memset(new_bh->b_data, 0, osb->sb->s_blocksize);
22558c2ecf20Sopenharmony_ci
22568c2ecf20Sopenharmony_ci	de = ocfs2_fill_initial_dirents(inode, parent, new_bh->b_data, size);
22578c2ecf20Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(inode)) {
22588c2ecf20Sopenharmony_ci		int size = le16_to_cpu(de->rec_len);
22598c2ecf20Sopenharmony_ci
22608c2ecf20Sopenharmony_ci		/*
22618c2ecf20Sopenharmony_ci		 * Figure out the size of the hole left over after
22628c2ecf20Sopenharmony_ci		 * insertion of '.' and '..'. The trailer wants this
22638c2ecf20Sopenharmony_ci		 * information.
22648c2ecf20Sopenharmony_ci		 */
22658c2ecf20Sopenharmony_ci		size -= OCFS2_DIR_REC_LEN(2);
22668c2ecf20Sopenharmony_ci		size -= sizeof(struct ocfs2_dir_block_trailer);
22678c2ecf20Sopenharmony_ci
22688c2ecf20Sopenharmony_ci		ocfs2_init_dir_trailer(inode, new_bh, size);
22698c2ecf20Sopenharmony_ci	}
22708c2ecf20Sopenharmony_ci
22718c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, new_bh);
22728c2ecf20Sopenharmony_ci
22738c2ecf20Sopenharmony_ci	i_size_write(inode, inode->i_sb->s_blocksize);
22748c2ecf20Sopenharmony_ci	set_nlink(inode, 2);
22758c2ecf20Sopenharmony_ci	inode->i_blocks = ocfs2_inode_sector_count(inode);
22768c2ecf20Sopenharmony_ci	status = ocfs2_mark_inode_dirty(handle, inode, fe_bh);
22778c2ecf20Sopenharmony_ci	if (status < 0) {
22788c2ecf20Sopenharmony_ci		mlog_errno(status);
22798c2ecf20Sopenharmony_ci		goto bail;
22808c2ecf20Sopenharmony_ci	}
22818c2ecf20Sopenharmony_ci
22828c2ecf20Sopenharmony_ci	status = 0;
22838c2ecf20Sopenharmony_ci	if (ret_new_bh) {
22848c2ecf20Sopenharmony_ci		*ret_new_bh = new_bh;
22858c2ecf20Sopenharmony_ci		new_bh = NULL;
22868c2ecf20Sopenharmony_ci	}
22878c2ecf20Sopenharmony_cibail:
22888c2ecf20Sopenharmony_ci	brelse(new_bh);
22898c2ecf20Sopenharmony_ci
22908c2ecf20Sopenharmony_ci	return status;
22918c2ecf20Sopenharmony_ci}
22928c2ecf20Sopenharmony_ci
22938c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_attach_index(struct ocfs2_super *osb,
22948c2ecf20Sopenharmony_ci				     handle_t *handle, struct inode *dir,
22958c2ecf20Sopenharmony_ci				     struct buffer_head *di_bh,
22968c2ecf20Sopenharmony_ci				     struct buffer_head *dirdata_bh,
22978c2ecf20Sopenharmony_ci				     struct ocfs2_alloc_context *meta_ac,
22988c2ecf20Sopenharmony_ci				     int dx_inline, u32 num_entries,
22998c2ecf20Sopenharmony_ci				     struct buffer_head **ret_dx_root_bh)
23008c2ecf20Sopenharmony_ci{
23018c2ecf20Sopenharmony_ci	int ret;
23028c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *) di_bh->b_data;
23038c2ecf20Sopenharmony_ci	u16 dr_suballoc_bit;
23048c2ecf20Sopenharmony_ci	u64 suballoc_loc, dr_blkno;
23058c2ecf20Sopenharmony_ci	unsigned int num_bits;
23068c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
23078c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
23088c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *trailer =
23098c2ecf20Sopenharmony_ci		ocfs2_trailer_from_bh(dirdata_bh, dir->i_sb);
23108c2ecf20Sopenharmony_ci
23118c2ecf20Sopenharmony_ci	ret = ocfs2_claim_metadata(handle, meta_ac, 1, &suballoc_loc,
23128c2ecf20Sopenharmony_ci				   &dr_suballoc_bit, &num_bits, &dr_blkno);
23138c2ecf20Sopenharmony_ci	if (ret) {
23148c2ecf20Sopenharmony_ci		mlog_errno(ret);
23158c2ecf20Sopenharmony_ci		goto out;
23168c2ecf20Sopenharmony_ci	}
23178c2ecf20Sopenharmony_ci
23188c2ecf20Sopenharmony_ci	trace_ocfs2_dx_dir_attach_index(
23198c2ecf20Sopenharmony_ci				(unsigned long long)OCFS2_I(dir)->ip_blkno,
23208c2ecf20Sopenharmony_ci				(unsigned long long)dr_blkno);
23218c2ecf20Sopenharmony_ci
23228c2ecf20Sopenharmony_ci	dx_root_bh = sb_getblk(osb->sb, dr_blkno);
23238c2ecf20Sopenharmony_ci	if (dx_root_bh == NULL) {
23248c2ecf20Sopenharmony_ci		ret = -ENOMEM;
23258c2ecf20Sopenharmony_ci		goto out;
23268c2ecf20Sopenharmony_ci	}
23278c2ecf20Sopenharmony_ci	ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dx_root_bh);
23288c2ecf20Sopenharmony_ci
23298c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
23308c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_CREATE);
23318c2ecf20Sopenharmony_ci	if (ret < 0) {
23328c2ecf20Sopenharmony_ci		mlog_errno(ret);
23338c2ecf20Sopenharmony_ci		goto out;
23348c2ecf20Sopenharmony_ci	}
23358c2ecf20Sopenharmony_ci
23368c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
23378c2ecf20Sopenharmony_ci	memset(dx_root, 0, osb->sb->s_blocksize);
23388c2ecf20Sopenharmony_ci	strcpy(dx_root->dr_signature, OCFS2_DX_ROOT_SIGNATURE);
23398c2ecf20Sopenharmony_ci	dx_root->dr_suballoc_slot = cpu_to_le16(meta_ac->ac_alloc_slot);
23408c2ecf20Sopenharmony_ci	dx_root->dr_suballoc_loc = cpu_to_le64(suballoc_loc);
23418c2ecf20Sopenharmony_ci	dx_root->dr_suballoc_bit = cpu_to_le16(dr_suballoc_bit);
23428c2ecf20Sopenharmony_ci	dx_root->dr_fs_generation = cpu_to_le32(osb->fs_generation);
23438c2ecf20Sopenharmony_ci	dx_root->dr_blkno = cpu_to_le64(dr_blkno);
23448c2ecf20Sopenharmony_ci	dx_root->dr_dir_blkno = cpu_to_le64(OCFS2_I(dir)->ip_blkno);
23458c2ecf20Sopenharmony_ci	dx_root->dr_num_entries = cpu_to_le32(num_entries);
23468c2ecf20Sopenharmony_ci	if (le16_to_cpu(trailer->db_free_rec_len))
23478c2ecf20Sopenharmony_ci		dx_root->dr_free_blk = cpu_to_le64(dirdata_bh->b_blocknr);
23488c2ecf20Sopenharmony_ci	else
23498c2ecf20Sopenharmony_ci		dx_root->dr_free_blk = cpu_to_le64(0);
23508c2ecf20Sopenharmony_ci
23518c2ecf20Sopenharmony_ci	if (dx_inline) {
23528c2ecf20Sopenharmony_ci		dx_root->dr_flags |= OCFS2_DX_FLAG_INLINE;
23538c2ecf20Sopenharmony_ci		dx_root->dr_entries.de_count =
23548c2ecf20Sopenharmony_ci			cpu_to_le16(ocfs2_dx_entries_per_root(osb->sb));
23558c2ecf20Sopenharmony_ci	} else {
23568c2ecf20Sopenharmony_ci		dx_root->dr_list.l_count =
23578c2ecf20Sopenharmony_ci			cpu_to_le16(ocfs2_extent_recs_per_dx_root(osb->sb));
23588c2ecf20Sopenharmony_ci	}
23598c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
23608c2ecf20Sopenharmony_ci
23618c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
23628c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_CREATE);
23638c2ecf20Sopenharmony_ci	if (ret) {
23648c2ecf20Sopenharmony_ci		mlog_errno(ret);
23658c2ecf20Sopenharmony_ci		goto out;
23668c2ecf20Sopenharmony_ci	}
23678c2ecf20Sopenharmony_ci
23688c2ecf20Sopenharmony_ci	di->i_dx_root = cpu_to_le64(dr_blkno);
23698c2ecf20Sopenharmony_ci
23708c2ecf20Sopenharmony_ci	spin_lock(&OCFS2_I(dir)->ip_lock);
23718c2ecf20Sopenharmony_ci	OCFS2_I(dir)->ip_dyn_features |= OCFS2_INDEXED_DIR_FL;
23728c2ecf20Sopenharmony_ci	di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
23738c2ecf20Sopenharmony_ci	spin_unlock(&OCFS2_I(dir)->ip_lock);
23748c2ecf20Sopenharmony_ci
23758c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
23768c2ecf20Sopenharmony_ci
23778c2ecf20Sopenharmony_ci	*ret_dx_root_bh = dx_root_bh;
23788c2ecf20Sopenharmony_ci	dx_root_bh = NULL;
23798c2ecf20Sopenharmony_ci
23808c2ecf20Sopenharmony_ciout:
23818c2ecf20Sopenharmony_ci	brelse(dx_root_bh);
23828c2ecf20Sopenharmony_ci	return ret;
23838c2ecf20Sopenharmony_ci}
23848c2ecf20Sopenharmony_ci
23858c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_format_cluster(struct ocfs2_super *osb,
23868c2ecf20Sopenharmony_ci				       handle_t *handle, struct inode *dir,
23878c2ecf20Sopenharmony_ci				       struct buffer_head **dx_leaves,
23888c2ecf20Sopenharmony_ci				       int num_dx_leaves, u64 start_blk)
23898c2ecf20Sopenharmony_ci{
23908c2ecf20Sopenharmony_ci	int ret, i;
23918c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
23928c2ecf20Sopenharmony_ci	struct buffer_head *bh;
23938c2ecf20Sopenharmony_ci
23948c2ecf20Sopenharmony_ci	for (i = 0; i < num_dx_leaves; i++) {
23958c2ecf20Sopenharmony_ci		bh = sb_getblk(osb->sb, start_blk + i);
23968c2ecf20Sopenharmony_ci		if (bh == NULL) {
23978c2ecf20Sopenharmony_ci			ret = -ENOMEM;
23988c2ecf20Sopenharmony_ci			goto out;
23998c2ecf20Sopenharmony_ci		}
24008c2ecf20Sopenharmony_ci		dx_leaves[i] = bh;
24018c2ecf20Sopenharmony_ci
24028c2ecf20Sopenharmony_ci		ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), bh);
24038c2ecf20Sopenharmony_ci
24048c2ecf20Sopenharmony_ci		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), bh,
24058c2ecf20Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_CREATE);
24068c2ecf20Sopenharmony_ci		if (ret < 0) {
24078c2ecf20Sopenharmony_ci			mlog_errno(ret);
24088c2ecf20Sopenharmony_ci			goto out;
24098c2ecf20Sopenharmony_ci		}
24108c2ecf20Sopenharmony_ci
24118c2ecf20Sopenharmony_ci		dx_leaf = (struct ocfs2_dx_leaf *) bh->b_data;
24128c2ecf20Sopenharmony_ci
24138c2ecf20Sopenharmony_ci		memset(dx_leaf, 0, osb->sb->s_blocksize);
24148c2ecf20Sopenharmony_ci		strcpy(dx_leaf->dl_signature, OCFS2_DX_LEAF_SIGNATURE);
24158c2ecf20Sopenharmony_ci		dx_leaf->dl_fs_generation = cpu_to_le32(osb->fs_generation);
24168c2ecf20Sopenharmony_ci		dx_leaf->dl_blkno = cpu_to_le64(bh->b_blocknr);
24178c2ecf20Sopenharmony_ci		dx_leaf->dl_list.de_count =
24188c2ecf20Sopenharmony_ci			cpu_to_le16(ocfs2_dx_entries_per_leaf(osb->sb));
24198c2ecf20Sopenharmony_ci
24208c2ecf20Sopenharmony_ci		trace_ocfs2_dx_dir_format_cluster(
24218c2ecf20Sopenharmony_ci				(unsigned long long)OCFS2_I(dir)->ip_blkno,
24228c2ecf20Sopenharmony_ci				(unsigned long long)bh->b_blocknr,
24238c2ecf20Sopenharmony_ci				le16_to_cpu(dx_leaf->dl_list.de_count));
24248c2ecf20Sopenharmony_ci
24258c2ecf20Sopenharmony_ci		ocfs2_journal_dirty(handle, bh);
24268c2ecf20Sopenharmony_ci	}
24278c2ecf20Sopenharmony_ci
24288c2ecf20Sopenharmony_ci	ret = 0;
24298c2ecf20Sopenharmony_ciout:
24308c2ecf20Sopenharmony_ci	return ret;
24318c2ecf20Sopenharmony_ci}
24328c2ecf20Sopenharmony_ci
24338c2ecf20Sopenharmony_ci/*
24348c2ecf20Sopenharmony_ci * Allocates and formats a new cluster for use in an indexed dir
24358c2ecf20Sopenharmony_ci * leaf. This version will not do the extent insert, so that it can be
24368c2ecf20Sopenharmony_ci * used by operations which need careful ordering.
24378c2ecf20Sopenharmony_ci */
24388c2ecf20Sopenharmony_cistatic int __ocfs2_dx_dir_new_cluster(struct inode *dir,
24398c2ecf20Sopenharmony_ci				      u32 cpos, handle_t *handle,
24408c2ecf20Sopenharmony_ci				      struct ocfs2_alloc_context *data_ac,
24418c2ecf20Sopenharmony_ci				      struct buffer_head **dx_leaves,
24428c2ecf20Sopenharmony_ci				      int num_dx_leaves, u64 *ret_phys_blkno)
24438c2ecf20Sopenharmony_ci{
24448c2ecf20Sopenharmony_ci	int ret;
24458c2ecf20Sopenharmony_ci	u32 phys, num;
24468c2ecf20Sopenharmony_ci	u64 phys_blkno;
24478c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
24488c2ecf20Sopenharmony_ci
24498c2ecf20Sopenharmony_ci	/*
24508c2ecf20Sopenharmony_ci	 * XXX: For create, this should claim cluster for the index
24518c2ecf20Sopenharmony_ci	 * *before* the unindexed insert so that we have a better
24528c2ecf20Sopenharmony_ci	 * chance of contiguousness as the directory grows in number
24538c2ecf20Sopenharmony_ci	 * of entries.
24548c2ecf20Sopenharmony_ci	 */
24558c2ecf20Sopenharmony_ci	ret = __ocfs2_claim_clusters(handle, data_ac, 1, 1, &phys, &num);
24568c2ecf20Sopenharmony_ci	if (ret) {
24578c2ecf20Sopenharmony_ci		mlog_errno(ret);
24588c2ecf20Sopenharmony_ci		goto out;
24598c2ecf20Sopenharmony_ci	}
24608c2ecf20Sopenharmony_ci
24618c2ecf20Sopenharmony_ci	/*
24628c2ecf20Sopenharmony_ci	 * Format the new cluster first. That way, we're inserting
24638c2ecf20Sopenharmony_ci	 * valid data.
24648c2ecf20Sopenharmony_ci	 */
24658c2ecf20Sopenharmony_ci	phys_blkno = ocfs2_clusters_to_blocks(osb->sb, phys);
24668c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_format_cluster(osb, handle, dir, dx_leaves,
24678c2ecf20Sopenharmony_ci					  num_dx_leaves, phys_blkno);
24688c2ecf20Sopenharmony_ci	if (ret) {
24698c2ecf20Sopenharmony_ci		mlog_errno(ret);
24708c2ecf20Sopenharmony_ci		goto out;
24718c2ecf20Sopenharmony_ci	}
24728c2ecf20Sopenharmony_ci
24738c2ecf20Sopenharmony_ci	*ret_phys_blkno = phys_blkno;
24748c2ecf20Sopenharmony_ciout:
24758c2ecf20Sopenharmony_ci	return ret;
24768c2ecf20Sopenharmony_ci}
24778c2ecf20Sopenharmony_ci
24788c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_new_cluster(struct inode *dir,
24798c2ecf20Sopenharmony_ci				    struct ocfs2_extent_tree *et,
24808c2ecf20Sopenharmony_ci				    u32 cpos, handle_t *handle,
24818c2ecf20Sopenharmony_ci				    struct ocfs2_alloc_context *data_ac,
24828c2ecf20Sopenharmony_ci				    struct ocfs2_alloc_context *meta_ac,
24838c2ecf20Sopenharmony_ci				    struct buffer_head **dx_leaves,
24848c2ecf20Sopenharmony_ci				    int num_dx_leaves)
24858c2ecf20Sopenharmony_ci{
24868c2ecf20Sopenharmony_ci	int ret;
24878c2ecf20Sopenharmony_ci	u64 phys_blkno;
24888c2ecf20Sopenharmony_ci
24898c2ecf20Sopenharmony_ci	ret = __ocfs2_dx_dir_new_cluster(dir, cpos, handle, data_ac, dx_leaves,
24908c2ecf20Sopenharmony_ci					 num_dx_leaves, &phys_blkno);
24918c2ecf20Sopenharmony_ci	if (ret) {
24928c2ecf20Sopenharmony_ci		mlog_errno(ret);
24938c2ecf20Sopenharmony_ci		goto out;
24948c2ecf20Sopenharmony_ci	}
24958c2ecf20Sopenharmony_ci
24968c2ecf20Sopenharmony_ci	ret = ocfs2_insert_extent(handle, et, cpos, phys_blkno, 1, 0,
24978c2ecf20Sopenharmony_ci				  meta_ac);
24988c2ecf20Sopenharmony_ci	if (ret)
24998c2ecf20Sopenharmony_ci		mlog_errno(ret);
25008c2ecf20Sopenharmony_ciout:
25018c2ecf20Sopenharmony_ci	return ret;
25028c2ecf20Sopenharmony_ci}
25038c2ecf20Sopenharmony_ci
25048c2ecf20Sopenharmony_cistatic struct buffer_head **ocfs2_dx_dir_kmalloc_leaves(struct super_block *sb,
25058c2ecf20Sopenharmony_ci							int *ret_num_leaves)
25068c2ecf20Sopenharmony_ci{
25078c2ecf20Sopenharmony_ci	int num_dx_leaves = ocfs2_clusters_to_blocks(sb, 1);
25088c2ecf20Sopenharmony_ci	struct buffer_head **dx_leaves;
25098c2ecf20Sopenharmony_ci
25108c2ecf20Sopenharmony_ci	dx_leaves = kcalloc(num_dx_leaves, sizeof(struct buffer_head *),
25118c2ecf20Sopenharmony_ci			    GFP_NOFS);
25128c2ecf20Sopenharmony_ci	if (dx_leaves && ret_num_leaves)
25138c2ecf20Sopenharmony_ci		*ret_num_leaves = num_dx_leaves;
25148c2ecf20Sopenharmony_ci
25158c2ecf20Sopenharmony_ci	return dx_leaves;
25168c2ecf20Sopenharmony_ci}
25178c2ecf20Sopenharmony_ci
25188c2ecf20Sopenharmony_cistatic int ocfs2_fill_new_dir_dx(struct ocfs2_super *osb,
25198c2ecf20Sopenharmony_ci				 handle_t *handle,
25208c2ecf20Sopenharmony_ci				 struct inode *parent,
25218c2ecf20Sopenharmony_ci				 struct inode *inode,
25228c2ecf20Sopenharmony_ci				 struct buffer_head *di_bh,
25238c2ecf20Sopenharmony_ci				 struct ocfs2_alloc_context *data_ac,
25248c2ecf20Sopenharmony_ci				 struct ocfs2_alloc_context *meta_ac)
25258c2ecf20Sopenharmony_ci{
25268c2ecf20Sopenharmony_ci	int ret;
25278c2ecf20Sopenharmony_ci	struct buffer_head *leaf_bh = NULL;
25288c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
25298c2ecf20Sopenharmony_ci	struct ocfs2_dx_hinfo hinfo;
25308c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
25318c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
25328c2ecf20Sopenharmony_ci
25338c2ecf20Sopenharmony_ci	/*
25348c2ecf20Sopenharmony_ci	 * Our strategy is to create the directory as though it were
25358c2ecf20Sopenharmony_ci	 * unindexed, then add the index block. This works with very
25368c2ecf20Sopenharmony_ci	 * little complication since the state of a new directory is a
25378c2ecf20Sopenharmony_ci	 * very well known quantity.
25388c2ecf20Sopenharmony_ci	 *
25398c2ecf20Sopenharmony_ci	 * Essentially, we have two dirents ("." and ".."), in the 1st
25408c2ecf20Sopenharmony_ci	 * block which need indexing. These are easily inserted into
25418c2ecf20Sopenharmony_ci	 * the index block.
25428c2ecf20Sopenharmony_ci	 */
25438c2ecf20Sopenharmony_ci
25448c2ecf20Sopenharmony_ci	ret = ocfs2_fill_new_dir_el(osb, handle, parent, inode, di_bh,
25458c2ecf20Sopenharmony_ci				    data_ac, &leaf_bh);
25468c2ecf20Sopenharmony_ci	if (ret) {
25478c2ecf20Sopenharmony_ci		mlog_errno(ret);
25488c2ecf20Sopenharmony_ci		goto out;
25498c2ecf20Sopenharmony_ci	}
25508c2ecf20Sopenharmony_ci
25518c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_attach_index(osb, handle, inode, di_bh, leaf_bh,
25528c2ecf20Sopenharmony_ci					meta_ac, 1, 2, &dx_root_bh);
25538c2ecf20Sopenharmony_ci	if (ret) {
25548c2ecf20Sopenharmony_ci		mlog_errno(ret);
25558c2ecf20Sopenharmony_ci		goto out;
25568c2ecf20Sopenharmony_ci	}
25578c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
25588c2ecf20Sopenharmony_ci	entry_list = &dx_root->dr_entries;
25598c2ecf20Sopenharmony_ci
25608c2ecf20Sopenharmony_ci	/* Buffer has been journaled for us by ocfs2_dx_dir_attach_index */
25618c2ecf20Sopenharmony_ci	ocfs2_dx_dir_name_hash(inode, ".", 1, &hinfo);
25628c2ecf20Sopenharmony_ci	ocfs2_dx_entry_list_insert(entry_list, &hinfo, leaf_bh->b_blocknr);
25638c2ecf20Sopenharmony_ci
25648c2ecf20Sopenharmony_ci	ocfs2_dx_dir_name_hash(inode, "..", 2, &hinfo);
25658c2ecf20Sopenharmony_ci	ocfs2_dx_entry_list_insert(entry_list, &hinfo, leaf_bh->b_blocknr);
25668c2ecf20Sopenharmony_ci
25678c2ecf20Sopenharmony_ciout:
25688c2ecf20Sopenharmony_ci	brelse(dx_root_bh);
25698c2ecf20Sopenharmony_ci	brelse(leaf_bh);
25708c2ecf20Sopenharmony_ci	return ret;
25718c2ecf20Sopenharmony_ci}
25728c2ecf20Sopenharmony_ci
25738c2ecf20Sopenharmony_ciint ocfs2_fill_new_dir(struct ocfs2_super *osb,
25748c2ecf20Sopenharmony_ci		       handle_t *handle,
25758c2ecf20Sopenharmony_ci		       struct inode *parent,
25768c2ecf20Sopenharmony_ci		       struct inode *inode,
25778c2ecf20Sopenharmony_ci		       struct buffer_head *fe_bh,
25788c2ecf20Sopenharmony_ci		       struct ocfs2_alloc_context *data_ac,
25798c2ecf20Sopenharmony_ci		       struct ocfs2_alloc_context *meta_ac)
25808c2ecf20Sopenharmony_ci
25818c2ecf20Sopenharmony_ci{
25828c2ecf20Sopenharmony_ci	BUG_ON(!ocfs2_supports_inline_data(osb) && data_ac == NULL);
25838c2ecf20Sopenharmony_ci
25848c2ecf20Sopenharmony_ci	if (OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
25858c2ecf20Sopenharmony_ci		return ocfs2_fill_new_dir_id(osb, handle, parent, inode, fe_bh);
25868c2ecf20Sopenharmony_ci
25878c2ecf20Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb))
25888c2ecf20Sopenharmony_ci		return ocfs2_fill_new_dir_dx(osb, handle, parent, inode, fe_bh,
25898c2ecf20Sopenharmony_ci					     data_ac, meta_ac);
25908c2ecf20Sopenharmony_ci
25918c2ecf20Sopenharmony_ci	return ocfs2_fill_new_dir_el(osb, handle, parent, inode, fe_bh,
25928c2ecf20Sopenharmony_ci				     data_ac, NULL);
25938c2ecf20Sopenharmony_ci}
25948c2ecf20Sopenharmony_ci
25958c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_index_block(struct inode *dir,
25968c2ecf20Sopenharmony_ci				    handle_t *handle,
25978c2ecf20Sopenharmony_ci				    struct buffer_head **dx_leaves,
25988c2ecf20Sopenharmony_ci				    int num_dx_leaves,
25998c2ecf20Sopenharmony_ci				    u32 *num_dx_entries,
26008c2ecf20Sopenharmony_ci				    struct buffer_head *dirent_bh)
26018c2ecf20Sopenharmony_ci{
26028c2ecf20Sopenharmony_ci	int ret = 0, namelen, i;
26038c2ecf20Sopenharmony_ci	char *de_buf, *limit;
26048c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
26058c2ecf20Sopenharmony_ci	struct buffer_head *dx_leaf_bh;
26068c2ecf20Sopenharmony_ci	struct ocfs2_dx_hinfo hinfo;
26078c2ecf20Sopenharmony_ci	u64 dirent_blk = dirent_bh->b_blocknr;
26088c2ecf20Sopenharmony_ci
26098c2ecf20Sopenharmony_ci	de_buf = dirent_bh->b_data;
26108c2ecf20Sopenharmony_ci	limit = de_buf + dir->i_sb->s_blocksize;
26118c2ecf20Sopenharmony_ci
26128c2ecf20Sopenharmony_ci	while (de_buf < limit) {
26138c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
26148c2ecf20Sopenharmony_ci
26158c2ecf20Sopenharmony_ci		namelen = de->name_len;
26168c2ecf20Sopenharmony_ci		if (!namelen || !de->inode)
26178c2ecf20Sopenharmony_ci			goto inc;
26188c2ecf20Sopenharmony_ci
26198c2ecf20Sopenharmony_ci		ocfs2_dx_dir_name_hash(dir, de->name, namelen, &hinfo);
26208c2ecf20Sopenharmony_ci
26218c2ecf20Sopenharmony_ci		i = ocfs2_dx_dir_hash_idx(OCFS2_SB(dir->i_sb), &hinfo);
26228c2ecf20Sopenharmony_ci		dx_leaf_bh = dx_leaves[i];
26238c2ecf20Sopenharmony_ci
26248c2ecf20Sopenharmony_ci		ret = __ocfs2_dx_dir_leaf_insert(dir, handle, &hinfo,
26258c2ecf20Sopenharmony_ci						 dirent_blk, dx_leaf_bh);
26268c2ecf20Sopenharmony_ci		if (ret) {
26278c2ecf20Sopenharmony_ci			mlog_errno(ret);
26288c2ecf20Sopenharmony_ci			goto out;
26298c2ecf20Sopenharmony_ci		}
26308c2ecf20Sopenharmony_ci
26318c2ecf20Sopenharmony_ci		*num_dx_entries = *num_dx_entries + 1;
26328c2ecf20Sopenharmony_ci
26338c2ecf20Sopenharmony_ciinc:
26348c2ecf20Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
26358c2ecf20Sopenharmony_ci	}
26368c2ecf20Sopenharmony_ci
26378c2ecf20Sopenharmony_ciout:
26388c2ecf20Sopenharmony_ci	return ret;
26398c2ecf20Sopenharmony_ci}
26408c2ecf20Sopenharmony_ci
26418c2ecf20Sopenharmony_ci/*
26428c2ecf20Sopenharmony_ci * XXX: This expects dx_root_bh to already be part of the transaction.
26438c2ecf20Sopenharmony_ci */
26448c2ecf20Sopenharmony_cistatic void ocfs2_dx_dir_index_root_block(struct inode *dir,
26458c2ecf20Sopenharmony_ci					 struct buffer_head *dx_root_bh,
26468c2ecf20Sopenharmony_ci					 struct buffer_head *dirent_bh)
26478c2ecf20Sopenharmony_ci{
26488c2ecf20Sopenharmony_ci	char *de_buf, *limit;
26498c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
26508c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
26518c2ecf20Sopenharmony_ci	struct ocfs2_dx_hinfo hinfo;
26528c2ecf20Sopenharmony_ci	u64 dirent_blk = dirent_bh->b_blocknr;
26538c2ecf20Sopenharmony_ci
26548c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
26558c2ecf20Sopenharmony_ci
26568c2ecf20Sopenharmony_ci	de_buf = dirent_bh->b_data;
26578c2ecf20Sopenharmony_ci	limit = de_buf + dir->i_sb->s_blocksize;
26588c2ecf20Sopenharmony_ci
26598c2ecf20Sopenharmony_ci	while (de_buf < limit) {
26608c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
26618c2ecf20Sopenharmony_ci
26628c2ecf20Sopenharmony_ci		if (!de->name_len || !de->inode)
26638c2ecf20Sopenharmony_ci			goto inc;
26648c2ecf20Sopenharmony_ci
26658c2ecf20Sopenharmony_ci		ocfs2_dx_dir_name_hash(dir, de->name, de->name_len, &hinfo);
26668c2ecf20Sopenharmony_ci
26678c2ecf20Sopenharmony_ci		trace_ocfs2_dx_dir_index_root_block(
26688c2ecf20Sopenharmony_ci				(unsigned long long)dir->i_ino,
26698c2ecf20Sopenharmony_ci				hinfo.major_hash, hinfo.minor_hash,
26708c2ecf20Sopenharmony_ci				de->name_len, de->name,
26718c2ecf20Sopenharmony_ci				le16_to_cpu(dx_root->dr_entries.de_num_used));
26728c2ecf20Sopenharmony_ci
26738c2ecf20Sopenharmony_ci		ocfs2_dx_entry_list_insert(&dx_root->dr_entries, &hinfo,
26748c2ecf20Sopenharmony_ci					   dirent_blk);
26758c2ecf20Sopenharmony_ci
26768c2ecf20Sopenharmony_ci		le32_add_cpu(&dx_root->dr_num_entries, 1);
26778c2ecf20Sopenharmony_ciinc:
26788c2ecf20Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
26798c2ecf20Sopenharmony_ci	}
26808c2ecf20Sopenharmony_ci}
26818c2ecf20Sopenharmony_ci
26828c2ecf20Sopenharmony_ci/*
26838c2ecf20Sopenharmony_ci * Count the number of inline directory entries in di_bh and compare
26848c2ecf20Sopenharmony_ci * them against the number of entries we can hold in an inline dx root
26858c2ecf20Sopenharmony_ci * block.
26868c2ecf20Sopenharmony_ci */
26878c2ecf20Sopenharmony_cistatic int ocfs2_new_dx_should_be_inline(struct inode *dir,
26888c2ecf20Sopenharmony_ci					 struct buffer_head *di_bh)
26898c2ecf20Sopenharmony_ci{
26908c2ecf20Sopenharmony_ci	int dirent_count = 0;
26918c2ecf20Sopenharmony_ci	char *de_buf, *limit;
26928c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
26938c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
26948c2ecf20Sopenharmony_ci
26958c2ecf20Sopenharmony_ci	de_buf = di->id2.i_data.id_data;
26968c2ecf20Sopenharmony_ci	limit = de_buf + i_size_read(dir);
26978c2ecf20Sopenharmony_ci
26988c2ecf20Sopenharmony_ci	while (de_buf < limit) {
26998c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
27008c2ecf20Sopenharmony_ci
27018c2ecf20Sopenharmony_ci		if (de->name_len && de->inode)
27028c2ecf20Sopenharmony_ci			dirent_count++;
27038c2ecf20Sopenharmony_ci
27048c2ecf20Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
27058c2ecf20Sopenharmony_ci	}
27068c2ecf20Sopenharmony_ci
27078c2ecf20Sopenharmony_ci	/* We are careful to leave room for one extra record. */
27088c2ecf20Sopenharmony_ci	return dirent_count < ocfs2_dx_entries_per_root(dir->i_sb);
27098c2ecf20Sopenharmony_ci}
27108c2ecf20Sopenharmony_ci
27118c2ecf20Sopenharmony_ci/*
27128c2ecf20Sopenharmony_ci * Expand rec_len of the rightmost dirent in a directory block so that it
27138c2ecf20Sopenharmony_ci * contains the end of our valid space for dirents. We do this during
27148c2ecf20Sopenharmony_ci * expansion from an inline directory to one with extents. The first dir block
27158c2ecf20Sopenharmony_ci * in that case is taken from the inline data portion of the inode block.
27168c2ecf20Sopenharmony_ci *
27178c2ecf20Sopenharmony_ci * This will also return the largest amount of contiguous space for a dirent
27188c2ecf20Sopenharmony_ci * in the block. That value is *not* necessarily the last dirent, even after
27198c2ecf20Sopenharmony_ci * expansion. The directory indexing code wants this value for free space
27208c2ecf20Sopenharmony_ci * accounting. We do this here since we're already walking the entire dir
27218c2ecf20Sopenharmony_ci * block.
27228c2ecf20Sopenharmony_ci *
27238c2ecf20Sopenharmony_ci * We add the dir trailer if this filesystem wants it.
27248c2ecf20Sopenharmony_ci */
27258c2ecf20Sopenharmony_cistatic unsigned int ocfs2_expand_last_dirent(char *start, unsigned int old_size,
27268c2ecf20Sopenharmony_ci					     struct inode *dir)
27278c2ecf20Sopenharmony_ci{
27288c2ecf20Sopenharmony_ci	struct super_block *sb = dir->i_sb;
27298c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
27308c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *prev_de;
27318c2ecf20Sopenharmony_ci	char *de_buf, *limit;
27328c2ecf20Sopenharmony_ci	unsigned int new_size = sb->s_blocksize;
27338c2ecf20Sopenharmony_ci	unsigned int bytes, this_hole;
27348c2ecf20Sopenharmony_ci	unsigned int largest_hole = 0;
27358c2ecf20Sopenharmony_ci
27368c2ecf20Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(dir))
27378c2ecf20Sopenharmony_ci		new_size = ocfs2_dir_trailer_blk_off(sb);
27388c2ecf20Sopenharmony_ci
27398c2ecf20Sopenharmony_ci	bytes = new_size - old_size;
27408c2ecf20Sopenharmony_ci
27418c2ecf20Sopenharmony_ci	limit = start + old_size;
27428c2ecf20Sopenharmony_ci	de_buf = start;
27438c2ecf20Sopenharmony_ci	de = (struct ocfs2_dir_entry *)de_buf;
27448c2ecf20Sopenharmony_ci	do {
27458c2ecf20Sopenharmony_ci		this_hole = ocfs2_figure_dirent_hole(de);
27468c2ecf20Sopenharmony_ci		if (this_hole > largest_hole)
27478c2ecf20Sopenharmony_ci			largest_hole = this_hole;
27488c2ecf20Sopenharmony_ci
27498c2ecf20Sopenharmony_ci		prev_de = de;
27508c2ecf20Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
27518c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
27528c2ecf20Sopenharmony_ci	} while (de_buf < limit);
27538c2ecf20Sopenharmony_ci
27548c2ecf20Sopenharmony_ci	le16_add_cpu(&prev_de->rec_len, bytes);
27558c2ecf20Sopenharmony_ci
27568c2ecf20Sopenharmony_ci	/* We need to double check this after modification of the final
27578c2ecf20Sopenharmony_ci	 * dirent. */
27588c2ecf20Sopenharmony_ci	this_hole = ocfs2_figure_dirent_hole(prev_de);
27598c2ecf20Sopenharmony_ci	if (this_hole > largest_hole)
27608c2ecf20Sopenharmony_ci		largest_hole = this_hole;
27618c2ecf20Sopenharmony_ci
27628c2ecf20Sopenharmony_ci	if (largest_hole >= OCFS2_DIR_MIN_REC_LEN)
27638c2ecf20Sopenharmony_ci		return largest_hole;
27648c2ecf20Sopenharmony_ci	return 0;
27658c2ecf20Sopenharmony_ci}
27668c2ecf20Sopenharmony_ci
27678c2ecf20Sopenharmony_ci/*
27688c2ecf20Sopenharmony_ci * We allocate enough clusters to fulfill "blocks_wanted", but set
27698c2ecf20Sopenharmony_ci * i_size to exactly one block. Ocfs2_extend_dir() will handle the
27708c2ecf20Sopenharmony_ci * rest automatically for us.
27718c2ecf20Sopenharmony_ci *
27728c2ecf20Sopenharmony_ci * *first_block_bh is a pointer to the 1st data block allocated to the
27738c2ecf20Sopenharmony_ci *  directory.
27748c2ecf20Sopenharmony_ci */
27758c2ecf20Sopenharmony_cistatic int ocfs2_expand_inline_dir(struct inode *dir, struct buffer_head *di_bh,
27768c2ecf20Sopenharmony_ci				   unsigned int blocks_wanted,
27778c2ecf20Sopenharmony_ci				   struct ocfs2_dir_lookup_result *lookup,
27788c2ecf20Sopenharmony_ci				   struct buffer_head **first_block_bh)
27798c2ecf20Sopenharmony_ci{
27808c2ecf20Sopenharmony_ci	u32 alloc, dx_alloc, bit_off, len, num_dx_entries = 0;
27818c2ecf20Sopenharmony_ci	struct super_block *sb = dir->i_sb;
27828c2ecf20Sopenharmony_ci	int ret, i, num_dx_leaves = 0, dx_inline = 0,
27838c2ecf20Sopenharmony_ci		credits = ocfs2_inline_to_extents_credits(sb);
27848c2ecf20Sopenharmony_ci	u64 dx_insert_blkno, blkno,
27858c2ecf20Sopenharmony_ci		bytes = blocks_wanted << sb->s_blocksize_bits;
27868c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
27878c2ecf20Sopenharmony_ci	struct ocfs2_inode_info *oi = OCFS2_I(dir);
27888c2ecf20Sopenharmony_ci	struct ocfs2_alloc_context *data_ac = NULL;
27898c2ecf20Sopenharmony_ci	struct ocfs2_alloc_context *meta_ac = NULL;
27908c2ecf20Sopenharmony_ci	struct buffer_head *dirdata_bh = NULL;
27918c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
27928c2ecf20Sopenharmony_ci	struct buffer_head **dx_leaves = NULL;
27938c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
27948c2ecf20Sopenharmony_ci	handle_t *handle;
27958c2ecf20Sopenharmony_ci	struct ocfs2_extent_tree et;
27968c2ecf20Sopenharmony_ci	struct ocfs2_extent_tree dx_et;
27978c2ecf20Sopenharmony_ci	int did_quota = 0, bytes_allocated = 0;
27988c2ecf20Sopenharmony_ci
27998c2ecf20Sopenharmony_ci	ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir), di_bh);
28008c2ecf20Sopenharmony_ci
28018c2ecf20Sopenharmony_ci	alloc = ocfs2_clusters_for_bytes(sb, bytes);
28028c2ecf20Sopenharmony_ci	dx_alloc = 0;
28038c2ecf20Sopenharmony_ci
28048c2ecf20Sopenharmony_ci	down_write(&oi->ip_alloc_sem);
28058c2ecf20Sopenharmony_ci
28068c2ecf20Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb)) {
28078c2ecf20Sopenharmony_ci		credits += ocfs2_add_dir_index_credits(sb);
28088c2ecf20Sopenharmony_ci
28098c2ecf20Sopenharmony_ci		dx_inline = ocfs2_new_dx_should_be_inline(dir, di_bh);
28108c2ecf20Sopenharmony_ci		if (!dx_inline) {
28118c2ecf20Sopenharmony_ci			/* Add one more cluster for an index leaf */
28128c2ecf20Sopenharmony_ci			dx_alloc++;
28138c2ecf20Sopenharmony_ci			dx_leaves = ocfs2_dx_dir_kmalloc_leaves(sb,
28148c2ecf20Sopenharmony_ci								&num_dx_leaves);
28158c2ecf20Sopenharmony_ci			if (!dx_leaves) {
28168c2ecf20Sopenharmony_ci				ret = -ENOMEM;
28178c2ecf20Sopenharmony_ci				mlog_errno(ret);
28188c2ecf20Sopenharmony_ci				goto out;
28198c2ecf20Sopenharmony_ci			}
28208c2ecf20Sopenharmony_ci		}
28218c2ecf20Sopenharmony_ci
28228c2ecf20Sopenharmony_ci		/* This gets us the dx_root */
28238c2ecf20Sopenharmony_ci		ret = ocfs2_reserve_new_metadata_blocks(osb, 1, &meta_ac);
28248c2ecf20Sopenharmony_ci		if (ret) {
28258c2ecf20Sopenharmony_ci			mlog_errno(ret);
28268c2ecf20Sopenharmony_ci			goto out;
28278c2ecf20Sopenharmony_ci		}
28288c2ecf20Sopenharmony_ci	}
28298c2ecf20Sopenharmony_ci
28308c2ecf20Sopenharmony_ci	/*
28318c2ecf20Sopenharmony_ci	 * We should never need more than 2 clusters for the unindexed
28328c2ecf20Sopenharmony_ci	 * tree - maximum dirent size is far less than one block. In
28338c2ecf20Sopenharmony_ci	 * fact, the only time we'd need more than one cluster is if
28348c2ecf20Sopenharmony_ci	 * blocksize == clustersize and the dirent won't fit in the
28358c2ecf20Sopenharmony_ci	 * extra space that the expansion to a single block gives. As
28368c2ecf20Sopenharmony_ci	 * of today, that only happens on 4k/4k file systems.
28378c2ecf20Sopenharmony_ci	 */
28388c2ecf20Sopenharmony_ci	BUG_ON(alloc > 2);
28398c2ecf20Sopenharmony_ci
28408c2ecf20Sopenharmony_ci	ret = ocfs2_reserve_clusters(osb, alloc + dx_alloc, &data_ac);
28418c2ecf20Sopenharmony_ci	if (ret) {
28428c2ecf20Sopenharmony_ci		mlog_errno(ret);
28438c2ecf20Sopenharmony_ci		goto out;
28448c2ecf20Sopenharmony_ci	}
28458c2ecf20Sopenharmony_ci
28468c2ecf20Sopenharmony_ci	/*
28478c2ecf20Sopenharmony_ci	 * Prepare for worst case allocation scenario of two separate
28488c2ecf20Sopenharmony_ci	 * extents in the unindexed tree.
28498c2ecf20Sopenharmony_ci	 */
28508c2ecf20Sopenharmony_ci	if (alloc == 2)
28518c2ecf20Sopenharmony_ci		credits += OCFS2_SUBALLOC_ALLOC;
28528c2ecf20Sopenharmony_ci
28538c2ecf20Sopenharmony_ci	handle = ocfs2_start_trans(osb, credits);
28548c2ecf20Sopenharmony_ci	if (IS_ERR(handle)) {
28558c2ecf20Sopenharmony_ci		ret = PTR_ERR(handle);
28568c2ecf20Sopenharmony_ci		mlog_errno(ret);
28578c2ecf20Sopenharmony_ci		goto out;
28588c2ecf20Sopenharmony_ci	}
28598c2ecf20Sopenharmony_ci
28608c2ecf20Sopenharmony_ci	ret = dquot_alloc_space_nodirty(dir,
28618c2ecf20Sopenharmony_ci		ocfs2_clusters_to_bytes(osb->sb, alloc + dx_alloc));
28628c2ecf20Sopenharmony_ci	if (ret)
28638c2ecf20Sopenharmony_ci		goto out_commit;
28648c2ecf20Sopenharmony_ci	did_quota = 1;
28658c2ecf20Sopenharmony_ci
28668c2ecf20Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb) && !dx_inline) {
28678c2ecf20Sopenharmony_ci		/*
28688c2ecf20Sopenharmony_ci		 * Allocate our index cluster first, to maximize the
28698c2ecf20Sopenharmony_ci		 * possibility that unindexed leaves grow
28708c2ecf20Sopenharmony_ci		 * contiguously.
28718c2ecf20Sopenharmony_ci		 */
28728c2ecf20Sopenharmony_ci		ret = __ocfs2_dx_dir_new_cluster(dir, 0, handle, data_ac,
28738c2ecf20Sopenharmony_ci						 dx_leaves, num_dx_leaves,
28748c2ecf20Sopenharmony_ci						 &dx_insert_blkno);
28758c2ecf20Sopenharmony_ci		if (ret) {
28768c2ecf20Sopenharmony_ci			mlog_errno(ret);
28778c2ecf20Sopenharmony_ci			goto out_commit;
28788c2ecf20Sopenharmony_ci		}
28798c2ecf20Sopenharmony_ci		bytes_allocated += ocfs2_clusters_to_bytes(dir->i_sb, 1);
28808c2ecf20Sopenharmony_ci	}
28818c2ecf20Sopenharmony_ci
28828c2ecf20Sopenharmony_ci	/*
28838c2ecf20Sopenharmony_ci	 * Try to claim as many clusters as the bitmap can give though
28848c2ecf20Sopenharmony_ci	 * if we only get one now, that's enough to continue. The rest
28858c2ecf20Sopenharmony_ci	 * will be claimed after the conversion to extents.
28868c2ecf20Sopenharmony_ci	 */
28878c2ecf20Sopenharmony_ci	if (ocfs2_dir_resv_allowed(osb))
28888c2ecf20Sopenharmony_ci		data_ac->ac_resv = &oi->ip_la_data_resv;
28898c2ecf20Sopenharmony_ci	ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off, &len);
28908c2ecf20Sopenharmony_ci	if (ret) {
28918c2ecf20Sopenharmony_ci		mlog_errno(ret);
28928c2ecf20Sopenharmony_ci		goto out_commit;
28938c2ecf20Sopenharmony_ci	}
28948c2ecf20Sopenharmony_ci	bytes_allocated += ocfs2_clusters_to_bytes(dir->i_sb, 1);
28958c2ecf20Sopenharmony_ci
28968c2ecf20Sopenharmony_ci	/*
28978c2ecf20Sopenharmony_ci	 * Operations are carefully ordered so that we set up the new
28988c2ecf20Sopenharmony_ci	 * data block first. The conversion from inline data to
28998c2ecf20Sopenharmony_ci	 * extents follows.
29008c2ecf20Sopenharmony_ci	 */
29018c2ecf20Sopenharmony_ci	blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
29028c2ecf20Sopenharmony_ci	dirdata_bh = sb_getblk(sb, blkno);
29038c2ecf20Sopenharmony_ci	if (!dirdata_bh) {
29048c2ecf20Sopenharmony_ci		ret = -ENOMEM;
29058c2ecf20Sopenharmony_ci		mlog_errno(ret);
29068c2ecf20Sopenharmony_ci		goto out_commit;
29078c2ecf20Sopenharmony_ci	}
29088c2ecf20Sopenharmony_ci
29098c2ecf20Sopenharmony_ci	ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), dirdata_bh);
29108c2ecf20Sopenharmony_ci
29118c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_db(handle, INODE_CACHE(dir), dirdata_bh,
29128c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_CREATE);
29138c2ecf20Sopenharmony_ci	if (ret) {
29148c2ecf20Sopenharmony_ci		mlog_errno(ret);
29158c2ecf20Sopenharmony_ci		goto out_commit;
29168c2ecf20Sopenharmony_ci	}
29178c2ecf20Sopenharmony_ci
29188c2ecf20Sopenharmony_ci	memcpy(dirdata_bh->b_data, di->id2.i_data.id_data, i_size_read(dir));
29198c2ecf20Sopenharmony_ci	memset(dirdata_bh->b_data + i_size_read(dir), 0,
29208c2ecf20Sopenharmony_ci	       sb->s_blocksize - i_size_read(dir));
29218c2ecf20Sopenharmony_ci	i = ocfs2_expand_last_dirent(dirdata_bh->b_data, i_size_read(dir), dir);
29228c2ecf20Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(dir)) {
29238c2ecf20Sopenharmony_ci		/*
29248c2ecf20Sopenharmony_ci		 * Prepare the dir trailer up front. It will otherwise look
29258c2ecf20Sopenharmony_ci		 * like a valid dirent. Even if inserting the index fails
29268c2ecf20Sopenharmony_ci		 * (unlikely), then all we'll have done is given first dir
29278c2ecf20Sopenharmony_ci		 * block a small amount of fragmentation.
29288c2ecf20Sopenharmony_ci		 */
29298c2ecf20Sopenharmony_ci		ocfs2_init_dir_trailer(dir, dirdata_bh, i);
29308c2ecf20Sopenharmony_ci	}
29318c2ecf20Sopenharmony_ci
29328c2ecf20Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
29338c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, dirdata_bh);
29348c2ecf20Sopenharmony_ci
29358c2ecf20Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb) && !dx_inline) {
29368c2ecf20Sopenharmony_ci		/*
29378c2ecf20Sopenharmony_ci		 * Dx dirs with an external cluster need to do this up
29388c2ecf20Sopenharmony_ci		 * front. Inline dx root's get handled later, after
29398c2ecf20Sopenharmony_ci		 * we've allocated our root block. We get passed back
29408c2ecf20Sopenharmony_ci		 * a total number of items so that dr_num_entries can
29418c2ecf20Sopenharmony_ci		 * be correctly set once the dx_root has been
29428c2ecf20Sopenharmony_ci		 * allocated.
29438c2ecf20Sopenharmony_ci		 */
29448c2ecf20Sopenharmony_ci		ret = ocfs2_dx_dir_index_block(dir, handle, dx_leaves,
29458c2ecf20Sopenharmony_ci					       num_dx_leaves, &num_dx_entries,
29468c2ecf20Sopenharmony_ci					       dirdata_bh);
29478c2ecf20Sopenharmony_ci		if (ret) {
29488c2ecf20Sopenharmony_ci			mlog_errno(ret);
29498c2ecf20Sopenharmony_ci			goto out_commit;
29508c2ecf20Sopenharmony_ci		}
29518c2ecf20Sopenharmony_ci	}
29528c2ecf20Sopenharmony_ci
29538c2ecf20Sopenharmony_ci	/*
29548c2ecf20Sopenharmony_ci	 * Set extent, i_size, etc on the directory. After this, the
29558c2ecf20Sopenharmony_ci	 * inode should contain the same exact dirents as before and
29568c2ecf20Sopenharmony_ci	 * be fully accessible from system calls.
29578c2ecf20Sopenharmony_ci	 *
29588c2ecf20Sopenharmony_ci	 * We let the later dirent insert modify c/mtime - to the user
29598c2ecf20Sopenharmony_ci	 * the data hasn't changed.
29608c2ecf20Sopenharmony_ci	 */
29618c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
29628c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_CREATE);
29638c2ecf20Sopenharmony_ci	if (ret) {
29648c2ecf20Sopenharmony_ci		mlog_errno(ret);
29658c2ecf20Sopenharmony_ci		goto out_commit;
29668c2ecf20Sopenharmony_ci	}
29678c2ecf20Sopenharmony_ci
29688c2ecf20Sopenharmony_ci	spin_lock(&oi->ip_lock);
29698c2ecf20Sopenharmony_ci	oi->ip_dyn_features &= ~OCFS2_INLINE_DATA_FL;
29708c2ecf20Sopenharmony_ci	di->i_dyn_features = cpu_to_le16(oi->ip_dyn_features);
29718c2ecf20Sopenharmony_ci	spin_unlock(&oi->ip_lock);
29728c2ecf20Sopenharmony_ci
29738c2ecf20Sopenharmony_ci	ocfs2_dinode_new_extent_list(dir, di);
29748c2ecf20Sopenharmony_ci
29758c2ecf20Sopenharmony_ci	i_size_write(dir, sb->s_blocksize);
29768c2ecf20Sopenharmony_ci	dir->i_mtime = dir->i_ctime = current_time(dir);
29778c2ecf20Sopenharmony_ci
29788c2ecf20Sopenharmony_ci	di->i_size = cpu_to_le64(sb->s_blocksize);
29798c2ecf20Sopenharmony_ci	di->i_ctime = di->i_mtime = cpu_to_le64(dir->i_ctime.tv_sec);
29808c2ecf20Sopenharmony_ci	di->i_ctime_nsec = di->i_mtime_nsec = cpu_to_le32(dir->i_ctime.tv_nsec);
29818c2ecf20Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
29828c2ecf20Sopenharmony_ci
29838c2ecf20Sopenharmony_ci	/*
29848c2ecf20Sopenharmony_ci	 * This should never fail as our extent list is empty and all
29858c2ecf20Sopenharmony_ci	 * related blocks have been journaled already.
29868c2ecf20Sopenharmony_ci	 */
29878c2ecf20Sopenharmony_ci	ret = ocfs2_insert_extent(handle, &et, 0, blkno, len,
29888c2ecf20Sopenharmony_ci				  0, NULL);
29898c2ecf20Sopenharmony_ci	if (ret) {
29908c2ecf20Sopenharmony_ci		mlog_errno(ret);
29918c2ecf20Sopenharmony_ci		goto out_commit;
29928c2ecf20Sopenharmony_ci	}
29938c2ecf20Sopenharmony_ci
29948c2ecf20Sopenharmony_ci	/*
29958c2ecf20Sopenharmony_ci	 * Set i_blocks after the extent insert for the most up to
29968c2ecf20Sopenharmony_ci	 * date ip_clusters value.
29978c2ecf20Sopenharmony_ci	 */
29988c2ecf20Sopenharmony_ci	dir->i_blocks = ocfs2_inode_sector_count(dir);
29998c2ecf20Sopenharmony_ci
30008c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
30018c2ecf20Sopenharmony_ci
30028c2ecf20Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb)) {
30038c2ecf20Sopenharmony_ci		ret = ocfs2_dx_dir_attach_index(osb, handle, dir, di_bh,
30048c2ecf20Sopenharmony_ci						dirdata_bh, meta_ac, dx_inline,
30058c2ecf20Sopenharmony_ci						num_dx_entries, &dx_root_bh);
30068c2ecf20Sopenharmony_ci		if (ret) {
30078c2ecf20Sopenharmony_ci			mlog_errno(ret);
30088c2ecf20Sopenharmony_ci			goto out_commit;
30098c2ecf20Sopenharmony_ci		}
30108c2ecf20Sopenharmony_ci
30118c2ecf20Sopenharmony_ci		if (dx_inline) {
30128c2ecf20Sopenharmony_ci			ocfs2_dx_dir_index_root_block(dir, dx_root_bh,
30138c2ecf20Sopenharmony_ci						      dirdata_bh);
30148c2ecf20Sopenharmony_ci		} else {
30158c2ecf20Sopenharmony_ci			ocfs2_init_dx_root_extent_tree(&dx_et,
30168c2ecf20Sopenharmony_ci						       INODE_CACHE(dir),
30178c2ecf20Sopenharmony_ci						       dx_root_bh);
30188c2ecf20Sopenharmony_ci			ret = ocfs2_insert_extent(handle, &dx_et, 0,
30198c2ecf20Sopenharmony_ci						  dx_insert_blkno, 1, 0, NULL);
30208c2ecf20Sopenharmony_ci			if (ret)
30218c2ecf20Sopenharmony_ci				mlog_errno(ret);
30228c2ecf20Sopenharmony_ci		}
30238c2ecf20Sopenharmony_ci	}
30248c2ecf20Sopenharmony_ci
30258c2ecf20Sopenharmony_ci	/*
30268c2ecf20Sopenharmony_ci	 * We asked for two clusters, but only got one in the 1st
30278c2ecf20Sopenharmony_ci	 * pass. Claim the 2nd cluster as a separate extent.
30288c2ecf20Sopenharmony_ci	 */
30298c2ecf20Sopenharmony_ci	if (alloc > len) {
30308c2ecf20Sopenharmony_ci		ret = ocfs2_claim_clusters(handle, data_ac, 1, &bit_off,
30318c2ecf20Sopenharmony_ci					   &len);
30328c2ecf20Sopenharmony_ci		if (ret) {
30338c2ecf20Sopenharmony_ci			mlog_errno(ret);
30348c2ecf20Sopenharmony_ci			goto out_commit;
30358c2ecf20Sopenharmony_ci		}
30368c2ecf20Sopenharmony_ci		blkno = ocfs2_clusters_to_blocks(dir->i_sb, bit_off);
30378c2ecf20Sopenharmony_ci
30388c2ecf20Sopenharmony_ci		ret = ocfs2_insert_extent(handle, &et, 1,
30398c2ecf20Sopenharmony_ci					  blkno, len, 0, NULL);
30408c2ecf20Sopenharmony_ci		if (ret) {
30418c2ecf20Sopenharmony_ci			mlog_errno(ret);
30428c2ecf20Sopenharmony_ci			goto out_commit;
30438c2ecf20Sopenharmony_ci		}
30448c2ecf20Sopenharmony_ci		bytes_allocated += ocfs2_clusters_to_bytes(dir->i_sb, 1);
30458c2ecf20Sopenharmony_ci	}
30468c2ecf20Sopenharmony_ci
30478c2ecf20Sopenharmony_ci	*first_block_bh = dirdata_bh;
30488c2ecf20Sopenharmony_ci	dirdata_bh = NULL;
30498c2ecf20Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb)) {
30508c2ecf20Sopenharmony_ci		unsigned int off;
30518c2ecf20Sopenharmony_ci
30528c2ecf20Sopenharmony_ci		if (!dx_inline) {
30538c2ecf20Sopenharmony_ci			/*
30548c2ecf20Sopenharmony_ci			 * We need to return the correct block within the
30558c2ecf20Sopenharmony_ci			 * cluster which should hold our entry.
30568c2ecf20Sopenharmony_ci			 */
30578c2ecf20Sopenharmony_ci			off = ocfs2_dx_dir_hash_idx(osb,
30588c2ecf20Sopenharmony_ci						    &lookup->dl_hinfo);
30598c2ecf20Sopenharmony_ci			get_bh(dx_leaves[off]);
30608c2ecf20Sopenharmony_ci			lookup->dl_dx_leaf_bh = dx_leaves[off];
30618c2ecf20Sopenharmony_ci		}
30628c2ecf20Sopenharmony_ci		lookup->dl_dx_root_bh = dx_root_bh;
30638c2ecf20Sopenharmony_ci		dx_root_bh = NULL;
30648c2ecf20Sopenharmony_ci	}
30658c2ecf20Sopenharmony_ci
30668c2ecf20Sopenharmony_ciout_commit:
30678c2ecf20Sopenharmony_ci	if (ret < 0 && did_quota)
30688c2ecf20Sopenharmony_ci		dquot_free_space_nodirty(dir, bytes_allocated);
30698c2ecf20Sopenharmony_ci
30708c2ecf20Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
30718c2ecf20Sopenharmony_ci
30728c2ecf20Sopenharmony_ciout:
30738c2ecf20Sopenharmony_ci	up_write(&oi->ip_alloc_sem);
30748c2ecf20Sopenharmony_ci	if (data_ac)
30758c2ecf20Sopenharmony_ci		ocfs2_free_alloc_context(data_ac);
30768c2ecf20Sopenharmony_ci	if (meta_ac)
30778c2ecf20Sopenharmony_ci		ocfs2_free_alloc_context(meta_ac);
30788c2ecf20Sopenharmony_ci
30798c2ecf20Sopenharmony_ci	if (dx_leaves) {
30808c2ecf20Sopenharmony_ci		for (i = 0; i < num_dx_leaves; i++)
30818c2ecf20Sopenharmony_ci			brelse(dx_leaves[i]);
30828c2ecf20Sopenharmony_ci		kfree(dx_leaves);
30838c2ecf20Sopenharmony_ci	}
30848c2ecf20Sopenharmony_ci
30858c2ecf20Sopenharmony_ci	brelse(dirdata_bh);
30868c2ecf20Sopenharmony_ci	brelse(dx_root_bh);
30878c2ecf20Sopenharmony_ci
30888c2ecf20Sopenharmony_ci	return ret;
30898c2ecf20Sopenharmony_ci}
30908c2ecf20Sopenharmony_ci
30918c2ecf20Sopenharmony_ci/* returns a bh of the 1st new block in the allocation. */
30928c2ecf20Sopenharmony_cistatic int ocfs2_do_extend_dir(struct super_block *sb,
30938c2ecf20Sopenharmony_ci			       handle_t *handle,
30948c2ecf20Sopenharmony_ci			       struct inode *dir,
30958c2ecf20Sopenharmony_ci			       struct buffer_head *parent_fe_bh,
30968c2ecf20Sopenharmony_ci			       struct ocfs2_alloc_context *data_ac,
30978c2ecf20Sopenharmony_ci			       struct ocfs2_alloc_context *meta_ac,
30988c2ecf20Sopenharmony_ci			       struct buffer_head **new_bh)
30998c2ecf20Sopenharmony_ci{
31008c2ecf20Sopenharmony_ci	int status;
31018c2ecf20Sopenharmony_ci	int extend, did_quota = 0;
31028c2ecf20Sopenharmony_ci	u64 p_blkno, v_blkno;
31038c2ecf20Sopenharmony_ci
31048c2ecf20Sopenharmony_ci	spin_lock(&OCFS2_I(dir)->ip_lock);
31058c2ecf20Sopenharmony_ci	extend = (i_size_read(dir) == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters));
31068c2ecf20Sopenharmony_ci	spin_unlock(&OCFS2_I(dir)->ip_lock);
31078c2ecf20Sopenharmony_ci
31088c2ecf20Sopenharmony_ci	if (extend) {
31098c2ecf20Sopenharmony_ci		u32 offset = OCFS2_I(dir)->ip_clusters;
31108c2ecf20Sopenharmony_ci
31118c2ecf20Sopenharmony_ci		status = dquot_alloc_space_nodirty(dir,
31128c2ecf20Sopenharmony_ci					ocfs2_clusters_to_bytes(sb, 1));
31138c2ecf20Sopenharmony_ci		if (status)
31148c2ecf20Sopenharmony_ci			goto bail;
31158c2ecf20Sopenharmony_ci		did_quota = 1;
31168c2ecf20Sopenharmony_ci
31178c2ecf20Sopenharmony_ci		status = ocfs2_add_inode_data(OCFS2_SB(sb), dir, &offset,
31188c2ecf20Sopenharmony_ci					      1, 0, parent_fe_bh, handle,
31198c2ecf20Sopenharmony_ci					      data_ac, meta_ac, NULL);
31208c2ecf20Sopenharmony_ci		BUG_ON(status == -EAGAIN);
31218c2ecf20Sopenharmony_ci		if (status < 0) {
31228c2ecf20Sopenharmony_ci			mlog_errno(status);
31238c2ecf20Sopenharmony_ci			goto bail;
31248c2ecf20Sopenharmony_ci		}
31258c2ecf20Sopenharmony_ci	}
31268c2ecf20Sopenharmony_ci
31278c2ecf20Sopenharmony_ci	v_blkno = ocfs2_blocks_for_bytes(sb, i_size_read(dir));
31288c2ecf20Sopenharmony_ci	status = ocfs2_extent_map_get_blocks(dir, v_blkno, &p_blkno, NULL, NULL);
31298c2ecf20Sopenharmony_ci	if (status < 0) {
31308c2ecf20Sopenharmony_ci		mlog_errno(status);
31318c2ecf20Sopenharmony_ci		goto bail;
31328c2ecf20Sopenharmony_ci	}
31338c2ecf20Sopenharmony_ci
31348c2ecf20Sopenharmony_ci	*new_bh = sb_getblk(sb, p_blkno);
31358c2ecf20Sopenharmony_ci	if (!*new_bh) {
31368c2ecf20Sopenharmony_ci		status = -ENOMEM;
31378c2ecf20Sopenharmony_ci		mlog_errno(status);
31388c2ecf20Sopenharmony_ci		goto bail;
31398c2ecf20Sopenharmony_ci	}
31408c2ecf20Sopenharmony_ci	status = 0;
31418c2ecf20Sopenharmony_cibail:
31428c2ecf20Sopenharmony_ci	if (did_quota && status < 0)
31438c2ecf20Sopenharmony_ci		dquot_free_space_nodirty(dir, ocfs2_clusters_to_bytes(sb, 1));
31448c2ecf20Sopenharmony_ci	return status;
31458c2ecf20Sopenharmony_ci}
31468c2ecf20Sopenharmony_ci
31478c2ecf20Sopenharmony_ci/*
31488c2ecf20Sopenharmony_ci * Assumes you already have a cluster lock on the directory.
31498c2ecf20Sopenharmony_ci *
31508c2ecf20Sopenharmony_ci * 'blocks_wanted' is only used if we have an inline directory which
31518c2ecf20Sopenharmony_ci * is to be turned into an extent based one. The size of the dirent to
31528c2ecf20Sopenharmony_ci * insert might be larger than the space gained by growing to just one
31538c2ecf20Sopenharmony_ci * block, so we may have to grow the inode by two blocks in that case.
31548c2ecf20Sopenharmony_ci *
31558c2ecf20Sopenharmony_ci * If the directory is already indexed, dx_root_bh must be provided.
31568c2ecf20Sopenharmony_ci */
31578c2ecf20Sopenharmony_cistatic int ocfs2_extend_dir(struct ocfs2_super *osb,
31588c2ecf20Sopenharmony_ci			    struct inode *dir,
31598c2ecf20Sopenharmony_ci			    struct buffer_head *parent_fe_bh,
31608c2ecf20Sopenharmony_ci			    unsigned int blocks_wanted,
31618c2ecf20Sopenharmony_ci			    struct ocfs2_dir_lookup_result *lookup,
31628c2ecf20Sopenharmony_ci			    struct buffer_head **new_de_bh)
31638c2ecf20Sopenharmony_ci{
31648c2ecf20Sopenharmony_ci	int status = 0;
31658c2ecf20Sopenharmony_ci	int credits, num_free_extents, drop_alloc_sem = 0;
31668c2ecf20Sopenharmony_ci	loff_t dir_i_size;
31678c2ecf20Sopenharmony_ci	struct ocfs2_dinode *fe = (struct ocfs2_dinode *) parent_fe_bh->b_data;
31688c2ecf20Sopenharmony_ci	struct ocfs2_extent_list *el = &fe->id2.i_list;
31698c2ecf20Sopenharmony_ci	struct ocfs2_alloc_context *data_ac = NULL;
31708c2ecf20Sopenharmony_ci	struct ocfs2_alloc_context *meta_ac = NULL;
31718c2ecf20Sopenharmony_ci	handle_t *handle = NULL;
31728c2ecf20Sopenharmony_ci	struct buffer_head *new_bh = NULL;
31738c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry * de;
31748c2ecf20Sopenharmony_ci	struct super_block *sb = osb->sb;
31758c2ecf20Sopenharmony_ci	struct ocfs2_extent_tree et;
31768c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = lookup->dl_dx_root_bh;
31778c2ecf20Sopenharmony_ci
31788c2ecf20Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
31798c2ecf20Sopenharmony_ci		/*
31808c2ecf20Sopenharmony_ci		 * This would be a code error as an inline directory should
31818c2ecf20Sopenharmony_ci		 * never have an index root.
31828c2ecf20Sopenharmony_ci		 */
31838c2ecf20Sopenharmony_ci		BUG_ON(dx_root_bh);
31848c2ecf20Sopenharmony_ci
31858c2ecf20Sopenharmony_ci		status = ocfs2_expand_inline_dir(dir, parent_fe_bh,
31868c2ecf20Sopenharmony_ci						 blocks_wanted, lookup,
31878c2ecf20Sopenharmony_ci						 &new_bh);
31888c2ecf20Sopenharmony_ci		if (status) {
31898c2ecf20Sopenharmony_ci			mlog_errno(status);
31908c2ecf20Sopenharmony_ci			goto bail;
31918c2ecf20Sopenharmony_ci		}
31928c2ecf20Sopenharmony_ci
31938c2ecf20Sopenharmony_ci		/* Expansion from inline to an indexed directory will
31948c2ecf20Sopenharmony_ci		 * have given us this. */
31958c2ecf20Sopenharmony_ci		dx_root_bh = lookup->dl_dx_root_bh;
31968c2ecf20Sopenharmony_ci
31978c2ecf20Sopenharmony_ci		if (blocks_wanted == 1) {
31988c2ecf20Sopenharmony_ci			/*
31998c2ecf20Sopenharmony_ci			 * If the new dirent will fit inside the space
32008c2ecf20Sopenharmony_ci			 * created by pushing out to one block, then
32018c2ecf20Sopenharmony_ci			 * we can complete the operation
32028c2ecf20Sopenharmony_ci			 * here. Otherwise we have to expand i_size
32038c2ecf20Sopenharmony_ci			 * and format the 2nd block below.
32048c2ecf20Sopenharmony_ci			 */
32058c2ecf20Sopenharmony_ci			BUG_ON(new_bh == NULL);
32068c2ecf20Sopenharmony_ci			goto bail_bh;
32078c2ecf20Sopenharmony_ci		}
32088c2ecf20Sopenharmony_ci
32098c2ecf20Sopenharmony_ci		/*
32108c2ecf20Sopenharmony_ci		 * Get rid of 'new_bh' - we want to format the 2nd
32118c2ecf20Sopenharmony_ci		 * data block and return that instead.
32128c2ecf20Sopenharmony_ci		 */
32138c2ecf20Sopenharmony_ci		brelse(new_bh);
32148c2ecf20Sopenharmony_ci		new_bh = NULL;
32158c2ecf20Sopenharmony_ci
32168c2ecf20Sopenharmony_ci		down_write(&OCFS2_I(dir)->ip_alloc_sem);
32178c2ecf20Sopenharmony_ci		drop_alloc_sem = 1;
32188c2ecf20Sopenharmony_ci		dir_i_size = i_size_read(dir);
32198c2ecf20Sopenharmony_ci		credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
32208c2ecf20Sopenharmony_ci		goto do_extend;
32218c2ecf20Sopenharmony_ci	}
32228c2ecf20Sopenharmony_ci
32238c2ecf20Sopenharmony_ci	down_write(&OCFS2_I(dir)->ip_alloc_sem);
32248c2ecf20Sopenharmony_ci	drop_alloc_sem = 1;
32258c2ecf20Sopenharmony_ci	dir_i_size = i_size_read(dir);
32268c2ecf20Sopenharmony_ci	trace_ocfs2_extend_dir((unsigned long long)OCFS2_I(dir)->ip_blkno,
32278c2ecf20Sopenharmony_ci			       dir_i_size);
32288c2ecf20Sopenharmony_ci
32298c2ecf20Sopenharmony_ci	/* dir->i_size is always block aligned. */
32308c2ecf20Sopenharmony_ci	spin_lock(&OCFS2_I(dir)->ip_lock);
32318c2ecf20Sopenharmony_ci	if (dir_i_size == ocfs2_clusters_to_bytes(sb, OCFS2_I(dir)->ip_clusters)) {
32328c2ecf20Sopenharmony_ci		spin_unlock(&OCFS2_I(dir)->ip_lock);
32338c2ecf20Sopenharmony_ci		ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(dir),
32348c2ecf20Sopenharmony_ci					      parent_fe_bh);
32358c2ecf20Sopenharmony_ci		num_free_extents = ocfs2_num_free_extents(&et);
32368c2ecf20Sopenharmony_ci		if (num_free_extents < 0) {
32378c2ecf20Sopenharmony_ci			status = num_free_extents;
32388c2ecf20Sopenharmony_ci			mlog_errno(status);
32398c2ecf20Sopenharmony_ci			goto bail;
32408c2ecf20Sopenharmony_ci		}
32418c2ecf20Sopenharmony_ci
32428c2ecf20Sopenharmony_ci		if (!num_free_extents) {
32438c2ecf20Sopenharmony_ci			status = ocfs2_reserve_new_metadata(osb, el, &meta_ac);
32448c2ecf20Sopenharmony_ci			if (status < 0) {
32458c2ecf20Sopenharmony_ci				if (status != -ENOSPC)
32468c2ecf20Sopenharmony_ci					mlog_errno(status);
32478c2ecf20Sopenharmony_ci				goto bail;
32488c2ecf20Sopenharmony_ci			}
32498c2ecf20Sopenharmony_ci		}
32508c2ecf20Sopenharmony_ci
32518c2ecf20Sopenharmony_ci		status = ocfs2_reserve_clusters(osb, 1, &data_ac);
32528c2ecf20Sopenharmony_ci		if (status < 0) {
32538c2ecf20Sopenharmony_ci			if (status != -ENOSPC)
32548c2ecf20Sopenharmony_ci				mlog_errno(status);
32558c2ecf20Sopenharmony_ci			goto bail;
32568c2ecf20Sopenharmony_ci		}
32578c2ecf20Sopenharmony_ci
32588c2ecf20Sopenharmony_ci		if (ocfs2_dir_resv_allowed(osb))
32598c2ecf20Sopenharmony_ci			data_ac->ac_resv = &OCFS2_I(dir)->ip_la_data_resv;
32608c2ecf20Sopenharmony_ci
32618c2ecf20Sopenharmony_ci		credits = ocfs2_calc_extend_credits(sb, el);
32628c2ecf20Sopenharmony_ci	} else {
32638c2ecf20Sopenharmony_ci		spin_unlock(&OCFS2_I(dir)->ip_lock);
32648c2ecf20Sopenharmony_ci		credits = OCFS2_SIMPLE_DIR_EXTEND_CREDITS;
32658c2ecf20Sopenharmony_ci	}
32668c2ecf20Sopenharmony_ci
32678c2ecf20Sopenharmony_cido_extend:
32688c2ecf20Sopenharmony_ci	if (ocfs2_dir_indexed(dir))
32698c2ecf20Sopenharmony_ci		credits++; /* For attaching the new dirent block to the
32708c2ecf20Sopenharmony_ci			    * dx_root */
32718c2ecf20Sopenharmony_ci
32728c2ecf20Sopenharmony_ci	handle = ocfs2_start_trans(osb, credits);
32738c2ecf20Sopenharmony_ci	if (IS_ERR(handle)) {
32748c2ecf20Sopenharmony_ci		status = PTR_ERR(handle);
32758c2ecf20Sopenharmony_ci		handle = NULL;
32768c2ecf20Sopenharmony_ci		mlog_errno(status);
32778c2ecf20Sopenharmony_ci		goto bail;
32788c2ecf20Sopenharmony_ci	}
32798c2ecf20Sopenharmony_ci
32808c2ecf20Sopenharmony_ci	status = ocfs2_do_extend_dir(osb->sb, handle, dir, parent_fe_bh,
32818c2ecf20Sopenharmony_ci				     data_ac, meta_ac, &new_bh);
32828c2ecf20Sopenharmony_ci	if (status < 0) {
32838c2ecf20Sopenharmony_ci		mlog_errno(status);
32848c2ecf20Sopenharmony_ci		goto bail;
32858c2ecf20Sopenharmony_ci	}
32868c2ecf20Sopenharmony_ci
32878c2ecf20Sopenharmony_ci	ocfs2_set_new_buffer_uptodate(INODE_CACHE(dir), new_bh);
32888c2ecf20Sopenharmony_ci
32898c2ecf20Sopenharmony_ci	status = ocfs2_journal_access_db(handle, INODE_CACHE(dir), new_bh,
32908c2ecf20Sopenharmony_ci					 OCFS2_JOURNAL_ACCESS_CREATE);
32918c2ecf20Sopenharmony_ci	if (status < 0) {
32928c2ecf20Sopenharmony_ci		mlog_errno(status);
32938c2ecf20Sopenharmony_ci		goto bail;
32948c2ecf20Sopenharmony_ci	}
32958c2ecf20Sopenharmony_ci	memset(new_bh->b_data, 0, sb->s_blocksize);
32968c2ecf20Sopenharmony_ci
32978c2ecf20Sopenharmony_ci	de = (struct ocfs2_dir_entry *) new_bh->b_data;
32988c2ecf20Sopenharmony_ci	de->inode = 0;
32998c2ecf20Sopenharmony_ci	if (ocfs2_supports_dir_trailer(dir)) {
33008c2ecf20Sopenharmony_ci		de->rec_len = cpu_to_le16(ocfs2_dir_trailer_blk_off(sb));
33018c2ecf20Sopenharmony_ci
33028c2ecf20Sopenharmony_ci		ocfs2_init_dir_trailer(dir, new_bh, le16_to_cpu(de->rec_len));
33038c2ecf20Sopenharmony_ci
33048c2ecf20Sopenharmony_ci		if (ocfs2_dir_indexed(dir)) {
33058c2ecf20Sopenharmony_ci			status = ocfs2_dx_dir_link_trailer(dir, handle,
33068c2ecf20Sopenharmony_ci							   dx_root_bh, new_bh);
33078c2ecf20Sopenharmony_ci			if (status) {
33088c2ecf20Sopenharmony_ci				mlog_errno(status);
33098c2ecf20Sopenharmony_ci				goto bail;
33108c2ecf20Sopenharmony_ci			}
33118c2ecf20Sopenharmony_ci		}
33128c2ecf20Sopenharmony_ci	} else {
33138c2ecf20Sopenharmony_ci		de->rec_len = cpu_to_le16(sb->s_blocksize);
33148c2ecf20Sopenharmony_ci	}
33158c2ecf20Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
33168c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, new_bh);
33178c2ecf20Sopenharmony_ci
33188c2ecf20Sopenharmony_ci	dir_i_size += dir->i_sb->s_blocksize;
33198c2ecf20Sopenharmony_ci	i_size_write(dir, dir_i_size);
33208c2ecf20Sopenharmony_ci	dir->i_blocks = ocfs2_inode_sector_count(dir);
33218c2ecf20Sopenharmony_ci	status = ocfs2_mark_inode_dirty(handle, dir, parent_fe_bh);
33228c2ecf20Sopenharmony_ci	if (status < 0) {
33238c2ecf20Sopenharmony_ci		mlog_errno(status);
33248c2ecf20Sopenharmony_ci		goto bail;
33258c2ecf20Sopenharmony_ci	}
33268c2ecf20Sopenharmony_ci
33278c2ecf20Sopenharmony_cibail_bh:
33288c2ecf20Sopenharmony_ci	*new_de_bh = new_bh;
33298c2ecf20Sopenharmony_ci	get_bh(*new_de_bh);
33308c2ecf20Sopenharmony_cibail:
33318c2ecf20Sopenharmony_ci	if (handle)
33328c2ecf20Sopenharmony_ci		ocfs2_commit_trans(osb, handle);
33338c2ecf20Sopenharmony_ci	if (drop_alloc_sem)
33348c2ecf20Sopenharmony_ci		up_write(&OCFS2_I(dir)->ip_alloc_sem);
33358c2ecf20Sopenharmony_ci
33368c2ecf20Sopenharmony_ci	if (data_ac)
33378c2ecf20Sopenharmony_ci		ocfs2_free_alloc_context(data_ac);
33388c2ecf20Sopenharmony_ci	if (meta_ac)
33398c2ecf20Sopenharmony_ci		ocfs2_free_alloc_context(meta_ac);
33408c2ecf20Sopenharmony_ci
33418c2ecf20Sopenharmony_ci	brelse(new_bh);
33428c2ecf20Sopenharmony_ci
33438c2ecf20Sopenharmony_ci	return status;
33448c2ecf20Sopenharmony_ci}
33458c2ecf20Sopenharmony_ci
33468c2ecf20Sopenharmony_cistatic int ocfs2_find_dir_space_id(struct inode *dir, struct buffer_head *di_bh,
33478c2ecf20Sopenharmony_ci				   const char *name, int namelen,
33488c2ecf20Sopenharmony_ci				   struct buffer_head **ret_de_bh,
33498c2ecf20Sopenharmony_ci				   unsigned int *blocks_wanted)
33508c2ecf20Sopenharmony_ci{
33518c2ecf20Sopenharmony_ci	int ret;
33528c2ecf20Sopenharmony_ci	struct super_block *sb = dir->i_sb;
33538c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
33548c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de, *last_de = NULL;
33558c2ecf20Sopenharmony_ci	char *first_de, *de_buf, *limit;
33568c2ecf20Sopenharmony_ci	unsigned long offset = 0;
33578c2ecf20Sopenharmony_ci	unsigned int rec_len, new_rec_len, free_space = dir->i_sb->s_blocksize;
33588c2ecf20Sopenharmony_ci
33598c2ecf20Sopenharmony_ci	/*
33608c2ecf20Sopenharmony_ci	 * This calculates how many free bytes we'd have in block zero, should
33618c2ecf20Sopenharmony_ci	 * this function force expansion to an extent tree.
33628c2ecf20Sopenharmony_ci	 */
33638c2ecf20Sopenharmony_ci	if (ocfs2_new_dir_wants_trailer(dir))
33648c2ecf20Sopenharmony_ci		free_space = ocfs2_dir_trailer_blk_off(sb) - i_size_read(dir);
33658c2ecf20Sopenharmony_ci	else
33668c2ecf20Sopenharmony_ci		free_space = dir->i_sb->s_blocksize - i_size_read(dir);
33678c2ecf20Sopenharmony_ci
33688c2ecf20Sopenharmony_ci	first_de = di->id2.i_data.id_data;
33698c2ecf20Sopenharmony_ci	de_buf = first_de;
33708c2ecf20Sopenharmony_ci	limit = de_buf + i_size_read(dir);
33718c2ecf20Sopenharmony_ci	rec_len = OCFS2_DIR_REC_LEN(namelen);
33728c2ecf20Sopenharmony_ci
33738c2ecf20Sopenharmony_ci	while (de_buf < limit) {
33748c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *)de_buf;
33758c2ecf20Sopenharmony_ci
33768c2ecf20Sopenharmony_ci		if (!ocfs2_check_dir_entry(dir, de, di_bh, first_de,
33778c2ecf20Sopenharmony_ci					   i_size_read(dir), offset)) {
33788c2ecf20Sopenharmony_ci			ret = -ENOENT;
33798c2ecf20Sopenharmony_ci			goto out;
33808c2ecf20Sopenharmony_ci		}
33818c2ecf20Sopenharmony_ci		if (ocfs2_match(namelen, name, de)) {
33828c2ecf20Sopenharmony_ci			ret = -EEXIST;
33838c2ecf20Sopenharmony_ci			goto out;
33848c2ecf20Sopenharmony_ci		}
33858c2ecf20Sopenharmony_ci		/*
33868c2ecf20Sopenharmony_ci		 * No need to check for a trailing dirent record here as
33878c2ecf20Sopenharmony_ci		 * they're not used for inline dirs.
33888c2ecf20Sopenharmony_ci		 */
33898c2ecf20Sopenharmony_ci
33908c2ecf20Sopenharmony_ci		if (ocfs2_dirent_would_fit(de, rec_len)) {
33918c2ecf20Sopenharmony_ci			/* Ok, we found a spot. Return this bh and let
33928c2ecf20Sopenharmony_ci			 * the caller actually fill it in. */
33938c2ecf20Sopenharmony_ci			*ret_de_bh = di_bh;
33948c2ecf20Sopenharmony_ci			get_bh(*ret_de_bh);
33958c2ecf20Sopenharmony_ci			ret = 0;
33968c2ecf20Sopenharmony_ci			goto out;
33978c2ecf20Sopenharmony_ci		}
33988c2ecf20Sopenharmony_ci
33998c2ecf20Sopenharmony_ci		last_de = de;
34008c2ecf20Sopenharmony_ci		de_buf += le16_to_cpu(de->rec_len);
34018c2ecf20Sopenharmony_ci		offset += le16_to_cpu(de->rec_len);
34028c2ecf20Sopenharmony_ci	}
34038c2ecf20Sopenharmony_ci
34048c2ecf20Sopenharmony_ci	/*
34058c2ecf20Sopenharmony_ci	 * We're going to require expansion of the directory - figure
34068c2ecf20Sopenharmony_ci	 * out how many blocks we'll need so that a place for the
34078c2ecf20Sopenharmony_ci	 * dirent can be found.
34088c2ecf20Sopenharmony_ci	 */
34098c2ecf20Sopenharmony_ci	*blocks_wanted = 1;
34108c2ecf20Sopenharmony_ci	new_rec_len = le16_to_cpu(last_de->rec_len) + free_space;
34118c2ecf20Sopenharmony_ci	if (new_rec_len < (rec_len + OCFS2_DIR_REC_LEN(last_de->name_len)))
34128c2ecf20Sopenharmony_ci		*blocks_wanted = 2;
34138c2ecf20Sopenharmony_ci
34148c2ecf20Sopenharmony_ci	ret = -ENOSPC;
34158c2ecf20Sopenharmony_ciout:
34168c2ecf20Sopenharmony_ci	return ret;
34178c2ecf20Sopenharmony_ci}
34188c2ecf20Sopenharmony_ci
34198c2ecf20Sopenharmony_cistatic int ocfs2_find_dir_space_el(struct inode *dir, const char *name,
34208c2ecf20Sopenharmony_ci				   int namelen, struct buffer_head **ret_de_bh)
34218c2ecf20Sopenharmony_ci{
34228c2ecf20Sopenharmony_ci	unsigned long offset;
34238c2ecf20Sopenharmony_ci	struct buffer_head *bh = NULL;
34248c2ecf20Sopenharmony_ci	unsigned short rec_len;
34258c2ecf20Sopenharmony_ci	struct ocfs2_dir_entry *de;
34268c2ecf20Sopenharmony_ci	struct super_block *sb = dir->i_sb;
34278c2ecf20Sopenharmony_ci	int status;
34288c2ecf20Sopenharmony_ci	int blocksize = dir->i_sb->s_blocksize;
34298c2ecf20Sopenharmony_ci
34308c2ecf20Sopenharmony_ci	status = ocfs2_read_dir_block(dir, 0, &bh, 0);
34318c2ecf20Sopenharmony_ci	if (status)
34328c2ecf20Sopenharmony_ci		goto bail;
34338c2ecf20Sopenharmony_ci
34348c2ecf20Sopenharmony_ci	rec_len = OCFS2_DIR_REC_LEN(namelen);
34358c2ecf20Sopenharmony_ci	offset = 0;
34368c2ecf20Sopenharmony_ci	de = (struct ocfs2_dir_entry *) bh->b_data;
34378c2ecf20Sopenharmony_ci	while (1) {
34388c2ecf20Sopenharmony_ci		if ((char *)de >= sb->s_blocksize + bh->b_data) {
34398c2ecf20Sopenharmony_ci			brelse(bh);
34408c2ecf20Sopenharmony_ci			bh = NULL;
34418c2ecf20Sopenharmony_ci
34428c2ecf20Sopenharmony_ci			if (i_size_read(dir) <= offset) {
34438c2ecf20Sopenharmony_ci				/*
34448c2ecf20Sopenharmony_ci				 * Caller will have to expand this
34458c2ecf20Sopenharmony_ci				 * directory.
34468c2ecf20Sopenharmony_ci				 */
34478c2ecf20Sopenharmony_ci				status = -ENOSPC;
34488c2ecf20Sopenharmony_ci				goto bail;
34498c2ecf20Sopenharmony_ci			}
34508c2ecf20Sopenharmony_ci			status = ocfs2_read_dir_block(dir,
34518c2ecf20Sopenharmony_ci					     offset >> sb->s_blocksize_bits,
34528c2ecf20Sopenharmony_ci					     &bh, 0);
34538c2ecf20Sopenharmony_ci			if (status)
34548c2ecf20Sopenharmony_ci				goto bail;
34558c2ecf20Sopenharmony_ci
34568c2ecf20Sopenharmony_ci			/* move to next block */
34578c2ecf20Sopenharmony_ci			de = (struct ocfs2_dir_entry *) bh->b_data;
34588c2ecf20Sopenharmony_ci		}
34598c2ecf20Sopenharmony_ci		if (!ocfs2_check_dir_entry(dir, de, bh, bh->b_data, blocksize,
34608c2ecf20Sopenharmony_ci					   offset)) {
34618c2ecf20Sopenharmony_ci			status = -ENOENT;
34628c2ecf20Sopenharmony_ci			goto bail;
34638c2ecf20Sopenharmony_ci		}
34648c2ecf20Sopenharmony_ci		if (ocfs2_match(namelen, name, de)) {
34658c2ecf20Sopenharmony_ci			status = -EEXIST;
34668c2ecf20Sopenharmony_ci			goto bail;
34678c2ecf20Sopenharmony_ci		}
34688c2ecf20Sopenharmony_ci
34698c2ecf20Sopenharmony_ci		if (ocfs2_skip_dir_trailer(dir, de, offset % blocksize,
34708c2ecf20Sopenharmony_ci					   blocksize))
34718c2ecf20Sopenharmony_ci			goto next;
34728c2ecf20Sopenharmony_ci
34738c2ecf20Sopenharmony_ci		if (ocfs2_dirent_would_fit(de, rec_len)) {
34748c2ecf20Sopenharmony_ci			/* Ok, we found a spot. Return this bh and let
34758c2ecf20Sopenharmony_ci			 * the caller actually fill it in. */
34768c2ecf20Sopenharmony_ci			*ret_de_bh = bh;
34778c2ecf20Sopenharmony_ci			get_bh(*ret_de_bh);
34788c2ecf20Sopenharmony_ci			status = 0;
34798c2ecf20Sopenharmony_ci			goto bail;
34808c2ecf20Sopenharmony_ci		}
34818c2ecf20Sopenharmony_cinext:
34828c2ecf20Sopenharmony_ci		offset += le16_to_cpu(de->rec_len);
34838c2ecf20Sopenharmony_ci		de = (struct ocfs2_dir_entry *)((char *) de + le16_to_cpu(de->rec_len));
34848c2ecf20Sopenharmony_ci	}
34858c2ecf20Sopenharmony_ci
34868c2ecf20Sopenharmony_cibail:
34878c2ecf20Sopenharmony_ci	brelse(bh);
34888c2ecf20Sopenharmony_ci	if (status)
34898c2ecf20Sopenharmony_ci		mlog_errno(status);
34908c2ecf20Sopenharmony_ci
34918c2ecf20Sopenharmony_ci	return status;
34928c2ecf20Sopenharmony_ci}
34938c2ecf20Sopenharmony_ci
34948c2ecf20Sopenharmony_cistatic int dx_leaf_sort_cmp(const void *a, const void *b)
34958c2ecf20Sopenharmony_ci{
34968c2ecf20Sopenharmony_ci	const struct ocfs2_dx_entry *entry1 = a;
34978c2ecf20Sopenharmony_ci	const struct ocfs2_dx_entry *entry2 = b;
34988c2ecf20Sopenharmony_ci	u32 major_hash1 = le32_to_cpu(entry1->dx_major_hash);
34998c2ecf20Sopenharmony_ci	u32 major_hash2 = le32_to_cpu(entry2->dx_major_hash);
35008c2ecf20Sopenharmony_ci	u32 minor_hash1 = le32_to_cpu(entry1->dx_minor_hash);
35018c2ecf20Sopenharmony_ci	u32 minor_hash2 = le32_to_cpu(entry2->dx_minor_hash);
35028c2ecf20Sopenharmony_ci
35038c2ecf20Sopenharmony_ci	if (major_hash1 > major_hash2)
35048c2ecf20Sopenharmony_ci		return 1;
35058c2ecf20Sopenharmony_ci	if (major_hash1 < major_hash2)
35068c2ecf20Sopenharmony_ci		return -1;
35078c2ecf20Sopenharmony_ci
35088c2ecf20Sopenharmony_ci	/*
35098c2ecf20Sopenharmony_ci	 * It is not strictly necessary to sort by minor
35108c2ecf20Sopenharmony_ci	 */
35118c2ecf20Sopenharmony_ci	if (minor_hash1 > minor_hash2)
35128c2ecf20Sopenharmony_ci		return 1;
35138c2ecf20Sopenharmony_ci	if (minor_hash1 < minor_hash2)
35148c2ecf20Sopenharmony_ci		return -1;
35158c2ecf20Sopenharmony_ci	return 0;
35168c2ecf20Sopenharmony_ci}
35178c2ecf20Sopenharmony_ci
35188c2ecf20Sopenharmony_cistatic void dx_leaf_sort_swap(void *a, void *b, int size)
35198c2ecf20Sopenharmony_ci{
35208c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry *entry1 = a;
35218c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry *entry2 = b;
35228c2ecf20Sopenharmony_ci
35238c2ecf20Sopenharmony_ci	BUG_ON(size != sizeof(*entry1));
35248c2ecf20Sopenharmony_ci
35258c2ecf20Sopenharmony_ci	swap(*entry1, *entry2);
35268c2ecf20Sopenharmony_ci}
35278c2ecf20Sopenharmony_ci
35288c2ecf20Sopenharmony_cistatic int ocfs2_dx_leaf_same_major(struct ocfs2_dx_leaf *dx_leaf)
35298c2ecf20Sopenharmony_ci{
35308c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry_list *dl_list = &dx_leaf->dl_list;
35318c2ecf20Sopenharmony_ci	int i, num = le16_to_cpu(dl_list->de_num_used);
35328c2ecf20Sopenharmony_ci
35338c2ecf20Sopenharmony_ci	for (i = 0; i < (num - 1); i++) {
35348c2ecf20Sopenharmony_ci		if (le32_to_cpu(dl_list->de_entries[i].dx_major_hash) !=
35358c2ecf20Sopenharmony_ci		    le32_to_cpu(dl_list->de_entries[i + 1].dx_major_hash))
35368c2ecf20Sopenharmony_ci			return 0;
35378c2ecf20Sopenharmony_ci	}
35388c2ecf20Sopenharmony_ci
35398c2ecf20Sopenharmony_ci	return 1;
35408c2ecf20Sopenharmony_ci}
35418c2ecf20Sopenharmony_ci
35428c2ecf20Sopenharmony_ci/*
35438c2ecf20Sopenharmony_ci * Find the optimal value to split this leaf on. This expects the leaf
35448c2ecf20Sopenharmony_ci * entries to be in sorted order.
35458c2ecf20Sopenharmony_ci *
35468c2ecf20Sopenharmony_ci * leaf_cpos is the cpos of the leaf we're splitting. insert_hash is
35478c2ecf20Sopenharmony_ci * the hash we want to insert.
35488c2ecf20Sopenharmony_ci *
35498c2ecf20Sopenharmony_ci * This function is only concerned with the major hash - that which
35508c2ecf20Sopenharmony_ci * determines which cluster an item belongs to.
35518c2ecf20Sopenharmony_ci */
35528c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_find_leaf_split(struct ocfs2_dx_leaf *dx_leaf,
35538c2ecf20Sopenharmony_ci					u32 leaf_cpos, u32 insert_hash,
35548c2ecf20Sopenharmony_ci					u32 *split_hash)
35558c2ecf20Sopenharmony_ci{
35568c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry_list *dl_list = &dx_leaf->dl_list;
35578c2ecf20Sopenharmony_ci	int i, num_used = le16_to_cpu(dl_list->de_num_used);
35588c2ecf20Sopenharmony_ci	int allsame;
35598c2ecf20Sopenharmony_ci
35608c2ecf20Sopenharmony_ci	/*
35618c2ecf20Sopenharmony_ci	 * There's a couple rare, but nasty corner cases we have to
35628c2ecf20Sopenharmony_ci	 * check for here. All of them involve a leaf where all value
35638c2ecf20Sopenharmony_ci	 * have the same hash, which is what we look for first.
35648c2ecf20Sopenharmony_ci	 *
35658c2ecf20Sopenharmony_ci	 * Most of the time, all of the above is false, and we simply
35668c2ecf20Sopenharmony_ci	 * pick the median value for a split.
35678c2ecf20Sopenharmony_ci	 */
35688c2ecf20Sopenharmony_ci	allsame = ocfs2_dx_leaf_same_major(dx_leaf);
35698c2ecf20Sopenharmony_ci	if (allsame) {
35708c2ecf20Sopenharmony_ci		u32 val = le32_to_cpu(dl_list->de_entries[0].dx_major_hash);
35718c2ecf20Sopenharmony_ci
35728c2ecf20Sopenharmony_ci		if (val == insert_hash) {
35738c2ecf20Sopenharmony_ci			/*
35748c2ecf20Sopenharmony_ci			 * No matter where we would choose to split,
35758c2ecf20Sopenharmony_ci			 * the new entry would want to occupy the same
35768c2ecf20Sopenharmony_ci			 * block as these. Since there's no space left
35778c2ecf20Sopenharmony_ci			 * in their existing block, we know there
35788c2ecf20Sopenharmony_ci			 * won't be space after the split.
35798c2ecf20Sopenharmony_ci			 */
35808c2ecf20Sopenharmony_ci			return -ENOSPC;
35818c2ecf20Sopenharmony_ci		}
35828c2ecf20Sopenharmony_ci
35838c2ecf20Sopenharmony_ci		if (val == leaf_cpos) {
35848c2ecf20Sopenharmony_ci			/*
35858c2ecf20Sopenharmony_ci			 * Because val is the same as leaf_cpos (which
35868c2ecf20Sopenharmony_ci			 * is the smallest value this leaf can have),
35878c2ecf20Sopenharmony_ci			 * yet is not equal to insert_hash, then we
35888c2ecf20Sopenharmony_ci			 * know that insert_hash *must* be larger than
35898c2ecf20Sopenharmony_ci			 * val (and leaf_cpos). At least cpos+1 in value.
35908c2ecf20Sopenharmony_ci			 *
35918c2ecf20Sopenharmony_ci			 * We also know then, that there cannot be an
35928c2ecf20Sopenharmony_ci			 * adjacent extent (otherwise we'd be looking
35938c2ecf20Sopenharmony_ci			 * at it). Choosing this value gives us a
35948c2ecf20Sopenharmony_ci			 * chance to get some contiguousness.
35958c2ecf20Sopenharmony_ci			 */
35968c2ecf20Sopenharmony_ci			*split_hash = leaf_cpos + 1;
35978c2ecf20Sopenharmony_ci			return 0;
35988c2ecf20Sopenharmony_ci		}
35998c2ecf20Sopenharmony_ci
36008c2ecf20Sopenharmony_ci		if (val > insert_hash) {
36018c2ecf20Sopenharmony_ci			/*
36028c2ecf20Sopenharmony_ci			 * val can not be the same as insert hash, and
36038c2ecf20Sopenharmony_ci			 * also must be larger than leaf_cpos. Also,
36048c2ecf20Sopenharmony_ci			 * we know that there can't be a leaf between
36058c2ecf20Sopenharmony_ci			 * cpos and val, otherwise the entries with
36068c2ecf20Sopenharmony_ci			 * hash 'val' would be there.
36078c2ecf20Sopenharmony_ci			 */
36088c2ecf20Sopenharmony_ci			*split_hash = val;
36098c2ecf20Sopenharmony_ci			return 0;
36108c2ecf20Sopenharmony_ci		}
36118c2ecf20Sopenharmony_ci
36128c2ecf20Sopenharmony_ci		*split_hash = insert_hash;
36138c2ecf20Sopenharmony_ci		return 0;
36148c2ecf20Sopenharmony_ci	}
36158c2ecf20Sopenharmony_ci
36168c2ecf20Sopenharmony_ci	/*
36178c2ecf20Sopenharmony_ci	 * Since the records are sorted and the checks above
36188c2ecf20Sopenharmony_ci	 * guaranteed that not all records in this block are the same,
36198c2ecf20Sopenharmony_ci	 * we simple travel forward, from the median, and pick the 1st
36208c2ecf20Sopenharmony_ci	 * record whose value is larger than leaf_cpos.
36218c2ecf20Sopenharmony_ci	 */
36228c2ecf20Sopenharmony_ci	for (i = (num_used / 2); i < num_used; i++)
36238c2ecf20Sopenharmony_ci		if (le32_to_cpu(dl_list->de_entries[i].dx_major_hash) >
36248c2ecf20Sopenharmony_ci		    leaf_cpos)
36258c2ecf20Sopenharmony_ci			break;
36268c2ecf20Sopenharmony_ci
36278c2ecf20Sopenharmony_ci	BUG_ON(i == num_used); /* Should be impossible */
36288c2ecf20Sopenharmony_ci	*split_hash = le32_to_cpu(dl_list->de_entries[i].dx_major_hash);
36298c2ecf20Sopenharmony_ci	return 0;
36308c2ecf20Sopenharmony_ci}
36318c2ecf20Sopenharmony_ci
36328c2ecf20Sopenharmony_ci/*
36338c2ecf20Sopenharmony_ci * Transfer all entries in orig_dx_leaves whose major hash is equal to or
36348c2ecf20Sopenharmony_ci * larger than split_hash into new_dx_leaves. We use a temporary
36358c2ecf20Sopenharmony_ci * buffer (tmp_dx_leaf) to make the changes to the original leaf blocks.
36368c2ecf20Sopenharmony_ci *
36378c2ecf20Sopenharmony_ci * Since the block offset inside a leaf (cluster) is a constant mask
36388c2ecf20Sopenharmony_ci * of minor_hash, we can optimize - an item at block offset X within
36398c2ecf20Sopenharmony_ci * the original cluster, will be at offset X within the new cluster.
36408c2ecf20Sopenharmony_ci */
36418c2ecf20Sopenharmony_cistatic void ocfs2_dx_dir_transfer_leaf(struct inode *dir, u32 split_hash,
36428c2ecf20Sopenharmony_ci				       handle_t *handle,
36438c2ecf20Sopenharmony_ci				       struct ocfs2_dx_leaf *tmp_dx_leaf,
36448c2ecf20Sopenharmony_ci				       struct buffer_head **orig_dx_leaves,
36458c2ecf20Sopenharmony_ci				       struct buffer_head **new_dx_leaves,
36468c2ecf20Sopenharmony_ci				       int num_dx_leaves)
36478c2ecf20Sopenharmony_ci{
36488c2ecf20Sopenharmony_ci	int i, j, num_used;
36498c2ecf20Sopenharmony_ci	u32 major_hash;
36508c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *orig_dx_leaf, *new_dx_leaf;
36518c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry_list *orig_list, *tmp_list;
36528c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry;
36538c2ecf20Sopenharmony_ci
36548c2ecf20Sopenharmony_ci	tmp_list = &tmp_dx_leaf->dl_list;
36558c2ecf20Sopenharmony_ci
36568c2ecf20Sopenharmony_ci	for (i = 0; i < num_dx_leaves; i++) {
36578c2ecf20Sopenharmony_ci		orig_dx_leaf = (struct ocfs2_dx_leaf *) orig_dx_leaves[i]->b_data;
36588c2ecf20Sopenharmony_ci		orig_list = &orig_dx_leaf->dl_list;
36598c2ecf20Sopenharmony_ci		new_dx_leaf = (struct ocfs2_dx_leaf *) new_dx_leaves[i]->b_data;
36608c2ecf20Sopenharmony_ci
36618c2ecf20Sopenharmony_ci		num_used = le16_to_cpu(orig_list->de_num_used);
36628c2ecf20Sopenharmony_ci
36638c2ecf20Sopenharmony_ci		memcpy(tmp_dx_leaf, orig_dx_leaf, dir->i_sb->s_blocksize);
36648c2ecf20Sopenharmony_ci		tmp_list->de_num_used = cpu_to_le16(0);
36658c2ecf20Sopenharmony_ci		memset(&tmp_list->de_entries, 0, sizeof(*dx_entry)*num_used);
36668c2ecf20Sopenharmony_ci
36678c2ecf20Sopenharmony_ci		for (j = 0; j < num_used; j++) {
36688c2ecf20Sopenharmony_ci			dx_entry = &orig_list->de_entries[j];
36698c2ecf20Sopenharmony_ci			major_hash = le32_to_cpu(dx_entry->dx_major_hash);
36708c2ecf20Sopenharmony_ci			if (major_hash >= split_hash)
36718c2ecf20Sopenharmony_ci				ocfs2_dx_dir_leaf_insert_tail(new_dx_leaf,
36728c2ecf20Sopenharmony_ci							      dx_entry);
36738c2ecf20Sopenharmony_ci			else
36748c2ecf20Sopenharmony_ci				ocfs2_dx_dir_leaf_insert_tail(tmp_dx_leaf,
36758c2ecf20Sopenharmony_ci							      dx_entry);
36768c2ecf20Sopenharmony_ci		}
36778c2ecf20Sopenharmony_ci		memcpy(orig_dx_leaf, tmp_dx_leaf, dir->i_sb->s_blocksize);
36788c2ecf20Sopenharmony_ci
36798c2ecf20Sopenharmony_ci		ocfs2_journal_dirty(handle, orig_dx_leaves[i]);
36808c2ecf20Sopenharmony_ci		ocfs2_journal_dirty(handle, new_dx_leaves[i]);
36818c2ecf20Sopenharmony_ci	}
36828c2ecf20Sopenharmony_ci}
36838c2ecf20Sopenharmony_ci
36848c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_rebalance_credits(struct ocfs2_super *osb,
36858c2ecf20Sopenharmony_ci					  struct ocfs2_dx_root_block *dx_root)
36868c2ecf20Sopenharmony_ci{
36878c2ecf20Sopenharmony_ci	int credits = ocfs2_clusters_to_blocks(osb->sb, 3);
36888c2ecf20Sopenharmony_ci
36898c2ecf20Sopenharmony_ci	credits += ocfs2_calc_extend_credits(osb->sb, &dx_root->dr_list);
36908c2ecf20Sopenharmony_ci	credits += ocfs2_quota_trans_credits(osb->sb);
36918c2ecf20Sopenharmony_ci	return credits;
36928c2ecf20Sopenharmony_ci}
36938c2ecf20Sopenharmony_ci
36948c2ecf20Sopenharmony_ci/*
36958c2ecf20Sopenharmony_ci * Find the median value in dx_leaf_bh and allocate a new leaf to move
36968c2ecf20Sopenharmony_ci * half our entries into.
36978c2ecf20Sopenharmony_ci */
36988c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_rebalance(struct ocfs2_super *osb, struct inode *dir,
36998c2ecf20Sopenharmony_ci				  struct buffer_head *dx_root_bh,
37008c2ecf20Sopenharmony_ci				  struct buffer_head *dx_leaf_bh,
37018c2ecf20Sopenharmony_ci				  struct ocfs2_dx_hinfo *hinfo, u32 leaf_cpos,
37028c2ecf20Sopenharmony_ci				  u64 leaf_blkno)
37038c2ecf20Sopenharmony_ci{
37048c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_bh->b_data;
37058c2ecf20Sopenharmony_ci	int credits, ret, i, num_used, did_quota = 0;
37068c2ecf20Sopenharmony_ci	u32 cpos, split_hash, insert_hash = hinfo->major_hash;
37078c2ecf20Sopenharmony_ci	u64 orig_leaves_start;
37088c2ecf20Sopenharmony_ci	int num_dx_leaves;
37098c2ecf20Sopenharmony_ci	struct buffer_head **orig_dx_leaves = NULL;
37108c2ecf20Sopenharmony_ci	struct buffer_head **new_dx_leaves = NULL;
37118c2ecf20Sopenharmony_ci	struct ocfs2_alloc_context *data_ac = NULL, *meta_ac = NULL;
37128c2ecf20Sopenharmony_ci	struct ocfs2_extent_tree et;
37138c2ecf20Sopenharmony_ci	handle_t *handle = NULL;
37148c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
37158c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *tmp_dx_leaf = NULL;
37168c2ecf20Sopenharmony_ci
37178c2ecf20Sopenharmony_ci	trace_ocfs2_dx_dir_rebalance((unsigned long long)OCFS2_I(dir)->ip_blkno,
37188c2ecf20Sopenharmony_ci				     (unsigned long long)leaf_blkno,
37198c2ecf20Sopenharmony_ci				     insert_hash);
37208c2ecf20Sopenharmony_ci
37218c2ecf20Sopenharmony_ci	ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
37228c2ecf20Sopenharmony_ci
37238c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
37248c2ecf20Sopenharmony_ci	/*
37258c2ecf20Sopenharmony_ci	 * XXX: This is a rather large limit. We should use a more
37268c2ecf20Sopenharmony_ci	 * realistic value.
37278c2ecf20Sopenharmony_ci	 */
37288c2ecf20Sopenharmony_ci	if (le32_to_cpu(dx_root->dr_clusters) == UINT_MAX)
37298c2ecf20Sopenharmony_ci		return -ENOSPC;
37308c2ecf20Sopenharmony_ci
37318c2ecf20Sopenharmony_ci	num_used = le16_to_cpu(dx_leaf->dl_list.de_num_used);
37328c2ecf20Sopenharmony_ci	if (num_used < le16_to_cpu(dx_leaf->dl_list.de_count)) {
37338c2ecf20Sopenharmony_ci		mlog(ML_ERROR, "DX Dir: %llu, Asked to rebalance empty leaf: "
37348c2ecf20Sopenharmony_ci		     "%llu, %d\n", (unsigned long long)OCFS2_I(dir)->ip_blkno,
37358c2ecf20Sopenharmony_ci		     (unsigned long long)leaf_blkno, num_used);
37368c2ecf20Sopenharmony_ci		ret = -EIO;
37378c2ecf20Sopenharmony_ci		goto out;
37388c2ecf20Sopenharmony_ci	}
37398c2ecf20Sopenharmony_ci
37408c2ecf20Sopenharmony_ci	orig_dx_leaves = ocfs2_dx_dir_kmalloc_leaves(osb->sb, &num_dx_leaves);
37418c2ecf20Sopenharmony_ci	if (!orig_dx_leaves) {
37428c2ecf20Sopenharmony_ci		ret = -ENOMEM;
37438c2ecf20Sopenharmony_ci		mlog_errno(ret);
37448c2ecf20Sopenharmony_ci		goto out;
37458c2ecf20Sopenharmony_ci	}
37468c2ecf20Sopenharmony_ci
37478c2ecf20Sopenharmony_ci	new_dx_leaves = ocfs2_dx_dir_kmalloc_leaves(osb->sb, NULL);
37488c2ecf20Sopenharmony_ci	if (!new_dx_leaves) {
37498c2ecf20Sopenharmony_ci		ret = -ENOMEM;
37508c2ecf20Sopenharmony_ci		mlog_errno(ret);
37518c2ecf20Sopenharmony_ci		goto out;
37528c2ecf20Sopenharmony_ci	}
37538c2ecf20Sopenharmony_ci
37548c2ecf20Sopenharmony_ci	ret = ocfs2_lock_allocators(dir, &et, 1, 0, &data_ac, &meta_ac);
37558c2ecf20Sopenharmony_ci	if (ret) {
37568c2ecf20Sopenharmony_ci		if (ret != -ENOSPC)
37578c2ecf20Sopenharmony_ci			mlog_errno(ret);
37588c2ecf20Sopenharmony_ci		goto out;
37598c2ecf20Sopenharmony_ci	}
37608c2ecf20Sopenharmony_ci
37618c2ecf20Sopenharmony_ci	credits = ocfs2_dx_dir_rebalance_credits(osb, dx_root);
37628c2ecf20Sopenharmony_ci	handle = ocfs2_start_trans(osb, credits);
37638c2ecf20Sopenharmony_ci	if (IS_ERR(handle)) {
37648c2ecf20Sopenharmony_ci		ret = PTR_ERR(handle);
37658c2ecf20Sopenharmony_ci		handle = NULL;
37668c2ecf20Sopenharmony_ci		mlog_errno(ret);
37678c2ecf20Sopenharmony_ci		goto out;
37688c2ecf20Sopenharmony_ci	}
37698c2ecf20Sopenharmony_ci
37708c2ecf20Sopenharmony_ci	ret = dquot_alloc_space_nodirty(dir,
37718c2ecf20Sopenharmony_ci				       ocfs2_clusters_to_bytes(dir->i_sb, 1));
37728c2ecf20Sopenharmony_ci	if (ret)
37738c2ecf20Sopenharmony_ci		goto out_commit;
37748c2ecf20Sopenharmony_ci	did_quota = 1;
37758c2ecf20Sopenharmony_ci
37768c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir), dx_leaf_bh,
37778c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
37788c2ecf20Sopenharmony_ci	if (ret) {
37798c2ecf20Sopenharmony_ci		mlog_errno(ret);
37808c2ecf20Sopenharmony_ci		goto out_commit;
37818c2ecf20Sopenharmony_ci	}
37828c2ecf20Sopenharmony_ci
37838c2ecf20Sopenharmony_ci	/*
37848c2ecf20Sopenharmony_ci	 * This block is changing anyway, so we can sort it in place.
37858c2ecf20Sopenharmony_ci	 */
37868c2ecf20Sopenharmony_ci	sort(dx_leaf->dl_list.de_entries, num_used,
37878c2ecf20Sopenharmony_ci	     sizeof(struct ocfs2_dx_entry), dx_leaf_sort_cmp,
37888c2ecf20Sopenharmony_ci	     dx_leaf_sort_swap);
37898c2ecf20Sopenharmony_ci
37908c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_leaf_bh);
37918c2ecf20Sopenharmony_ci
37928c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_find_leaf_split(dx_leaf, leaf_cpos, insert_hash,
37938c2ecf20Sopenharmony_ci					   &split_hash);
37948c2ecf20Sopenharmony_ci	if (ret) {
37958c2ecf20Sopenharmony_ci		mlog_errno(ret);
37968c2ecf20Sopenharmony_ci		goto  out_commit;
37978c2ecf20Sopenharmony_ci	}
37988c2ecf20Sopenharmony_ci
37998c2ecf20Sopenharmony_ci	trace_ocfs2_dx_dir_rebalance_split(leaf_cpos, split_hash, insert_hash);
38008c2ecf20Sopenharmony_ci
38018c2ecf20Sopenharmony_ci	/*
38028c2ecf20Sopenharmony_ci	 * We have to carefully order operations here. There are items
38038c2ecf20Sopenharmony_ci	 * which want to be in the new cluster before insert, but in
38048c2ecf20Sopenharmony_ci	 * order to put those items in the new cluster, we alter the
38058c2ecf20Sopenharmony_ci	 * old cluster. A failure to insert gets nasty.
38068c2ecf20Sopenharmony_ci	 *
38078c2ecf20Sopenharmony_ci	 * So, start by reserving writes to the old
38088c2ecf20Sopenharmony_ci	 * cluster. ocfs2_dx_dir_new_cluster will reserve writes on
38098c2ecf20Sopenharmony_ci	 * the new cluster for us, before inserting it. The insert
38108c2ecf20Sopenharmony_ci	 * won't happen if there's an error before that. Once the
38118c2ecf20Sopenharmony_ci	 * insert is done then, we can transfer from one leaf into the
38128c2ecf20Sopenharmony_ci	 * other without fear of hitting any error.
38138c2ecf20Sopenharmony_ci	 */
38148c2ecf20Sopenharmony_ci
38158c2ecf20Sopenharmony_ci	/*
38168c2ecf20Sopenharmony_ci	 * The leaf transfer wants some scratch space so that we don't
38178c2ecf20Sopenharmony_ci	 * wind up doing a bunch of expensive memmove().
38188c2ecf20Sopenharmony_ci	 */
38198c2ecf20Sopenharmony_ci	tmp_dx_leaf = kmalloc(osb->sb->s_blocksize, GFP_NOFS);
38208c2ecf20Sopenharmony_ci	if (!tmp_dx_leaf) {
38218c2ecf20Sopenharmony_ci		ret = -ENOMEM;
38228c2ecf20Sopenharmony_ci		mlog_errno(ret);
38238c2ecf20Sopenharmony_ci		goto out_commit;
38248c2ecf20Sopenharmony_ci	}
38258c2ecf20Sopenharmony_ci
38268c2ecf20Sopenharmony_ci	orig_leaves_start = ocfs2_block_to_cluster_start(dir->i_sb, leaf_blkno);
38278c2ecf20Sopenharmony_ci	ret = ocfs2_read_dx_leaves(dir, orig_leaves_start, num_dx_leaves,
38288c2ecf20Sopenharmony_ci				   orig_dx_leaves);
38298c2ecf20Sopenharmony_ci	if (ret) {
38308c2ecf20Sopenharmony_ci		mlog_errno(ret);
38318c2ecf20Sopenharmony_ci		goto out_commit;
38328c2ecf20Sopenharmony_ci	}
38338c2ecf20Sopenharmony_ci
38348c2ecf20Sopenharmony_ci	cpos = split_hash;
38358c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_new_cluster(dir, &et, cpos, handle,
38368c2ecf20Sopenharmony_ci				       data_ac, meta_ac, new_dx_leaves,
38378c2ecf20Sopenharmony_ci				       num_dx_leaves);
38388c2ecf20Sopenharmony_ci	if (ret) {
38398c2ecf20Sopenharmony_ci		mlog_errno(ret);
38408c2ecf20Sopenharmony_ci		goto out_commit;
38418c2ecf20Sopenharmony_ci	}
38428c2ecf20Sopenharmony_ci
38438c2ecf20Sopenharmony_ci	for (i = 0; i < num_dx_leaves; i++) {
38448c2ecf20Sopenharmony_ci		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
38458c2ecf20Sopenharmony_ci					      orig_dx_leaves[i],
38468c2ecf20Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_WRITE);
38478c2ecf20Sopenharmony_ci		if (ret) {
38488c2ecf20Sopenharmony_ci			mlog_errno(ret);
38498c2ecf20Sopenharmony_ci			goto out_commit;
38508c2ecf20Sopenharmony_ci		}
38518c2ecf20Sopenharmony_ci
38528c2ecf20Sopenharmony_ci		ret = ocfs2_journal_access_dl(handle, INODE_CACHE(dir),
38538c2ecf20Sopenharmony_ci					      new_dx_leaves[i],
38548c2ecf20Sopenharmony_ci					      OCFS2_JOURNAL_ACCESS_WRITE);
38558c2ecf20Sopenharmony_ci		if (ret) {
38568c2ecf20Sopenharmony_ci			mlog_errno(ret);
38578c2ecf20Sopenharmony_ci			goto out_commit;
38588c2ecf20Sopenharmony_ci		}
38598c2ecf20Sopenharmony_ci	}
38608c2ecf20Sopenharmony_ci
38618c2ecf20Sopenharmony_ci	ocfs2_dx_dir_transfer_leaf(dir, split_hash, handle, tmp_dx_leaf,
38628c2ecf20Sopenharmony_ci				   orig_dx_leaves, new_dx_leaves, num_dx_leaves);
38638c2ecf20Sopenharmony_ci
38648c2ecf20Sopenharmony_ciout_commit:
38658c2ecf20Sopenharmony_ci	if (ret < 0 && did_quota)
38668c2ecf20Sopenharmony_ci		dquot_free_space_nodirty(dir,
38678c2ecf20Sopenharmony_ci				ocfs2_clusters_to_bytes(dir->i_sb, 1));
38688c2ecf20Sopenharmony_ci
38698c2ecf20Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
38708c2ecf20Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
38718c2ecf20Sopenharmony_ci
38728c2ecf20Sopenharmony_ciout:
38738c2ecf20Sopenharmony_ci	if (orig_dx_leaves || new_dx_leaves) {
38748c2ecf20Sopenharmony_ci		for (i = 0; i < num_dx_leaves; i++) {
38758c2ecf20Sopenharmony_ci			if (orig_dx_leaves)
38768c2ecf20Sopenharmony_ci				brelse(orig_dx_leaves[i]);
38778c2ecf20Sopenharmony_ci			if (new_dx_leaves)
38788c2ecf20Sopenharmony_ci				brelse(new_dx_leaves[i]);
38798c2ecf20Sopenharmony_ci		}
38808c2ecf20Sopenharmony_ci		kfree(orig_dx_leaves);
38818c2ecf20Sopenharmony_ci		kfree(new_dx_leaves);
38828c2ecf20Sopenharmony_ci	}
38838c2ecf20Sopenharmony_ci
38848c2ecf20Sopenharmony_ci	if (meta_ac)
38858c2ecf20Sopenharmony_ci		ocfs2_free_alloc_context(meta_ac);
38868c2ecf20Sopenharmony_ci	if (data_ac)
38878c2ecf20Sopenharmony_ci		ocfs2_free_alloc_context(data_ac);
38888c2ecf20Sopenharmony_ci
38898c2ecf20Sopenharmony_ci	kfree(tmp_dx_leaf);
38908c2ecf20Sopenharmony_ci	return ret;
38918c2ecf20Sopenharmony_ci}
38928c2ecf20Sopenharmony_ci
38938c2ecf20Sopenharmony_cistatic int ocfs2_find_dir_space_dx(struct ocfs2_super *osb, struct inode *dir,
38948c2ecf20Sopenharmony_ci				   struct buffer_head *di_bh,
38958c2ecf20Sopenharmony_ci				   struct buffer_head *dx_root_bh,
38968c2ecf20Sopenharmony_ci				   const char *name, int namelen,
38978c2ecf20Sopenharmony_ci				   struct ocfs2_dir_lookup_result *lookup)
38988c2ecf20Sopenharmony_ci{
38998c2ecf20Sopenharmony_ci	int ret, rebalanced = 0;
39008c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
39018c2ecf20Sopenharmony_ci	struct buffer_head *dx_leaf_bh = NULL;
39028c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *dx_leaf;
39038c2ecf20Sopenharmony_ci	u64 blkno;
39048c2ecf20Sopenharmony_ci	u32 leaf_cpos;
39058c2ecf20Sopenharmony_ci
39068c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
39078c2ecf20Sopenharmony_ci
39088c2ecf20Sopenharmony_cirestart_search:
39098c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_lookup(dir, &dx_root->dr_list, &lookup->dl_hinfo,
39108c2ecf20Sopenharmony_ci				  &leaf_cpos, &blkno);
39118c2ecf20Sopenharmony_ci	if (ret) {
39128c2ecf20Sopenharmony_ci		mlog_errno(ret);
39138c2ecf20Sopenharmony_ci		goto out;
39148c2ecf20Sopenharmony_ci	}
39158c2ecf20Sopenharmony_ci
39168c2ecf20Sopenharmony_ci	ret = ocfs2_read_dx_leaf(dir, blkno, &dx_leaf_bh);
39178c2ecf20Sopenharmony_ci	if (ret) {
39188c2ecf20Sopenharmony_ci		mlog_errno(ret);
39198c2ecf20Sopenharmony_ci		goto out;
39208c2ecf20Sopenharmony_ci	}
39218c2ecf20Sopenharmony_ci
39228c2ecf20Sopenharmony_ci	dx_leaf = (struct ocfs2_dx_leaf *)dx_leaf_bh->b_data;
39238c2ecf20Sopenharmony_ci
39248c2ecf20Sopenharmony_ci	if (le16_to_cpu(dx_leaf->dl_list.de_num_used) >=
39258c2ecf20Sopenharmony_ci	    le16_to_cpu(dx_leaf->dl_list.de_count)) {
39268c2ecf20Sopenharmony_ci		if (rebalanced) {
39278c2ecf20Sopenharmony_ci			/*
39288c2ecf20Sopenharmony_ci			 * Rebalancing should have provided us with
39298c2ecf20Sopenharmony_ci			 * space in an appropriate leaf.
39308c2ecf20Sopenharmony_ci			 *
39318c2ecf20Sopenharmony_ci			 * XXX: Is this an abnormal condition then?
39328c2ecf20Sopenharmony_ci			 * Should we print a message here?
39338c2ecf20Sopenharmony_ci			 */
39348c2ecf20Sopenharmony_ci			ret = -ENOSPC;
39358c2ecf20Sopenharmony_ci			goto out;
39368c2ecf20Sopenharmony_ci		}
39378c2ecf20Sopenharmony_ci
39388c2ecf20Sopenharmony_ci		ret = ocfs2_dx_dir_rebalance(osb, dir, dx_root_bh, dx_leaf_bh,
39398c2ecf20Sopenharmony_ci					     &lookup->dl_hinfo, leaf_cpos,
39408c2ecf20Sopenharmony_ci					     blkno);
39418c2ecf20Sopenharmony_ci		if (ret) {
39428c2ecf20Sopenharmony_ci			if (ret != -ENOSPC)
39438c2ecf20Sopenharmony_ci				mlog_errno(ret);
39448c2ecf20Sopenharmony_ci			goto out;
39458c2ecf20Sopenharmony_ci		}
39468c2ecf20Sopenharmony_ci
39478c2ecf20Sopenharmony_ci		/*
39488c2ecf20Sopenharmony_ci		 * Restart the lookup. The rebalance might have
39498c2ecf20Sopenharmony_ci		 * changed which block our item fits into. Mark our
39508c2ecf20Sopenharmony_ci		 * progress, so we only execute this once.
39518c2ecf20Sopenharmony_ci		 */
39528c2ecf20Sopenharmony_ci		brelse(dx_leaf_bh);
39538c2ecf20Sopenharmony_ci		dx_leaf_bh = NULL;
39548c2ecf20Sopenharmony_ci		rebalanced = 1;
39558c2ecf20Sopenharmony_ci		goto restart_search;
39568c2ecf20Sopenharmony_ci	}
39578c2ecf20Sopenharmony_ci
39588c2ecf20Sopenharmony_ci	lookup->dl_dx_leaf_bh = dx_leaf_bh;
39598c2ecf20Sopenharmony_ci	dx_leaf_bh = NULL;
39608c2ecf20Sopenharmony_ci
39618c2ecf20Sopenharmony_ciout:
39628c2ecf20Sopenharmony_ci	brelse(dx_leaf_bh);
39638c2ecf20Sopenharmony_ci	return ret;
39648c2ecf20Sopenharmony_ci}
39658c2ecf20Sopenharmony_ci
39668c2ecf20Sopenharmony_cistatic int ocfs2_search_dx_free_list(struct inode *dir,
39678c2ecf20Sopenharmony_ci				     struct buffer_head *dx_root_bh,
39688c2ecf20Sopenharmony_ci				     int namelen,
39698c2ecf20Sopenharmony_ci				     struct ocfs2_dir_lookup_result *lookup)
39708c2ecf20Sopenharmony_ci{
39718c2ecf20Sopenharmony_ci	int ret = -ENOSPC;
39728c2ecf20Sopenharmony_ci	struct buffer_head *leaf_bh = NULL, *prev_leaf_bh = NULL;
39738c2ecf20Sopenharmony_ci	struct ocfs2_dir_block_trailer *db;
39748c2ecf20Sopenharmony_ci	u64 next_block;
39758c2ecf20Sopenharmony_ci	int rec_len = OCFS2_DIR_REC_LEN(namelen);
39768c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
39778c2ecf20Sopenharmony_ci
39788c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
39798c2ecf20Sopenharmony_ci	next_block = le64_to_cpu(dx_root->dr_free_blk);
39808c2ecf20Sopenharmony_ci
39818c2ecf20Sopenharmony_ci	while (next_block) {
39828c2ecf20Sopenharmony_ci		brelse(prev_leaf_bh);
39838c2ecf20Sopenharmony_ci		prev_leaf_bh = leaf_bh;
39848c2ecf20Sopenharmony_ci		leaf_bh = NULL;
39858c2ecf20Sopenharmony_ci
39868c2ecf20Sopenharmony_ci		ret = ocfs2_read_dir_block_direct(dir, next_block, &leaf_bh);
39878c2ecf20Sopenharmony_ci		if (ret) {
39888c2ecf20Sopenharmony_ci			mlog_errno(ret);
39898c2ecf20Sopenharmony_ci			goto out;
39908c2ecf20Sopenharmony_ci		}
39918c2ecf20Sopenharmony_ci
39928c2ecf20Sopenharmony_ci		db = ocfs2_trailer_from_bh(leaf_bh, dir->i_sb);
39938c2ecf20Sopenharmony_ci		if (rec_len <= le16_to_cpu(db->db_free_rec_len)) {
39948c2ecf20Sopenharmony_ci			lookup->dl_leaf_bh = leaf_bh;
39958c2ecf20Sopenharmony_ci			lookup->dl_prev_leaf_bh = prev_leaf_bh;
39968c2ecf20Sopenharmony_ci			leaf_bh = NULL;
39978c2ecf20Sopenharmony_ci			prev_leaf_bh = NULL;
39988c2ecf20Sopenharmony_ci			break;
39998c2ecf20Sopenharmony_ci		}
40008c2ecf20Sopenharmony_ci
40018c2ecf20Sopenharmony_ci		next_block = le64_to_cpu(db->db_free_next);
40028c2ecf20Sopenharmony_ci	}
40038c2ecf20Sopenharmony_ci
40048c2ecf20Sopenharmony_ci	if (!next_block)
40058c2ecf20Sopenharmony_ci		ret = -ENOSPC;
40068c2ecf20Sopenharmony_ci
40078c2ecf20Sopenharmony_ciout:
40088c2ecf20Sopenharmony_ci
40098c2ecf20Sopenharmony_ci	brelse(leaf_bh);
40108c2ecf20Sopenharmony_ci	brelse(prev_leaf_bh);
40118c2ecf20Sopenharmony_ci	return ret;
40128c2ecf20Sopenharmony_ci}
40138c2ecf20Sopenharmony_ci
40148c2ecf20Sopenharmony_cistatic int ocfs2_expand_inline_dx_root(struct inode *dir,
40158c2ecf20Sopenharmony_ci				       struct buffer_head *dx_root_bh)
40168c2ecf20Sopenharmony_ci{
40178c2ecf20Sopenharmony_ci	int ret, num_dx_leaves, i, j, did_quota = 0;
40188c2ecf20Sopenharmony_ci	struct buffer_head **dx_leaves = NULL;
40198c2ecf20Sopenharmony_ci	struct ocfs2_extent_tree et;
40208c2ecf20Sopenharmony_ci	u64 insert_blkno;
40218c2ecf20Sopenharmony_ci	struct ocfs2_alloc_context *data_ac = NULL;
40228c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
40238c2ecf20Sopenharmony_ci	handle_t *handle = NULL;
40248c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
40258c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
40268c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry *dx_entry;
40278c2ecf20Sopenharmony_ci	struct ocfs2_dx_leaf *target_leaf;
40288c2ecf20Sopenharmony_ci
40298c2ecf20Sopenharmony_ci	ret = ocfs2_reserve_clusters(osb, 1, &data_ac);
40308c2ecf20Sopenharmony_ci	if (ret) {
40318c2ecf20Sopenharmony_ci		mlog_errno(ret);
40328c2ecf20Sopenharmony_ci		goto out;
40338c2ecf20Sopenharmony_ci	}
40348c2ecf20Sopenharmony_ci
40358c2ecf20Sopenharmony_ci	dx_leaves = ocfs2_dx_dir_kmalloc_leaves(osb->sb, &num_dx_leaves);
40368c2ecf20Sopenharmony_ci	if (!dx_leaves) {
40378c2ecf20Sopenharmony_ci		ret = -ENOMEM;
40388c2ecf20Sopenharmony_ci		mlog_errno(ret);
40398c2ecf20Sopenharmony_ci		goto out;
40408c2ecf20Sopenharmony_ci	}
40418c2ecf20Sopenharmony_ci
40428c2ecf20Sopenharmony_ci	handle = ocfs2_start_trans(osb, ocfs2_calc_dxi_expand_credits(osb->sb));
40438c2ecf20Sopenharmony_ci	if (IS_ERR(handle)) {
40448c2ecf20Sopenharmony_ci		ret = PTR_ERR(handle);
40458c2ecf20Sopenharmony_ci		mlog_errno(ret);
40468c2ecf20Sopenharmony_ci		goto out;
40478c2ecf20Sopenharmony_ci	}
40488c2ecf20Sopenharmony_ci
40498c2ecf20Sopenharmony_ci	ret = dquot_alloc_space_nodirty(dir,
40508c2ecf20Sopenharmony_ci				       ocfs2_clusters_to_bytes(osb->sb, 1));
40518c2ecf20Sopenharmony_ci	if (ret)
40528c2ecf20Sopenharmony_ci		goto out_commit;
40538c2ecf20Sopenharmony_ci	did_quota = 1;
40548c2ecf20Sopenharmony_ci
40558c2ecf20Sopenharmony_ci	/*
40568c2ecf20Sopenharmony_ci	 * We do this up front, before the allocation, so that a
40578c2ecf20Sopenharmony_ci	 * failure to add the dx_root_bh to the journal won't result
40588c2ecf20Sopenharmony_ci	 * us losing clusters.
40598c2ecf20Sopenharmony_ci	 */
40608c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_dr(handle, INODE_CACHE(dir), dx_root_bh,
40618c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
40628c2ecf20Sopenharmony_ci	if (ret) {
40638c2ecf20Sopenharmony_ci		mlog_errno(ret);
40648c2ecf20Sopenharmony_ci		goto out_commit;
40658c2ecf20Sopenharmony_ci	}
40668c2ecf20Sopenharmony_ci
40678c2ecf20Sopenharmony_ci	ret = __ocfs2_dx_dir_new_cluster(dir, 0, handle, data_ac, dx_leaves,
40688c2ecf20Sopenharmony_ci					 num_dx_leaves, &insert_blkno);
40698c2ecf20Sopenharmony_ci	if (ret) {
40708c2ecf20Sopenharmony_ci		mlog_errno(ret);
40718c2ecf20Sopenharmony_ci		goto out_commit;
40728c2ecf20Sopenharmony_ci	}
40738c2ecf20Sopenharmony_ci
40748c2ecf20Sopenharmony_ci	/*
40758c2ecf20Sopenharmony_ci	 * Transfer the entries from our dx_root into the appropriate
40768c2ecf20Sopenharmony_ci	 * block
40778c2ecf20Sopenharmony_ci	 */
40788c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
40798c2ecf20Sopenharmony_ci	entry_list = &dx_root->dr_entries;
40808c2ecf20Sopenharmony_ci
40818c2ecf20Sopenharmony_ci	for (i = 0; i < le16_to_cpu(entry_list->de_num_used); i++) {
40828c2ecf20Sopenharmony_ci		dx_entry = &entry_list->de_entries[i];
40838c2ecf20Sopenharmony_ci
40848c2ecf20Sopenharmony_ci		j = __ocfs2_dx_dir_hash_idx(osb,
40858c2ecf20Sopenharmony_ci					    le32_to_cpu(dx_entry->dx_minor_hash));
40868c2ecf20Sopenharmony_ci		target_leaf = (struct ocfs2_dx_leaf *)dx_leaves[j]->b_data;
40878c2ecf20Sopenharmony_ci
40888c2ecf20Sopenharmony_ci		ocfs2_dx_dir_leaf_insert_tail(target_leaf, dx_entry);
40898c2ecf20Sopenharmony_ci
40908c2ecf20Sopenharmony_ci		/* Each leaf has been passed to the journal already
40918c2ecf20Sopenharmony_ci		 * via __ocfs2_dx_dir_new_cluster() */
40928c2ecf20Sopenharmony_ci	}
40938c2ecf20Sopenharmony_ci
40948c2ecf20Sopenharmony_ci	dx_root->dr_flags &= ~OCFS2_DX_FLAG_INLINE;
40958c2ecf20Sopenharmony_ci	memset(&dx_root->dr_list, 0, osb->sb->s_blocksize -
40968c2ecf20Sopenharmony_ci	       offsetof(struct ocfs2_dx_root_block, dr_list));
40978c2ecf20Sopenharmony_ci	dx_root->dr_list.l_count =
40988c2ecf20Sopenharmony_ci		cpu_to_le16(ocfs2_extent_recs_per_dx_root(osb->sb));
40998c2ecf20Sopenharmony_ci
41008c2ecf20Sopenharmony_ci	/* This should never fail considering we start with an empty
41018c2ecf20Sopenharmony_ci	 * dx_root. */
41028c2ecf20Sopenharmony_ci	ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
41038c2ecf20Sopenharmony_ci	ret = ocfs2_insert_extent(handle, &et, 0, insert_blkno, 1, 0, NULL);
41048c2ecf20Sopenharmony_ci	if (ret)
41058c2ecf20Sopenharmony_ci		mlog_errno(ret);
41068c2ecf20Sopenharmony_ci	did_quota = 0;
41078c2ecf20Sopenharmony_ci
41088c2ecf20Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
41098c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, dx_root_bh);
41108c2ecf20Sopenharmony_ci
41118c2ecf20Sopenharmony_ciout_commit:
41128c2ecf20Sopenharmony_ci	if (ret < 0 && did_quota)
41138c2ecf20Sopenharmony_ci		dquot_free_space_nodirty(dir,
41148c2ecf20Sopenharmony_ci					  ocfs2_clusters_to_bytes(dir->i_sb, 1));
41158c2ecf20Sopenharmony_ci
41168c2ecf20Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
41178c2ecf20Sopenharmony_ci
41188c2ecf20Sopenharmony_ciout:
41198c2ecf20Sopenharmony_ci	if (data_ac)
41208c2ecf20Sopenharmony_ci		ocfs2_free_alloc_context(data_ac);
41218c2ecf20Sopenharmony_ci
41228c2ecf20Sopenharmony_ci	if (dx_leaves) {
41238c2ecf20Sopenharmony_ci		for (i = 0; i < num_dx_leaves; i++)
41248c2ecf20Sopenharmony_ci			brelse(dx_leaves[i]);
41258c2ecf20Sopenharmony_ci		kfree(dx_leaves);
41268c2ecf20Sopenharmony_ci	}
41278c2ecf20Sopenharmony_ci	return ret;
41288c2ecf20Sopenharmony_ci}
41298c2ecf20Sopenharmony_ci
41308c2ecf20Sopenharmony_cistatic int ocfs2_inline_dx_has_space(struct buffer_head *dx_root_bh)
41318c2ecf20Sopenharmony_ci{
41328c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
41338c2ecf20Sopenharmony_ci	struct ocfs2_dx_entry_list *entry_list;
41348c2ecf20Sopenharmony_ci
41358c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
41368c2ecf20Sopenharmony_ci	entry_list = &dx_root->dr_entries;
41378c2ecf20Sopenharmony_ci
41388c2ecf20Sopenharmony_ci	if (le16_to_cpu(entry_list->de_num_used) >=
41398c2ecf20Sopenharmony_ci	    le16_to_cpu(entry_list->de_count))
41408c2ecf20Sopenharmony_ci		return -ENOSPC;
41418c2ecf20Sopenharmony_ci
41428c2ecf20Sopenharmony_ci	return 0;
41438c2ecf20Sopenharmony_ci}
41448c2ecf20Sopenharmony_ci
41458c2ecf20Sopenharmony_cistatic int ocfs2_prepare_dx_dir_for_insert(struct inode *dir,
41468c2ecf20Sopenharmony_ci					   struct buffer_head *di_bh,
41478c2ecf20Sopenharmony_ci					   const char *name,
41488c2ecf20Sopenharmony_ci					   int namelen,
41498c2ecf20Sopenharmony_ci					   struct ocfs2_dir_lookup_result *lookup)
41508c2ecf20Sopenharmony_ci{
41518c2ecf20Sopenharmony_ci	int ret, free_dx_root = 1;
41528c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
41538c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
41548c2ecf20Sopenharmony_ci	struct buffer_head *leaf_bh = NULL;
41558c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
41568c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
41578c2ecf20Sopenharmony_ci
41588c2ecf20Sopenharmony_ci	ret = ocfs2_read_dx_root(dir, di, &dx_root_bh);
41598c2ecf20Sopenharmony_ci	if (ret) {
41608c2ecf20Sopenharmony_ci		mlog_errno(ret);
41618c2ecf20Sopenharmony_ci		goto out;
41628c2ecf20Sopenharmony_ci	}
41638c2ecf20Sopenharmony_ci
41648c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
41658c2ecf20Sopenharmony_ci	if (le32_to_cpu(dx_root->dr_num_entries) == OCFS2_DX_ENTRIES_MAX) {
41668c2ecf20Sopenharmony_ci		ret = -ENOSPC;
41678c2ecf20Sopenharmony_ci		mlog_errno(ret);
41688c2ecf20Sopenharmony_ci		goto out;
41698c2ecf20Sopenharmony_ci	}
41708c2ecf20Sopenharmony_ci
41718c2ecf20Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root)) {
41728c2ecf20Sopenharmony_ci		ret = ocfs2_inline_dx_has_space(dx_root_bh);
41738c2ecf20Sopenharmony_ci
41748c2ecf20Sopenharmony_ci		if (ret == 0)
41758c2ecf20Sopenharmony_ci			goto search_el;
41768c2ecf20Sopenharmony_ci
41778c2ecf20Sopenharmony_ci		/*
41788c2ecf20Sopenharmony_ci		 * We ran out of room in the root block. Expand it to
41798c2ecf20Sopenharmony_ci		 * an extent, then allow ocfs2_find_dir_space_dx to do
41808c2ecf20Sopenharmony_ci		 * the rest.
41818c2ecf20Sopenharmony_ci		 */
41828c2ecf20Sopenharmony_ci		ret = ocfs2_expand_inline_dx_root(dir, dx_root_bh);
41838c2ecf20Sopenharmony_ci		if (ret) {
41848c2ecf20Sopenharmony_ci			mlog_errno(ret);
41858c2ecf20Sopenharmony_ci			goto out;
41868c2ecf20Sopenharmony_ci		}
41878c2ecf20Sopenharmony_ci	}
41888c2ecf20Sopenharmony_ci
41898c2ecf20Sopenharmony_ci	/*
41908c2ecf20Sopenharmony_ci	 * Insert preparation for an indexed directory is split into two
41918c2ecf20Sopenharmony_ci	 * steps. The call to find_dir_space_dx reserves room in the index for
41928c2ecf20Sopenharmony_ci	 * an additional item. If we run out of space there, it's a real error
41938c2ecf20Sopenharmony_ci	 * we can't continue on.
41948c2ecf20Sopenharmony_ci	 */
41958c2ecf20Sopenharmony_ci	ret = ocfs2_find_dir_space_dx(osb, dir, di_bh, dx_root_bh, name,
41968c2ecf20Sopenharmony_ci				      namelen, lookup);
41978c2ecf20Sopenharmony_ci	if (ret) {
41988c2ecf20Sopenharmony_ci		mlog_errno(ret);
41998c2ecf20Sopenharmony_ci		goto out;
42008c2ecf20Sopenharmony_ci	}
42018c2ecf20Sopenharmony_ci
42028c2ecf20Sopenharmony_cisearch_el:
42038c2ecf20Sopenharmony_ci	/*
42048c2ecf20Sopenharmony_ci	 * Next, we need to find space in the unindexed tree. This call
42058c2ecf20Sopenharmony_ci	 * searches using the free space linked list. If the unindexed tree
42068c2ecf20Sopenharmony_ci	 * lacks sufficient space, we'll expand it below. The expansion code
42078c2ecf20Sopenharmony_ci	 * is smart enough to add any new blocks to the free space list.
42088c2ecf20Sopenharmony_ci	 */
42098c2ecf20Sopenharmony_ci	ret = ocfs2_search_dx_free_list(dir, dx_root_bh, namelen, lookup);
42108c2ecf20Sopenharmony_ci	if (ret && ret != -ENOSPC) {
42118c2ecf20Sopenharmony_ci		mlog_errno(ret);
42128c2ecf20Sopenharmony_ci		goto out;
42138c2ecf20Sopenharmony_ci	}
42148c2ecf20Sopenharmony_ci
42158c2ecf20Sopenharmony_ci	/* Do this up here - ocfs2_extend_dir might need the dx_root */
42168c2ecf20Sopenharmony_ci	lookup->dl_dx_root_bh = dx_root_bh;
42178c2ecf20Sopenharmony_ci	free_dx_root = 0;
42188c2ecf20Sopenharmony_ci
42198c2ecf20Sopenharmony_ci	if (ret == -ENOSPC) {
42208c2ecf20Sopenharmony_ci		ret = ocfs2_extend_dir(osb, dir, di_bh, 1, lookup, &leaf_bh);
42218c2ecf20Sopenharmony_ci
42228c2ecf20Sopenharmony_ci		if (ret) {
42238c2ecf20Sopenharmony_ci			mlog_errno(ret);
42248c2ecf20Sopenharmony_ci			goto out;
42258c2ecf20Sopenharmony_ci		}
42268c2ecf20Sopenharmony_ci
42278c2ecf20Sopenharmony_ci		/*
42288c2ecf20Sopenharmony_ci		 * We make the assumption here that new leaf blocks are added
42298c2ecf20Sopenharmony_ci		 * to the front of our free list.
42308c2ecf20Sopenharmony_ci		 */
42318c2ecf20Sopenharmony_ci		lookup->dl_prev_leaf_bh = NULL;
42328c2ecf20Sopenharmony_ci		lookup->dl_leaf_bh = leaf_bh;
42338c2ecf20Sopenharmony_ci	}
42348c2ecf20Sopenharmony_ci
42358c2ecf20Sopenharmony_ciout:
42368c2ecf20Sopenharmony_ci	if (free_dx_root)
42378c2ecf20Sopenharmony_ci		brelse(dx_root_bh);
42388c2ecf20Sopenharmony_ci	return ret;
42398c2ecf20Sopenharmony_ci}
42408c2ecf20Sopenharmony_ci
42418c2ecf20Sopenharmony_ci/*
42428c2ecf20Sopenharmony_ci * Get a directory ready for insert. Any directory allocation required
42438c2ecf20Sopenharmony_ci * happens here. Success returns zero, and enough context in the dir
42448c2ecf20Sopenharmony_ci * lookup result that ocfs2_add_entry() will be able complete the task
42458c2ecf20Sopenharmony_ci * with minimal performance impact.
42468c2ecf20Sopenharmony_ci */
42478c2ecf20Sopenharmony_ciint ocfs2_prepare_dir_for_insert(struct ocfs2_super *osb,
42488c2ecf20Sopenharmony_ci				 struct inode *dir,
42498c2ecf20Sopenharmony_ci				 struct buffer_head *parent_fe_bh,
42508c2ecf20Sopenharmony_ci				 const char *name,
42518c2ecf20Sopenharmony_ci				 int namelen,
42528c2ecf20Sopenharmony_ci				 struct ocfs2_dir_lookup_result *lookup)
42538c2ecf20Sopenharmony_ci{
42548c2ecf20Sopenharmony_ci	int ret;
42558c2ecf20Sopenharmony_ci	unsigned int blocks_wanted = 1;
42568c2ecf20Sopenharmony_ci	struct buffer_head *bh = NULL;
42578c2ecf20Sopenharmony_ci
42588c2ecf20Sopenharmony_ci	trace_ocfs2_prepare_dir_for_insert(
42598c2ecf20Sopenharmony_ci		(unsigned long long)OCFS2_I(dir)->ip_blkno, namelen);
42608c2ecf20Sopenharmony_ci
42618c2ecf20Sopenharmony_ci	if (!namelen) {
42628c2ecf20Sopenharmony_ci		ret = -EINVAL;
42638c2ecf20Sopenharmony_ci		mlog_errno(ret);
42648c2ecf20Sopenharmony_ci		goto out;
42658c2ecf20Sopenharmony_ci	}
42668c2ecf20Sopenharmony_ci
42678c2ecf20Sopenharmony_ci	/*
42688c2ecf20Sopenharmony_ci	 * Do this up front to reduce confusion.
42698c2ecf20Sopenharmony_ci	 *
42708c2ecf20Sopenharmony_ci	 * The directory might start inline, then be turned into an
42718c2ecf20Sopenharmony_ci	 * indexed one, in which case we'd need to hash deep inside
42728c2ecf20Sopenharmony_ci	 * ocfs2_find_dir_space_id(). Since
42738c2ecf20Sopenharmony_ci	 * ocfs2_prepare_dx_dir_for_insert() also needs this hash
42748c2ecf20Sopenharmony_ci	 * done, there seems no point in spreading out the calls. We
42758c2ecf20Sopenharmony_ci	 * can optimize away the case where the file system doesn't
42768c2ecf20Sopenharmony_ci	 * support indexing.
42778c2ecf20Sopenharmony_ci	 */
42788c2ecf20Sopenharmony_ci	if (ocfs2_supports_indexed_dirs(osb))
42798c2ecf20Sopenharmony_ci		ocfs2_dx_dir_name_hash(dir, name, namelen, &lookup->dl_hinfo);
42808c2ecf20Sopenharmony_ci
42818c2ecf20Sopenharmony_ci	if (ocfs2_dir_indexed(dir)) {
42828c2ecf20Sopenharmony_ci		ret = ocfs2_prepare_dx_dir_for_insert(dir, parent_fe_bh,
42838c2ecf20Sopenharmony_ci						      name, namelen, lookup);
42848c2ecf20Sopenharmony_ci		if (ret)
42858c2ecf20Sopenharmony_ci			mlog_errno(ret);
42868c2ecf20Sopenharmony_ci		goto out;
42878c2ecf20Sopenharmony_ci	}
42888c2ecf20Sopenharmony_ci
42898c2ecf20Sopenharmony_ci	if (OCFS2_I(dir)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
42908c2ecf20Sopenharmony_ci		ret = ocfs2_find_dir_space_id(dir, parent_fe_bh, name,
42918c2ecf20Sopenharmony_ci					      namelen, &bh, &blocks_wanted);
42928c2ecf20Sopenharmony_ci	} else
42938c2ecf20Sopenharmony_ci		ret = ocfs2_find_dir_space_el(dir, name, namelen, &bh);
42948c2ecf20Sopenharmony_ci
42958c2ecf20Sopenharmony_ci	if (ret && ret != -ENOSPC) {
42968c2ecf20Sopenharmony_ci		mlog_errno(ret);
42978c2ecf20Sopenharmony_ci		goto out;
42988c2ecf20Sopenharmony_ci	}
42998c2ecf20Sopenharmony_ci
43008c2ecf20Sopenharmony_ci	if (ret == -ENOSPC) {
43018c2ecf20Sopenharmony_ci		/*
43028c2ecf20Sopenharmony_ci		 * We have to expand the directory to add this name.
43038c2ecf20Sopenharmony_ci		 */
43048c2ecf20Sopenharmony_ci		BUG_ON(bh);
43058c2ecf20Sopenharmony_ci
43068c2ecf20Sopenharmony_ci		ret = ocfs2_extend_dir(osb, dir, parent_fe_bh, blocks_wanted,
43078c2ecf20Sopenharmony_ci				       lookup, &bh);
43088c2ecf20Sopenharmony_ci		if (ret) {
43098c2ecf20Sopenharmony_ci			if (ret != -ENOSPC)
43108c2ecf20Sopenharmony_ci				mlog_errno(ret);
43118c2ecf20Sopenharmony_ci			goto out;
43128c2ecf20Sopenharmony_ci		}
43138c2ecf20Sopenharmony_ci
43148c2ecf20Sopenharmony_ci		BUG_ON(!bh);
43158c2ecf20Sopenharmony_ci	}
43168c2ecf20Sopenharmony_ci
43178c2ecf20Sopenharmony_ci	lookup->dl_leaf_bh = bh;
43188c2ecf20Sopenharmony_ci	bh = NULL;
43198c2ecf20Sopenharmony_ciout:
43208c2ecf20Sopenharmony_ci	brelse(bh);
43218c2ecf20Sopenharmony_ci	return ret;
43228c2ecf20Sopenharmony_ci}
43238c2ecf20Sopenharmony_ci
43248c2ecf20Sopenharmony_cistatic int ocfs2_dx_dir_remove_index(struct inode *dir,
43258c2ecf20Sopenharmony_ci				     struct buffer_head *di_bh,
43268c2ecf20Sopenharmony_ci				     struct buffer_head *dx_root_bh)
43278c2ecf20Sopenharmony_ci{
43288c2ecf20Sopenharmony_ci	int ret;
43298c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
43308c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
43318c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
43328c2ecf20Sopenharmony_ci	struct inode *dx_alloc_inode = NULL;
43338c2ecf20Sopenharmony_ci	struct buffer_head *dx_alloc_bh = NULL;
43348c2ecf20Sopenharmony_ci	handle_t *handle;
43358c2ecf20Sopenharmony_ci	u64 blk;
43368c2ecf20Sopenharmony_ci	u16 bit;
43378c2ecf20Sopenharmony_ci	u64 bg_blkno;
43388c2ecf20Sopenharmony_ci
43398c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *) dx_root_bh->b_data;
43408c2ecf20Sopenharmony_ci
43418c2ecf20Sopenharmony_ci	dx_alloc_inode = ocfs2_get_system_file_inode(osb,
43428c2ecf20Sopenharmony_ci					EXTENT_ALLOC_SYSTEM_INODE,
43438c2ecf20Sopenharmony_ci					le16_to_cpu(dx_root->dr_suballoc_slot));
43448c2ecf20Sopenharmony_ci	if (!dx_alloc_inode) {
43458c2ecf20Sopenharmony_ci		ret = -ENOMEM;
43468c2ecf20Sopenharmony_ci		mlog_errno(ret);
43478c2ecf20Sopenharmony_ci		goto out;
43488c2ecf20Sopenharmony_ci	}
43498c2ecf20Sopenharmony_ci	inode_lock(dx_alloc_inode);
43508c2ecf20Sopenharmony_ci
43518c2ecf20Sopenharmony_ci	ret = ocfs2_inode_lock(dx_alloc_inode, &dx_alloc_bh, 1);
43528c2ecf20Sopenharmony_ci	if (ret) {
43538c2ecf20Sopenharmony_ci		mlog_errno(ret);
43548c2ecf20Sopenharmony_ci		goto out_mutex;
43558c2ecf20Sopenharmony_ci	}
43568c2ecf20Sopenharmony_ci
43578c2ecf20Sopenharmony_ci	handle = ocfs2_start_trans(osb, OCFS2_DX_ROOT_REMOVE_CREDITS);
43588c2ecf20Sopenharmony_ci	if (IS_ERR(handle)) {
43598c2ecf20Sopenharmony_ci		ret = PTR_ERR(handle);
43608c2ecf20Sopenharmony_ci		mlog_errno(ret);
43618c2ecf20Sopenharmony_ci		goto out_unlock;
43628c2ecf20Sopenharmony_ci	}
43638c2ecf20Sopenharmony_ci
43648c2ecf20Sopenharmony_ci	ret = ocfs2_journal_access_di(handle, INODE_CACHE(dir), di_bh,
43658c2ecf20Sopenharmony_ci				      OCFS2_JOURNAL_ACCESS_WRITE);
43668c2ecf20Sopenharmony_ci	if (ret) {
43678c2ecf20Sopenharmony_ci		mlog_errno(ret);
43688c2ecf20Sopenharmony_ci		goto out_commit;
43698c2ecf20Sopenharmony_ci	}
43708c2ecf20Sopenharmony_ci
43718c2ecf20Sopenharmony_ci	spin_lock(&OCFS2_I(dir)->ip_lock);
43728c2ecf20Sopenharmony_ci	OCFS2_I(dir)->ip_dyn_features &= ~OCFS2_INDEXED_DIR_FL;
43738c2ecf20Sopenharmony_ci	di->i_dyn_features = cpu_to_le16(OCFS2_I(dir)->ip_dyn_features);
43748c2ecf20Sopenharmony_ci	spin_unlock(&OCFS2_I(dir)->ip_lock);
43758c2ecf20Sopenharmony_ci	di->i_dx_root = cpu_to_le64(0ULL);
43768c2ecf20Sopenharmony_ci	ocfs2_update_inode_fsync_trans(handle, dir, 1);
43778c2ecf20Sopenharmony_ci
43788c2ecf20Sopenharmony_ci	ocfs2_journal_dirty(handle, di_bh);
43798c2ecf20Sopenharmony_ci
43808c2ecf20Sopenharmony_ci	blk = le64_to_cpu(dx_root->dr_blkno);
43818c2ecf20Sopenharmony_ci	bit = le16_to_cpu(dx_root->dr_suballoc_bit);
43828c2ecf20Sopenharmony_ci	if (dx_root->dr_suballoc_loc)
43838c2ecf20Sopenharmony_ci		bg_blkno = le64_to_cpu(dx_root->dr_suballoc_loc);
43848c2ecf20Sopenharmony_ci	else
43858c2ecf20Sopenharmony_ci		bg_blkno = ocfs2_which_suballoc_group(blk, bit);
43868c2ecf20Sopenharmony_ci	ret = ocfs2_free_suballoc_bits(handle, dx_alloc_inode, dx_alloc_bh,
43878c2ecf20Sopenharmony_ci				       bit, bg_blkno, 1);
43888c2ecf20Sopenharmony_ci	if (ret)
43898c2ecf20Sopenharmony_ci		mlog_errno(ret);
43908c2ecf20Sopenharmony_ci
43918c2ecf20Sopenharmony_ciout_commit:
43928c2ecf20Sopenharmony_ci	ocfs2_commit_trans(osb, handle);
43938c2ecf20Sopenharmony_ci
43948c2ecf20Sopenharmony_ciout_unlock:
43958c2ecf20Sopenharmony_ci	ocfs2_inode_unlock(dx_alloc_inode, 1);
43968c2ecf20Sopenharmony_ci
43978c2ecf20Sopenharmony_ciout_mutex:
43988c2ecf20Sopenharmony_ci	inode_unlock(dx_alloc_inode);
43998c2ecf20Sopenharmony_ci	brelse(dx_alloc_bh);
44008c2ecf20Sopenharmony_ciout:
44018c2ecf20Sopenharmony_ci	iput(dx_alloc_inode);
44028c2ecf20Sopenharmony_ci	return ret;
44038c2ecf20Sopenharmony_ci}
44048c2ecf20Sopenharmony_ci
44058c2ecf20Sopenharmony_ciint ocfs2_dx_dir_truncate(struct inode *dir, struct buffer_head *di_bh)
44068c2ecf20Sopenharmony_ci{
44078c2ecf20Sopenharmony_ci	int ret;
44088c2ecf20Sopenharmony_ci	unsigned int clen;
44098c2ecf20Sopenharmony_ci	u32 major_hash = UINT_MAX, p_cpos, cpos;
44108c2ecf20Sopenharmony_ci	u64 blkno;
44118c2ecf20Sopenharmony_ci	struct ocfs2_super *osb = OCFS2_SB(dir->i_sb);
44128c2ecf20Sopenharmony_ci	struct buffer_head *dx_root_bh = NULL;
44138c2ecf20Sopenharmony_ci	struct ocfs2_dx_root_block *dx_root;
44148c2ecf20Sopenharmony_ci	struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
44158c2ecf20Sopenharmony_ci	struct ocfs2_cached_dealloc_ctxt dealloc;
44168c2ecf20Sopenharmony_ci	struct ocfs2_extent_tree et;
44178c2ecf20Sopenharmony_ci
44188c2ecf20Sopenharmony_ci	ocfs2_init_dealloc_ctxt(&dealloc);
44198c2ecf20Sopenharmony_ci
44208c2ecf20Sopenharmony_ci	if (!ocfs2_dir_indexed(dir))
44218c2ecf20Sopenharmony_ci		return 0;
44228c2ecf20Sopenharmony_ci
44238c2ecf20Sopenharmony_ci	ret = ocfs2_read_dx_root(dir, di, &dx_root_bh);
44248c2ecf20Sopenharmony_ci	if (ret) {
44258c2ecf20Sopenharmony_ci		mlog_errno(ret);
44268c2ecf20Sopenharmony_ci		goto out;
44278c2ecf20Sopenharmony_ci	}
44288c2ecf20Sopenharmony_ci	dx_root = (struct ocfs2_dx_root_block *)dx_root_bh->b_data;
44298c2ecf20Sopenharmony_ci
44308c2ecf20Sopenharmony_ci	if (ocfs2_dx_root_inline(dx_root))
44318c2ecf20Sopenharmony_ci		goto remove_index;
44328c2ecf20Sopenharmony_ci
44338c2ecf20Sopenharmony_ci	ocfs2_init_dx_root_extent_tree(&et, INODE_CACHE(dir), dx_root_bh);
44348c2ecf20Sopenharmony_ci
44358c2ecf20Sopenharmony_ci	/* XXX: What if dr_clusters is too large? */
44368c2ecf20Sopenharmony_ci	while (le32_to_cpu(dx_root->dr_clusters)) {
44378c2ecf20Sopenharmony_ci		ret = ocfs2_dx_dir_lookup_rec(dir, &dx_root->dr_list,
44388c2ecf20Sopenharmony_ci					      major_hash, &cpos, &blkno, &clen);
44398c2ecf20Sopenharmony_ci		if (ret) {
44408c2ecf20Sopenharmony_ci			mlog_errno(ret);
44418c2ecf20Sopenharmony_ci			goto out;
44428c2ecf20Sopenharmony_ci		}
44438c2ecf20Sopenharmony_ci
44448c2ecf20Sopenharmony_ci		p_cpos = ocfs2_blocks_to_clusters(dir->i_sb, blkno);
44458c2ecf20Sopenharmony_ci
44468c2ecf20Sopenharmony_ci		ret = ocfs2_remove_btree_range(dir, &et, cpos, p_cpos, clen, 0,
44478c2ecf20Sopenharmony_ci					       &dealloc, 0, false);
44488c2ecf20Sopenharmony_ci		if (ret) {
44498c2ecf20Sopenharmony_ci			mlog_errno(ret);
44508c2ecf20Sopenharmony_ci			goto out;
44518c2ecf20Sopenharmony_ci		}
44528c2ecf20Sopenharmony_ci
44538c2ecf20Sopenharmony_ci		if (cpos == 0)
44548c2ecf20Sopenharmony_ci			break;
44558c2ecf20Sopenharmony_ci
44568c2ecf20Sopenharmony_ci		major_hash = cpos - 1;
44578c2ecf20Sopenharmony_ci	}
44588c2ecf20Sopenharmony_ci
44598c2ecf20Sopenharmony_ciremove_index:
44608c2ecf20Sopenharmony_ci	ret = ocfs2_dx_dir_remove_index(dir, di_bh, dx_root_bh);
44618c2ecf20Sopenharmony_ci	if (ret) {
44628c2ecf20Sopenharmony_ci		mlog_errno(ret);
44638c2ecf20Sopenharmony_ci		goto out;
44648c2ecf20Sopenharmony_ci	}
44658c2ecf20Sopenharmony_ci
44668c2ecf20Sopenharmony_ci	ocfs2_remove_from_cache(INODE_CACHE(dir), dx_root_bh);
44678c2ecf20Sopenharmony_ciout:
44688c2ecf20Sopenharmony_ci	ocfs2_schedule_truncate_log_flush(osb, 1);
44698c2ecf20Sopenharmony_ci	ocfs2_run_deallocs(osb, &dealloc);
44708c2ecf20Sopenharmony_ci
44718c2ecf20Sopenharmony_ci	brelse(dx_root_bh);
44728c2ecf20Sopenharmony_ci	return ret;
44738c2ecf20Sopenharmony_ci}
4474