@@ -513,7 +513,7 @@ ext4_next_entry(struct ext4_dir_entry_2 *p, unsigned long blocksize)
513
513
514
514
static 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
519
519
static 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
739
struct dx_frame * ret_err = ERR_PTR (ERR_BAD_DX_DIR );
740
740
u32 hash ;
741
741
742
+ memset (frame_in , 0 , EXT4_HTREE_LEVEL * sizeof (frame_in [0 ]));
742
743
frame -> bh = ext4_read_dirblock (dir , 0 , INDEX );
743
744
if (IS_ERR (frame -> bh ))
744
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
771
indirect = root -> info .indirect_levels ;
771
- if (indirect > 1 ) {
772
- ext4_warning_inode (dir , "Unimplemented hash depth: %#06x" ,
773
- root -> info .indirect_levels );
772
+ if (indirect >= ext4_dir_htree_level (dir -> i_sb )) {
773
+ ext4_warning (dir -> i_sb ,
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
781
goto fail ;
775
782
}
776
783
@@ -859,12 +866,19 @@ dx_probe(struct ext4_filename *fname, struct inode *dir,
859
866
860
867
static void dx_release (struct dx_frame * frames )
861
868
{
869
+ struct dx_root_info * info ;
870
+ int i ;
871
+
862
872
if (frames [0 ].bh == NULL )
863
873
return ;
864
874
865
- if (((struct dx_root * )frames [0 ].bh -> b_data )-> info .indirect_levels )
866
- brelse (frames [1 ].bh );
867
- brelse (frames [0 ].bh );
875
+ info = & ((struct dx_root * )frames [0 ].bh -> b_data )-> info ;
876
+ for (i = 0 ; i <= info -> indirect_levels ; i ++ ) {
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
1065
struct dx_hash_info hinfo ;
1052
1066
struct ext4_dir_entry_2 * de ;
1053
- struct dx_frame frames [2 ], * frame ;
1067
+ struct dx_frame frames [EXT4_HTREE_LEVEL ], * frame ;
1054
1068
struct inode * dir ;
1055
1069
ext4_lblk_t block ;
1056
1070
int count = 0 ;
@@ -1485,7 +1499,7 @@ static struct buffer_head * ext4_dx_find_entry(struct inode *dir,
1485
1499
struct ext4_dir_entry_2 * * res_dir )
1486
1500
{
1487
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
1503
struct buffer_head * bh ;
1490
1504
ext4_lblk_t block ;
1491
1505
int retval ;
@@ -1889,7 +1903,7 @@ static int add_dirent_to_buf(handle_t *handle, struct ext4_filename *fname,
1889
1903
*/
1890
1904
dir -> i_mtime = dir -> i_ctime = current_time (dir );
1891
1905
ext4_update_dx_flag (dir );
1892
- dir -> i_version ++ ;
1906
+ inode_inc_iversion ( dir ) ;
1893
1907
ext4_mark_inode_dirty (handle , dir );
1894
1908
BUFFER_TRACE (bh , "call ext4_handle_dirty_metadata" );
1895
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
1923
struct buffer_head * bh2 ;
1910
1924
struct dx_root * root ;
1911
- struct dx_frame frames [2 ], * frame ;
1925
+ struct dx_frame frames [EXT4_HTREE_LEVEL ], * frame ;
1912
1926
struct dx_entry * entries ;
1913
1927
struct ext4_dir_entry_2 * de , * de2 ;
1914
1928
struct ext4_dir_entry_tail * t ;
@@ -2127,13 +2141,16 @@ static int ext4_add_entry(handle_t *handle, struct dentry *dentry,
2127
2141
static int ext4_dx_add_entry (handle_t * handle , struct ext4_filename * fname ,
2128
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
2145
struct dx_entry * entries , * at ;
2132
2146
struct buffer_head * bh ;
2133
2147
struct super_block * sb = dir -> i_sb ;
2134
2148
struct ext4_dir_entry_2 * de ;
2149
+ int restart ;
2135
2150
int err ;
2136
2151
2152
+ again :
2153
+ restart = 0 ;
2137
2154
frame = dx_probe (fname , dir , NULL , frames );
2138
2155
if (IS_ERR (frame ))
2139
2156
return PTR_ERR (frame );
@@ -2155,24 +2172,44 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2155
2172
if (err != - ENOSPC )
2156
2173
goto cleanup ;
2157
2174
2175
+ err = 0 ;
2158
2176
/* Block full, should compress but for now just split */
2159
2177
dxtrace (printk (KERN_DEBUG "using %u of %u node entries\n" ,
2160
2178
dx_get_count (entries ), dx_get_limit (entries )));
2161
2179
/* Need to split index? */
2162
2180
if (dx_get_count (entries ) == dx_get_limit (entries )) {
2163
2181
ext4_lblk_t newblock ;
2164
- unsigned icount = dx_get_count (entries );
2165
- int levels = frame - frames ;
2182
+ int levels = frame - frames + 1 ;
2183
+ unsigned int icount ;
2184
+ int add_level = 1 ;
2166
2185
struct dx_entry * entries2 ;
2167
2186
struct dx_node * node2 ;
2168
2187
struct buffer_head * bh2 ;
2169
2188
2170
- if (levels && (dx_get_count (frames -> entries ) ==
2171
- dx_get_limit (frames -> entries ))) {
2172
- ext4_warning_inode (dir , "Directory index full!" );
2189
+ while (frame > frames ) {
2190
+ if (dx_get_count ((frame - 1 )-> entries ) <
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
2209
err = - ENOSPC ;
2174
2210
goto cleanup ;
2175
2211
}
2212
+ icount = dx_get_count (entries );
2176
2213
bh2 = ext4_append (handle , dir , & newblock );
2177
2214
if (IS_ERR (bh2 )) {
2178
2215
err = PTR_ERR (bh2 );
@@ -2187,15 +2224,15 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2187
2224
err = ext4_journal_get_write_access (handle , frame -> bh );
2188
2225
if (err )
2189
2226
goto journal_error ;
2190
- if (levels ) {
2227
+ if (! add_level ) {
2191
2228
unsigned icount1 = icount /2 , icount2 = icount - icount1 ;
2192
2229
unsigned hash2 = dx_get_hash (entries + icount1 );
2193
2230
dxtrace (printk (KERN_DEBUG "Split index %i/%i\n" ,
2194
2231
icount1 , icount2 ));
2195
2232
2196
2233
BUFFER_TRACE (frame -> bh , "get_write_access" ); /* index root */
2197
2234
err = ext4_journal_get_write_access (handle ,
2198
- frames [ 0 ]. bh );
2235
+ ( frame - 1 ) -> bh );
2199
2236
if (err )
2200
2237
goto journal_error ;
2201
2238
@@ -2211,40 +2248,44 @@ static int ext4_dx_add_entry(handle_t *handle, struct ext4_filename *fname,
2211
2248
frame -> entries = entries = entries2 ;
2212
2249
swap (frame -> bh , bh2 );
2213
2250
}
2214
- dx_insert_block (frames + 0 , hash2 , newblock );
2215
- dxtrace (dx_show_index ("node" , frames [ 1 ]. entries ));
2251
+ dx_insert_block (( frame - 1 ) , hash2 , newblock );
2252
+ dxtrace (dx_show_index ("node" , frame -> entries ));
2216
2253
dxtrace (dx_show_index ("node" ,
2217
2254
((struct dx_node * ) bh2 -> b_data )-> entries ));
2218
2255
err = ext4_handle_dirty_dx_node (handle , dir , bh2 );
2219
2256
if (err )
2220
2257
goto journal_error ;
2221
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
2268
} else {
2223
- dxtrace (printk (KERN_DEBUG
2224
- "Creating second level index...\n" ));
2269
+ struct dx_root * dxroot ;
2225
2270
memcpy ((char * ) entries2 , (char * ) entries ,
2226
2271
icount * sizeof (struct dx_entry ));
2227
2272
dx_set_limit (entries2 , dx_node_limit (dir ));
2228
2273
2229
2274
/* Set up root */
2230
2275
dx_set_count (entries , 1 );
2231
2276
dx_set_block (entries + 0 , newblock );
2232
- ((struct dx_root * ) frames [0 ].bh -> b_data )-> info .indirect_levels = 1 ;
2233
-
2234
- /* Add new access path frame */
2235
- frame = frames + 1 ;
2236
- frame -> at = at = at - entries + entries2 ;
2237
- frame -> entries = entries = entries2 ;
2238
- frame -> bh = bh2 ;
2239
- err = ext4_journal_get_write_access (handle ,
2240
- frame -> bh );
2277
+ dxroot = (struct dx_root * )frames [0 ].bh -> b_data ;
2278
+ dxroot -> info .indirect_levels += 1 ;
2279
+ dxtrace (printk (KERN_DEBUG
2280
+ "Creating %d level index...\n" ,
2281
+ info -> indirect_levels ));
2282
+ err = ext4_handle_dirty_dx_node (handle , dir , frame -> bh );
2241
2283
if (err )
2242
2284
goto journal_error ;
2243
- }
2244
- err = ext4_handle_dirty_dx_node (handle , dir , frames [0 ].bh );
2245
- if (err ) {
2246
- ext4_std_error (inode -> i_sb , err );
2247
- goto cleanup ;
2285
+ err = ext4_handle_dirty_dx_node (handle , dir , bh2 );
2286
+ brelse (bh2 );
2287
+ restart = 1 ;
2288
+ goto journal_error ;
2248
2289
}
2249
2290
}
2250
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
2297
goto cleanup ;
2257
2298
2258
2299
journal_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 */
2260
2301
cleanup :
2261
2302
brelse (bh );
2262
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
2309
return err ;
2264
2310
}
2265
2311
@@ -2296,7 +2342,7 @@ int ext4_generic_delete_entry(handle_t *handle,
2296
2342
blocksize );
2297
2343
else
2298
2344
de -> inode = 0 ;
2299
- dir -> i_version ++ ;
2345
+ inode_inc_iversion ( dir ) ;
2300
2346
return 0 ;
2301
2347
}
2302
2348
i += ext4_rec_len_from_disk (de -> rec_len , blocksize );
0 commit comments