diff options
Diffstat (limited to 'fs/reiserfs/item_ops.c')
-rw-r--r-- | fs/reiserfs/item_ops.c | 788 |
1 files changed, 788 insertions, 0 deletions
diff --git a/fs/reiserfs/item_ops.c b/fs/reiserfs/item_ops.c new file mode 100644 index 000000000000..9cf7c13b120d --- /dev/null +++ b/fs/reiserfs/item_ops.c | |||
@@ -0,0 +1,788 @@ | |||
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 | __u32 * unp, prev = INT_MAX; | ||
300 | int num; | ||
301 | |||
302 | unp = (__u32 *)item; | ||
303 | |||
304 | if (ih_item_len(ih) % UNFM_P_SIZE) | ||
305 | reiserfs_warning (NULL, "indirect_print_item: invalid item len"); | ||
306 | |||
307 | printk ("%d pointers\n[ ", (int)I_UNFM_NUM (ih)); | ||
308 | for (j = 0; j < I_UNFM_NUM (ih); j ++) { | ||
309 | if (sequence_finished (prev, &num, get_block_num(unp, j))) { | ||
310 | print_sequence (prev, num); | ||
311 | start_new_sequence (&prev, &num, get_block_num(unp, j)); | ||
312 | } | ||
313 | } | ||
314 | print_sequence (prev, num); | ||
315 | printk ("]\n"); | ||
316 | } | ||
317 | |||
318 | static void indirect_check_item (struct item_head * ih, char * item) | ||
319 | { | ||
320 | // FIXME: type something here! | ||
321 | } | ||
322 | |||
323 | |||
324 | static int indirect_create_vi (struct virtual_node * vn, | ||
325 | struct virtual_item * vi, | ||
326 | int is_affected, | ||
327 | int insert_size) | ||
328 | { | ||
329 | vi->vi_index = TYPE_INDIRECT; | ||
330 | //vi->vi_type |= VI_TYPE_INDIRECT; | ||
331 | return 0; | ||
332 | } | ||
333 | |||
334 | static int indirect_check_left (struct virtual_item * vi, int free, | ||
335 | int start_skip, int end_skip) | ||
336 | { | ||
337 | int bytes; | ||
338 | |||
339 | bytes = free - free % UNFM_P_SIZE; | ||
340 | return bytes ?: -1; | ||
341 | } | ||
342 | |||
343 | |||
344 | static int indirect_check_right (struct virtual_item * vi, int free) | ||
345 | { | ||
346 | return indirect_check_left (vi, free, 0, 0); | ||
347 | } | ||
348 | |||
349 | |||
350 | |||
351 | // return size in bytes of 'units' units. If first == 0 - calculate from the head (left), otherwise - from tail (right) | ||
352 | static int indirect_part_size (struct virtual_item * vi, int first, int units) | ||
353 | { | ||
354 | // unit of indirect item is byte (yet) | ||
355 | return units; | ||
356 | } | ||
357 | |||
358 | static int indirect_unit_num (struct virtual_item * vi) | ||
359 | { | ||
360 | // unit of indirect item is byte (yet) | ||
361 | return vi->vi_item_len - IH_SIZE; | ||
362 | } | ||
363 | |||
364 | static void indirect_print_vi (struct virtual_item * vi) | ||
365 | { | ||
366 | reiserfs_warning (NULL, "INDIRECT, index %d, type 0x%x, %h", | ||
367 | vi->vi_index, vi->vi_type, vi->vi_ih); | ||
368 | } | ||
369 | |||
370 | static struct item_operations indirect_ops = { | ||
371 | .bytes_number = indirect_bytes_number, | ||
372 | .decrement_key = indirect_decrement_key, | ||
373 | .is_left_mergeable = indirect_is_left_mergeable, | ||
374 | .print_item = indirect_print_item, | ||
375 | .check_item = indirect_check_item, | ||
376 | |||
377 | .create_vi = indirect_create_vi, | ||
378 | .check_left = indirect_check_left, | ||
379 | .check_right = indirect_check_right, | ||
380 | .part_size = indirect_part_size, | ||
381 | .unit_num = indirect_unit_num, | ||
382 | .print_vi = indirect_print_vi | ||
383 | }; | ||
384 | |||
385 | |||
386 | ////////////////////////////////////////////////////////////////////////////// | ||
387 | // direntry functions | ||
388 | // | ||
389 | |||
390 | |||
391 | static int direntry_bytes_number (struct item_head * ih, int block_size) | ||
392 | { | ||
393 | reiserfs_warning (NULL, "vs-16090: direntry_bytes_number: " | ||
394 | "bytes number is asked for direntry"); | ||
395 | return 0; | ||
396 | } | ||
397 | |||
398 | static void direntry_decrement_key (struct cpu_key * key) | ||
399 | { | ||
400 | cpu_key_k_offset_dec (key); | ||
401 | if (cpu_key_k_offset (key) == 0) | ||
402 | set_cpu_key_k_type (key, TYPE_STAT_DATA); | ||
403 | } | ||
404 | |||
405 | |||
406 | static int direntry_is_left_mergeable (struct reiserfs_key * key, unsigned long bsize) | ||
407 | { | ||
408 | if (le32_to_cpu (key->u.k_offset_v1.k_offset) == DOT_OFFSET) | ||
409 | return 0; | ||
410 | return 1; | ||
411 | |||
412 | } | ||
413 | |||
414 | |||
415 | static void direntry_print_item (struct item_head * ih, char * item) | ||
416 | { | ||
417 | int i; | ||
418 | int namelen; | ||
419 | struct reiserfs_de_head * deh; | ||
420 | char * name; | ||
421 | static char namebuf [80]; | ||
422 | |||
423 | |||
424 | printk ("\n # %-15s%-30s%-15s%-15s%-15s\n", "Name", "Key of pointed object", "Hash", "Gen number", "Status"); | ||
425 | |||
426 | deh = (struct reiserfs_de_head *)item; | ||
427 | |||
428 | for (i = 0; i < I_ENTRY_COUNT (ih); i ++, deh ++) { | ||
429 | namelen = (i ? (deh_location(deh - 1)) : ih_item_len(ih)) - deh_location(deh); | ||
430 | name = item + deh_location(deh); | ||
431 | if (name[namelen-1] == 0) | ||
432 | namelen = strlen (name); | ||
433 | namebuf[0] = '"'; | ||
434 | if (namelen > sizeof (namebuf) - 3) { | ||
435 | strncpy (namebuf + 1, name, sizeof (namebuf) - 3); | ||
436 | namebuf[sizeof (namebuf) - 2] = '"'; | ||
437 | namebuf[sizeof (namebuf) - 1] = 0; | ||
438 | } else { | ||
439 | memcpy (namebuf + 1, name, namelen); | ||
440 | namebuf[namelen + 1] = '"'; | ||
441 | namebuf[namelen + 2] = 0; | ||
442 | } | ||
443 | |||
444 | printk ("%d: %-15s%-15d%-15d%-15Ld%-15Ld(%s)\n", | ||
445 | i, namebuf, | ||
446 | deh_dir_id(deh), deh_objectid(deh), | ||
447 | GET_HASH_VALUE (deh_offset (deh)), GET_GENERATION_NUMBER ((deh_offset (deh))), | ||
448 | (de_hidden (deh)) ? "HIDDEN" : "VISIBLE"); | ||
449 | } | ||
450 | } | ||
451 | |||
452 | |||
453 | static void direntry_check_item (struct item_head * ih, char * item) | ||
454 | { | ||
455 | int i; | ||
456 | struct reiserfs_de_head * deh; | ||
457 | |||
458 | // FIXME: type something here! | ||
459 | deh = (struct reiserfs_de_head *)item; | ||
460 | for (i = 0; i < I_ENTRY_COUNT (ih); i ++, deh ++) { | ||
461 | ; | ||
462 | } | ||
463 | } | ||
464 | |||
465 | |||
466 | |||
467 | #define DIRENTRY_VI_FIRST_DIRENTRY_ITEM 1 | ||
468 | |||
469 | /* | ||
470 | * function returns old entry number in directory item in real node | ||
471 | * using new entry number in virtual item in virtual node */ | ||
472 | static inline int old_entry_num (int is_affected, int virtual_entry_num, int pos_in_item, int mode) | ||
473 | { | ||
474 | if ( mode == M_INSERT || mode == M_DELETE) | ||
475 | return virtual_entry_num; | ||
476 | |||
477 | if (!is_affected) | ||
478 | /* cut or paste is applied to another item */ | ||
479 | return virtual_entry_num; | ||
480 | |||
481 | if (virtual_entry_num < pos_in_item) | ||
482 | return virtual_entry_num; | ||
483 | |||
484 | if (mode == M_CUT) | ||
485 | return virtual_entry_num + 1; | ||
486 | |||
487 | RFALSE( mode != M_PASTE || virtual_entry_num == 0, | ||
488 | "vs-8015: old_entry_num: mode must be M_PASTE (mode = \'%c\'", mode); | ||
489 | |||
490 | return virtual_entry_num - 1; | ||
491 | } | ||
492 | |||
493 | |||
494 | |||
495 | |||
496 | /* Create an array of sizes of directory entries for virtual | ||
497 | item. Return space used by an item. FIXME: no control over | ||
498 | consuming of space used by this item handler */ | ||
499 | static int direntry_create_vi (struct virtual_node * vn, | ||
500 | struct virtual_item * vi, | ||
501 | int is_affected, | ||
502 | int insert_size) | ||
503 | { | ||
504 | struct direntry_uarea * dir_u = vi->vi_uarea; | ||
505 | int i, j; | ||
506 | int size = sizeof (struct direntry_uarea); | ||
507 | struct reiserfs_de_head * deh; | ||
508 | |||
509 | vi->vi_index = TYPE_DIRENTRY; | ||
510 | |||
511 | if (!(vi->vi_ih) || !vi->vi_item) | ||
512 | BUG (); | ||
513 | |||
514 | |||
515 | dir_u->flags = 0; | ||
516 | if (le_ih_k_offset (vi->vi_ih) == DOT_OFFSET) | ||
517 | dir_u->flags |= DIRENTRY_VI_FIRST_DIRENTRY_ITEM; | ||
518 | |||
519 | deh = (struct reiserfs_de_head *)(vi->vi_item); | ||
520 | |||
521 | |||
522 | /* virtual directory item have this amount of entry after */ | ||
523 | dir_u->entry_count = ih_entry_count (vi->vi_ih) + | ||
524 | ((is_affected) ? ((vn->vn_mode == M_CUT) ? -1 : | ||
525 | (vn->vn_mode == M_PASTE ? 1 : 0)) : 0); | ||
526 | |||
527 | for (i = 0; i < dir_u->entry_count; i ++) { | ||
528 | j = old_entry_num (is_affected, i, vn->vn_pos_in_item, vn->vn_mode); | ||
529 | dir_u->entry_sizes[i] = (j ? deh_location( &(deh[j - 1]) ) : | ||
530 | ih_item_len (vi->vi_ih)) - | ||
531 | deh_location( &(deh[j])) + DEH_SIZE; | ||
532 | } | ||
533 | |||
534 | size += (dir_u->entry_count * sizeof (short)); | ||
535 | |||
536 | /* set size of pasted entry */ | ||
537 | if (is_affected && vn->vn_mode == M_PASTE) | ||
538 | dir_u->entry_sizes[vn->vn_pos_in_item] = insert_size; | ||
539 | |||
540 | |||
541 | #ifdef CONFIG_REISERFS_CHECK | ||
542 | /* compare total size of entries with item length */ | ||
543 | { | ||
544 | int k, l; | ||
545 | |||
546 | l = 0; | ||
547 | for (k = 0; k < dir_u->entry_count; k ++) | ||
548 | l += dir_u->entry_sizes[k]; | ||
549 | |||
550 | if (l + IH_SIZE != vi->vi_item_len + | ||
551 | ((is_affected && (vn->vn_mode == M_PASTE || vn->vn_mode == M_CUT)) ? insert_size : 0) ) { | ||
552 | reiserfs_panic (NULL, "vs-8025: set_entry_sizes: (mode==%c, insert_size==%d), invalid length of directory item", | ||
553 | vn->vn_mode, insert_size); | ||
554 | } | ||
555 | } | ||
556 | #endif | ||
557 | |||
558 | return size; | ||
559 | |||
560 | |||
561 | } | ||
562 | |||
563 | |||
564 | // | ||
565 | // return number of entries which may fit into specified amount of | ||
566 | // free space, or -1 if free space is not enough even for 1 entry | ||
567 | // | ||
568 | static int direntry_check_left (struct virtual_item * vi, int free, | ||
569 | int start_skip, int end_skip) | ||
570 | { | ||
571 | int i; | ||
572 | int entries = 0; | ||
573 | struct direntry_uarea * dir_u = vi->vi_uarea; | ||
574 | |||
575 | for (i = start_skip; i < dir_u->entry_count - end_skip; i ++) { | ||
576 | if (dir_u->entry_sizes[i] > free) | ||
577 | /* i-th entry doesn't fit into the remaining free space */ | ||
578 | break; | ||
579 | |||
580 | free -= dir_u->entry_sizes[i]; | ||
581 | entries ++; | ||
582 | } | ||
583 | |||
584 | if (entries == dir_u->entry_count) { | ||
585 | reiserfs_panic (NULL, "free space %d, entry_count %d\n", free, dir_u->entry_count); | ||
586 | } | ||
587 | |||
588 | /* "." and ".." can not be separated from each other */ | ||
589 | if (start_skip == 0 && (dir_u->flags & DIRENTRY_VI_FIRST_DIRENTRY_ITEM) && entries < 2) | ||
590 | entries = 0; | ||
591 | |||
592 | return entries ?: -1; | ||
593 | } | ||
594 | |||
595 | |||
596 | static int direntry_check_right (struct virtual_item * vi, int free) | ||
597 | { | ||
598 | int i; | ||
599 | int entries = 0; | ||
600 | struct direntry_uarea * dir_u = vi->vi_uarea; | ||
601 | |||
602 | for (i = dir_u->entry_count - 1; i >= 0; i --) { | ||
603 | if (dir_u->entry_sizes[i] > free) | ||
604 | /* i-th entry doesn't fit into the remaining free space */ | ||
605 | break; | ||
606 | |||
607 | free -= dir_u->entry_sizes[i]; | ||
608 | entries ++; | ||
609 | } | ||
610 | if (entries == dir_u->entry_count) | ||
611 | BUG (); | ||
612 | |||
613 | /* "." and ".." can not be separated from each other */ | ||
614 | if ((dir_u->flags & DIRENTRY_VI_FIRST_DIRENTRY_ITEM) && entries > dir_u->entry_count - 2) | ||
615 | entries = dir_u->entry_count - 2; | ||
616 | |||
617 | return entries ?: -1; | ||
618 | } | ||
619 | |||
620 | |||
621 | /* sum of entry sizes between from-th and to-th entries including both edges */ | ||
622 | static int direntry_part_size (struct virtual_item * vi, int first, int count) | ||
623 | { | ||
624 | int i, retval; | ||
625 | int from, to; | ||
626 | struct direntry_uarea * dir_u = vi->vi_uarea; | ||
627 | |||
628 | retval = 0; | ||
629 | if (first == 0) | ||
630 | from = 0; | ||
631 | else | ||
632 | from = dir_u->entry_count - count; | ||
633 | to = from + count - 1; | ||
634 | |||
635 | for (i = from; i <= to; i ++) | ||
636 | retval += dir_u->entry_sizes[i]; | ||
637 | |||
638 | return retval; | ||
639 | } | ||
640 | |||
641 | static int direntry_unit_num (struct virtual_item * vi) | ||
642 | { | ||
643 | struct direntry_uarea * dir_u = vi->vi_uarea; | ||
644 | |||
645 | return dir_u->entry_count; | ||
646 | } | ||
647 | |||
648 | |||
649 | |||
650 | static void direntry_print_vi (struct virtual_item * vi) | ||
651 | { | ||
652 | int i; | ||
653 | struct direntry_uarea * dir_u = vi->vi_uarea; | ||
654 | |||
655 | reiserfs_warning (NULL, "DIRENTRY, index %d, type 0x%x, %h, flags 0x%x", | ||
656 | vi->vi_index, vi->vi_type, vi->vi_ih, dir_u->flags); | ||
657 | printk ("%d entries: ", dir_u->entry_count); | ||
658 | for (i = 0; i < dir_u->entry_count; i ++) | ||
659 | printk ("%d ", dir_u->entry_sizes[i]); | ||
660 | printk ("\n"); | ||
661 | } | ||
662 | |||
663 | static struct item_operations direntry_ops = { | ||
664 | .bytes_number = direntry_bytes_number, | ||
665 | .decrement_key = direntry_decrement_key, | ||
666 | .is_left_mergeable = direntry_is_left_mergeable, | ||
667 | .print_item = direntry_print_item, | ||
668 | .check_item = direntry_check_item, | ||
669 | |||
670 | .create_vi = direntry_create_vi, | ||
671 | .check_left = direntry_check_left, | ||
672 | .check_right = direntry_check_right, | ||
673 | .part_size = direntry_part_size, | ||
674 | .unit_num = direntry_unit_num, | ||
675 | .print_vi = direntry_print_vi | ||
676 | }; | ||
677 | |||
678 | |||
679 | ////////////////////////////////////////////////////////////////////////////// | ||
680 | // Error catching functions to catch errors caused by incorrect item types. | ||
681 | // | ||
682 | static int errcatch_bytes_number (struct item_head * ih, int block_size) | ||
683 | { | ||
684 | reiserfs_warning (NULL, "green-16001: Invalid item type observed, run fsck ASAP"); | ||
685 | return 0; | ||
686 | } | ||
687 | |||
688 | static void errcatch_decrement_key (struct cpu_key * key) | ||
689 | { | ||
690 | reiserfs_warning (NULL, "green-16002: Invalid item type observed, run fsck ASAP"); | ||
691 | } | ||
692 | |||
693 | |||
694 | static int errcatch_is_left_mergeable (struct reiserfs_key * key, unsigned long bsize) | ||
695 | { | ||
696 | reiserfs_warning (NULL, "green-16003: Invalid item type observed, run fsck ASAP"); | ||
697 | return 0; | ||
698 | } | ||
699 | |||
700 | |||
701 | static void errcatch_print_item (struct item_head * ih, char * item) | ||
702 | { | ||
703 | reiserfs_warning (NULL, "green-16004: Invalid item type observed, run fsck ASAP"); | ||
704 | } | ||
705 | |||
706 | |||
707 | static void errcatch_check_item (struct item_head * ih, char * item) | ||
708 | { | ||
709 | reiserfs_warning (NULL, "green-16005: Invalid item type observed, run fsck ASAP"); | ||
710 | } | ||
711 | |||
712 | static int errcatch_create_vi (struct virtual_node * vn, | ||
713 | struct virtual_item * vi, | ||
714 | int is_affected, | ||
715 | int insert_size) | ||
716 | { | ||
717 | reiserfs_warning (NULL, "green-16006: Invalid item type observed, run fsck ASAP"); | ||
718 | return 0; // We might return -1 here as well, but it won't help as create_virtual_node() from where | ||
719 | // this operation is called from is of return type void. | ||
720 | } | ||
721 | |||
722 | static int errcatch_check_left (struct virtual_item * vi, int free, | ||
723 | int start_skip, int end_skip) | ||
724 | { | ||
725 | reiserfs_warning (NULL, "green-16007: Invalid item type observed, run fsck ASAP"); | ||
726 | return -1; | ||
727 | } | ||
728 | |||
729 | |||
730 | static int errcatch_check_right (struct virtual_item * vi, int free) | ||
731 | { | ||
732 | reiserfs_warning (NULL, "green-16008: Invalid item type observed, run fsck ASAP"); | ||
733 | return -1; | ||
734 | } | ||
735 | |||
736 | static int errcatch_part_size (struct virtual_item * vi, int first, int count) | ||
737 | { | ||
738 | reiserfs_warning (NULL, "green-16009: Invalid item type observed, run fsck ASAP"); | ||
739 | return 0; | ||
740 | } | ||
741 | |||
742 | static int errcatch_unit_num (struct virtual_item * vi) | ||
743 | { | ||
744 | reiserfs_warning (NULL, "green-16010: Invalid item type observed, run fsck ASAP"); | ||
745 | return 0; | ||
746 | } | ||
747 | |||
748 | static void errcatch_print_vi (struct virtual_item * vi) | ||
749 | { | ||
750 | reiserfs_warning (NULL, "green-16011: Invalid item type observed, run fsck ASAP"); | ||
751 | } | ||
752 | |||
753 | static struct item_operations errcatch_ops = { | ||
754 | errcatch_bytes_number, | ||
755 | errcatch_decrement_key, | ||
756 | errcatch_is_left_mergeable, | ||
757 | errcatch_print_item, | ||
758 | errcatch_check_item, | ||
759 | |||
760 | errcatch_create_vi, | ||
761 | errcatch_check_left, | ||
762 | errcatch_check_right, | ||
763 | errcatch_part_size, | ||
764 | errcatch_unit_num, | ||
765 | errcatch_print_vi | ||
766 | }; | ||
767 | |||
768 | |||
769 | |||
770 | ////////////////////////////////////////////////////////////////////////////// | ||
771 | // | ||
772 | // | ||
773 | #if ! (TYPE_STAT_DATA == 0 && TYPE_INDIRECT == 1 && TYPE_DIRECT == 2 && TYPE_DIRENTRY == 3) | ||
774 | do not compile | ||
775 | #endif | ||
776 | |||
777 | struct item_operations * item_ops [TYPE_ANY + 1] = { | ||
778 | &stat_data_ops, | ||
779 | &indirect_ops, | ||
780 | &direct_ops, | ||
781 | &direntry_ops, | ||
782 | NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, | ||
783 | &errcatch_ops /* This is to catch errors with invalid type (15th entry for TYPE_ANY) */ | ||
784 | }; | ||
785 | |||
786 | |||
787 | |||
788 | |||