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