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