File: /usr/src/linux/fs/reiserfs/item_ops.c

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