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