Whamcloud - gitweb
Add export from obdfilter to hold open file handles.
[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,433 @@
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 +               if (de->name_len && de->inode) {
424 +                       map[count].hash = dx_hash (de->name, de->name_len);
425 +                       map[count].offs = (u32) ((char *) de - base);
426 +                       count++;
427 +               }
428 +               de = (ext3_dirent *) ((char *) de + le16_to_cpu(de->rec_len));
429 +       }
430 +       return count;
431 +}
432 +
433 +static void dx_sort_map (struct dx_map_entry *map, unsigned count)
434 +{
435 +        struct dx_map_entry *p, *q, *top = map + count - 1;
436 +        int more;
437 +        /* Combsort until bubble sort doesn't suck */
438 +        while (count > 2)
439 +       {
440 +                count = count*10/13;
441 +                if (count - 9 < 2) /* 9, 10 -> 11 */
442 +                        count = 11;
443 +                for (p = top, q = p - count; q >= map; p--, q--)
444 +                        if (p->hash < q->hash)
445 +                                swap(*p, *q);
446 +        }
447 +        /* Garden variety bubble sort */
448 +        do {
449 +                more = 0;
450 +                q = top;
451 +                while (q-- > map)
452 +               {
453 +                        if (q[1].hash >= q[0].hash)
454 +                               continue;
455 +                        swap(*(q+1), *q);
456 +                        more = 1;
457 +               }
458 +       } while(more);
459 +}
460 +
461 +static void dx_insert_block(struct dx_frame *frame, u32 hash, u32 block)
462 +{
463 +       struct dx_entry *entries = frame->entries;
464 +       struct dx_entry *old = frame->at, *new = old + 1;
465 +       int count = dx_get_count(entries);
466 +
467 +       assert(count < dx_get_limit(entries));
468 +       assert(old < entries + count);
469 +       memmove(new + 1, new, (char *)(entries + count) - (char *)(new));
470 +       dx_set_hash(new, hash);
471 +       dx_set_block(new, block);
472 +       dx_set_count(entries, count + 1);
473 +}
474 +#endif
475 +
476 +static void ext3_update_dx_flag(struct inode *inode)
477 +{
478 +       if (!test_opt(inode->i_sb, INDEX))
479 +               EXT3_I(inode)->i_flags &= ~EXT3_INDEX_FL;
480 +}
481 +
482  /*
483   * NOTE! unlike strncmp, ext3_match returns 1 for success, 0 for failure.
484   *
485 @@ -95,6 +529,15 @@
486  }
487  
488  /*
489 + * p is at least 6 bytes before the end of page
490 + */
491 +static inline ext3_dirent *ext3_next_entry(ext3_dirent *p)
492 +{
493 +       return (ext3_dirent *)((char*)p + le16_to_cpu(p->rec_len));
494 +}
495 +
496 +
497 +/*
498   *     ext3_find_entry()
499   *
500   * finds an entry in the specified directory with the wanted name. It
501 @@ -105,6 +548,8 @@
502   * The returned buffer_head has ->b_count elevated.  The caller is expected
503   * to brelse() it when appropriate.
504   */
505 +
506 +       
507  static struct buffer_head * ext3_find_entry (struct dentry *dentry,
508                                         struct ext3_dir_entry_2 ** res_dir)
509  {
510 @@ -119,10 +564,76 @@
511         int num = 0;
512         int nblocks, i, err;
513         struct inode *dir = dentry->d_parent->d_inode;
514 +       int namelen;
515 +       const u8 *name;
516 +       unsigned blocksize;
517 +       ext3_dirent *de, *top;
518  
519         *res_dir = NULL;
520         sb = dir->i_sb;
521 +       blocksize = sb->s_blocksize;
522 +       namelen = dentry->d_name.len;
523 +       name = dentry->d_name.name;
524 +       if (namelen > EXT3_NAME_LEN)
525 +               return NULL;
526 +       if (ext3_dx && is_dx(dir)) {
527 +               u32 hash = dx_hash (name, namelen);
528 +               struct dx_frame frames[2], *frame;
529 +               if (!(frame = dx_probe (dir, hash, frames)))
530 +                       return NULL;
531 +dxnext:
532 +               block = dx_get_block(frame->at);
533 +               if (!(bh = ext3_bread (NULL,dir, block, 0, &err)))
534 +                       goto dxfail;
535 +               de = (ext3_dirent *) bh->b_data;
536 +               top = (ext3_dirent *) ((char *) de + blocksize -
537 +                               EXT3_DIR_REC_LEN(0));
538 +               for (; de < top; de = ext3_next_entry(de))
539 +                       if (ext3_match (namelen, name, de)) {
540 +                               if (!ext3_check_dir_entry("ext3_find_entry",
541 +                                         dir, de, bh,
542 +                                         (block<<EXT3_BLOCK_SIZE_BITS(sb))
543 +                                          +((char *)de - bh->b_data))) {
544 +                                       brelse (bh);
545 +                                       goto dxfail;
546 +                               }
547 +                               *res_dir = de;
548 +                               goto dxfound;
549 +                       }
550 +               brelse (bh);
551 +               /* Same hash continues in next block?  Search on. */
552 +               if (++(frame->at) == frame->entries + dx_get_count(frame->entries))
553 +               {
554 +                       struct buffer_head *bh2;
555 +                       if (frame == frames)
556 +                               goto dxfail;
557 +                       if (++(frames->at) == frames->entries + dx_get_count(frames->entries))
558 +                               goto dxfail;
559 +                       /* should omit read if not continued */
560 +                       if (!(bh2 = ext3_bread (NULL, dir,
561 +                                               dx_get_block(frames->at),
562 +                                               0, &err)))
563 +                               goto dxfail;
564 +                       brelse (frame->bh);
565 +                       frame->bh = bh2;
566 +                       frame->at = frame->entries = ((struct dx_node *) bh2->b_data)->entries;
567 +                       /* Subtle: the 0th entry has the count, find the hash in frame above */
568 +                       if ((dx_get_hash(frames->at) & -2) == hash)
569 +                               goto dxnext;
570 +                       goto dxfail;
571 +               }
572 +               if ((dx_get_hash(frame->at) & -2) == hash)
573 +                       goto dxnext;
574 +dxfail:
575 +               dxtrace(printk("%s not found\n", name));
576 +               dx_release (frames);
577 +               return NULL;
578 +dxfound:
579 +               dx_release (frames);
580 +               return bh;
581  
582 +       }
583 +       
584         nblocks = dir->i_size >> EXT3_BLOCK_SIZE_BITS(sb);
585         start = dir->u.ext3_i.i_dir_start_lookup;
586         if (start >= nblocks)
587 @@ -237,6 +748,92 @@
588                 de->file_type = ext3_type_by_mode[(mode & S_IFMT)>>S_SHIFT];
589  }
590  
591 +static ext3_dirent *
592 +dx_copy_dirents (char *from, char *to, struct dx_map_entry *map, int count)
593 +{
594 +       unsigned rec_len = 0;
595 +
596 +       while (count--) {
597 +               ext3_dirent *de = (ext3_dirent *) (from + map->offs);
598 +               rec_len = EXT3_DIR_REC_LEN(de->name_len);
599 +               memcpy (to, de, rec_len);
600 +               ((ext3_dirent *) to)->rec_len = rec_len;
601 +               to += rec_len;
602 +               map++;
603 +       }
604 +       return (ext3_dirent *) (to - rec_len);
605 +}
606 +
607 +#ifdef CONFIG_EXT3_INDEX
608 +static ext3_dirent *do_split(handle_t *handle, struct inode *dir,
609 +                       struct buffer_head **bh,struct dx_frame *frame,
610 +                       u32 hash, int *error)
611 +{
612 +       unsigned blocksize = dir->i_sb->s_blocksize;
613 +       unsigned count, continued;
614 +       struct buffer_head *bh2;
615 +       u32 newblock;
616 +       unsigned MAX_DX_MAP = PAGE_CACHE_SIZE/EXT3_DIR_REC_LEN(1) + 1;
617 +       u32 hash2;
618 +       struct dx_map_entry *map;
619 +       char *data1 = (*bh)->b_data, *data2, *data3;
620 +       unsigned split;
621 +       ext3_dirent *de, *de2;
622 +
623 +       bh2 = ext3_append (handle, dir, &newblock, error);
624 +       if (!(bh2))
625 +       {
626 +               brelse(*bh);
627 +               *bh = NULL;
628 +               return (ext3_dirent *)bh2;
629 +       }
630 +
631 +       BUFFER_TRACE(*bh, "get_write_access");
632 +       ext3_journal_get_write_access(handle, *bh);
633 +       BUFFER_TRACE(frame->bh, "get_write_access");
634 +       ext3_journal_get_write_access(handle, frame->bh);
635 +
636 +       data2 = bh2->b_data;
637 +
638 +       map = kmalloc(sizeof(*map) * MAX_DX_MAP, GFP_KERNEL);
639 +       if (!map)
640 +               panic("no memory for do_split\n");
641 +       count = dx_make_map ((ext3_dirent *) data1, blocksize, map);
642 +       split = count/2; // need to adjust to actual middle
643 +       dx_sort_map (map, count);
644 +       hash2 = map[split].hash;
645 +       continued = hash2 == map[split - 1].hash;
646 +       dxtrace(printk("Split block %i at %x, %i/%i\n",
647 +               dx_get_block(frame->at), hash2, split, count-split));
648 +
649 +       /* Fancy dance to stay within two buffers */
650 +       de2 = dx_copy_dirents (data1, data2, map + split, count - split);
651 +       data3 = (char *) de2 + de2->rec_len;
652 +       de = dx_copy_dirents (data1, data3, map, split);
653 +       memcpy(data1, data3, (char *) de + de->rec_len - data3);
654 +       de = (ext3_dirent *) ((char *) de - data3 + data1); // relocate de
655 +       de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
656 +       de2->rec_len = cpu_to_le16(data2 + blocksize - (char *) de2);
657 +       dxtrace(dx_show_leaf ((ext3_dirent *) data1, blocksize, 1));
658 +       dxtrace(dx_show_leaf ((ext3_dirent *) data2, blocksize, 1));
659 +
660 +       /* Which block gets the new entry? */
661 +       if (hash >= hash2)
662 +       {
663 +               swap(*bh, bh2);
664 +               de = de2;
665 +       }
666 +       dx_insert_block (frame, hash2 + continued, newblock);
667 +       ext3_journal_dirty_metadata (handle, bh2);
668 +       brelse (bh2);
669 +       ext3_journal_dirty_metadata (handle, frame->bh);
670 +       dxtrace(dx_show_index ("frame", frame->entries));
671 +       kfree(map);
672 +       return de;
673 +}
674 +#endif
675 +
676 +
677  /*
678   *     ext3_add_entry()
679   *
680 @@ -251,6 +844,7 @@
681  /*
682   * AKPM: the journalling code here looks wrong on the error paths
683   */
684 +
685  static int ext3_add_entry (handle_t *handle, struct dentry *dentry,
686         struct inode *inode)
687  {
688 @@ -258,117 +852,281 @@
689         const char *name = dentry->d_name.name;
690         int namelen = dentry->d_name.len;
691         unsigned long offset;
692 -       unsigned short rec_len;
693         struct buffer_head * bh;
694 -       struct ext3_dir_entry_2 * de, * de1;
695 -       struct super_block * sb;
696 +       ext3_dirent *de;
697 +       struct super_block * sb = dir->i_sb;
698         int     retval;
699 +       unsigned short reclen = EXT3_DIR_REC_LEN(namelen);
700  
701 -       sb = dir->i_sb;
702 +       unsigned blocksize = sb->s_blocksize;
703 +       unsigned nlen, rlen;
704 +       u32 block, blocks;
705 +       char *top;
706  
707         if (!namelen)
708                 return -EINVAL;
709 -       bh = ext3_bread (handle, dir, 0, 0, &retval);
710 -       if (!bh)
711 -               return retval;
712 -       rec_len = EXT3_DIR_REC_LEN(namelen);
713 -       offset = 0;
714 -       de = (struct ext3_dir_entry_2 *) bh->b_data;
715 -       while (1) {
716 -               if ((char *)de >= sb->s_blocksize + bh->b_data) {
717 -                       brelse (bh);
718 -                       bh = NULL;
719 -                       bh = ext3_bread (handle, dir,
720 -                               offset >> EXT3_BLOCK_SIZE_BITS(sb), 1, &retval);
721 -                       if (!bh)
722 -                               return retval;
723 -                       if (dir->i_size <= offset) {
724 -                               if (dir->i_size == 0) {
725 -                                       brelse(bh);
726 -                                       return -ENOENT;
727 +       if (ext3_dx && is_dx(dir)) {
728 +               struct dx_frame frames[2], *frame;
729 +               struct dx_entry *entries, *at;
730 +               u32 hash;
731 +               char *data1;
732 +
733 +               hash = dx_hash(name, namelen);
734 +               /* FIXME: do something if dx_probe() fails here */
735 +               frame = dx_probe(dir, hash, frames);
736 +               entries = frame->entries;
737 +               at = frame->at;
738 +
739 +               if (!(bh = ext3_bread(handle,dir, dx_get_block(at), 0,&retval)))
740 +                       goto dxfail1;
741 +
742 +               BUFFER_TRACE(bh, "get_write_access");
743 +               ext3_journal_get_write_access(handle, bh);
744 +
745 +               data1 = bh->b_data;
746 +               de = (ext3_dirent *) data1;
747 +               top = data1 + (0? 200: blocksize);
748 +               while ((char *) de < top)
749 +               {
750 +                       /* FIXME: check EEXIST and dir */
751 +                       nlen = EXT3_DIR_REC_LEN(de->name_len);
752 +                       rlen = le16_to_cpu(de->rec_len);
753 +                       if ((de->inode? rlen - nlen: rlen) >= reclen)
754 +                               goto dx_add;
755 +                       de = (ext3_dirent *) ((char *) de + rlen);
756 +               }
757 +               /* Block full, should compress but for now just split */
758 +               dxtrace(printk("using %u of %u node entries\n",
759 +                       dx_get_count(entries), dx_get_limit(entries)));
760 +               /* Need to split index? */
761 +               if (dx_get_count(entries) == dx_get_limit(entries))
762 +               {
763 +                       u32 newblock;
764 +                       unsigned icount = dx_get_count(entries);
765 +                       int levels = frame - frames;
766 +                       struct dx_entry *entries2;
767 +                       struct dx_node *node2;
768 +                       struct buffer_head *bh2;
769 +                       if (levels && dx_get_count(frames->entries) == dx_get_limit(frames->entries))
770 +                               goto dxfull;
771 +                       bh2 = ext3_append (handle, dir, &newblock, &retval);
772 +                       if (!(bh2))
773 +                               goto dxfail2;
774 +                       node2 = (struct dx_node *)(bh2->b_data);
775 +                       entries2 = node2->entries;
776 +                       node2->fake.rec_len = cpu_to_le16(blocksize);
777 +                       node2->fake.inode = 0;
778 +                       BUFFER_TRACE(frame->bh, "get_write_access");
779 +                       ext3_journal_get_write_access(handle, frame->bh);
780 +                       if (levels)
781 +                       {
782 +                               unsigned icount1 = icount/2, icount2 = icount - icount1;
783 +                               unsigned hash2 = dx_get_hash(entries + icount1);
784 +                               dxtrace(printk("Split index %i/%i\n", icount1, icount2));
785 +                               
786 +                               BUFFER_TRACE(frame->bh, "get_write_access"); /* index root */
787 +                               ext3_journal_get_write_access(handle, frames[0].bh);
788 +                               
789 +                               memcpy ((char *) entries2, (char *) (entries + icount1),
790 +                                       icount2 * sizeof(struct dx_entry));
791 +                               dx_set_count (entries, icount1);
792 +                               dx_set_count (entries2, icount2);
793 +                               dx_set_limit (entries2, dx_node_limit(dir));
794 +
795 +                               /* Which index block gets the new entry? */
796 +                               if (at - entries >= icount1) {
797 +                                       frame->at = at = at - entries - icount1 + entries2;
798 +                                       frame->entries = entries = entries2;
799 +                                       swap(frame->bh, bh2);
800                                 }
801 -
802 -                               ext3_debug ("creating next block\n");
803 -
804 -                               BUFFER_TRACE(bh, "get_write_access");
805 -                               ext3_journal_get_write_access(handle, bh);
806 -                               de = (struct ext3_dir_entry_2 *) bh->b_data;
807 -                               de->inode = 0;
808 -                               de->rec_len = le16_to_cpu(sb->s_blocksize);
809 -                               dir->u.ext3_i.i_disksize =
810 -                                       dir->i_size = offset + sb->s_blocksize;
811 -                               dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
812 -                               ext3_mark_inode_dirty(handle, dir);
813 +                               dx_insert_block (frames + 0, hash2, newblock);
814 +                               dxtrace(dx_show_index ("node", frames[1].entries));
815 +                               dxtrace(dx_show_index ("node",
816 +                                       ((struct dx_node *) bh2->b_data)->entries));
817 +                               ext3_journal_dirty_metadata(handle, bh2);
818 +                               brelse (bh2);
819                         } else {
820 -
821 -                               ext3_debug ("skipping to next block\n");
822 -
823 -                               de = (struct ext3_dir_entry_2 *) bh->b_data;
824 +                               dxtrace(printk("Creating second level index...\n"));
825 +                               memcpy((char *) entries2, (char *) entries,
826 +                                       icount * sizeof(struct dx_entry));
827 +                               dx_set_limit(entries2, dx_node_limit(dir));
828 +
829 +                               /* Set up root */
830 +                               dx_set_count(entries, 1);
831 +                               dx_set_block(entries + 0, newblock);
832 +                               ((struct dx_root *) frames[0].bh->b_data)->info.indirect_levels = 1;
833 +
834 +                               /* Add new access path frame */
835 +                               frame = frames + 1;
836 +                               frame->at = at = at - entries + entries2;
837 +                               frame->entries = entries = entries2;
838 +                               frame->bh = bh2;
839 +                               ext3_journal_get_write_access(handle, frame->bh);
840                         }
841 +                       ext3_journal_dirty_metadata(handle, frames[0].bh);
842                 }
843 -               if (!ext3_check_dir_entry ("ext3_add_entry", dir, de, bh,
844 -                                          offset)) {
845 -                       brelse (bh);
846 -                       return -ENOENT;
847 -               }
848 -               if (ext3_match (namelen, name, de)) {
849 +               de = do_split(handle, dir, &bh, frame, hash, &retval);
850 +               dx_release (frames);
851 +               if (!(de))
852 +                       goto fail;
853 +               nlen = EXT3_DIR_REC_LEN(de->name_len);
854 +               rlen = le16_to_cpu(de->rec_len);
855 +               goto add;
856 +
857 +dx_add:
858 +               dx_release (frames);
859 +               goto add;
860 +
861 +dxfull:
862 +               ext3_warning(sb, __FUNCTION__, "Directory index full!\n");
863 +               retval = -ENOSPC;
864 +dxfail2:
865 +               brelse(bh);
866 +dxfail1:
867 +               dx_release (frames);
868 +               goto fail1;
869 +       }
870 +
871 +       blocks = dir->i_size >> sb->s_blocksize_bits;
872 +       for (block = 0, offset = 0; block < blocks; block++) {
873 +               bh = ext3_bread(handle, dir, block, 0, &retval);
874 +               if(!bh)
875 +                       return retval;
876 +               de = (ext3_dirent *)bh->b_data;
877 +               top = bh->b_data + blocksize - reclen;
878 +               while ((char *) de <= top) {
879 +                       if (!ext3_check_dir_entry("ext3_add_entry", dir, de,
880 +                                                 bh, offset)) {
881 +                               brelse (bh);
882 +                               return -EIO;
883 +                       }
884 +                       if (ext3_match (namelen, name, de)) {
885                                 brelse (bh);
886                                 return -EEXIST;
887 -               }
888 -               if ((le32_to_cpu(de->inode) == 0 &&
889 -                               le16_to_cpu(de->rec_len) >= rec_len) ||
890 -                   (le16_to_cpu(de->rec_len) >=
891 -                               EXT3_DIR_REC_LEN(de->name_len) + rec_len)) {
892 -                       BUFFER_TRACE(bh, "get_write_access");
893 -                       ext3_journal_get_write_access(handle, bh);
894 -                       /* By now the buffer is marked for journaling */
895 -                       offset += le16_to_cpu(de->rec_len);
896 -                       if (le32_to_cpu(de->inode)) {
897 -                               de1 = (struct ext3_dir_entry_2 *) ((char *) de +
898 -                                       EXT3_DIR_REC_LEN(de->name_len));
899 -                               de1->rec_len =
900 -                                       cpu_to_le16(le16_to_cpu(de->rec_len) -
901 -                                       EXT3_DIR_REC_LEN(de->name_len));
902 -                               de->rec_len = cpu_to_le16(
903 -                                               EXT3_DIR_REC_LEN(de->name_len));
904 -                               de = de1;
905                         }
906 -                       de->file_type = EXT3_FT_UNKNOWN;
907 -                       if (inode) {
908 -                               de->inode = cpu_to_le32(inode->i_ino);
909 -                               ext3_set_de_type(dir->i_sb, de, inode->i_mode);
910 -                       } else
911 -                               de->inode = 0;
912 -                       de->name_len = namelen;
913 -                       memcpy (de->name, name, namelen);
914 -                       /*
915 -                        * XXX shouldn't update any times until successful
916 -                        * completion of syscall, but too many callers depend
917 -                        * on this.
918 -                        *
919 -                        * XXX similarly, too many callers depend on
920 -                        * ext3_new_inode() setting the times, but error
921 -                        * recovery deletes the inode, so the worst that can
922 -                        * happen is that the times are slightly out of date
923 -                        * and/or different from the directory change time.
924 -                        */
925 -                       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
926 -                       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
927 -                       dir->i_version = ++event;
928 -                       ext3_mark_inode_dirty(handle, dir);
929 -                       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
930 -                       ext3_journal_dirty_metadata(handle, bh);
931 +                       nlen = EXT3_DIR_REC_LEN(de->name_len);
932 +                       rlen = le16_to_cpu(de->rec_len);
933 +                       if ((de->inode? rlen - nlen: rlen) >= reclen)
934 +                               goto add;
935 +                       de = (ext3_dirent *)((char *)de + rlen);
936 +                       offset += rlen;
937 +               }
938 +               if (ext3_dx && blocks == 1 && test_opt(sb, INDEX))
939 +                       goto dx_make_index;
940 +               brelse(bh);
941 +       }
942 +       bh = ext3_append(handle, dir, &block, &retval);
943 +       if (!bh)
944 +               return retval;
945 +       de = (ext3_dirent *) bh->b_data;
946 +       de->inode = 0;
947 +       de->rec_len = cpu_to_le16(rlen = blocksize);
948 +       nlen = 0;
949 +       goto add;
950 +
951 +add:
952 +       BUFFER_TRACE(bh, "get_write_access");
953 +       ext3_journal_get_write_access(handle, bh);
954 +       /* By now the buffer is marked for journaling */
955 +       if (de->inode) {
956 +               ext3_dirent *de1 = (ext3_dirent *)((char *)de + nlen);
957 +               de1->rec_len = cpu_to_le16(rlen - nlen);
958 +               de->rec_len = cpu_to_le16(nlen);
959 +               de = de1;
960 +       }
961 +       de->file_type = EXT3_FT_UNKNOWN;
962 +       if (inode) {
963 +               de->inode = cpu_to_le32(inode->i_ino);
964 +               ext3_set_de_type(dir->i_sb, de, inode->i_mode);
965 +       } else
966 +               de->inode = 0;
967 +       de->name_len = namelen;
968 +       memcpy (de->name, name, namelen);
969 +       /*
970 +        * XXX shouldn't update any times until successful
971 +        * completion of syscall, but too many callers depend
972 +        * on this.
973 +        *
974 +        * XXX similarly, too many callers depend on
975 +        * ext3_new_inode() setting the times, but error
976 +        * recovery deletes the inode, so the worst that can
977 +        * happen is that the times are slightly out of date
978 +        * and/or different from the directory change time.
979 +        */
980 +       dir->i_mtime = dir->i_ctime = CURRENT_TIME;
981 +       ext3_update_dx_flag(dir);
982 +       dir->i_version = ++event;
983 +       ext3_mark_inode_dirty(handle, dir);
984 +       BUFFER_TRACE(bh, "call ext3_journal_dirty_metadata");
985 +       ext3_journal_dirty_metadata(handle, bh);
986 +       brelse(bh);
987 +       return 0;
988 +
989 +dx_make_index:
990 +       {
991 +               struct buffer_head *bh2;
992 +               struct dx_root *root;
993 +               struct dx_frame frames[2], *frame;
994 +               struct dx_entry *entries;
995 +               ext3_dirent *de2;
996 +               char *data1;
997 +               unsigned len;
998 +               u32 hash;
999 +               
1000 +               dxtrace(printk("Creating index\n"));
1001 +               ext3_journal_get_write_access(handle, bh);
1002 +               root = (struct dx_root *) bh->b_data;
1003 +               
1004 +               EXT3_I(dir)->i_flags |= EXT3_INDEX_FL;
1005 +               bh2 = ext3_append (handle, dir, &block, &retval);
1006 +               if (!(bh2))
1007 +               {
1008                         brelse(bh);
1009 -                       return 0;
1010 +                       return retval;
1011                 }
1012 -               offset += le16_to_cpu(de->rec_len);
1013 -               de = (struct ext3_dir_entry_2 *)
1014 -                       ((char *) de + le16_to_cpu(de->rec_len));
1015 +               data1 = bh2->b_data;
1016 +
1017 +               /* The 0th block becomes the root, move the dirents out */
1018 +               de = (ext3_dirent *) &root->info;
1019 +               len = ((char *) root) + blocksize - (char *) de;
1020 +               memcpy (data1, de, len);
1021 +               de = (ext3_dirent *) data1;
1022 +               top = data1 + len;
1023 +               while (((char *) de2=(char*)de+le16_to_cpu(de->rec_len)) < top)
1024 +                       de = de2;
1025 +               de->rec_len = cpu_to_le16(data1 + blocksize - (char *) de);
1026 +               /* Initialize the root; the dot dirents already exist */
1027 +               de = (ext3_dirent *) (&root->dotdot);
1028 +               de->rec_len = cpu_to_le16(blocksize - EXT3_DIR_REC_LEN(2));
1029 +               memset (&root->info, 0, sizeof(root->info));
1030 +               root->info.info_length = sizeof(root->info);
1031 +               entries = root->entries;
1032 +               dx_set_block (entries, 1);
1033 +               dx_set_count (entries, 1);
1034 +               dx_set_limit (entries, dx_root_limit(dir, sizeof(root->info)));
1035 +
1036 +               /* Initialize as for dx_probe */
1037 +               hash = dx_hash (name, namelen);
1038 +               frame = frames;
1039 +               frame->entries = entries;
1040 +               frame->at = entries;
1041 +               frame->bh = bh;
1042 +               bh = bh2;
1043 +               de = do_split(handle,dir, &bh, frame, hash, &retval);
1044 +               dx_release (frames);
1045 +               if (!(de))
1046 +                       return retval;
1047 +               nlen = EXT3_DIR_REC_LEN(de->name_len);
1048 +               rlen = le16_to_cpu(de->rec_len);
1049 +               goto add;
1050         }
1051 -       brelse (bh);
1052 -       return -ENOSPC;
1053 +fail1:
1054 +       return retval;
1055 +fail:
1056 +       return -ENOENT;
1057  }
1058  
1059 +
1060  /*
1061   * ext3_delete_entry deletes a directory entry by merging it with the
1062   * previous entry
1063 @@ -451,7 +1212,8 @@
1064         struct inode * inode;
1065         int err;
1066  
1067 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
1068 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1069 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
1070         if (IS_ERR(handle))
1071                 return PTR_ERR(handle);
1072  
1073 @@ -478,7 +1240,8 @@
1074         struct inode *inode;
1075         int err;
1076  
1077 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
1078 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1079 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
1080         if (IS_ERR(handle))
1081                 return PTR_ERR(handle);
1082  
1083 @@ -507,7 +1270,8 @@
1084         if (dir->i_nlink >= EXT3_LINK_MAX)
1085                 return -EMLINK;
1086  
1087 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 3);
1088 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1089 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3);
1090         if (IS_ERR(handle))
1091                 return PTR_ERR(handle);
1092  
1093 @@ -550,7 +1320,7 @@
1094         if (err)
1095                 goto out_no_entry;
1096         dir->i_nlink++;
1097 -       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1098 +       ext3_update_dx_flag(dir);
1099         ext3_mark_inode_dirty(handle, dir);
1100         d_instantiate(dentry, inode);
1101  out_stop:
1102 @@ -832,7 +1596,7 @@
1103         ext3_mark_inode_dirty(handle, inode);
1104         dir->i_nlink--;
1105         inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1106 -       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1107 +       ext3_update_dx_flag(dir);
1108         ext3_mark_inode_dirty(handle, dir);
1109  
1110  end_rmdir:
1111 @@ -878,7 +1642,7 @@
1112         if (retval)
1113                 goto end_unlink;
1114         dir->i_ctime = dir->i_mtime = CURRENT_TIME;
1115 -       dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1116 +       ext3_update_dx_flag(dir);
1117         ext3_mark_inode_dirty(handle, dir);
1118         inode->i_nlink--;
1119         if (!inode->i_nlink)
1120 @@ -904,7 +1668,8 @@
1121         if (l > dir->i_sb->s_blocksize)
1122                 return -ENAMETOOLONG;
1123  
1124 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS + 5);
1125 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1126 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5);
1127         if (IS_ERR(handle))
1128                 return PTR_ERR(handle);
1129  
1130 @@ -959,7 +1724,8 @@
1131         if (inode->i_nlink >= EXT3_LINK_MAX)
1132                 return -EMLINK;
1133  
1134 -       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS);
1135 +       handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS +
1136 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS);
1137         if (IS_ERR(handle))
1138                 return PTR_ERR(handle);
1139  
1140 @@ -995,7 +1761,8 @@
1141  
1142         old_bh = new_bh = dir_bh = NULL;
1143  
1144 -       handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS + 2);
1145 +       handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS +
1146 +                                       EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2);
1147         if (IS_ERR(handle))
1148                 return PTR_ERR(handle);
1149  
1150 @@ -1077,7 +1844,7 @@
1151                 new_inode->i_ctime = CURRENT_TIME;
1152         }
1153         old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME;
1154 -       old_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1155 +       ext3_update_dx_flag(old_dir);
1156         if (dir_bh) {
1157                 BUFFER_TRACE(dir_bh, "get_write_access");
1158                 ext3_journal_get_write_access(handle, dir_bh);
1159 @@ -1089,7 +1856,7 @@
1160                         new_inode->i_nlink--;
1161                 } else {
1162                         new_dir->i_nlink++;
1163 -                       new_dir->u.ext3_i.i_flags &= ~EXT3_INDEX_FL;
1164 +                       ext3_update_dx_flag(new_dir);
1165                         ext3_mark_inode_dirty(handle, new_dir);
1166                 }
1167         }
1168 --- ./include/linux/ext3_fs.h   2002/03/05 06:18:59     2.1
1169 +++ ./include/linux/ext3_fs.h   2002/03/05 06:26:56
1170 @@ -339,6 +339,7 @@
1171    #define EXT3_MOUNT_WRITEBACK_DATA    0x0C00  /* No data ordering */
1172  #define EXT3_MOUNT_UPDATE_JOURNAL      0x1000  /* Update the journal format */
1173  #define EXT3_MOUNT_NO_UID32            0x2000  /* Disable 32-bit UIDs */
1174 +#define EXT3_MOUNT_INDEX               0x4000  /* Enable directory index */
1175  
1176  /* Compatibility, for having both ext2_fs.h and ext3_fs.h included at once */
1177  #ifndef _LINUX_EXT2_FS_H
1178 @@ -575,6 +576,24 @@
1179  #define EXT3_DIR_ROUND                 (EXT3_DIR_PAD - 1)
1180  #define EXT3_DIR_REC_LEN(name_len)     (((name_len) + 8 + EXT3_DIR_ROUND) & \
1181                                          ~EXT3_DIR_ROUND)
1182 +/*
1183 + * Hash Tree Directory indexing
1184 + * (c) Daniel Phillips, 2001
1185 + */
1186 +
1187 +#define CONFIG_EXT3_INDEX
1188 +
1189 +#ifdef CONFIG_EXT3_INDEX
1190 +  enum {ext3_dx = 1};
1191 +  #define is_dx(dir) (EXT3_I(dir)->i_flags & EXT3_INDEX_FL)
1192 +#define EXT3_DIR_LINK_MAX(dir) (!is_dx(dir) && (dir)->i_nlink >= EXT3_LINK_MAX)
1193 +#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2 || (dir)->i_nlink == 1)
1194 +#else
1195 +  enum {ext3_dx = 0};
1196 +  #define is_dx(dir) 0
1197 +#define EXT3_DIR_LINK_MAX(dir) ((dir)->i_nlink >= EXT3_LINK_MAX)
1198 +#define EXT3_DIR_LINK_EMPTY(dir) ((dir)->i_nlink == 2)
1199 +#endif
1200  
1201  #ifdef __KERNEL__
1202  /*
1203 --- ./include/linux/ext3_jbd.h  2002/03/05 06:18:59     2.1
1204 +++ ./include/linux/ext3_jbd.h  2002/03/05 06:33:54
1205 @@ -63,6 +63,8 @@
1206  
1207  #define EXT3_RESERVE_TRANS_BLOCKS      12
1208  
1209 +#define EXT3_INDEX_EXTRA_TRANS_BLOCKS  8
1210 +
1211  int
1212  ext3_mark_iloc_dirty(handle_t *handle, 
1213                      struct inode *inode,