revert-mm-fix-blkdev-size-calculation-in-generic_write_checks
[linux-2.6/linux-trees-mm.git] / fs / reiser4 / plugin / item / item.c
blobe226f045f03dfce417b0b1e3c7931a7eba4ae857
1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */
3 /* definition of item plugins. */
5 #include "../../forward.h"
6 #include "../../debug.h"
7 #include "../../key.h"
8 #include "../../coord.h"
9 #include "../plugin_header.h"
10 #include "sde.h"
11 #include "internal.h"
12 #include "item.h"
13 #include "static_stat.h"
14 #include "../plugin.h"
15 #include "../../znode.h"
16 #include "../../tree.h"
17 #include "../../context.h"
18 #include "ctail.h"
20 /* return pointer to item body */
21 void item_body_by_coord_hard(coord_t * coord /* coord to query */ )
23 assert("nikita-324", coord != NULL);
24 assert("nikita-325", coord->node != NULL);
25 assert("nikita-326", znode_is_loaded(coord->node));
26 assert("nikita-3200", coord->offset == INVALID_OFFSET);
28 coord->offset =
29 node_plugin_by_node(coord->node)->item_by_coord(coord) -
30 zdata(coord->node);
31 ON_DEBUG(coord->body_v = coord->node->times_locked);
34 void *item_body_by_coord_easy(const coord_t * coord /* coord to query */ )
36 return zdata(coord->node) + coord->offset;
39 #if REISER4_DEBUG
41 int item_body_is_valid(const coord_t * coord)
43 return
44 coord->offset ==
45 node_plugin_by_node(coord->node)->item_by_coord(coord) -
46 zdata(coord->node);
49 #endif
51 /* return length of item at @coord */
52 pos_in_node_t item_length_by_coord(const coord_t * coord /* coord to query */ )
54 int len;
56 assert("nikita-327", coord != NULL);
57 assert("nikita-328", coord->node != NULL);
58 assert("nikita-329", znode_is_loaded(coord->node));
60 len = node_plugin_by_node(coord->node)->length_by_coord(coord);
61 return len;
64 void obtain_item_plugin(const coord_t * coord)
66 assert("nikita-330", coord != NULL);
67 assert("nikita-331", coord->node != NULL);
68 assert("nikita-332", znode_is_loaded(coord->node));
70 coord_set_iplug((coord_t *) coord,
71 node_plugin_by_node(coord->node)->
72 plugin_by_coord(coord));
73 assert("nikita-2479",
74 coord_iplug(coord) ==
75 node_plugin_by_node(coord->node)->plugin_by_coord(coord));
78 /* return id of item */
79 /* Audited by: green(2002.06.15) */
80 item_id item_id_by_coord(const coord_t * coord /* coord to query */ )
82 assert("vs-539", coord != NULL);
83 assert("vs-538", coord->node != NULL);
84 assert("vs-537", znode_is_loaded(coord->node));
85 assert("vs-536", item_plugin_by_coord(coord) != NULL);
86 assert("vs-540",
87 item_id_by_plugin(item_plugin_by_coord(coord)) < LAST_ITEM_ID);
89 return item_id_by_plugin(item_plugin_by_coord(coord));
92 /* return key of item at @coord */
93 /* Audited by: green(2002.06.15) */
94 reiser4_key *item_key_by_coord(const coord_t * coord /* coord to query */ ,
95 reiser4_key * key /* result */ )
97 assert("nikita-338", coord != NULL);
98 assert("nikita-339", coord->node != NULL);
99 assert("nikita-340", znode_is_loaded(coord->node));
101 return node_plugin_by_node(coord->node)->key_at(coord, key);
104 /* this returns max key in the item */
105 reiser4_key *max_item_key_by_coord(const coord_t * coord /* coord to query */ ,
106 reiser4_key * key /* result */ )
108 coord_t last;
110 assert("nikita-338", coord != NULL);
111 assert("nikita-339", coord->node != NULL);
112 assert("nikita-340", znode_is_loaded(coord->node));
114 /* make coord pointing to last item's unit */
115 coord_dup(&last, coord);
116 last.unit_pos = coord_num_units(&last) - 1;
117 assert("vs-1560", coord_is_existing_unit(&last));
119 max_unit_key_by_coord(&last, key);
120 return key;
123 /* return key of unit at @coord */
124 reiser4_key *unit_key_by_coord(const coord_t * coord /* coord to query */ ,
125 reiser4_key * key /* result */ )
127 assert("nikita-772", coord != NULL);
128 assert("nikita-774", coord->node != NULL);
129 assert("nikita-775", znode_is_loaded(coord->node));
131 if (item_plugin_by_coord(coord)->b.unit_key != NULL)
132 return item_plugin_by_coord(coord)->b.unit_key(coord, key);
133 else
134 return item_key_by_coord(coord, key);
137 /* return the biggest key contained the unit @coord */
138 reiser4_key *max_unit_key_by_coord(const coord_t * coord /* coord to query */ ,
139 reiser4_key * key /* result */ )
141 assert("nikita-772", coord != NULL);
142 assert("nikita-774", coord->node != NULL);
143 assert("nikita-775", znode_is_loaded(coord->node));
145 if (item_plugin_by_coord(coord)->b.max_unit_key != NULL)
146 return item_plugin_by_coord(coord)->b.max_unit_key(coord, key);
147 else
148 return unit_key_by_coord(coord, key);
151 /* ->max_key_inside() method for items consisting of exactly one key (like
152 stat-data) */
153 static reiser4_key *max_key_inside_single_key(const coord_t *
154 coord /* coord of item */ ,
155 reiser4_key *
156 result /* resulting key */ )
158 assert("nikita-604", coord != NULL);
160 /* coord -> key is starting key of this item and it has to be already
161 filled in */
162 return unit_key_by_coord(coord, result);
165 /* ->nr_units() method for items consisting of exactly one unit always */
166 pos_in_node_t
167 nr_units_single_unit(const coord_t * coord UNUSED_ARG /* coord of item */ )
169 return 1;
172 static int
173 paste_no_paste(coord_t * coord UNUSED_ARG,
174 reiser4_item_data * data UNUSED_ARG,
175 carry_plugin_info * info UNUSED_ARG)
177 return 0;
180 /* default ->fast_paste() method */
181 static int
182 agree_to_fast_op(const coord_t * coord UNUSED_ARG /* coord of item */ )
184 return 1;
187 int item_can_contain_key(const coord_t * item /* coord of item */ ,
188 const reiser4_key * key /* key to check */ ,
189 const reiser4_item_data * data /* parameters of item
190 * being created */ )
192 item_plugin *iplug;
193 reiser4_key min_key_in_item;
194 reiser4_key max_key_in_item;
196 assert("nikita-1658", item != NULL);
197 assert("nikita-1659", key != NULL);
199 iplug = item_plugin_by_coord(item);
200 if (iplug->b.can_contain_key != NULL)
201 return iplug->b.can_contain_key(item, key, data);
202 else {
203 assert("nikita-1681", iplug->b.max_key_inside != NULL);
204 item_key_by_coord(item, &min_key_in_item);
205 iplug->b.max_key_inside(item, &max_key_in_item);
207 /* can contain key if
208 min_key_in_item <= key &&
209 key <= max_key_in_item
211 return keyle(&min_key_in_item, key)
212 && keyle(key, &max_key_in_item);
216 /* mergeable method for non mergeable items */
217 static int
218 not_mergeable(const coord_t * i1 UNUSED_ARG, const coord_t * i2 UNUSED_ARG)
220 return 0;
223 /* return 0 if @item1 and @item2 are not mergeable, !0 - otherwise */
224 int are_items_mergeable(const coord_t * i1 /* coord of first item */ ,
225 const coord_t * i2 /* coord of second item */ )
227 item_plugin *iplug;
228 reiser4_key k1;
229 reiser4_key k2;
231 assert("nikita-1336", i1 != NULL);
232 assert("nikita-1337", i2 != NULL);
234 iplug = item_plugin_by_coord(i1);
235 assert("nikita-1338", iplug != NULL);
237 /* NOTE-NIKITA are_items_mergeable() is also called by assertions in
238 shifting code when nodes are in "suspended" state. */
239 assert("nikita-1663",
240 keyle(item_key_by_coord(i1, &k1), item_key_by_coord(i2, &k2)));
242 if (iplug->b.mergeable != NULL) {
243 return iplug->b.mergeable(i1, i2);
244 } else if (iplug->b.max_key_inside != NULL) {
245 iplug->b.max_key_inside(i1, &k1);
246 item_key_by_coord(i2, &k2);
248 /* mergeable if ->max_key_inside() >= key of i2; */
249 return keyge(iplug->b.max_key_inside(i1, &k1),
250 item_key_by_coord(i2, &k2));
251 } else {
252 item_key_by_coord(i1, &k1);
253 item_key_by_coord(i2, &k2);
255 return
256 (get_key_locality(&k1) == get_key_locality(&k2)) &&
257 (get_key_objectid(&k1) == get_key_objectid(&k2))
258 && (iplug == item_plugin_by_coord(i2));
262 int item_is_extent(const coord_t * item)
264 assert("vs-482", coord_is_existing_item(item));
265 return item_id_by_coord(item) == EXTENT_POINTER_ID;
268 int item_is_tail(const coord_t * item)
270 assert("vs-482", coord_is_existing_item(item));
271 return item_id_by_coord(item) == FORMATTING_ID;
274 #if REISER4_DEBUG
276 int item_is_statdata(const coord_t * item)
278 assert("vs-516", coord_is_existing_item(item));
279 return plugin_of_group(item_plugin_by_coord(item), STAT_DATA_ITEM_TYPE);
282 int item_is_ctail(const coord_t * item)
284 assert("edward-xx", coord_is_existing_item(item));
285 return item_id_by_coord(item) == CTAIL_ID;
288 #endif /* REISER4_DEBUG */
290 static int change_item(struct inode *inode,
291 reiser4_plugin * plugin,
292 pset_member memb)
294 /* cannot change constituent item (sd, or dir_item) */
295 return RETERR(-EINVAL);
298 static reiser4_plugin_ops item_plugin_ops = {
299 .init = NULL,
300 .load = NULL,
301 .save_len = NULL,
302 .save = NULL,
303 .change = change_item
306 item_plugin item_plugins[LAST_ITEM_ID] = {
307 [STATIC_STAT_DATA_ID] = {
308 .h = {
309 .type_id = REISER4_ITEM_PLUGIN_TYPE,
310 .id = STATIC_STAT_DATA_ID,
311 .groups = (1 << STAT_DATA_ITEM_TYPE),
312 .pops = &item_plugin_ops,
313 .label = "sd",
314 .desc = "stat-data",
315 .linkage = {NULL, NULL}
317 .b = {
318 .max_key_inside = max_key_inside_single_key,
319 .can_contain_key = NULL,
320 .mergeable = not_mergeable,
321 .nr_units = nr_units_single_unit,
322 .lookup = NULL,
323 .init = NULL,
324 .paste = paste_no_paste,
325 .fast_paste = NULL,
326 .can_shift = NULL,
327 .copy_units = NULL,
328 .create_hook = NULL,
329 .kill_hook = NULL,
330 .shift_hook = NULL,
331 .cut_units = NULL,
332 .kill_units = NULL,
333 .unit_key = NULL,
334 .max_unit_key = NULL,
335 .estimate = NULL,
336 .item_data_by_flow = NULL,
337 #if REISER4_DEBUG
338 .check = NULL
339 #endif
341 .f = {
342 .utmost_child = NULL,
343 .utmost_child_real_block = NULL,
344 .update = NULL,
345 .scan = NULL,
346 .convert = NULL
348 .s = {
349 .sd = {
350 .init_inode = init_inode_static_sd,
351 .save_len = save_len_static_sd,
352 .save = save_static_sd
356 [SIMPLE_DIR_ENTRY_ID] = {
357 .h = {
358 .type_id = REISER4_ITEM_PLUGIN_TYPE,
359 .id = SIMPLE_DIR_ENTRY_ID,
360 .groups = (1 << DIR_ENTRY_ITEM_TYPE),
361 .pops = &item_plugin_ops,
362 .label = "de",
363 .desc = "directory entry",
364 .linkage = {NULL, NULL}
366 .b = {
367 .max_key_inside = max_key_inside_single_key,
368 .can_contain_key = NULL,
369 .mergeable = NULL,
370 .nr_units = nr_units_single_unit,
371 .lookup = NULL,
372 .init = NULL,
373 .paste = NULL,
374 .fast_paste = NULL,
375 .can_shift = NULL,
376 .copy_units = NULL,
377 .create_hook = NULL,
378 .kill_hook = NULL,
379 .shift_hook = NULL,
380 .cut_units = NULL,
381 .kill_units = NULL,
382 .unit_key = NULL,
383 .max_unit_key = NULL,
384 .estimate = NULL,
385 .item_data_by_flow = NULL,
386 #if REISER4_DEBUG
387 .check = NULL
388 #endif
390 .f = {
391 .utmost_child = NULL,
392 .utmost_child_real_block = NULL,
393 .update = NULL,
394 .scan = NULL,
395 .convert = NULL
397 .s = {
398 .dir = {
399 .extract_key = extract_key_de,
400 .update_key = update_key_de,
401 .extract_name = extract_name_de,
402 .extract_file_type = extract_file_type_de,
403 .add_entry = add_entry_de,
404 .rem_entry = rem_entry_de,
405 .max_name_len = max_name_len_de
409 [COMPOUND_DIR_ID] = {
410 .h = {
411 .type_id = REISER4_ITEM_PLUGIN_TYPE,
412 .id = COMPOUND_DIR_ID,
413 .groups = (1 << DIR_ENTRY_ITEM_TYPE),
414 .pops = &item_plugin_ops,
415 .label = "cde",
416 .desc = "compressed directory entry",
417 .linkage = {NULL, NULL}
419 .b = {
420 .max_key_inside = max_key_inside_cde,
421 .can_contain_key = can_contain_key_cde,
422 .mergeable = mergeable_cde,
423 .nr_units = nr_units_cde,
424 .lookup = lookup_cde,
425 .init = init_cde,
426 .paste = paste_cde,
427 .fast_paste = agree_to_fast_op,
428 .can_shift = can_shift_cde,
429 .copy_units = copy_units_cde,
430 .create_hook = NULL,
431 .kill_hook = NULL,
432 .shift_hook = NULL,
433 .cut_units = cut_units_cde,
434 .kill_units = kill_units_cde,
435 .unit_key = unit_key_cde,
436 .max_unit_key = unit_key_cde,
437 .estimate = estimate_cde,
438 .item_data_by_flow = NULL,
439 #if REISER4_DEBUG
440 .check = reiser4_check_cde
441 #endif
443 .f = {
444 .utmost_child = NULL,
445 .utmost_child_real_block = NULL,
446 .update = NULL,
447 .scan = NULL,
448 .convert = NULL
450 .s = {
451 .dir = {
452 .extract_key = extract_key_cde,
453 .update_key = update_key_cde,
454 .extract_name = extract_name_cde,
455 .extract_file_type = extract_file_type_de,
456 .add_entry = add_entry_cde,
457 .rem_entry = rem_entry_cde,
458 .max_name_len = max_name_len_cde
462 [NODE_POINTER_ID] = {
463 .h = {
464 .type_id = REISER4_ITEM_PLUGIN_TYPE,
465 .id = NODE_POINTER_ID,
466 .groups = (1 << INTERNAL_ITEM_TYPE),
467 .pops = NULL,
468 .label = "internal",
469 .desc = "internal item",
470 .linkage = {NULL, NULL}
472 .b = {
473 .max_key_inside = NULL,
474 .can_contain_key = NULL,
475 .mergeable = mergeable_internal,
476 .nr_units = nr_units_single_unit,
477 .lookup = lookup_internal,
478 .init = NULL,
479 .paste = NULL,
480 .fast_paste = NULL,
481 .can_shift = NULL,
482 .copy_units = NULL,
483 .create_hook = create_hook_internal,
484 .kill_hook = kill_hook_internal,
485 .shift_hook = shift_hook_internal,
486 .cut_units = NULL,
487 .kill_units = NULL,
488 .unit_key = NULL,
489 .max_unit_key = NULL,
490 .estimate = NULL,
491 .item_data_by_flow = NULL,
492 #if REISER4_DEBUG
493 .check = check__internal
494 #endif
496 .f = {
497 .utmost_child = utmost_child_internal,
498 .utmost_child_real_block =
499 utmost_child_real_block_internal,
500 .update = reiser4_update_internal,
501 .scan = NULL,
502 .convert = NULL
504 .s = {
505 .internal = {
506 .down_link = down_link_internal,
507 .has_pointer_to = has_pointer_to_internal
511 [EXTENT_POINTER_ID] = {
512 .h = {
513 .type_id = REISER4_ITEM_PLUGIN_TYPE,
514 .id = EXTENT_POINTER_ID,
515 .groups = (1 << UNIX_FILE_METADATA_ITEM_TYPE),
516 .pops = NULL,
517 .label = "extent",
518 .desc = "extent item",
519 .linkage = {NULL, NULL}
521 .b = {
522 .max_key_inside = max_key_inside_extent,
523 .can_contain_key = can_contain_key_extent,
524 .mergeable = mergeable_extent,
525 .nr_units = nr_units_extent,
526 .lookup = lookup_extent,
527 .init = NULL,
528 .paste = paste_extent,
529 .fast_paste = agree_to_fast_op,
530 .can_shift = can_shift_extent,
531 .create_hook = create_hook_extent,
532 .copy_units = copy_units_extent,
533 .kill_hook = kill_hook_extent,
534 .shift_hook = NULL,
535 .cut_units = cut_units_extent,
536 .kill_units = kill_units_extent,
537 .unit_key = unit_key_extent,
538 .max_unit_key = max_unit_key_extent,
539 .estimate = NULL,
540 .item_data_by_flow = NULL,
541 #if REISER4_DEBUG
542 .check = reiser4_check_extent
543 #endif
545 .f = {
546 .utmost_child = utmost_child_extent,
547 .utmost_child_real_block =
548 utmost_child_real_block_extent,
549 .update = NULL,
550 .scan = reiser4_scan_extent,
551 .convert = NULL,
552 .key_by_offset = key_by_offset_extent
554 .s = {
555 .file = {
556 .write = reiser4_write_extent,
557 .read = reiser4_read_extent,
558 .readpage = reiser4_readpage_extent,
559 .get_block = get_block_address_extent,
560 .append_key = append_key_extent,
561 .init_coord_extension =
562 init_coord_extension_extent
566 [FORMATTING_ID] = {
567 .h = {
568 .type_id = REISER4_ITEM_PLUGIN_TYPE,
569 .id = FORMATTING_ID,
570 .groups = (1 << UNIX_FILE_METADATA_ITEM_TYPE),
571 .pops = NULL,
572 .label = "body",
573 .desc = "body (or tail?) item",
574 .linkage = {NULL, NULL}
576 .b = {
577 .max_key_inside = max_key_inside_tail,
578 .can_contain_key = can_contain_key_tail,
579 .mergeable = mergeable_tail,
580 .nr_units = nr_units_tail,
581 .lookup = lookup_tail,
582 .init = NULL,
583 .paste = paste_tail,
584 .fast_paste = agree_to_fast_op,
585 .can_shift = can_shift_tail,
586 .create_hook = NULL,
587 .copy_units = copy_units_tail,
588 .kill_hook = kill_hook_tail,
589 .shift_hook = NULL,
590 .cut_units = cut_units_tail,
591 .kill_units = kill_units_tail,
592 .unit_key = unit_key_tail,
593 .max_unit_key = unit_key_tail,
594 .estimate = NULL,
595 .item_data_by_flow = NULL,
596 #if REISER4_DEBUG
597 .check = NULL
598 #endif
600 .f = {
601 .utmost_child = NULL,
602 .utmost_child_real_block = NULL,
603 .update = NULL,
604 .scan = NULL,
605 .convert = NULL
607 .s = {
608 .file = {
609 .write = reiser4_write_tail,
610 .read = reiser4_read_tail,
611 .readpage = readpage_tail,
612 .get_block = get_block_address_tail,
613 .append_key = append_key_tail,
614 .init_coord_extension =
615 init_coord_extension_tail
619 [CTAIL_ID] = {
620 .h = {
621 .type_id = REISER4_ITEM_PLUGIN_TYPE,
622 .id = CTAIL_ID,
623 .groups = (1 << UNIX_FILE_METADATA_ITEM_TYPE),
624 .pops = NULL,
625 .label = "ctail",
626 .desc = "cryptcompress tail item",
627 .linkage = {NULL, NULL}
629 .b = {
630 .max_key_inside = max_key_inside_tail,
631 .can_contain_key = can_contain_key_ctail,
632 .mergeable = mergeable_ctail,
633 .nr_units = nr_units_ctail,
634 .lookup = NULL,
635 .init = init_ctail,
636 .paste = paste_ctail,
637 .fast_paste = agree_to_fast_op,
638 .can_shift = can_shift_ctail,
639 .create_hook = create_hook_ctail,
640 .copy_units = copy_units_ctail,
641 .kill_hook = kill_hook_ctail,
642 .shift_hook = shift_hook_ctail,
643 .cut_units = cut_units_ctail,
644 .kill_units = kill_units_ctail,
645 .unit_key = unit_key_tail,
646 .max_unit_key = unit_key_tail,
647 .estimate = estimate_ctail,
648 .item_data_by_flow = NULL,
649 #if REISER4_DEBUG
650 .check = check_ctail
651 #endif
653 .f = {
654 .utmost_child = utmost_child_ctail,
655 /* FIXME-EDWARD: write this */
656 .utmost_child_real_block = NULL,
657 .update = NULL,
658 .scan = scan_ctail,
659 .convert = convert_ctail
661 .s = {
662 .file = {
663 .write = NULL,
664 .read = read_ctail,
665 .readpage = readpage_ctail,
666 .get_block = get_block_address_tail,
667 .append_key = append_key_ctail,
668 .init_coord_extension =
669 init_coord_extension_tail
673 [BLACK_BOX_ID] = {
674 .h = {
675 .type_id = REISER4_ITEM_PLUGIN_TYPE,
676 .id = BLACK_BOX_ID,
677 .groups = (1 << OTHER_ITEM_TYPE),
678 .pops = NULL,
679 .label = "blackbox",
680 .desc = "black box item",
681 .linkage = {NULL, NULL}
683 .b = {
684 .max_key_inside = NULL,
685 .can_contain_key = NULL,
686 .mergeable = not_mergeable,
687 .nr_units = nr_units_single_unit,
688 /* to need for ->lookup method */
689 .lookup = NULL,
690 .init = NULL,
691 .paste = NULL,
692 .fast_paste = NULL,
693 .can_shift = NULL,
694 .copy_units = NULL,
695 .create_hook = NULL,
696 .kill_hook = NULL,
697 .shift_hook = NULL,
698 .cut_units = NULL,
699 .kill_units = NULL,
700 .unit_key = NULL,
701 .max_unit_key = NULL,
702 .estimate = NULL,
703 .item_data_by_flow = NULL,
704 #if REISER4_DEBUG
705 .check = NULL
706 #endif
711 /* Make Linus happy.
712 Local variables:
713 c-indentation-style: "K&R"
714 mode-name: "LC"
715 c-basic-offset: 8
716 tab-width: 8
717 fill-column: 120
718 End: