Whamcloud - gitweb
Don't allocate so much space on the stack!!!
[fs/lustre-release.git] / lustre / extN / htree-ext3-2.4.18.diff
1 --- ./fs/ext3/super.c   2002/03/05 06:18:59     2.1
2 +++ ./fs/ext3/super.c   2002/03/05 06:26:56
3 @@ -529,6 +529,12 @@
4                                        "EXT3 Check option not supported\n");
5  #endif
6                 }
7 +               else if (!strcmp (this_char, "index"))
8 +#ifdef CONFIG_EXT3_INDEX
9 +                       set_opt (*mount_options, INDEX);
10 +#else
11 +                       printk("EXT3 index option not supported\n");
12 +#endif
13                 else if (!strcmp (this_char, "debug"))
14                         set_opt (*mount_options, DEBUG);
15                 else if (!strcmp (this_char, "errors")) {
16 @@ -702,6 +708,12 @@ static int ext3_setup_super(struct super
17         es->s_mtime = cpu_to_le32(CURRENT_TIME);
18         ext3_update_dynamic_rev(sb);
19         EXT3_SET_INCOMPAT_FEATURE(sb, EXT3_FEATURE_INCOMPAT_RECOVER);
20 +
21 +       if (test_opt(sb, INDEX))
22 +               EXT3_SET_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX);
23 +       else if (EXT3_HAS_COMPAT_FEATURE(sb, EXT3_FEATURE_COMPAT_DIR_INDEX))
24 +               set_opt (EXT3_SB(sb)->s_mount_opt, INDEX);
25 +
26         ext3_commit_super (sb, es, 1);
27         if (test_opt (sb, DEBUG))
28                 printk (KERN_INFO
29 --- ./fs/ext3/namei.c   2002/03/05 06:18:59     2.1
30 +++ ./fs/ext3/namei.c   2002/03/06 00:13:18
31 @@ -16,6 +16,10 @@
32   *        David S. Miller (davem@caip.rutgers.edu), 1995
33   *  Directory entry file type support and forward compatibility hooks
34   *     for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998
35 + *  Hash Tree Directory indexing (c)
36 + *     Daniel Phillips, 2001
37 + *  Hash Tree Directory indexing porting
38 + *     Christopher Li, 2002
39   */
40  
41  #include <linux/fs.h>
42 @@ -33,7 +33,7 @@
43  #include <linux/string.h>
44  #include <linux/locks.h>
45  #include <linux/quotaops.h>
46 -
47 +#include <linux/slab.h>
48  
49  /*
50   * define how far ahead to read directories while searching them.
51 @@ -38,6 +42,432 @@
52  #define NAMEI_RA_SIZE        (NAMEI_RA_CHUNKS * NAMEI_RA_BLOCKS)
53  #define NAMEI_RA_INDEX(c,b)  (((c) * NAMEI_RA_BLOCKS) + (b))
54  
55 +static struct buffer_head *ext3_append(handle_t *handle,
56 +                                       struct inode *inode,
57 +                                       u32 *block, int *err)
58 +{
59 +       struct buffer_head *bh;
60 +
61 +       *block = inode->i_size >> inode->i_sb->s_blocksize_bits;
62 +
63 +       if ((bh = ext3_bread(handle, inode, *block, 1, err))) {
64 +               inode->i_size += inode->i_sb->s_blocksize;
65 +               EXT3_I(inode)->i_disksize = inode->i_size;
66 +               ext3_journal_get_write_access(handle,bh);
67 +       }
68 +       return bh;
69 +}
70 +
71 +#ifndef assert
72 +#define assert(test) J_ASSERT(test)
73 +#endif
74 +
75 +#ifndef swap
76 +#define swap(x, y) do { typeof(x) z = x; x = y; y = z; } while (0)
77 +#endif
78 +
79 +typedef struct { u32 v; } le_u32;
80 +typedef struct { u16 v; } le_u16;
81 +
82 +#define dxtrace_on(command) command
83 +#define dxtrace_off(command)
84 +#define dxtrace dxtrace_off
85 +
86 +struct fake_dirent
87 +{
88 +       /*le*/u32 inode;
89 +       /*le*/u16 rec_len;
90 +       u8 name_len;
91 +       u8 file_type;
92 +};
93 +
94 +struct dx_countlimit
95 +{
96 +       le_u16 limit;
97 +       le_u16 count;
98 +};
99 +
100 +struct dx_entry
101 +{
102 +       le_u32 hash;
103 +       le_u32 block;
104 +};
105 +
106 +/*
107 + * dx_root_info is laid out so that if it should somehow get overlaid by a
108 + * dirent the two low bits of the hash version will be zero.  Therefore, the
109 + * hash version mod 4 should never be 0.  Sincerely, the paranoia department.
110 + */
111 +
112 +struct dx_root
113 +{
114 +       struct fake_dirent dot;
115 +       char dot_name[4];
116 +       struct fake_dirent dotdot;
117 +       char dotdot_name[4];
118 +       struct dx_root_info
119 +       {
120 +               le_u32 reserved_zero;
121 +               u8 hash_version; /* 0 now, 1 at release */
122 +               u8 info_length; /* 8 */
123 +               u8 indirect_levels;
124 +               u8 unused_flags;
125 +       }
126 +       info;
127 +       struct dx_entry entries[0];
128 +};
129 +
130 +struct dx_node
131 +{
132 +       struct fake_dirent fake;
133 +       struct dx_entry entries[0];
134 +};
135 +
136 +
137 +struct dx_frame
138 +{
139 +       struct buffer_head *bh;
140 +       struct dx_entry *entries;
141 +       struct dx_entry *at;
142 +};
143 +
144 +struct dx_map_entry
145 +{
146 +       u32 hash;
147 +       u32 offs;
148 +};
149 +
150 +typedef struct ext3_dir_entry_2 ext3_dirent;
151 +static inline unsigned dx_get_block (struct dx_entry *entry);
152 +static void dx_set_block (struct dx_entry *entry, unsigned value);
153 +static inline unsigned dx_get_hash (struct dx_entry *entry);
154 +static void dx_set_hash (struct dx_entry *entry, unsigned value);
155 +static unsigned dx_get_count (struct dx_entry *entries);
156 +static unsigned dx_get_limit (struct dx_entry *entries);
157 +static void dx_set_count (struct dx_entry *entries, unsigned value);
158 +static void dx_set_limit (struct dx_entry *entries, unsigned value);
159 +static unsigned dx_root_limit (struct inode *dir, unsigned infosize);
160 +static unsigned dx_node_limit (struct inode *dir);
161 +static unsigned dx_hack_hash (const u8 *name, int len);
162 +static struct dx_frame *dx_probe (struct inode *dir, u32 hash, struct dx_frame *frame);
163 +static void dx_release (struct dx_frame *frames);
164 +static int dx_make_map (ext3_dirent *de, int size, struct dx_map_entry map[]);
165 +static void dx_sort_map(struct dx_map_entry *map, unsigned count);
166 +static ext3_dirent *dx_copy_dirents (char *from, char *to,
167 +     struct dx_map_entry *map, int count);
168 +static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block);
169 +
170 +
171 +#ifdef CONFIG_EXT3_INDEX
172 +/*
173 + * Future: use high four bits of block for coalesce-on-delete flags
174 + * Mask them off for now.
175 + */
176 +
177 +static inline unsigned dx_get_block (struct dx_entry *entry)
178 +{
179 +       return le32_to_cpu(entry->block.v) & 0x00ffffff;
180 +}
181 +
182 +static inline void dx_set_block (struct dx_entry *entry, unsigned value)
183 +{
184 +       entry->block.v = cpu_to_le32(value);
185 +}
186 +
187 +static inline unsigned dx_get_hash (struct dx_entry *entry)
188 +{
189 +       return le32_to_cpu(entry->hash.v);
190 +}
191 +
192 +static inline void dx_set_hash (struct dx_entry *entry, unsigned value)
193 +{
194 +       entry->hash.v = cpu_to_le32(value);
195 +}
196 +
197 +static inline unsigned dx_get_count (struct dx_entry *entries)
198 +{
199 +       return le16_to_cpu(((struct dx_countlimit *) entries)->count.v);
200 +}
201 +
202 +static inline unsigned dx_get_limit (struct dx_entry *entries)
203 +{
204 +       return le16_to_cpu(((struct dx_countlimit *) entries)->limit.v);
205 +}
206 +
207 +static inline void dx_set_count (struct dx_entry *entries, unsigned value)
208 +{
209 +       ((struct dx_countlimit *) entries)->count.v = cpu_to_le16(value);
210 +}
211 +
212 +static inline void dx_set_limit (struct dx_entry *entries, unsigned value)
213 +{
214 +       ((struct dx_countlimit *) entries)->limit.v = cpu_to_le16(value);
215 +}
216 +
217 +static inline unsigned dx_root_limit (struct inode *dir, unsigned infosize)
218 +{
219 +       unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(1) -
220 +               EXT3_DIR_REC_LEN(2) - infosize;
221 +       return 0? 20: entry_space / sizeof(struct dx_entry);
222 +}
223 +
224 +static inline unsigned dx_node_limit (struct inode *dir)
225 +{
226 +       unsigned entry_space = dir->i_sb->s_blocksize - EXT3_DIR_REC_LEN(0);
227 +       return 0? 22: entry_space / sizeof(struct dx_entry);
228 +}
229 +
230 +/* Hash function - not bad, but still looking for an ideal default */
231 +
232 +static unsigned dx_hack_hash (const u8 *name, int len)
233 +{
234 +       u32 hash0 = 0x12a3fe2d, hash1 = 0x37abe8f9;
235 +       while (len--)
236 +       {
237 +               u32 hash = hash1 + (hash0 ^ (*name++ * 7152373));
238 +               if (hash & 0x80000000) hash -= 0x7fffffff;
239 +               hash1 = hash0;
240 +               hash0 = hash;
241 +       }
242 +       return hash0;
243 +}
244 +
245 +#define dx_hash(s,n) (dx_hack_hash(s,n) << 1)
246 +
247 +/*
248 + * Debug
249 + */
250 +static void dx_show_index (char * label, struct dx_entry *entries)
251 +{
252 +       int i, n = dx_get_count (entries);
253 +       printk("%s index ", label);
254 +       for (i = 0; i < n; i++)
255 +       {
256 +               printk("%x->%u ", i? dx_get_hash(entries + i): 0, dx_get_block(entries + i));
257 +       }
258 +       printk("\n");
259 +}
260 +
261 +struct stats
262 +{ 
263 +       unsigned names;
264 +       unsigned space;
265 +       unsigned bcount;
266 +};
267 +
268 +static struct stats dx_show_leaf (ext3_dirent *de, int size, int show_names)
269 +{
270 +       unsigned names = 0, space = 0;
271 +       char *base = (char *) de;
272 +       printk("names: ");
273 +       while ((char *) de < base + size)
274 +       {
275 +               if (de->inode)
276 +               {
277 +                       if (show_names)
278 +                       {
279 +                               int len = de->name_len;
280 +                               char *name = de->name;
281 +                               while (len--) printk("%c", *name++);
282 +                               printk(":%x.%u ", dx_hash (de->name, de->name_len), ((char *) de - base));
283 +                       }
284 +                       space += EXT3_DIR_REC_LEN(de->name_len);
285 +                       names++;
286 +               }
287 +               de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
288 +       }
289 +       printk("(%i)\n", names);
290 +       return (struct stats) { names, space, 1 };
291 +}
292 +
293 +struct stats dx_show_entries (struct inode *dir, struct dx_entry *entries, int levels)
294 +{
295 +       unsigned blocksize = dir->i_sb->s_blocksize;
296 +       unsigned count = dx_get_count (entries), names = 0, space = 0, i;
297 +       unsigned bcount = 0;
298 +       struct buffer_head *bh;
299 +       int err;
300 +       printk("%i indexed blocks...\n", count);
301 +       for (i = 0; i < count; i++, entries++)
302 +       {
303 +               u32 block = dx_get_block(entries), hash = i? dx_get_hash(entries): 0;
304 +               u32 range = i < count - 1? (dx_get_hash(entries + 1) - hash): ~hash;
305 +               struct stats stats;
306 +               printk("%s%3u:%03u hash %8x/%8x ",levels?"":"   ", i, block, hash, range);
307 +               if (!(bh = ext3_bread (NULL,dir, block, 0,&err))) continue;
308 +               stats = levels?
309 +                  dx_show_entries (dir, ((struct dx_node *) bh->b_data)->entries, levels - 1):
310 +                  dx_show_leaf ((ext3_dirent *) bh->b_data, blocksize, 0);
311 +               names += stats.names;
312 +               space += stats.space;
313 +               bcount += stats.bcount;
314 +               brelse (bh);
315 +       }
316 +       if (bcount)
317 +               printk("%snames %u, fullness %u (%u%%)\n", levels?"":"   ",
318 +                       names, space/bcount,(space/bcount)*100/blocksize);
319 +       return (struct stats) { names, space, bcount};
320 +}
321 +
322 +/*
323 + * Probe for a directory leaf block to search
324 + */
325 +
326 +static struct dx_frame *
327 +dx_probe(struct inode *dir, u32 hash, struct dx_frame *frame_in)
328 +{
329 +       unsigned count, indirect;
330 +       struct dx_entry *at, *entries, *p, *q, *m;
331 +       struct dx_root *root;
332 +       struct buffer_head *bh;
333 +       struct dx_frame *frame = frame_in;
334 +       int err;
335 +
336 +       frame->bh = NULL;
337 +       if (!(bh = ext3_bread(NULL, dir, 0, 0, &err)))
338 +               goto fail;
339 +       root = (struct dx_root *) bh->b_data;
340 +       if (root->info.hash_version > 0 || root->info.unused_flags & 1) {
341 +               brelse(bh);
342 +               goto fail;
343 +       }
344 +       if ((indirect = root->info.indirect_levels) > 1) {
345 +               brelse(bh);
346 +               goto fail;
347 +       }
348 +       entries = (struct dx_entry *) (((char *) &root->info) + root->info.info_length);
349 +       assert (dx_get_limit(entries) == dx_root_limit(dir, root->info.info_length));
350 +       dxtrace (printk("Look up %x", hash));
351 +       while (1)
352 +       {
353 +               count = dx_get_count(entries);
354 +               assert (count && count <= dx_get_limit(entries));
355 +               p = entries + 1;
356 +               q = entries + count - 1;
357 +               while (p <= q)
358 +               {
359 +                       m = p + (q - p)/2;
360 +                       dxtrace(printk("."));
361 +                       if (dx_get_hash(m) > hash)
362 +                               q = m - 1;
363 +                       else
364 +                               p = m + 1;
365 +               }
366 +
367 +               if (0) // linear search cross check
368 +               {
369 +                       unsigned n = count - 1;
370 +                       at = entries;
371 +                       while (n--)
372 +                       {
373 +                               dxtrace(printk(","));
374 +                               if (dx_get_hash(++at) > hash)
375 +                               {
376 +                                       at--;
377 +                                       break;
378 +                               }
379 +                       }
380 +                       assert (at == p - 1);
381 +               }
382 +
383 +               at = p - 1;
384 +               dxtrace(printk(" %x->%u\n", at == entries? 0: dx_get_hash(at), dx_get_block(at)));
385 +               frame->bh = bh;
386 +               frame->entries = entries;
387 +               frame->at = at;
388 +               if (!indirect--) return frame;
389 +               if (!(bh = ext3_bread (NULL,dir, dx_get_block(at), 0,&err)))
390 +                       goto fail2;
391 +               at = entries = ((struct dx_node *) bh->b_data)->entries;
392 +               assert (dx_get_limit(entries) == dx_node_limit (dir));
393 +               frame++;
394 +       }
395 +fail2:
396 +       while (frame >= frame_in) {
397 +               brelse(frame->bh);
398 +               frame--;
399 +       }
400 +fail:
401 +       return NULL;
402 +}
403 +
404 +static void dx_release (struct dx_frame *frames)
405 +{
406 +       if (frames[0].bh == NULL)
407 +               return;
408 +
409 +       if (((struct dx_root *)frames[0].bh->b_data)->info.indirect_levels)
410 +               brelse (frames[1].bh);
411 +       brelse (frames[0].bh);
412 +}
413 +
414 +/*
415 + * Directory block splitting, compacting
416 + */
417 +
418 +static int dx_make_map (ext3_dirent *de, int size, struct dx_map_entry map[])
419 +{
420 +       int count = 0;
421 +       char *base = (char *) de;
422 +       while ((char *) de < base + size)
423 +       {
424 +               map[count].hash = dx_hash (de->name, de->name_len);
425 +               map[count].offs = (u32) ((char *) de - base);
426 +               de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
427 +               count++;
428 +       }
429 +       return count;
430 +}
431 +
432 +static void dx_sort_map (struct dx_map_entry *map, unsigned count)
433 +{
434 +        struct dx_map_entry *p, *q, *top = map + count - 1;
435 +        int more;
436 +        /* Combsort until bubble sort doesn't suck */
437 +        while (count > 2)
438 +       {
439 +                count = count*10/13;
440 +                if (count - 9 < 2) /* 9, 10 -> 11 */
441 +                        count = 11;
442 +                for (p = top, q = p - count; q >= map; p--, q--)
443 +                        if (p->hash < q->hash)
444 +                                swap(*p, *q);
445 +        }
446 +        /* Garden variety bubble sort */
447 +        do {
448 +                more = 0;
449 +                q = top;
450 +                while (q-- > map)
451 +               {
452 +                        if (q[1].hash >= q[0].hash)
453 +                               continue;
454 +                        swap(*(q+1), *q);
455 +                        more = 1;
456 +               }
457 +       } while(more);
458 +}
459 +
460 +static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
461 +{
462 +       struct dx_entry *entries = frame->entries;
463 +       struct dx_entry *old = frame->at, *new = old + 1;
464 +       int count = dx_get_count(entries);
465 +
466 +       assert(count < dx_get_limit(entries));
467 +       assert(old < entries + count);
468 +       memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
469 +       dx_set_hash(new, hash);
470 +       dx_set_block(new, block);
471 +       dx_set_count(entries, count + 1);
472 +}
473 +#endif
474 +
475 +static void ext3_update_dx_flag(struct inode *inode)
476 +{
477 +       if (!test_opt(inode->i_sb, INDEX))
478 +               EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
479 +}
480 +
481  /*
482   * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure.
483   *
484 @@ -95,6 +529,15 @@
485  }
486  
487  /*
488 + * p is at least 6 bytes before the end of page
489 + */
490 +static inline ext3_dirent *ext3_next_entry(ext3_dirent *p)
491 +{
492 +       return (ext3_dirent *)((char*)p + le16_to_cpu(p->rec_len));
493 +}
494 +
495 +
496 +/*
497   *     ext3_find_entry()
498   *
499   * finds an entry in the specified directory with the wanted name. It
500 @@ -105,6 +548,8 @@
501   * The returned buffer_head has ->b_count elevated.  The caller is expected
502   * to brelse() it when appropriate.
503   */
504 +
505 +       
506  static struct buffer_head * ext3_find_entry (struct dentry *dentry,
507                                         struct ext3_dir_entry_2 ** res_dir)
508  {
509 @@ -119,10 +564,76 @@
510         int num = 0;
511         int nblocks, i, err;
512         struct inode *dir = dentry->d_parent->d_inode;
513 +       int namelen;
514 +       const u8 *name;
515 +       unsigned blocksize;
516 +       ext3_dirent *de, *top;
517  
518         *res_dir = NULL;
519         sb = dir->i_sb;
520 +       blocksize = sb->s_blocksize;
521 +       namelen = dentry->d_name.len;
522 +       name = dentry->d_name.name;
523 +       if (namelen > EXT3_NAME_LEN)
524 +               return NULL;
525 +       if (ext3_dx && is_dx(dir)) {
526 +               u32 hash = dx_hash (name, namelen);
527 +               struct dx_frame frames[2], *frame;
528 +               if (!(frame = dx_probe (dir, hash, frames)))
529 +                       return NULL;
530 +dxnext:
531 +               block = dx_get_block(frame->at);
532 +               if (!(bh = ext3_bread (NULL,dir, block, 0, &err)))
533 +                       goto dxfail;
534 +               de = (ext3_dirent *) bh->b_data;
535 +               top = (ext3_dirent *) ((char *) de + blocksize -
536 +                               EXT3_DIR_REC_LEN(0));
537 +               for (; de < top; de = ext3_next_entry(de))
538 +                       if (ext3_match (namelen, name, de)) {
539 +                               if (!ext3_check_dir_entry("ext3_find_entry",
540 +                                         dir, de, bh,
541 +                                         (block<<EXT3_BLOCK_SIZE_BITS(sb))
542 +                                          +((char *)de - bh->b_data))) {
543 +                                       brelse (bh);
544 +                                       goto dxfail;
545 +                               }
546 +                               *res_dir = de;
547 +                               goto dxfound;
548 +                       }
549 +               brelse (bh);
550 +               /* Same hash continues in next block?  Search on. */
551 +               if (++(frame->at) == frame->entries + dx_get_count(frame->entries))
552 +               {
553 +                       struct buffer_head *bh2;
554 +                       if (frame == frames)
555 +                               goto dxfail;
556 +                       if (++(frames->at) == frames->entries + dx_get_count(frames->entries))
557 +                               goto dxfail;
558 +                       /* should omit read if not continued */
559 +                       if (!(bh2 = ext3_bread (NULL, dir,
560 +                                               dx_get_block(frames->at),
561 +                                               0, &err)))
562 +                               goto dxfail;
563 +                       brelse (frame->bh);
564 +                       frame->bh = bh2;
565 +                       frame->at = frame->entries = ((struct dx_node *) bh2->b_data)->entries;
566 +                       /* Subtle: the 0th entry has the count, find the hash in frame above */
567 +                       if ((dx_get_hash(frames->at) & -2) == hash)
568 +                               goto dxnext;
569 +                       goto dxfail;
570 +               }
571 +               if ((dx_get_hash(frame->at) & -2) == hash)
572 +                       goto dxnext;
573 +dxfail:
574 +               dxtrace(printk("%s not found\n", name));
575 +               dx_release (frames);
576 +               return NULL;
577 +dxfound:
578 +               dx_release (frames);
579 +               return bh;
580  
581 +       }
582 +       
583         nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
584         start = dir->u.ext3_i.i_dir_start_lookup;
585         if (start >= nblocks)
586 @@ -237,6 +748,92 @@
587                 de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
588  }
589  
590 +static ext3_dirent *
591 +dx_copy_dirents (char *from, char *to, struct dx_map_entry *map, int count)
592 +{
593 +       unsigned rec_len = 0;
594 +
595 +       while (count--) {
596 +               ext3_dirent *de = (ext3_dirent *) (from + map->offs);
597 +               rec_len = EXT3_DIR_REC_LEN(de->name_len);
598 +               memcpy (to, de, rec_len);
599 +               ((ext3_dirent *) to)->rec_len = rec_len;
600 +               to += rec_len;
601 +               map++;
602 +       }
603 +       return (ext3_dirent *) (to - rec_len);
604 +}
605 +
606 +#ifdef CONFIG_EXT3_INDEX
607 +static ext3_dirent *do_split(handle_t *handle, struct inode *dir,
608 +                       struct buffer_head **bh,struct dx_frame *frame,
609 +                       u32 hash, int *error)
610 +{
611 +       unsigned blocksize = dir->i_sb->s_blocksize;
612 +       unsigned count, continued;
613 +       struct buffer_head *bh2;
614 +       u32 newblock;
615 +       unsigned MAX_DX_MAP = PAGE_CACHE_SIZE/EXT3_DIR_REC_LEN(1) + 1;
616 +       u32 hash2;
617 +       struct dx_map_entry *map;
618 +       char *data1 = (*bh)->b_data, *data2, *data3;
619 +       unsigned split;
620 +       ext3_dirent *de, *de2;
621 +
622 +       bh2 = ext3_append (handle, dir, &newblock, error);
623 +       if (!(bh2))
624 +       {
625 +               brelse(*bh);
626 +               *bh = NULL;
627 +               return (ext3_dirent *)bh2;
628 +       }
629 +
630 +       BUFFER_TRACE(*bh, "get_write_access");
631 +       ext3_journal_get_write_access(handle, *bh);
632 +       BUFFER_TRACE(frame->bh, "get_write_access");
633 +       ext3_journal_get_write_access(handle, frame->bh);
634 +
635 +       data2 = bh2->b_data;
636 +
637 +       map = kmalloc(sizeof(*map) * MAX_DX_MAP, GFP_KERNEL);
638 +       if (!map)
639 +               panic("no memory for do_split\n");
640 +       count = dx_make_map ((ext3_dirent *) data1, blocksize, map);
641 +       split = count/2; // need to adjust to actual middle
642 +       dx_sort_map (map, count);
643 +       hash2 = map[split].hash;
644 +       continued = hash2 == map[split - 1].hash;
645 +       dxtrace(printk("Split block %i at %x, %i/%i\n",
646 +               dx_get_block(frame->at), hash2, split, count-split));
647 +
648 +       /* Fancy dance to stay within two buffers */
649 +       de2 = dx_copy_dirents (data1, data2, map + split, count - split);
650 +       data3 = (char *) de2 + de2->rec_len;
651 +       de = dx_copy_dirents (data1, data3, map, split);
652 +       memcpy(data1, data3, (char *) de + de->rec_len - data3);
653 +       de = (ext3_dirent *) ((char *) de - data3 + data1); // relocate de
654 +       de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
655 +       de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
656 +       dxtrace(dx_show_leaf ((ext3_dirent *) data1, blocksize, 1));
657 +       dxtrace(dx_show_leaf ((ext3_dirent *) data2, blocksize, 1));
658 +
659 +       /* Which block gets the new entry? */
660 +       if (hash >= hash2)
661 +       {
662 +               swap(*bh, bh2);
663 +               de = de2;
664 +       }
665 +       dx_insert_block (frame, hash2 + continued, newblock);
666 +       ext3_journal_dirty_metadata (handle, bh2);
667 +       brelse (bh2);
668 +       ext3_journal_dirty_metadata (handle, frame->bh);
669 +       dxtrace(dx_show_index ("frame", frame->entries));
670 +       kfree(map);
671 +       return de;
672 +}
673 +#endif
674 +
675 +
676  /*
677   *     ext3_add_entry()
678   *
679 @@ -251,6 +844,7 @@
680  /*
681   * AKPM: the journalling code here looks wrong on the error paths
682   */
683 +
684  static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
685         struct inode *inode)
686  {
687 @@ -258,117 +852,281 @@
688         const char *name = dentry->d_name.name;
689         int namelen = dentry->d_name.len;
690         unsigned long offset;
691 -       unsigned short rec_len;
692         struct buffer_head * bh;
693 -       struct ext3_dir_entry_2 * de, * de1;
694 -       struct super_block * sb;
695 +       ext3_dirent *de;
696 +       struct super_block * sb = dir->i_sb;
697         int     retval;
698 +       unsigned short reclen = EXT3_DIR_REC_LEN(namelen);
699  
700 -       sb = dir->i_sb;
701 +       unsigned blocksize = sb->s_blocksize;
702 +       unsigned nlen, rlen;
703 +       u32 block, blocks;
704 +       char *top;
705  
706         if (!namelen)
707                 return -EINVAL;
708 -       bh = ext3_bread (handle, dir, 0, 0, &retval);
709 -       if (!bh)
710 -               return retval;
711 -       rec_len = EXT3_DIR_REC_LEN(namelen);
712 -       offset = 0;
713 -       de = (struct ext3_dir_entry_2 *) bh->b_data;
714 -       while (1) {
715 -               if ((char *)de >= sb->s_blocksize + bh->b_data) {
716 -                       brelse (bh);
717 -                       bh = NULL;
718 -                       bh = ext3_bread (handle, dir,
719 -                               offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval);
720 -                       if (!bh)
721 -                               return retval;
722 -                       if (dir->i_size <= offset) {
723 -                               if (dir->i_size == 0) {
724 -                                       brelse(bh);
725 -                                       return -ENOENT;
726 +       if (ext3_dx && is_dx(dir)) {
727 +               struct dx_frame frames[2], *frame;
728 +               struct dx_entry *entries, *at;
729 +               u32 hash;
730 +               char *data1;
731 +
732 +               hash = dx_hash(name, namelen);
733 +               /* FIXME: do something if dx_probe() fails here */
734 +               frame = dx_probe(dir, hash, frames);
735 +               entries = frame->entries;
736 +               at = frame->at;
737 +
738 +               if (!(bh = ext3_bread(handle,dir, dx_get_block(at), 0,&retval)))
739 +                       goto dxfail1;
740 +
741 +               BUFFER_TRACE(bh, "get_write_access");
742 +               ext3_journal_get_write_access(handle, bh);
743 +
744 +               data1 = bh->b_data;
745 +               de = (ext3_dirent *) data1;
746 +               top = data1 + (0? 200: blocksize);
747 +               while ((char *) de < top)
748 +               {
749 +                       /* FIXME: check EEXIST and dir */
750 +                       nlen = EXT3_DIR_REC_LEN(de->name_len);
751 +                       rlen = le16_to_cpu(de->rec_len);
752 +                       if ((de->inode? rlen - nlen: rlen) >= reclen)
753 +                               goto dx_add;
754 +                       de = (ext3_dirent *) ((char *) de + rlen);
755 +               }
756 +               /* Block full, should compress but for now just split */
757 +               dxtrace(printk("using %u of %u node entries\n",
758 +                       dx_get_count(entries), dx_get_limit(entries)));
759 +               /* Need to split index? */
760 +               if (dx_get_count(entries) == dx_get_limit(entries))
761 +               {
762 +                       u32 newblock;
763 +                       unsigned icount = dx_get_count(entries);
764 +                       int levels = frame - frames;
765 +                       struct dx_entry *entries2;
766 +                       struct dx_node *node2;
767 +                       struct buffer_head *bh2;
768 +                       if (levels && dx_get_count(frames->entries) == dx_get_limit(frames->entries))
769 +                               goto dxfull;
770 +                       bh2 = ext3_append (handle, dir, &newblock, &retval);
771 +                       if (!(bh2))
772 +                               goto dxfail2;
773 +                       node2 = (struct dx_node *)(bh2->b_data);
774 +                       entries2 = node2->entries;
775 +                       node2->fake.rec_len = cpu_to_le16(blocksize);
776 +                       node2->fake.inode = 0;
777 +                       BUFFER_TRACE(frame->bh, "get_write_access");
778 +                       ext3_journal_get_write_access(handle, frame->bh);
779 +                       if (levels)
780 +                       {
781 +                               unsigned icount1 = icount/2, icount2 = icount - icount1;
782 +                               unsigned hash2 = dx_get_hash(entries + icount1);
783 +                               dxtrace(printk("Split index %i/%i\n", icount1, icount2));
784 +                               
785 +                               BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
786 +                               ext3_journal_get_write_access(handle, frames[0].bh);
787 +                               
788 +                               memcpy ((char *) entries2, (char *) (entries + icount1),
789 +                                       icount2 * sizeof(struct dx_entry));
790 +                               dx_set_count (entries, icount1);
791 +                               dx_set_count (entries2, icount2);
792 +                               dx_set_limit (entries2, dx_node_limit(dir));
793 +
794 +                               /* Which index block gets the new entry? */
795 +                               if (at - entries >= icount1) {
796 +                                       frame->at = at = at - entries - icount1 + entries2;
797 +                                       frame->entries = entries = entries2;
798 +                                       swap(frame->bh, bh2);
799                                 }
800 -
801 -                               ext3_debug ("creating next block\n");
802 -
803 -                               BUFFER_TRACE(bh, "get_write_access");
804 -                               ext3_journal_get_write_access(handle, bh);
805 -                               de = (struct ext3_dir_entry_2 *) bh->b_data;
806 -                               de->inode = 0;
807 -                               de->rec_len = le16_to_cpu(sb->s_blocksize);
808 -                               dir->u.ext3_i.i_disksize =
809 -                                       dir->i_size = offset + sb->s_blocksize;
810 -                               dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
811 -                               ext3_mark_inode_dirty(handle, dir);
812 +                               dx_insert_block (frames + 0, hash2, newblock);
813 +                               dxtrace(dx_show_index ("node", frames[1].entries));
814 +                               dxtrace(dx_show_index ("node",
815 +                                       ((struct dx_node *) bh2->b_data)->entries));
816 +                               ext3_journal_dirty_metadata(handle, bh2);
817 +                               brelse (bh2);
818                         } else {
819 -
820 -                               ext3_debug ("skipping to next block\n");
821 -
822 -                               de = (struct ext3_dir_entry_2 *) bh->b_data;
823 +                               dxtrace(printk("Creating second level index...\n"));
824 +                               memcpy((char *) entries2, (char *) entries,
825 +                                       icount * sizeof(struct dx_entry));
826 +                               dx_set_limit(entries2, dx_node_limit(dir));
827 +
828 +                               /* Set up root */
829 +                               dx_set_count(entries, 1);
830 +                               dx_set_block(entries + 0, newblock);
831 +                               ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
832 +
833 +                               /* Add new access path frame */
834 +                               frame = frames + 1;
835 +                               frame->at = at = at - entries + entries2;
836 +                               frame->entries = entries = entries2;
837 +                               frame->bh = bh2;
838 +                               ext3_journal_get_write_access(handle, frame->bh);
839                         }
840 +                       ext3_journal_dirty_metadata(handle, frames[0].bh);
841                 }
842 -               if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh,
843 -                                          offset)) {
844 -                       brelse (bh);
845 -                       return -ENOENT;
846 -               }
847 -               if (ext3_match (namelen, name, de)) {
848 +               de = do_split(handle, dir, &bh, frame, hash, &retval);
849 +               dx_release (frames);
850 +               if (!(de))
851 +                       goto fail;
852 +               nlen = EXT3_DIR_REC_LEN(de->name_len);
853 +               rlen = le16_to_cpu(de->rec_len);
854 +               goto add;
855 +
856 +dx_add:
857 +               dx_release (frames);
858 +               goto add;
859 +
860 +dxfull:
861 +               ext3_warning(sb, __FUNCTION__, "Directory index full!\n");
862 +               retval = -ENOSPC;
863 +dxfail2:
864 +               brelse(bh);
865 +dxfail1:
866 +               dx_release (frames);
867 +               goto fail1;
868 +       }
869 +
870 +       blocks = dir->i_size >> sb->s_blocksize_bits;
871 +       for (block = 0, offset = 0; block < blocks; block++) {
872 +               bh = ext3_bread(handle, dir, block, 0, &retval);
873 +               if(!bh)
874 +                       return retval;
875 +               de = (ext3_dirent *)bh->b_data;
876 +               top = bh->b_data + blocksize - reclen;
877 +               while ((char *) de <= top) {
878 +                       if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
879 +                                                 bh, offset)) {
880 +                               brelse (bh);
881 +                               return -EIO;
882 +                       }
883 +                       if (ext3_match (namelen, name, de)) {
884                                 brelse (bh);
885                                 return -EEXIST;
886 -               }
887 -               if ((le32_to_cpu(de->inode) == 0 &&
888 -                               le16_to_cpu(de->rec_len) >= rec_len) ||
889 -                   (le16_to_cpu(de->rec_len) >=
890 -                               EXT3_DIR_REC_LEN(de->name_len) + rec_len)) {
891 -                       BUFFER_TRACE(bh, "get_write_access");
892 -                       ext3_journal_get_write_access(handle, bh);
893 -                       /* By now the buffer is marked for journaling */
894 -                       offset += le16_to_cpu(de->rec_len);
895 -                       if (le32_to_cpu(de->inode)) {
896 -                               de1 = (struct ext3_dir_entry_2 *) ((char *) de +
897 -                                       EXT3_DIR_REC_LEN(de->name_len));
898 -                               de1->rec_len =
899 -                                       cpu_to_le16(le16_to_cpu(de->rec_len) -
900 -                                       EXT3_DIR_REC_LEN(de->name_len));
901 -                               de->rec_len = cpu_to_le16(
902 -                                               EXT3_DIR_REC_LEN(de->name_len));
903 -                               de = de1;
904                         }
905 -                       de->file_type = EXT3_FT_UNKNOWN;
906 -                       if (inode) {
907 -                               de->inode = cpu_to_le32(inode->i_ino);
908 -                               ext3_set_de_type(dir->i_sb, de, inode->i_mode);
909 -                       } else
910 -                               de->inode = 0;
911 -                       de->name_len = namelen;
912 -                       memcpy (de->name, name, namelen);
913 -                       /*
914 -                        * XXX shouldn't update any times until successful
915 -                        * completion of syscall, but too many callers depend
916 -                        * on this.
917 -                        *
918 -                        * XXX similarly, too many callers depend on
919 -                        * ext3_new_inode() setting the times, but error
920 -                        * recovery deletes the inode, so the worst that can
921 -                        * happen is that the times are slightly out of date
922 -                        * and/or different from the directory change time.
923 -                        */
924 -                       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
925 -                       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
926 -                       ext3_mark_inode_dirty(handle, dir);
927 -                       dir->i_version = ++event;
928 -                       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
929 -                       ext3_journal_dirty_metadata(handle, bh);
930 +                       nlen = EXT3_DIR_REC_LEN(de->name_len);
931 +                       rlen = le16_to_cpu(de->rec_len);
932 +                       if ((de->inode? rlen - nlen: rlen) >= reclen)
933 +                               goto add;
934 +                       de = (ext3_dirent *)((char *)de + rlen);
935 +                       offset += rlen;
936 +               }
937 +               if (ext3_dx && blocks == 1 && test_opt(sb, INDEX))
938 +                       goto dx_make_index;
939 +               brelse(bh);
940 +       }
941 +       bh = ext3_append(handle, dir, &block, &retval);
942 +       if (!bh)
943 +               return retval;
944 +       de = (ext3_dirent *) bh->b_data;
945 +       de->inode = 0;
946 +       de->rec_len = cpu_to_le16(rlen = blocksize);
947 +       nlen = 0;
948 +       goto add;
949 +
950 +add:
951 +       BUFFER_TRACE(bh, "get_write_access");
952 +       ext3_journal_get_write_access(handle, bh);
953 +       /* By now the buffer is marked for journaling */
954 +       if (de->inode) {
955 +               ext3_dirent *de1 = (ext3_dirent *)((char *)de + nlen);
956 +               de1->rec_len = cpu_to_le16(rlen - nlen);
957 +               de->rec_len = cpu_to_le16(nlen);
958 +               de = de1;
959 +       }
960 +       de->file_type = EXT3_FT_UNKNOWN;
961 +       if (inode) {
962 +               de->inode = cpu_to_le32(inode->i_ino);
963 +               ext3_set_de_type(dir->i_sb, de, inode->i_mode);
964 +       } else
965 +               de->inode = 0;
966 +       de->name_len = namelen;
967 +       memcpy (de->name, name, namelen);
968 +       /*
969 +        * XXX shouldn't update any times until successful
970 +        * completion of syscall, but too many callers depend
971 +        * on this.
972 +        *
973 +        * XXX similarly, too many callers depend on
974 +        * ext3_new_inode() setting the times, but error
975 +        * recovery deletes the inode, so the worst that can
976 +        * happen is that the times are slightly out of date
977 +        * and/or different from the directory change time.
978 +        */
979 +       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
980 +       ext3_update_dx_flag(dir);
981 +       dir->i_version = ++event;
982 +       ext3_mark_inode_dirty(handle, dir);
983 +       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
984 +       ext3_journal_dirty_metadata(handle, bh);
985 +       brelse(bh);
986 +       return 0;
987 +
988 +dx_make_index:
989 +       {
990 +               struct buffer_head *bh2;
991 +               struct dx_root *root;
992 +               struct dx_frame frames[2], *frame;
993 +               struct dx_entry *entries;
994 +               ext3_dirent *de2;
995 +               char *data1;
996 +               unsigned len;
997 +               u32 hash;
998 +               
999 +               dxtrace(printk("Creating index\n"));
1000 +               ext3_journal_get_write_access(handle, bh);
1001 +               root = (struct dx_root *) bh->b_data;
1002 +               
1003 +               EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
1004 +               bh2 = ext3_append (handle, dir, &block, &retval);
1005 +               if (!(bh2))
1006 +               {
1007                         brelse(bh);
1008 -                       return 0;
1009 +                       return retval;
1010                 }
1011 -               offset += le16_to_cpu(de->rec_len);
1012 -               de = (struct ext3_dir_entry_2 *)
1013 -                       ((char *) de + le16_to_cpu(de->rec_len));
1014 +               data1 = bh2->b_data;
1015 +
1016 +               /* The 0th block becomes the root, move the dirents out */
1017 +               de = (ext3_dirent *) &root->info;
1018 +               len = ((char *) root) + blocksize - (char *) de;
1019 +               memcpy (data1, de, len);
1020 +               de = (ext3_dirent *) data1;
1021 +               top = data1 + len;
1022 +               while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top)
1023 +                       de = de2;
1024 +               de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
1025 +               /* Initialize the root; the dot dirents already exist */
1026 +               de = (ext3_dirent *) (&root->dotdot);
1027 +               de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
1028 +               memset (&root->info, 0, sizeof(root->info));
1029 +               root->info.info_length = sizeof(root->info);
1030 +               entries = root->entries;
1031 +               dx_set_block (entries, 1);
1032 +               dx_set_count (entries, 1);
1033 +               dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
1034 +
1035 +               /* Initialize as for dx_probe */
1036 +               hash = dx_hash (name, namelen);
1037 +               frame = frames;
1038 +               frame->entries = entries;
1039 +               frame->at = entries;
1040 +               frame->bh = bh;
1041 +               bh = bh2;
1042 +               de = do_split(handle,dir, &bh, frame, hash, &retval);
1043 +               dx_release (frames);
1044 +               if (!(de))
1045 +                       return retval;
1046 +               nlen = EXT3_DIR_REC_LEN(de->name_len);
1047 +               rlen = le16_to_cpu(de->rec_len);
1048 +               goto add;
1049         }
1050 -       brelse (bh);
1051 -       return -ENOSPC;
1052 +fail1:
1053 +       return retval;
1054 +fail:
1055 +       return -ENOENT;
1056  }
1057  
1058 +
1059  /*
1060   * ext3_delete_entry deletes a directory entry by merging it with the
1061   * previous entry
1062 @@ -451,7 +1212,8 @@
1063         struct inode * inode;
1064         int err;
1065  
1066 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
1067 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1068 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
1069         if (IS_ERR(handle))
1070                 return PTR_ERR(handle);
1071  
1072 @@ -478,7 +1240,8 @@
1073         struct inode *inode;
1074         int err;
1075  
1076 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
1077 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1078 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
1079         if (IS_ERR(handle))
1080                 return PTR_ERR(handle);
1081  
1082 @@ -507,7 +1270,8 @@
1083         if (dir->i_nlink >= EXT3_LINK_MAX)
1084                 return -EMLINK;
1085  
1086 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
1087 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1088 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
1089         if (IS_ERR(handle))
1090                 return PTR_ERR(handle);
1091  
1092 @@ -550,7 +1320,7 @@
1093         if (err)
1094                 goto out_no_entry;
1095         dir->i_nlink++;
1096 -       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1097 +       ext3_update_dx_flag(dir);
1098         ext3_mark_inode_dirty(handle, dir);
1099         d_instantiate(dentry, inode);
1100  out_stop:
1101 @@ -832,7 +1596,7 @@
1102         ext3_mark_inode_dirty(handle, inode);
1103         dir->i_nlink--;
1104         inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1105 -       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1106 +       ext3_update_dx_flag(dir);
1107         ext3_mark_inode_dirty(handle, dir);
1108  
1109  end_rmdir:
1110 @@ -878,7 +1642,7 @@
1111         if (retval)
1112                 goto end_unlink;
1113         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1114 -       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1115 +       ext3_update_dx_flag(dir);
1116         ext3_mark_inode_dirty(handle, dir);
1117         inode->i_nlink--;
1118         if (!inode->i_nlink)
1119 @@ -904,7 +1668,8 @@
1120         if (l > dir->i_sb->s_blocksize)
1121                 return -ENAMETOOLONG;
1122  
1123 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5);
1124 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1125 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5);
1126         if (IS_ERR(handle))
1127                 return PTR_ERR(handle);
1128  
1129 @@ -959,7 +1724,8 @@
1130         if (inode->i_nlink >= EXT3_LINK_MAX)
1131                 return -EMLINK;
1132  
1133 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS);
1134 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1135 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS);
1136         if (IS_ERR(handle))
1137                 return PTR_ERR(handle);
1138  
1139 @@ -995,7 +1761,8 @@
1140  
1141         old_bh = new_bh = dir_bh = NULL;
1142  
1143 -       handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
1144 +       handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
1145 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
1146         if (IS_ERR(handle))
1147                 return PTR_ERR(handle);
1148  
1149 @@ -1077,7 +1844,7 @@
1150                 new_inode->i_ctime = CURRENT_TIME;
1151         }
1152         old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1153 -       old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1154 +       ext3_update_dx_flag(old_dir);
1155         if (dir_bh) {
1156                 BUFFER_TRACE(dir_bh, "get_write_access");
1157                 ext3_journal_get_write_access(handle, dir_bh);
1158 @@ -1089,7 +1856,7 @@
1159                         new_inode->i_nlink--;
1160                 } else {
1161                         new_dir->i_nlink++;
1162 -                       new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1163 +                       ext3_update_dx_flag(new_dir);
1164                         ext3_mark_inode_dirty(handle, new_dir);
1165                 }
1166         }
1167 --- ./include/linux/ext3_fs.h   2002/03/05 06:18:59     2.1
1168 +++ ./include/linux/ext3_fs.h   2002/03/05 06:26:56
1169 @@ -339,6 +339,7 @@
1170    #define EXT3_MOUNT_WRITEBACK_DATA    0x0C00  /* No data ordering */
1171  #define EXT3_MOUNT_UPDATE_JOURNAL      0x1000  /* Update the journal format */
1172  #define EXT3_MOUNT_NO_UID32            0x2000  /* Disable 32-bit UIDs */
1173 +#define EXT3_MOUNT_INDEX               0x4000  /* Enable directory index */
1174  
1175  /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
1176  #ifndef _LINUX_EXT2_FS_H
1177 @@ -575,6 +576,24 @@
1178  #define EXT3_DIR_ROUND                 (EXT3_DIR_PAD - 1)
1179  #define EXT3_DIR_REC_LEN(name_len)     (((name_len) + 8 + EXT3_DIR_ROUND) & \
1180                                          ~EXT3_DIR_ROUND)
1181 +/*
1182 + * Hash Tree Directory indexing
1183 + * (c) Daniel Phillips, 2001
1184 + */
1185 +
1186 +#define CONFIG_EXT3_INDEX
1187 +
1188 +#ifdef CONFIG_EXT3_INDEX
1189 +  enum {ext3_dx = 1};
1190 +  #define is_dx(dir) (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)
1191 +#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX)
1192 +#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
1193 +#else
1194 +  enum {ext3_dx = 0};
1195 +  #define is_dx(dir) 0
1196 +#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
1197 +#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
1198 +#endif
1199  
1200  #ifdef __KERNEL__
1201  /*
1202 --- ./include/linux/ext3_jbd.h  2002/03/05 06:18:59     2.1
1203 +++ ./include/linux/ext3_jbd.h  2002/03/05 06:33:54
1204 @@ -63,6 +63,8 @@
1205  
1206  #define EXT3_RESERVE_TRANS_BLOCKS      12
1207  
1208 +#define EXT3_INDEX_EXTRA_TRANS_BLOCKS  8
1209 +
1210  int
1211  ext3_mark_iloc_dirty(handle_t *handle, 
1212                      struct inode *inode,