1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */
5 #include "../../super.h"
6 #include "../../carry.h"
7 #include "../../inode.h"
8 #include "../../page_cache.h"
9 #include "../../flush.h"
10 #include "../object.h"
12 /* prepare structure reiser4_item_data. It is used to put one extent unit into tree */
13 /* Audited by: green(2002.06.13) */
14 reiser4_item_data
*init_new_extent(reiser4_item_data
* data
, void *ext_unit
,
17 data
->data
= ext_unit
;
18 /* data->data is kernel space */
20 data
->length
= sizeof(reiser4_extent
) * nr_extents
;
22 data
->iplug
= item_plugin_by_id(EXTENT_POINTER_ID
);
26 /* how many bytes are addressed by @nr first extents of the extent item */
27 reiser4_block_nr
reiser4_extent_size(const coord_t
* coord
, pos_in_node_t nr
)
30 reiser4_block_nr blocks
;
33 ext
= item_body_by_coord(coord
);
34 assert("vs-263", nr
<= nr_units_extent(coord
));
37 for (i
= 0; i
< nr
; i
++, ext
++) {
38 blocks
+= extent_get_width(ext
);
41 return blocks
* current_blocksize
;
44 extent_state
state_of_extent(reiser4_extent
* ext
)
46 switch ((int)extent_get_start(ext
)) {
50 return UNALLOCATED_EXTENT
;
54 return ALLOCATED_EXTENT
;
57 int extent_is_unallocated(const coord_t
* item
)
59 assert("jmacd-5133", item_is_extent(item
));
61 return state_of_extent(extent_by_coord(item
)) == UNALLOCATED_EXTENT
;
64 /* set extent's start and width */
65 void reiser4_set_extent(reiser4_extent
* ext
, reiser4_block_nr start
,
66 reiser4_block_nr width
)
68 extent_set_start(ext
, start
);
69 extent_set_width(ext
, width
);
73 * reiser4_replace_extent - replace extent and paste 1 or 2 after it
74 * @un_extent: coordinate of extent to be overwritten
75 * @lh: need better comment
76 * @key: need better comment
77 * @exts_to_add: data prepared for insertion into tree
78 * @replace: need better comment
79 * @flags: need better comment
80 * @return_insert_position: need better comment
82 * Overwrites one extent, pastes 1 or 2 more ones after overwritten one. If
83 * @return_inserted_position is 1 - @un_extent and @lh are returned set to
84 * first of newly inserted units, if it is 0 - @un_extent and @lh are returned
85 * set to extent which was overwritten.
87 int reiser4_replace_extent(struct replace_handle
*h
,
88 int return_inserted_position
)
92 /*ON_DEBUG(reiser4_extent orig_ext);*/ /* this is for debugging */
94 assert("vs-990", coord_is_existing_unit(h
->coord
));
95 assert("vs-1375", znode_is_write_locked(h
->coord
->node
));
96 assert("vs-1426", extent_get_width(&h
->overwrite
) != 0);
97 assert("vs-1427", extent_get_width(&h
->new_extents
[0]) != 0);
98 assert("vs-1427", ergo(h
->nr_new_extents
== 2,
99 extent_get_width(&h
->new_extents
[1]) != 0));
101 /* compose structure for paste */
102 init_new_extent(&h
->item
, &h
->new_extents
[0], h
->nr_new_extents
);
104 coord_dup(&h
->coord_after
, h
->coord
);
105 init_lh(&h
->lh_after
);
106 copy_lh(&h
->lh_after
, h
->lh
);
107 reiser4_tap_init(&h
->watch
, &h
->coord_after
, &h
->lh_after
, ZNODE_WRITE_LOCK
);
108 reiser4_tap_monitor(&h
->watch
);
110 ON_DEBUG(h
->orig_ext
= *extent_by_coord(h
->coord
));
111 orig_znode
= h
->coord
->node
;
114 /* make sure that key is set properly */
115 unit_key_by_coord(h
->coord
, &h
->tmp
);
116 set_key_offset(&h
->tmp
,
117 get_key_offset(&h
->tmp
) +
118 extent_get_width(&h
->overwrite
) * current_blocksize
);
119 assert("vs-1080", keyeq(&h
->tmp
, &h
->paste_key
));
122 /* set insert point after unit to be replaced */
123 h
->coord
->between
= AFTER_UNIT
;
125 result
= insert_into_item(h
->coord
, return_inserted_position
? h
->lh
: NULL
,
126 &h
->paste_key
, &h
->item
, h
->flags
);
128 /* now we have to replace the unit after which new units were
129 inserted. Its position is tracked by @watch */
133 node
= h
->coord_after
.node
;
134 if (node
!= orig_znode
) {
135 coord_clear_iplug(&h
->coord_after
);
136 result
= zload(node
);
139 if (likely(!result
)) {
140 ext
= extent_by_coord(&h
->coord_after
);
142 assert("vs-987", znode_is_loaded(node
));
143 assert("vs-988", !memcmp(ext
, &h
->orig_ext
, sizeof(*ext
)));
145 /* overwrite extent unit */
146 memcpy(ext
, &h
->overwrite
, sizeof(reiser4_extent
));
147 znode_make_dirty(node
);
149 if (node
!= orig_znode
)
152 if (return_inserted_position
== 0) {
153 /* coord and lh are to be set to overwritten
156 WITH_DATA(node
, !memcmp(&h
->overwrite
,
159 sizeof(reiser4_extent
))));
161 *h
->coord
= h
->coord_after
;
163 copy_lh(h
->lh
, &h
->lh_after
);
165 /* h->coord and h->lh are to be set to first of
168 WITH_DATA(h
->coord
->node
,
169 !memcmp(&h
->new_extents
[0],
170 extent_by_coord(h
->coord
),
171 sizeof(reiser4_extent
))));
172 assert("vs-1664", h
->lh
->node
== h
->coord
->node
);
176 reiser4_tap_done(&h
->watch
);
181 lock_handle
*znode_lh(znode
*node
)
183 assert("vs-1371", znode_is_write_locked(node
));
184 assert("vs-1372", znode_is_wlocked_once(node
));
185 return list_entry(node
->lock
.owners
.next
, lock_handle
, owners_link
);
190 * c-indentation-style: "K&R"