/* Execute actor for each item (or unit, depending on @through_units_p), starting from @coord, right-ward, until either: - end of the tree is reached - unformatted node is met - error occurred - @actor returns 0 or less Error code, or last actor return value is returned. This is used by plugin/dir/hashe_dir.c:reiser4_find_entry() to move through sequence of entries with identical keys and alikes. */ int reiser4_iterate_tree(reiser4_tree * tree /* tree to scan */ , coord_t *coord /* coord to start from */ , lock_handle * lh /* lock handle to start with and to * update along the way */ , tree_iterate_actor_t actor /* function to call on each * item/unit */ , void *arg /* argument to pass to @actor */ , znode_lock_mode mode /* lock mode on scanned nodes */ , int through_units_p /* call @actor on each item or on * each unit */ ) { int result; assert("nikita-1143", tree != NULL); assert("nikita-1145", coord != NULL); assert("nikita-1146", lh != NULL); assert("nikita-1147", actor != NULL); result = zload(coord->node); coord_clear_iplug(coord); if (result != 0) return result; if (!coord_is_existing_unit(coord)) { zrelse(coord->node); return -ENOENT; } while ((result = actor(tree, coord, lh, arg)) > 0) { /* move further */ if ((through_units_p && coord_next_unit(coord)) || (!through_units_p && coord_next_item(coord))) { do { lock_handle couple; /* move to the next node */ init_lh(&couple); result = reiser4_get_right_neighbor(&couple, coord->node, (int)mode, GN_CAN_USE_UPPER_LEVELS); zrelse(coord->node); if (result == 0) { result = zload(couple.node); if (result != 0) { done_lh(&couple); return result; } coord_init_first_unit(coord, couple.node); done_lh(lh); move_lh(lh, &couple); } else return result; } while (node_is_empty(coord->node)); } assert("nikita-1149", coord_is_existing_unit(coord)); } zrelse(coord->node); return result; }
/** * reiser4_replace_extent - replace extent and paste 1 or 2 after it * @un_extent: coordinate of extent to be overwritten * @lh: need better comment * @key: need better comment * @exts_to_add: data prepared for insertion into tree * @replace: need better comment * @flags: need better comment * @return_insert_position: need better comment * * Overwrites one extent, pastes 1 or 2 more ones after overwritten one. If * @return_inserted_position is 1 - @un_extent and @lh are returned set to * first of newly inserted units, if it is 0 - @un_extent and @lh are returned * set to extent which was overwritten. */ int reiser4_replace_extent(struct replace_handle *h, int return_inserted_position) { int result; znode *orig_znode; /*ON_DEBUG(reiser4_extent orig_ext);*/ /* this is for debugging */ assert("vs-990", coord_is_existing_unit(h->coord)); assert("vs-1375", znode_is_write_locked(h->coord->node)); assert("vs-1426", extent_get_width(&h->overwrite) != 0); assert("vs-1427", extent_get_width(&h->new_extents[0]) != 0); assert("vs-1427", ergo(h->nr_new_extents == 2, extent_get_width(&h->new_extents[1]) != 0)); /* compose structure for paste */ init_new_extent(&h->item, &h->new_extents[0], h->nr_new_extents); coord_dup(&h->coord_after, h->coord); init_lh(&h->lh_after); copy_lh(&h->lh_after, h->lh); reiser4_tap_init(&h->watch, &h->coord_after, &h->lh_after, ZNODE_WRITE_LOCK); reiser4_tap_monitor(&h->watch); ON_DEBUG(h->orig_ext = *extent_by_coord(h->coord)); orig_znode = h->coord->node; #if REISER4_DEBUG /* make sure that key is set properly */ unit_key_by_coord(h->coord, &h->tmp); set_key_offset(&h->tmp, get_key_offset(&h->tmp) + extent_get_width(&h->overwrite) * current_blocksize); assert("vs-1080", keyeq(&h->tmp, &h->paste_key)); #endif /* set insert point after unit to be replaced */ h->coord->between = AFTER_UNIT; result = insert_into_item(h->coord, return_inserted_position ? h->lh : NULL, &h->paste_key, &h->item, h->flags); if (!result) { /* now we have to replace the unit after which new units were inserted. Its position is tracked by @watch */ reiser4_extent *ext; znode *node; node = h->coord_after.node; if (node != orig_znode) { coord_clear_iplug(&h->coord_after); result = zload(node); } if (likely(!result)) { ext = extent_by_coord(&h->coord_after); assert("vs-987", znode_is_loaded(node)); assert("vs-988", !memcmp(ext, &h->orig_ext, sizeof(*ext))); /* overwrite extent unit */ memcpy(ext, &h->overwrite, sizeof(reiser4_extent)); znode_make_dirty(node); if (node != orig_znode) zrelse(node); if (return_inserted_position == 0) { /* coord and lh are to be set to overwritten extent */ assert("vs-1662", WITH_DATA(node, !memcmp(&h->overwrite, extent_by_coord( &h->coord_after), sizeof(reiser4_extent)))); *h->coord = h->coord_after; done_lh(h->lh); copy_lh(h->lh, &h->lh_after); } else { /* h->coord and h->lh are to be set to first of inserted units */ assert("vs-1663", WITH_DATA(h->coord->node, !memcmp(&h->new_extents[0], extent_by_coord(h->coord), sizeof(reiser4_extent)))); assert("vs-1664", h->lh->node == h->coord->node); } } } reiser4_tap_done(&h->watch); return result; }