item_ops.c revision 7fa94c8868edfef8cb6a201fcc9a5078b7b961da
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//
17static int sd_bytes_number (struct item_head * ih, int block_size)
18{
19  return 0;
20}
21
22static 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
29static int sd_is_left_mergeable (struct reiserfs_key * key, unsigned long bsize)
30{
31    return 0;
32}
33
34
35
36static char * print_time (time_t t)
37{
38    static char timebuf[256];
39
40    sprintf (timebuf, "%ld", t);
41    return timebuf;
42}
43
44
45static 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
63static void sd_check_item (struct item_head * ih, char * item)
64{
65    // FIXME: type something here!
66}
67
68
69static 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
80static 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
89static int sd_check_right (struct virtual_item * vi, int free)
90{
91    return -1;
92}
93
94static int sd_part_size (struct virtual_item * vi, int first, int count)
95{
96    if (count)
97	BUG ();
98    return 0;
99}
100
101static int sd_unit_num (struct virtual_item * vi)
102{
103    return vi->vi_item_len - IH_SIZE;
104}
105
106
107static 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
113static 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//
133static 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
140static 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
148static 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
155static 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
167static void direct_check_item (struct item_head * ih, char * item)
168{
169    // FIXME: type something here!
170}
171
172
173static 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
183static 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
193static int direct_check_right (struct virtual_item * vi, int free)
194{
195    return direct_check_left (vi, free, 0, 0);
196}
197
198static int direct_part_size (struct virtual_item * vi, int first, int count)
199{
200    return count;
201}
202
203
204static int direct_unit_num (struct virtual_item * vi)
205{
206    return vi->vi_item_len - IH_SIZE;
207}
208
209
210static 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
216static 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
237static 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
244static 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
253static 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
261static void start_new_sequence (__u32 * start, int * len, __u32 new)
262{
263    *start = new;
264    *len = 1;
265}
266
267
268static 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
284static 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
296static 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
319static void indirect_check_item (struct item_head * ih, char * item)
320{
321    // FIXME: type something here!
322}
323
324
325static 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
335static 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
345static 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)
353static 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
359static 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
365static 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
371static 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
392static 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
399static 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
407static 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
416static 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
454static 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 */
473static 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 */
500static 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//
569static 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
597static 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 */
623static 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
642static 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
651static 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
664static 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//
683static 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
689static 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
695static 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
702static 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
708static 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
713static 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
723static 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
731static 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
737static 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
743static 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
749static void errcatch_print_vi (struct virtual_item * vi)
750{
751    reiserfs_warning (NULL, "green-16011: Invalid item type observed, run fsck ASAP");
752}
753
754static 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#error Item types must use disk-format assigned values.
776#endif
777
778struct 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
790