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