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