vserver 2.0 rc7
[linux-2.6.git] / fs / reiserfs / item_ops.c
1 /*
2  * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
3  */
4
5 #include <linux/time.h>
6 #include <linux/reiserfs_fs.h>
7
8 // this contains item handlers for old item types: sd, direct,
9 // indirect, directory
10
11 /* and where are the comments? how about saying where we can find an
12    explanation of each item handler method? -Hans */
13
14 //////////////////////////////////////////////////////////////////////////////
15 // stat data functions
16 //
17 static int sd_bytes_number (struct item_head * ih, int block_size)
18 {
19   return 0;
20 }
21
22 static void sd_decrement_key (struct cpu_key * key)
23 {
24     key->on_disk_key.k_objectid --;
25     set_cpu_key_k_type (key, TYPE_ANY);
26     set_cpu_key_k_offset(key, (loff_t)(-1));
27 }
28
29 static int sd_is_left_mergeable (struct reiserfs_key * key, unsigned long bsize)
30 {
31     return 0;
32 }
33
34
35
36 static char * print_time (time_t t)
37 {
38     static char timebuf[256];
39
40     sprintf (timebuf, "%ld", t);
41     return timebuf;
42 }
43
44
45 static void sd_print_item (struct item_head * ih, char * item)
46 {
47     printk ("\tmode | size | nlinks | first direct | mtime\n");
48     if (stat_data_v1 (ih)) {
49         struct stat_data_v1 * sd = (struct stat_data_v1 *)item;
50
51         printk ("\t0%-6o | %6u | %2u | %d | %s\n", sd_v1_mode(sd),
52                 sd_v1_size(sd), sd_v1_nlink(sd), sd_v1_first_direct_byte(sd),
53                 print_time( sd_v1_mtime(sd) ) );
54     } else {
55         struct stat_data * sd = (struct stat_data *)item;
56
57         printk ("\t0%-6o | %6Lu | %2u | %d | %s\n", sd_v2_mode(sd),
58             (unsigned long long)sd_v2_size(sd), sd_v2_nlink(sd),
59             sd_v2_rdev(sd), print_time(sd_v2_mtime(sd)));
60     }
61 }
62
63 static void sd_check_item (struct item_head * ih, char * item)
64 {
65     // FIXME: type something here!
66 }
67
68
69 static int sd_create_vi (struct virtual_node * vn,
70                          struct virtual_item * vi, 
71                          int is_affected, 
72                          int insert_size)
73 {
74     vi->vi_index = TYPE_STAT_DATA;
75     //vi->vi_type |= VI_TYPE_STAT_DATA;// not needed?
76     return 0;
77 }
78
79
80 static int sd_check_left (struct virtual_item * vi, int free, 
81                           int start_skip, int end_skip)
82 {
83     if (start_skip || end_skip)
84         BUG ();
85     return -1;
86 }
87
88
89 static int sd_check_right (struct virtual_item * vi, int free)
90 {
91     return -1;
92 }
93
94 static int sd_part_size (struct virtual_item * vi, int first, int count)
95 {
96     if (count)
97         BUG ();
98     return 0;
99 }
100
101 static int sd_unit_num (struct virtual_item * vi)
102 {
103     return vi->vi_item_len - IH_SIZE;
104 }
105
106
107 static void sd_print_vi (struct virtual_item * vi)
108 {
109     reiserfs_warning (NULL, "STATDATA, index %d, type 0x%x, %h",
110                       vi->vi_index, vi->vi_type, vi->vi_ih);
111 }
112
113 static struct item_operations stat_data_ops = {
114         .bytes_number           = sd_bytes_number,
115         .decrement_key          = sd_decrement_key,
116         .is_left_mergeable      = sd_is_left_mergeable,
117         .print_item             = sd_print_item,
118         .check_item             = sd_check_item,
119
120         .create_vi              = sd_create_vi,
121         .check_left             = sd_check_left,
122         .check_right            = sd_check_right,
123         .part_size              = sd_part_size,
124         .unit_num               = sd_unit_num,
125         .print_vi               = sd_print_vi
126 };
127
128
129
130 //////////////////////////////////////////////////////////////////////////////
131 // direct item functions
132 //
133 static int direct_bytes_number (struct item_head * ih, int block_size)
134 {
135   return ih_item_len(ih);
136 }
137
138
139 // FIXME: this should probably switch to indirect as well
140 static void direct_decrement_key (struct cpu_key * key)
141 {
142     cpu_key_k_offset_dec (key);
143     if (cpu_key_k_offset (key) == 0)
144         set_cpu_key_k_type (key, TYPE_STAT_DATA);       
145 }
146
147
148 static int direct_is_left_mergeable (struct reiserfs_key * key, unsigned long bsize)
149 {
150     int version = le_key_version (key);
151     return ((le_key_k_offset (version, key) & (bsize - 1)) != 1);
152 }
153
154
155 static void direct_print_item (struct item_head * ih, char * item)
156 {
157     int j = 0;
158
159 //    return;
160     printk ("\"");
161     while (j < ih_item_len(ih))
162         printk ("%c", item[j++]);
163     printk ("\"\n");
164 }
165
166
167 static void direct_check_item (struct item_head * ih, char * item)
168 {
169     // FIXME: type something here!
170 }
171
172
173 static int direct_create_vi (struct virtual_node * vn,
174                              struct virtual_item * vi, 
175                              int is_affected, 
176                              int insert_size)
177 {
178     vi->vi_index = TYPE_DIRECT;
179     //vi->vi_type |= VI_TYPE_DIRECT;
180     return 0;
181 }
182
183 static int direct_check_left (struct virtual_item * vi, int free,
184                               int start_skip, int end_skip)
185 {
186     int bytes;
187
188     bytes = free - free % 8;
189     return bytes ?: -1;    
190 }
191
192
193 static int direct_check_right (struct virtual_item * vi, int free)
194 {
195     return direct_check_left (vi, free, 0, 0);
196 }
197
198 static int direct_part_size (struct virtual_item * vi, int first, int count)
199 {
200     return count;
201 }
202
203
204 static int direct_unit_num (struct virtual_item * vi)
205 {
206     return vi->vi_item_len - IH_SIZE;
207 }
208
209
210 static void direct_print_vi (struct virtual_item * vi)
211 {
212     reiserfs_warning (NULL, "DIRECT, index %d, type 0x%x, %h",
213                       vi->vi_index, vi->vi_type, vi->vi_ih);
214 }
215
216 static struct item_operations direct_ops = {
217         .bytes_number           = direct_bytes_number,
218         .decrement_key          = direct_decrement_key,
219         .is_left_mergeable      = direct_is_left_mergeable,
220         .print_item             = direct_print_item,
221         .check_item             = direct_check_item,
222
223         .create_vi              = direct_create_vi,
224         .check_left             = direct_check_left,
225         .check_right            = direct_check_right,
226         .part_size              = direct_part_size,
227         .unit_num               = direct_unit_num,
228         .print_vi               = direct_print_vi
229 };
230
231
232
233 //////////////////////////////////////////////////////////////////////////////
234 // indirect item functions
235 //
236
237 static int indirect_bytes_number (struct item_head * ih, int block_size)
238 {
239   return ih_item_len(ih) / UNFM_P_SIZE * block_size; //- get_ih_free_space (ih);
240 }
241
242
243 // decrease offset, if it becomes 0, change type to stat data
244 static void indirect_decrement_key (struct cpu_key * key)
245 {
246     cpu_key_k_offset_dec (key);
247     if (cpu_key_k_offset (key) == 0)
248         set_cpu_key_k_type (key, TYPE_STAT_DATA);
249 }
250
251
252 // if it is not first item of the body, then it is mergeable
253 static int indirect_is_left_mergeable (struct reiserfs_key * key, unsigned long bsize)
254 {
255     int version = le_key_version (key);
256     return (le_key_k_offset (version, key) != 1);
257 }
258
259
260 // printing of indirect item
261 static void start_new_sequence (__u32 * start, int * len, __u32 new)
262 {
263     *start = new;
264     *len = 1;
265 }
266
267
268 static int sequence_finished (__u32 start, int * len, __u32 new)
269 {
270     if (start == INT_MAX)
271         return 1;
272
273     if (start == 0 && new == 0) {
274         (*len) ++;
275         return 0;
276     }
277     if (start != 0 && (start + *len) == new) {
278         (*len) ++;
279         return 0;
280     }
281     return 1;
282 }
283
284 static void print_sequence (__u32 start, int len)
285 {
286     if (start == INT_MAX)
287         return;
288
289     if (len == 1)
290         printk (" %d", start);
291     else
292         printk (" %d(%d)", start, len);
293 }
294
295
296 static void indirect_print_item (struct item_head * ih, char * item)
297 {
298     int j;
299     __le32 * unp;
300     __u32 prev = INT_MAX;
301     int num;
302
303     unp = (__le32 *)item;
304
305     if (ih_item_len(ih) % UNFM_P_SIZE)
306         reiserfs_warning (NULL, "indirect_print_item: invalid item len");
307
308     printk ("%d pointers\n[ ", (int)I_UNFM_NUM (ih));
309     for (j = 0; j < I_UNFM_NUM (ih); j ++) {
310         if (sequence_finished (prev, &num, get_block_num(unp, j))) {
311             print_sequence (prev, num);
312             start_new_sequence (&prev, &num, get_block_num(unp, j));
313         }
314     }
315     print_sequence (prev, num);
316     printk ("]\n");
317 }
318
319 static void indirect_check_item (struct item_head * ih, char * item)
320 {
321     // FIXME: type something here!
322 }
323
324
325 static int indirect_create_vi (struct virtual_node * vn,
326                                struct virtual_item * vi, 
327                                int is_affected, 
328                                int insert_size)
329 {
330     vi->vi_index = TYPE_INDIRECT;
331     //vi->vi_type |= VI_TYPE_INDIRECT;
332     return 0;
333 }
334
335 static int indirect_check_left (struct virtual_item * vi, int free,
336                                 int start_skip, int end_skip)
337 {
338     int bytes;
339
340     bytes = free - free % UNFM_P_SIZE;
341     return bytes ?: -1;    
342 }
343
344
345 static int indirect_check_right (struct virtual_item * vi, int free)
346 {
347     return indirect_check_left (vi, free, 0, 0);
348 }
349
350
351
352 // return size in bytes of 'units' units. If first == 0 - calculate from the head (left), otherwise - from tail (right)
353 static int indirect_part_size (struct virtual_item * vi, int first, int units)
354 {
355     // unit of indirect item is byte (yet)
356     return units;
357 }
358
359 static int indirect_unit_num (struct virtual_item * vi)
360 {
361     // unit of indirect item is byte (yet)
362     return vi->vi_item_len - IH_SIZE;
363 }
364
365 static void indirect_print_vi (struct virtual_item * vi)
366 {
367     reiserfs_warning (NULL, "INDIRECT, index %d, type 0x%x, %h",
368                       vi->vi_index, vi->vi_type, vi->vi_ih);
369 }
370
371 static struct item_operations indirect_ops = {
372         .bytes_number           = indirect_bytes_number,
373         .decrement_key          = indirect_decrement_key,
374         .is_left_mergeable      = indirect_is_left_mergeable,
375         .print_item             = indirect_print_item,
376         .check_item             = indirect_check_item,
377
378         .create_vi              = indirect_create_vi,
379         .check_left             = indirect_check_left,
380         .check_right            = indirect_check_right,
381         .part_size              = indirect_part_size,
382         .unit_num               = indirect_unit_num,
383         .print_vi               = indirect_print_vi
384 };
385
386
387 //////////////////////////////////////////////////////////////////////////////
388 // direntry functions
389 //
390
391
392 static int direntry_bytes_number (struct item_head * ih, int block_size)
393 {
394     reiserfs_warning (NULL, "vs-16090: direntry_bytes_number: "
395                       "bytes number is asked for direntry");
396     return 0;
397 }
398
399 static void direntry_decrement_key (struct cpu_key * key)
400 {
401     cpu_key_k_offset_dec (key);
402     if (cpu_key_k_offset (key) == 0)
403         set_cpu_key_k_type (key, TYPE_STAT_DATA);       
404 }
405
406
407 static int direntry_is_left_mergeable (struct reiserfs_key * key, unsigned long bsize)
408 {
409     if (le32_to_cpu (key->u.k_offset_v1.k_offset) == DOT_OFFSET)
410         return 0;
411     return 1;
412         
413 }
414
415
416 static void direntry_print_item (struct item_head * ih, char * item)
417 {
418     int i;
419     int namelen;
420     struct reiserfs_de_head * deh;
421     char * name;
422     static char namebuf [80];
423
424
425     printk ("\n # %-15s%-30s%-15s%-15s%-15s\n", "Name", "Key of pointed object", "Hash", "Gen number", "Status");
426
427     deh = (struct reiserfs_de_head *)item;
428
429     for (i = 0; i < I_ENTRY_COUNT (ih); i ++, deh ++) {
430         namelen = (i ? (deh_location(deh - 1)) : ih_item_len(ih)) - deh_location(deh);
431         name = item + deh_location(deh);
432         if (name[namelen-1] == 0)
433           namelen = strlen (name);
434         namebuf[0] = '"';
435         if (namelen > sizeof (namebuf) - 3) {
436             strncpy (namebuf + 1, name, sizeof (namebuf) - 3);
437             namebuf[sizeof (namebuf) - 2] = '"';
438             namebuf[sizeof (namebuf) - 1] = 0;
439         } else {
440             memcpy (namebuf + 1, name, namelen);
441             namebuf[namelen + 1] = '"';
442             namebuf[namelen + 2] = 0;
443         }
444
445         printk ("%d:  %-15s%-15d%-15d%-15Ld%-15Ld(%s)\n", 
446                 i, namebuf,
447                 deh_dir_id(deh), deh_objectid(deh),
448                 GET_HASH_VALUE (deh_offset (deh)), GET_GENERATION_NUMBER ((deh_offset (deh))),
449                 (de_hidden (deh)) ? "HIDDEN" : "VISIBLE");
450     }
451 }
452
453
454 static void direntry_check_item (struct item_head * ih, char * item)
455 {
456     int i;
457     struct reiserfs_de_head * deh;
458
459     // FIXME: type something here!
460     deh = (struct reiserfs_de_head *)item;
461     for (i = 0; i < I_ENTRY_COUNT (ih); i ++, deh ++) {
462         ;
463     }
464 }
465
466
467
468 #define DIRENTRY_VI_FIRST_DIRENTRY_ITEM 1
469
470 /*
471  * function returns old entry number in directory item in real node
472  * using new entry number in virtual item in virtual node */
473 static inline int old_entry_num (int is_affected, int virtual_entry_num, int pos_in_item, int mode)
474 {
475     if ( mode == M_INSERT || mode == M_DELETE)
476         return virtual_entry_num;
477     
478     if (!is_affected)
479         /* cut or paste is applied to another item */
480         return virtual_entry_num;
481
482     if (virtual_entry_num < pos_in_item)
483         return virtual_entry_num;
484
485     if (mode == M_CUT)
486         return virtual_entry_num + 1;
487
488     RFALSE( mode != M_PASTE || virtual_entry_num == 0,
489             "vs-8015: old_entry_num: mode must be M_PASTE (mode = \'%c\'", mode);
490     
491     return virtual_entry_num - 1;
492 }
493
494
495
496
497 /* Create an array of sizes of directory entries for virtual
498    item. Return space used by an item. FIXME: no control over
499    consuming of space used by this item handler */
500 static int direntry_create_vi (struct virtual_node * vn,
501                                struct virtual_item * vi, 
502                                int is_affected, 
503                                int insert_size)
504 {
505     struct direntry_uarea * dir_u = vi->vi_uarea;
506     int i, j;
507     int size = sizeof (struct direntry_uarea);
508     struct reiserfs_de_head * deh;
509   
510     vi->vi_index = TYPE_DIRENTRY;
511
512     if (!(vi->vi_ih) || !vi->vi_item)
513         BUG ();
514
515
516     dir_u->flags = 0;
517     if (le_ih_k_offset (vi->vi_ih) == DOT_OFFSET)
518         dir_u->flags |= DIRENTRY_VI_FIRST_DIRENTRY_ITEM;
519
520     deh = (struct reiserfs_de_head *)(vi->vi_item);
521     
522     
523     /* virtual directory item have this amount of entry after */
524     dir_u->entry_count = ih_entry_count (vi->vi_ih) + 
525         ((is_affected) ? ((vn->vn_mode == M_CUT) ? -1 :
526                           (vn->vn_mode == M_PASTE ? 1 : 0)) : 0);
527     
528     for (i = 0; i < dir_u->entry_count; i ++) {
529         j = old_entry_num (is_affected, i, vn->vn_pos_in_item, vn->vn_mode);
530         dir_u->entry_sizes[i] = (j ? deh_location( &(deh[j - 1]) ) :
531                                 ih_item_len (vi->vi_ih)) -
532                                 deh_location( &(deh[j])) + DEH_SIZE;
533     }
534
535     size += (dir_u->entry_count * sizeof (short));
536     
537     /* set size of pasted entry */
538     if (is_affected && vn->vn_mode == M_PASTE)
539         dir_u->entry_sizes[vn->vn_pos_in_item] = insert_size;
540
541
542 #ifdef CONFIG_REISERFS_CHECK
543     /* compare total size of entries with item length */
544     {
545         int k, l;
546     
547         l = 0;
548         for (k = 0; k < dir_u->entry_count; k ++)
549             l += dir_u->entry_sizes[k];
550     
551         if (l + IH_SIZE != vi->vi_item_len + 
552             ((is_affected && (vn->vn_mode == M_PASTE || vn->vn_mode == M_CUT)) ? insert_size : 0) ) {
553             reiserfs_panic (NULL, "vs-8025: set_entry_sizes: (mode==%c, insert_size==%d), invalid length of directory item",
554                             vn->vn_mode, insert_size);
555         }
556     }
557 #endif
558
559     return size;
560
561
562 }
563
564
565 //
566 // return number of entries which may fit into specified amount of
567 // free space, or -1 if free space is not enough even for 1 entry
568 //
569 static int direntry_check_left (struct virtual_item * vi, int free,
570                                 int start_skip, int end_skip)
571 {
572     int i;
573     int entries = 0;
574     struct direntry_uarea * dir_u = vi->vi_uarea;
575
576     for (i = start_skip; i < dir_u->entry_count - end_skip; i ++) {
577         if (dir_u->entry_sizes[i] > free)
578             /* i-th entry doesn't fit into the remaining free space */
579             break;
580                   
581         free -= dir_u->entry_sizes[i];
582         entries ++;
583     }
584
585     if (entries == dir_u->entry_count) {
586         reiserfs_panic (NULL, "free space %d, entry_count %d\n", free, dir_u->entry_count);
587     }
588
589     /* "." and ".." can not be separated from each other */
590     if (start_skip == 0 && (dir_u->flags & DIRENTRY_VI_FIRST_DIRENTRY_ITEM) && entries < 2)
591         entries = 0;
592     
593     return entries ?: -1;
594 }
595
596
597 static int direntry_check_right (struct virtual_item * vi, int free)
598 {
599     int i;
600     int entries = 0;
601     struct direntry_uarea * dir_u = vi->vi_uarea;
602     
603     for (i = dir_u->entry_count - 1; i >= 0; i --) {
604         if (dir_u->entry_sizes[i] > free)
605             /* i-th entry doesn't fit into the remaining free space */
606             break;
607         
608         free -= dir_u->entry_sizes[i];
609         entries ++;
610     }
611     if (entries == dir_u->entry_count)
612         BUG ();
613
614     /* "." and ".." can not be separated from each other */
615     if ((dir_u->flags & DIRENTRY_VI_FIRST_DIRENTRY_ITEM) && entries > dir_u->entry_count - 2)
616         entries = dir_u->entry_count - 2;
617
618     return entries ?: -1;
619 }
620
621
622 /* sum of entry sizes between from-th and to-th entries including both edges */
623 static int direntry_part_size (struct virtual_item * vi, int first, int count)
624 {
625     int i, retval;
626     int from, to;
627     struct direntry_uarea * dir_u = vi->vi_uarea;
628     
629     retval = 0;
630     if (first == 0)
631         from = 0;
632     else
633         from = dir_u->entry_count - count;
634     to = from + count - 1;
635
636     for (i = from; i <= to; i ++)
637         retval += dir_u->entry_sizes[i];
638
639     return retval;
640 }
641
642 static int direntry_unit_num (struct virtual_item * vi)
643 {
644     struct direntry_uarea * dir_u = vi->vi_uarea;
645     
646     return dir_u->entry_count;
647 }
648
649
650
651 static void direntry_print_vi (struct virtual_item * vi)
652 {
653     int i;
654     struct direntry_uarea * dir_u = vi->vi_uarea;
655
656     reiserfs_warning (NULL, "DIRENTRY, index %d, type 0x%x, %h, flags 0x%x",
657                       vi->vi_index, vi->vi_type, vi->vi_ih, dir_u->flags);
658     printk ("%d entries: ", dir_u->entry_count);
659     for (i = 0; i < dir_u->entry_count; i ++)
660         printk ("%d ", dir_u->entry_sizes[i]);
661     printk ("\n");
662 }
663
664 static struct item_operations direntry_ops = {
665         .bytes_number           = direntry_bytes_number,
666         .decrement_key          = direntry_decrement_key,
667         .is_left_mergeable      = direntry_is_left_mergeable,
668         .print_item             = direntry_print_item,
669         .check_item             = direntry_check_item,
670
671         .create_vi              = direntry_create_vi,
672         .check_left             = direntry_check_left,
673         .check_right            = direntry_check_right,
674         .part_size              = direntry_part_size,
675         .unit_num               = direntry_unit_num,
676         .print_vi               = direntry_print_vi
677 };
678
679
680 //////////////////////////////////////////////////////////////////////////////
681 // Error catching functions to catch errors caused by incorrect item types.
682 //
683 static int errcatch_bytes_number (struct item_head * ih, int block_size)
684 {
685     reiserfs_warning (NULL, "green-16001: Invalid item type observed, run fsck ASAP");
686     return 0;
687 }
688
689 static void errcatch_decrement_key (struct cpu_key * key)
690 {
691     reiserfs_warning (NULL, "green-16002: Invalid item type observed, run fsck ASAP");
692 }
693
694
695 static int errcatch_is_left_mergeable (struct reiserfs_key * key, unsigned long bsize)
696 {
697     reiserfs_warning (NULL, "green-16003: Invalid item type observed, run fsck ASAP");
698     return 0;
699 }
700
701
702 static void errcatch_print_item (struct item_head * ih, char * item)
703 {
704     reiserfs_warning (NULL, "green-16004: Invalid item type observed, run fsck ASAP");
705 }
706
707
708 static void errcatch_check_item (struct item_head * ih, char * item)
709 {
710     reiserfs_warning (NULL, "green-16005: Invalid item type observed, run fsck ASAP");
711 }
712
713 static int errcatch_create_vi (struct virtual_node * vn,
714                                struct virtual_item * vi, 
715                                int is_affected, 
716                                int insert_size)
717 {
718     reiserfs_warning (NULL, "green-16006: Invalid item type observed, run fsck ASAP");
719     return 0;   // We might return -1 here as well, but it won't help as create_virtual_node() from where
720                 // this operation is called from is of return type void.
721 }
722
723 static int errcatch_check_left (struct virtual_item * vi, int free,
724                                 int start_skip, int end_skip)
725 {
726     reiserfs_warning (NULL, "green-16007: Invalid item type observed, run fsck ASAP");
727     return -1;
728 }
729
730
731 static int errcatch_check_right (struct virtual_item * vi, int free)
732 {
733     reiserfs_warning (NULL, "green-16008: Invalid item type observed, run fsck ASAP");
734     return -1;
735 }
736
737 static int errcatch_part_size (struct virtual_item * vi, int first, int count)
738 {
739     reiserfs_warning (NULL, "green-16009: Invalid item type observed, run fsck ASAP");
740     return 0;
741 }
742
743 static int errcatch_unit_num (struct virtual_item * vi)
744 {
745     reiserfs_warning (NULL, "green-16010: Invalid item type observed, run fsck ASAP");
746     return 0;
747 }
748
749 static void errcatch_print_vi (struct virtual_item * vi)
750 {
751     reiserfs_warning (NULL, "green-16011: Invalid item type observed, run fsck ASAP");
752 }
753
754 static struct item_operations errcatch_ops = {
755     errcatch_bytes_number,
756     errcatch_decrement_key,
757     errcatch_is_left_mergeable,
758     errcatch_print_item,
759     errcatch_check_item,
760
761     errcatch_create_vi,
762     errcatch_check_left,
763     errcatch_check_right,
764     errcatch_part_size,
765     errcatch_unit_num,
766     errcatch_print_vi
767 };
768
769
770
771 //////////////////////////////////////////////////////////////////////////////
772 //
773 //
774 #if ! (TYPE_STAT_DATA == 0 && TYPE_INDIRECT == 1 && TYPE_DIRECT == 2 && TYPE_DIRENTRY == 3)
775   do not compile
776 #endif
777
778 struct item_operations * item_ops [TYPE_ANY + 1] = {
779   &stat_data_ops,
780   &indirect_ops,
781   &direct_ops,
782   &direntry_ops,
783   NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
784   &errcatch_ops         /* This is to catch errors with invalid type (15th entry for TYPE_ANY) */
785 };
786
787
788
789