summaryrefslogtreecommitdiffstats
path: root/fs/ext4
diff options
context:
space:
mode:
authorArtem Blagodarenko <artem.blagodarenko@gmail.com>2017-06-21 21:09:57 -0400
committerTheodore Ts'o <tytso@mit.edu>2017-06-21 21:09:57 -0400
commite08ac99fa2a25626f573cfa377ef3ddedf2cfe8f (patch)
treef8d44249cdc7a8405a7a73344a7dc45b5a2455c3 /fs/ext4
parent67a7d5f561f469ad2fa5154d2888258ab8e6df7c (diff)
ext4: add largedir feature
This INCOMPAT_LARGEDIR feature allows larger directories to be created in ldiskfs, both with directory sizes over 2GB and and a maximum htree depth of 3 instead of the current limit of 2. These features are needed in order to exceed the current limit of approximately 10M entries in a single directory. This patch was originally written by Yang Sheng to support the Lustre server. [ Bumped the credits needed to update an indexed directory -- tytso ] Signed-off-by: Liang Zhen <liang.zhen@intel.com> Signed-off-by: Yang Sheng <yang.sheng@intel.com> Signed-off-by: Artem Blagodarenko <artem.blagodarenko@seagate.com> Signed-off-by: Theodore Ts'o <tytso@mit.edu> Reviewed-by: Andreas Dilger <andreas.dilger@intel.com>
Diffstat (limited to 'fs/ext4')
-rw-r--r--fs/ext4/ext4.h23
-rw-r--r--fs/ext4/ext4_jbd2.h9
-rw-r--r--fs/ext4/inode.c4
-rw-r--r--fs/ext4/namei.c124
4 files changed, 113 insertions, 47 deletions
diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h
index 32191548abed..f17a4e7075be 100644
--- a/fs/ext4/ext4.h
+++ b/fs/ext4/ext4.h
@@ -1800,7 +1800,8 @@ EXT4_FEATURE_INCOMPAT_FUNCS(encrypt, ENCRYPT)
1800 EXT4_FEATURE_INCOMPAT_MMP | \ 1800 EXT4_FEATURE_INCOMPAT_MMP | \
1801 EXT4_FEATURE_INCOMPAT_INLINE_DATA | \ 1801 EXT4_FEATURE_INCOMPAT_INLINE_DATA | \
1802 EXT4_FEATURE_INCOMPAT_ENCRYPT | \ 1802 EXT4_FEATURE_INCOMPAT_ENCRYPT | \
1803 EXT4_FEATURE_INCOMPAT_CSUM_SEED) 1803 EXT4_FEATURE_INCOMPAT_CSUM_SEED | \
1804 EXT4_FEATURE_INCOMPAT_LARGEDIR)
1804#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \ 1805#define EXT4_FEATURE_RO_COMPAT_SUPP (EXT4_FEATURE_RO_COMPAT_SPARSE_SUPER| \
1805 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \ 1806 EXT4_FEATURE_RO_COMPAT_LARGE_FILE| \
1806 EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \ 1807 EXT4_FEATURE_RO_COMPAT_GDT_CSUM| \
@@ -2126,6 +2127,16 @@ ext4_group_first_block_no(struct super_block *sb, ext4_group_t group_no)
2126 */ 2127 */
2127#define ERR_BAD_DX_DIR (-(MAX_ERRNO - 1)) 2128#define ERR_BAD_DX_DIR (-(MAX_ERRNO - 1))
2128 2129
2130/* htree levels for ext4 */
2131#define EXT4_HTREE_LEVEL_COMPAT 2
2132#define EXT4_HTREE_LEVEL 3
2133
2134static inline int ext4_dir_htree_level(struct super_block *sb)
2135{
2136 return ext4_has_feature_largedir(sb) ?
2137 EXT4_HTREE_LEVEL : EXT4_HTREE_LEVEL_COMPAT;
2138}
2139
2129/* 2140/*
2130 * Timeout and state flag for lazy initialization inode thread. 2141 * Timeout and state flag for lazy initialization inode thread.
2131 */ 2142 */
@@ -2756,13 +2767,15 @@ static inline void ext4_r_blocks_count_set(struct ext4_super_block *es,
2756 es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32); 2767 es->s_r_blocks_count_hi = cpu_to_le32(blk >> 32);
2757} 2768}
2758 2769
2759static inline loff_t ext4_isize(struct ext4_inode *raw_inode) 2770static inline loff_t ext4_isize(struct super_block *sb,
2771 struct ext4_inode *raw_inode)
2760{ 2772{
2761 if (S_ISREG(le16_to_cpu(raw_inode->i_mode))) 2773 if (ext4_has_feature_largedir(sb) ||
2774 S_ISREG(le16_to_cpu(raw_inode->i_mode)))
2762 return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) | 2775 return ((loff_t)le32_to_cpu(raw_inode->i_size_high) << 32) |
2763 le32_to_cpu(raw_inode->i_size_lo); 2776 le32_to_cpu(raw_inode->i_size_lo);
2764 else 2777
2765 return (loff_t) le32_to_cpu(raw_inode->i_size_lo); 2778 return (loff_t) le32_to_cpu(raw_inode->i_size_lo);
2766} 2779}
2767 2780
2768static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size) 2781static inline void ext4_isize_set(struct ext4_inode *raw_inode, loff_t i_size)
diff --git a/fs/ext4/ext4_jbd2.h b/fs/ext4/ext4_jbd2.h
index f97611171023..5e61e464d71c 100644
--- a/fs/ext4/ext4_jbd2.h
+++ b/fs/ext4/ext4_jbd2.h
@@ -77,7 +77,14 @@
77 77
78#define EXT4_RESERVE_TRANS_BLOCKS 12U 78#define EXT4_RESERVE_TRANS_BLOCKS 12U
79 79
80#define EXT4_INDEX_EXTRA_TRANS_BLOCKS 8 80/*
81 * Number of credits needed if we need to insert an entry into a
82 * directory. For each new index block, we need 4 blocks (old index
83 * block, new index block, bitmap block, bg summary). For normal
84 * htree directories there are 2 levels; if the largedir feature
85 * enabled it's 3 levels.
86 */
87#define EXT4_INDEX_EXTRA_TRANS_BLOCKS 12U
81 88
82#ifdef CONFIG_QUOTA 89#ifdef CONFIG_QUOTA
83/* Amount of blocks needed for quota update - we know that the structure was 90/* Amount of blocks needed for quota update - we know that the structure was
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 5cf82d03968c..47604d1352fc 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -4712,7 +4712,7 @@ struct inode *ext4_iget(struct super_block *sb, unsigned long ino)
4712 if (ext4_has_feature_64bit(sb)) 4712 if (ext4_has_feature_64bit(sb))
4713 ei->i_file_acl |= 4713 ei->i_file_acl |=
4714 ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32; 4714 ((__u64)le16_to_cpu(raw_inode->i_file_acl_high)) << 32;
4715 inode->i_size = ext4_isize(raw_inode); 4715 inode->i_size = ext4_isize(sb, raw_inode);
4716 if ((size = i_size_read(inode)) < 0) { 4716 if ((size = i_size_read(inode)) < 0) {
4717 EXT4_ERROR_INODE(inode, "bad i_size value: %lld", size); 4717 EXT4_ERROR_INODE(inode, "bad i_size value: %lld", size);
4718 ret = -EFSCORRUPTED; 4718 ret = -EFSCORRUPTED;
@@ -5037,7 +5037,7 @@ static int ext4_do_update_inode(handle_t *handle,
5037 raw_inode->i_file_acl_high = 5037 raw_inode->i_file_acl_high =
5038 cpu_to_le16(ei->i_file_acl >> 32); 5038 cpu_to_le16(ei->i_file_acl >> 32);
5039 raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl); 5039 raw_inode->i_file_acl_lo = cpu_to_le32(ei->i_file_acl);
5040 if (ei->i_disksize != ext4_isize(raw_inode)) { 5040 if (ei->i_disksize != ext4_isize(inode->i_sb, raw_inode)) {
5041 ext4_isize_set(raw_inode, ei->i_disksize); 5041 ext4_isize_set(raw_inode, ei->i_disksize);
5042 need_datasync = 1; 5042 need_datasync = 1;
5043 } 5043 }
diff --git a/fs/ext4/namei.c b/fs/ext4/namei.c
index 404256caf9cf..423e1f761768 100644
--- a/fs/ext4/namei.c
+++ b/fs/ext4/namei.c
@@ -513,7 +513,7 @@ ext4_next_entry(struct ext4_dir_entry_2 *p, unsigned long blocksize)
513 513
514static inline ext4_lblk_t dx_get_block(struct dx_entry *entry) 514static inline ext4_lblk_t dx_get_block(struct dx_entry *entry)
515{ 515{
516 return le32_to_cpu(entry->block) & 0x00ffffff; 516 return le32_to_cpu(entry->block) & 0x0fffffff;
517} 517}
518 518
519static inline void dx_set_block(struct dx_entry *entry, ext4_lblk_t value) 519static inline void dx_set_block(struct dx_entry *entry, ext4_lblk_t value)
@@ -739,6 +739,7 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
739 struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR); 739 struct dx_frame *ret_err = ERR_PTR(ERR_BAD_DX_DIR);
740 u32 hash; 740 u32 hash;
741 741
742 memset(frame_in, 0, EXT4_HTREE_LEVEL * sizeof(frame_in[0]));
742 frame->bh = ext4_read_dirblock(dir, 0, INDEX); 743 frame->bh = ext4_read_dirblock(dir, 0, INDEX);
743 if (IS_ERR(frame->bh)) 744 if (IS_ERR(frame->bh))
744 return (struct dx_frame *) frame->bh; 745 return (struct dx_frame *) frame->bh;
@@ -768,9 +769,15 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
768 } 769 }
769 770
770 indirect = root->info.indirect_levels; 771 indirect = root->info.indirect_levels;
771 if (indirect > 1) { 772 if (indirect >= ext4_dir_htree_level(dir->i_sb)) {
772 ext4_warning_inode(dir, "Unimplemented hash depth: %#06x", 773 ext4_warning(dir->i_sb,
773 root->info.indirect_levels); 774 "Directory (ino: %lu) htree depth %#06x exceed"
775 "supported value", dir->i_ino,
776 ext4_dir_htree_level(dir->i_sb));
777 if (ext4_dir_htree_level(dir->i_sb) < EXT4_HTREE_LEVEL) {
778 ext4_warning(dir->i_sb, "Enable large directory "
779 "feature to access it");
780 }
774 goto fail; 781 goto fail;
775 } 782 }
776 783
@@ -859,12 +866,19 @@ fail:
859 866
860static void dx_release(struct dx_frame *frames) 867static void dx_release(struct dx_frame *frames)
861{ 868{
869 struct dx_root_info *info;
870 int i;
871
862 if (frames[0].bh == NULL) 872 if (frames[0].bh == NULL)
863 return; 873 return;
864 874
865 if (((struct dx_root *)frames[0].bh->b_data)->info.indirect_levels) 875 info = &((struct dx_root *)frames[0].bh->b_data)->info;
866 brelse(frames[1].bh); 876 for (i = 0; i <= info->indirect_levels; i++) {
867 brelse(frames[0].bh); 877 if (frames[i].bh == NULL)
878 break;
879 brelse(frames[i].bh);
880 frames[i].bh = NULL;
881 }
868} 882}
869 883
870/* 884/*
@@ -1050,7 +1064,7 @@ int ext4_htree_fill_tree(struct file *dir_file, __u32 start_hash,
1050{ 1064{
1051 struct dx_hash_info hinfo; 1065 struct dx_hash_info hinfo;
1052 struct ext4_dir_entry_2 *de; 1066 struct ext4_dir_entry_2 *de;
1053 struct dx_frame frames[2], *frame; 1067 struct dx_frame frames[EXT4_HTREE_LEVEL], *frame;
1054 struct inode *dir; 1068 struct inode *dir;
1055 ext4_lblk_t block; 1069 ext4_lblk_t block;
1056 int count = 0; 1070 int count = 0;
@@ -1485,7 +1499,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
1485 struct ext4_dir_entry_2 **res_dir) 1499 struct ext4_dir_entry_2 **res_dir)
1486{ 1500{
1487 struct super_block * sb = dir->i_sb; 1501 struct super_block * sb = dir->i_sb;
1488 struct dx_frame frames[2], *frame; 1502 struct dx_frame frames[EXT4_HTREE_LEVEL], *frame;
1489 struct buffer_head *bh; 1503 struct buffer_head *bh;
1490 ext4_lblk_t block; 1504 ext4_lblk_t block;
1491 int retval; 1505 int retval;
@@ -1889,7 +1903,7 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
1889 */ 1903 */
1890 dir->i_mtime = dir->i_ctime = current_time(dir); 1904 dir->i_mtime = dir->i_ctime = current_time(dir);
1891 ext4_update_dx_flag(dir); 1905 ext4_update_dx_flag(dir);
1892 dir->i_version++; 1906 inode_inc_iversion(dir);
1893 ext4_mark_inode_dirty(handle, dir); 1907 ext4_mark_inode_dirty(handle, dir);
1894 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata"); 1908 BUFFER_TRACE(bh, "call ext4_handle_dirty_metadata");
1895 err = ext4_handle_dirty_dirent_node(handle, dir, bh); 1909 err = ext4_handle_dirty_dirent_node(handle, dir, bh);
@@ -1908,7 +1922,7 @@ static int make_indexed_dir(handle_t *handle, struct ext4_filename *fname,
1908{ 1922{
1909 struct buffer_head *bh2; 1923 struct buffer_head *bh2;
1910 struct dx_root *root; 1924 struct dx_root *root;
1911 struct dx_frame frames[2], *frame; 1925 struct dx_frame frames[EXT4_HTREE_LEVEL], *frame;
1912 struct dx_entry *entries; 1926 struct dx_entry *entries;
1913 struct ext4_dir_entry_2 *de, *de2; 1927 struct ext4_dir_entry_2 *de, *de2;
1914 struct ext4_dir_entry_tail *t; 1928 struct ext4_dir_entry_tail *t;
@@ -2127,13 +2141,16 @@ out:
2127static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname, 2141static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2128 struct inode *dir, struct inode *inode) 2142 struct inode *dir, struct inode *inode)
2129{ 2143{
2130 struct dx_frame frames[2], *frame; 2144 struct dx_frame frames[EXT4_HTREE_LEVEL], *frame;
2131 struct dx_entry *entries, *at; 2145 struct dx_entry *entries, *at;
2132 struct buffer_head *bh; 2146 struct buffer_head *bh;
2133 struct super_block *sb = dir->i_sb; 2147 struct super_block *sb = dir->i_sb;
2134 struct ext4_dir_entry_2 *de; 2148 struct ext4_dir_entry_2 *de;
2149 int restart;
2135 int err; 2150 int err;
2136 2151
2152again:
2153 restart = 0;
2137 frame = dx_probe(fname, dir, NULL, frames); 2154 frame = dx_probe(fname, dir, NULL, frames);
2138 if (IS_ERR(frame)) 2155 if (IS_ERR(frame))
2139 return PTR_ERR(frame); 2156 return PTR_ERR(frame);
@@ -2155,24 +2172,44 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2155 if (err != -ENOSPC) 2172 if (err != -ENOSPC)
2156 goto cleanup; 2173 goto cleanup;
2157 2174
2175 err = 0;
2158 /* Block full, should compress but for now just split */ 2176 /* Block full, should compress but for now just split */
2159 dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n", 2177 dxtrace(printk(KERN_DEBUG "using %u of %u node entries\n",
2160 dx_get_count(entries), dx_get_limit(entries))); 2178 dx_get_count(entries), dx_get_limit(entries)));
2161 /* Need to split index? */ 2179 /* Need to split index? */
2162 if (dx_get_count(entries) == dx_get_limit(entries)) { 2180 if (dx_get_count(entries) == dx_get_limit(entries)) {
2163 ext4_lblk_t newblock; 2181 ext4_lblk_t newblock;
2164 unsigned icount = dx_get_count(entries); 2182 int levels = frame - frames + 1;
2165 int levels = frame - frames; 2183 unsigned int icount;
2184 int add_level = 1;
2166 struct dx_entry *entries2; 2185 struct dx_entry *entries2;
2167 struct dx_node *node2; 2186 struct dx_node *node2;
2168 struct buffer_head *bh2; 2187 struct buffer_head *bh2;
2169 2188
2170 if (levels && (dx_get_count(frames->entries) == 2189 while (frame > frames) {
2171 dx_get_limit(frames->entries))) { 2190 if (dx_get_count((frame - 1)->entries) <
2172 ext4_warning_inode(dir, "Directory index full!"); 2191 dx_get_limit((frame - 1)->entries)) {
2192 add_level = 0;
2193 break;
2194 }
2195 frame--; /* split higher index block */
2196 at = frame->at;
2197 entries = frame->entries;
2198 restart = 1;
2199 }
2200 if (add_level && levels == ext4_dir_htree_level(sb)) {
2201 ext4_warning(sb, "Directory (ino: %lu) index full, "
2202 "reach max htree level :%d",
2203 dir->i_ino, levels);
2204 if (ext4_dir_htree_level(sb) < EXT4_HTREE_LEVEL) {
2205 ext4_warning(sb, "Large directory feature is "
2206 "not enabled on this "
2207 "filesystem");
2208 }
2173 err = -ENOSPC; 2209 err = -ENOSPC;
2174 goto cleanup; 2210 goto cleanup;
2175 } 2211 }
2212 icount = dx_get_count(entries);
2176 bh2 = ext4_append(handle, dir, &newblock); 2213 bh2 = ext4_append(handle, dir, &newblock);
2177 if (IS_ERR(bh2)) { 2214 if (IS_ERR(bh2)) {
2178 err = PTR_ERR(bh2); 2215 err = PTR_ERR(bh2);
@@ -2187,7 +2224,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2187 err = ext4_journal_get_write_access(handle, frame->bh); 2224 err = ext4_journal_get_write_access(handle, frame->bh);
2188 if (err) 2225 if (err)
2189 goto journal_error; 2226 goto journal_error;
2190 if (levels) { 2227 if (!add_level) {
2191 unsigned icount1 = icount/2, icount2 = icount - icount1; 2228 unsigned icount1 = icount/2, icount2 = icount - icount1;
2192 unsigned hash2 = dx_get_hash(entries + icount1); 2229 unsigned hash2 = dx_get_hash(entries + icount1);
2193 dxtrace(printk(KERN_DEBUG "Split index %i/%i\n", 2230 dxtrace(printk(KERN_DEBUG "Split index %i/%i\n",
@@ -2195,7 +2232,7 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2195 2232
2196 BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */ 2233 BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
2197 err = ext4_journal_get_write_access(handle, 2234 err = ext4_journal_get_write_access(handle,
2198 frames[0].bh); 2235 (frame - 1)->bh);
2199 if (err) 2236 if (err)
2200 goto journal_error; 2237 goto journal_error;
2201 2238
@@ -2211,17 +2248,25 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2211 frame->entries = entries = entries2; 2248 frame->entries = entries = entries2;
2212 swap(frame->bh, bh2); 2249 swap(frame->bh, bh2);
2213 } 2250 }
2214 dx_insert_block(frames + 0, hash2, newblock); 2251 dx_insert_block((frame - 1), hash2, newblock);
2215 dxtrace(dx_show_index("node", frames[1].entries)); 2252 dxtrace(dx_show_index("node", frame->entries));
2216 dxtrace(dx_show_index("node", 2253 dxtrace(dx_show_index("node",
2217 ((struct dx_node *) bh2->b_data)->entries)); 2254 ((struct dx_node *) bh2->b_data)->entries));
2218 err = ext4_handle_dirty_dx_node(handle, dir, bh2); 2255 err = ext4_handle_dirty_dx_node(handle, dir, bh2);
2219 if (err) 2256 if (err)
2220 goto journal_error; 2257 goto journal_error;
2221 brelse (bh2); 2258 brelse (bh2);
2259 err = ext4_handle_dirty_dx_node(handle, dir,
2260 (frame - 1)->bh);
2261 if (err)
2262 goto journal_error;
2263 if (restart) {
2264 err = ext4_handle_dirty_dx_node(handle, dir,
2265 frame->bh);
2266 goto journal_error;
2267 }
2222 } else { 2268 } else {
2223 dxtrace(printk(KERN_DEBUG 2269 struct dx_root *dxroot;
2224 "Creating second level index...\n"));
2225 memcpy((char *) entries2, (char *) entries, 2270 memcpy((char *) entries2, (char *) entries,
2226 icount * sizeof(struct dx_entry)); 2271 icount * sizeof(struct dx_entry));
2227 dx_set_limit(entries2, dx_node_limit(dir)); 2272 dx_set_limit(entries2, dx_node_limit(dir));
@@ -2229,22 +2274,18 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2229 /* Set up root */ 2274 /* Set up root */
2230 dx_set_count(entries, 1); 2275 dx_set_count(entries, 1);
2231 dx_set_block(entries + 0, newblock); 2276 dx_set_block(entries + 0, newblock);
2232 ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1; 2277 dxroot = (struct dx_root *)frames[0].bh->b_data;
2233 2278 dxroot->info.indirect_levels += 1;
2234 /* Add new access path frame */ 2279 dxtrace(printk(KERN_DEBUG
2235 frame = frames + 1; 2280 "Creating %d level index...\n",
2236 frame->at = at = at - entries + entries2; 2281 info->indirect_levels));
2237 frame->entries = entries = entries2; 2282 err = ext4_handle_dirty_dx_node(handle, dir, frame->bh);
2238 frame->bh = bh2;
2239 err = ext4_journal_get_write_access(handle,
2240 frame->bh);
2241 if (err) 2283 if (err)
2242 goto journal_error; 2284 goto journal_error;
2243 } 2285 err = ext4_handle_dirty_dx_node(handle, dir, bh2);
2244 err = ext4_handle_dirty_dx_node(handle, dir, frames[0].bh); 2286 brelse(bh2);
2245 if (err) { 2287 restart = 1;
2246 ext4_std_error(inode->i_sb, err); 2288 goto journal_error;
2247 goto cleanup;
2248 } 2289 }
2249 } 2290 }
2250 de = do_split(handle, dir, &bh, frame, &fname->hinfo); 2291 de = do_split(handle, dir, &bh, frame, &fname->hinfo);
@@ -2256,10 +2297,15 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2256 goto cleanup; 2297 goto cleanup;
2257 2298
2258journal_error: 2299journal_error:
2259 ext4_std_error(dir->i_sb, err); 2300 ext4_std_error(dir->i_sb, err); /* this is a no-op if err == 0 */
2260cleanup: 2301cleanup:
2261 brelse(bh); 2302 brelse(bh);
2262 dx_release(frames); 2303 dx_release(frames);
2304 /* @restart is true means htree-path has been changed, we need to
2305 * repeat dx_probe() to find out valid htree-path
2306 */
2307 if (restart && err == 0)
2308 goto again;
2263 return err; 2309 return err;
2264} 2310}
2265 2311
@@ -2296,7 +2342,7 @@ int ext4_generic_delete_entry(handle_t *handle,
2296 blocksize); 2342 blocksize);
2297 else 2343 else
2298 de->inode = 0; 2344 de->inode = 0;
2299 dir->i_version++; 2345 inode_inc_iversion(dir);
2300 return 0; 2346 return 0;
2301 } 2347 }
2302 i += ext4_rec_len_from_disk(de->rec_len, blocksize); 2348 i += ext4_rec_len_from_disk(de->rec_len, blocksize);