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