aboutsummaryrefslogtreecommitdiffstats
path: root/fs/reiserfs/lbalance.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /fs/reiserfs/lbalance.c
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'fs/reiserfs/lbalance.c')
-rw-r--r--fs/reiserfs/lbalance.c1222
1 files changed, 1222 insertions, 0 deletions
diff --git a/fs/reiserfs/lbalance.c b/fs/reiserfs/lbalance.c
new file mode 100644
index 000000000000..2406608fc5cd
--- /dev/null
+++ b/fs/reiserfs/lbalance.c
@@ -0,0 +1,1222 @@
1/*
2 * Copyright 2000 by Hans Reiser, licensing governed by reiserfs/README
3 */
4
5#include <linux/config.h>
6#include <asm/uaccess.h>
7#include <linux/string.h>
8#include <linux/time.h>
9#include <linux/reiserfs_fs.h>
10#include <linux/buffer_head.h>
11
12/* these are used in do_balance.c */
13
14/* leaf_move_items
15 leaf_shift_left
16 leaf_shift_right
17 leaf_delete_items
18 leaf_insert_into_buf
19 leaf_paste_in_buffer
20 leaf_cut_from_buffer
21 leaf_paste_entries
22 */
23
24
25/* copy copy_count entries from source directory item to dest buffer (creating new item if needed) */
26static void leaf_copy_dir_entries (struct buffer_info * dest_bi, struct buffer_head * source,
27 int last_first, int item_num, int from, int copy_count)
28{
29 struct buffer_head * dest = dest_bi->bi_bh;
30 int item_num_in_dest; /* either the number of target item,
31 or if we must create a new item,
32 the number of the item we will
33 create it next to */
34 struct item_head * ih;
35 struct reiserfs_de_head * deh;
36 int copy_records_len; /* length of all records in item to be copied */
37 char * records;
38
39 ih = B_N_PITEM_HEAD (source, item_num);
40
41 RFALSE( !is_direntry_le_ih (ih), "vs-10000: item must be directory item");
42
43 /* length of all record to be copied and first byte of the last of them */
44 deh = B_I_DEH (source, ih);
45 if (copy_count) {
46 copy_records_len = (from ? deh_location( &(deh[from - 1]) ) :
47 ih_item_len(ih)) - deh_location( &(deh[from + copy_count - 1]));
48 records = source->b_data + ih_location(ih) +
49 deh_location( &(deh[from + copy_count - 1]));
50 } else {
51 copy_records_len = 0;
52 records = NULL;
53 }
54
55 /* when copy last to first, dest buffer can contain 0 items */
56 item_num_in_dest = (last_first == LAST_TO_FIRST) ? (( B_NR_ITEMS(dest) ) ? 0 : -1) : (B_NR_ITEMS(dest) - 1);
57
58 /* if there are no items in dest or the first/last item in dest is not item of the same directory */
59 if ( (item_num_in_dest == - 1) ||
60 (last_first == FIRST_TO_LAST && le_ih_k_offset (ih) == DOT_OFFSET) ||
61 (last_first == LAST_TO_FIRST && comp_short_le_keys/*COMP_SHORT_KEYS*/ (&ih->ih_key, B_N_PKEY (dest, item_num_in_dest)))) {
62 /* create new item in dest */
63 struct item_head new_ih;
64
65 /* form item header */
66 memcpy (&new_ih.ih_key, &ih->ih_key, KEY_SIZE);
67 put_ih_version( &new_ih, KEY_FORMAT_3_5 );
68 /* calculate item len */
69 put_ih_item_len( &new_ih, DEH_SIZE * copy_count + copy_records_len );
70 put_ih_entry_count( &new_ih, 0 );
71
72 if (last_first == LAST_TO_FIRST) {
73 /* form key by the following way */
74 if (from < I_ENTRY_COUNT(ih)) {
75 set_le_ih_k_offset( &new_ih, deh_offset( &(deh[from]) ) );
76 /*memcpy (&new_ih.ih_key.k_offset, &deh[from].deh_offset, SHORT_KEY_SIZE);*/
77 } else {
78 /* no entries will be copied to this item in this function */
79 set_le_ih_k_offset (&new_ih, U32_MAX);
80 /* this item is not yet valid, but we want I_IS_DIRECTORY_ITEM to return 1 for it, so we -1 */
81 }
82 set_le_key_k_type (KEY_FORMAT_3_5, &(new_ih.ih_key), TYPE_DIRENTRY);
83 }
84
85 /* insert item into dest buffer */
86 leaf_insert_into_buf (dest_bi, (last_first == LAST_TO_FIRST) ? 0 : B_NR_ITEMS(dest), &new_ih, NULL, 0);
87 } else {
88 /* prepare space for entries */
89 leaf_paste_in_buffer (dest_bi, (last_first==FIRST_TO_LAST) ? (B_NR_ITEMS(dest) - 1) : 0, MAX_US_INT,
90 DEH_SIZE * copy_count + copy_records_len, records, 0
91 );
92 }
93
94 item_num_in_dest = (last_first == FIRST_TO_LAST) ? (B_NR_ITEMS(dest)-1) : 0;
95
96 leaf_paste_entries (dest_bi->bi_bh, item_num_in_dest,
97 (last_first == FIRST_TO_LAST) ? I_ENTRY_COUNT(B_N_PITEM_HEAD (dest, item_num_in_dest)) : 0,
98 copy_count, deh + from, records,
99 DEH_SIZE * copy_count + copy_records_len
100 );
101}
102
103
104/* Copy the first (if last_first == FIRST_TO_LAST) or last (last_first == LAST_TO_FIRST) item or
105 part of it or nothing (see the return 0 below) from SOURCE to the end
106 (if last_first) or beginning (!last_first) of the DEST */
107/* returns 1 if anything was copied, else 0 */
108static int leaf_copy_boundary_item (struct buffer_info * dest_bi, struct buffer_head * src, int last_first,
109 int bytes_or_entries)
110{
111 struct buffer_head * dest = dest_bi->bi_bh;
112 int dest_nr_item, src_nr_item; /* number of items in the source and destination buffers */
113 struct item_head * ih;
114 struct item_head * dih;
115
116 dest_nr_item = B_NR_ITEMS(dest);
117
118 if ( last_first == FIRST_TO_LAST ) {
119 /* if ( DEST is empty or first item of SOURCE and last item of DEST are the items of different objects
120 or of different types ) then there is no need to treat this item differently from the other items
121 that we copy, so we return */
122 ih = B_N_PITEM_HEAD (src, 0);
123 dih = B_N_PITEM_HEAD (dest, dest_nr_item - 1);
124 if (!dest_nr_item || (!op_is_left_mergeable (&(ih->ih_key), src->b_size)))
125 /* there is nothing to merge */
126 return 0;
127
128 RFALSE( ! ih_item_len(ih), "vs-10010: item can not have empty length");
129
130 if ( is_direntry_le_ih (ih) ) {
131 if ( bytes_or_entries == -1 )
132 /* copy all entries to dest */
133 bytes_or_entries = ih_entry_count(ih);
134 leaf_copy_dir_entries (dest_bi, src, FIRST_TO_LAST, 0, 0, bytes_or_entries);
135 return 1;
136 }
137
138 /* copy part of the body of the first item of SOURCE to the end of the body of the last item of the DEST
139 part defined by 'bytes_or_entries'; if bytes_or_entries == -1 copy whole body; don't create new item header
140 */
141 if ( bytes_or_entries == -1 )
142 bytes_or_entries = ih_item_len(ih);
143
144#ifdef CONFIG_REISERFS_CHECK
145 else {
146 if (bytes_or_entries == ih_item_len(ih) && is_indirect_le_ih(ih))
147 if (get_ih_free_space (ih))
148 reiserfs_panic (NULL, "vs-10020: leaf_copy_boundary_item: "
149 "last unformatted node must be filled entirely (%h)",
150 ih);
151 }
152#endif
153
154 /* merge first item (or its part) of src buffer with the last
155 item of dest buffer. Both are of the same file */
156 leaf_paste_in_buffer (dest_bi,
157 dest_nr_item - 1, ih_item_len(dih), bytes_or_entries, B_I_PITEM(src,ih), 0
158 );
159
160 if (is_indirect_le_ih (dih)) {
161 RFALSE( get_ih_free_space (dih),
162 "vs-10030: merge to left: last unformatted node of non-last indirect item %h must have zerto free space",
163 ih);
164 if (bytes_or_entries == ih_item_len(ih))
165 set_ih_free_space (dih, get_ih_free_space (ih));
166 }
167
168 return 1;
169 }
170
171
172 /* copy boundary item to right (last_first == LAST_TO_FIRST) */
173
174 /* ( DEST is empty or last item of SOURCE and first item of DEST
175 are the items of different object or of different types )
176 */
177 src_nr_item = B_NR_ITEMS (src);
178 ih = B_N_PITEM_HEAD (src, src_nr_item - 1);
179 dih = B_N_PITEM_HEAD (dest, 0);
180
181 if (!dest_nr_item || !op_is_left_mergeable (&(dih->ih_key), src->b_size))
182 return 0;
183
184 if ( is_direntry_le_ih (ih)) {
185 if ( bytes_or_entries == -1 )
186 /* bytes_or_entries = entries number in last item body of SOURCE */
187 bytes_or_entries = ih_entry_count(ih);
188
189 leaf_copy_dir_entries (dest_bi, src, LAST_TO_FIRST, src_nr_item - 1, ih_entry_count(ih) - bytes_or_entries, bytes_or_entries);
190 return 1;
191 }
192
193 /* copy part of the body of the last item of SOURCE to the begin of the body of the first item of the DEST;
194 part defined by 'bytes_or_entries'; if byte_or_entriess == -1 copy whole body; change first item key of the DEST;
195 don't create new item header
196 */
197
198 RFALSE( is_indirect_le_ih(ih) && get_ih_free_space (ih),
199 "vs-10040: merge to right: last unformatted node of non-last indirect item must be filled entirely (%h)",
200 ih);
201
202 if ( bytes_or_entries == -1 ) {
203 /* bytes_or_entries = length of last item body of SOURCE */
204 bytes_or_entries = ih_item_len(ih);
205
206 RFALSE( le_ih_k_offset (dih) !=
207 le_ih_k_offset (ih) + op_bytes_number (ih, src->b_size),
208 "vs-10050: items %h and %h do not match", ih, dih);
209
210 /* change first item key of the DEST */
211 set_le_ih_k_offset (dih, le_ih_k_offset (ih));
212
213 /* item becomes non-mergeable */
214 /* or mergeable if left item was */
215 set_le_ih_k_type (dih, le_ih_k_type (ih));
216 } else {
217 /* merge to right only part of item */
218 RFALSE( ih_item_len(ih) <= bytes_or_entries,
219 "vs-10060: no so much bytes %lu (needed %lu)",
220 ( unsigned long )ih_item_len(ih), ( unsigned long )bytes_or_entries);
221
222 /* change first item key of the DEST */
223 if ( is_direct_le_ih (dih) ) {
224 RFALSE( le_ih_k_offset (dih) <= (unsigned long)bytes_or_entries,
225 "vs-10070: dih %h, bytes_or_entries(%d)", dih, bytes_or_entries);
226 set_le_ih_k_offset (dih, le_ih_k_offset (dih) - bytes_or_entries);
227 } else {
228 RFALSE( le_ih_k_offset (dih) <=
229 (bytes_or_entries / UNFM_P_SIZE) * dest->b_size,
230 "vs-10080: dih %h, bytes_or_entries(%d)",
231 dih, (bytes_or_entries/UNFM_P_SIZE)*dest->b_size);
232 set_le_ih_k_offset (dih, le_ih_k_offset (dih) - ((bytes_or_entries / UNFM_P_SIZE) * dest->b_size));
233 }
234 }
235
236 leaf_paste_in_buffer (dest_bi, 0, 0, bytes_or_entries, B_I_PITEM(src,ih) + ih_item_len(ih) - bytes_or_entries, 0);
237 return 1;
238}
239
240
241/* copy cpy_mun items from buffer src to buffer dest
242 * last_first == FIRST_TO_LAST means, that we copy cpy_num items beginning from first-th item in src to tail of dest
243 * last_first == LAST_TO_FIRST means, that we copy cpy_num items beginning from first-th item in src to head of dest
244 */
245static void leaf_copy_items_entirely (struct buffer_info * dest_bi, struct buffer_head * src, int last_first,
246 int first, int cpy_num)
247{
248 struct buffer_head * dest;
249 int nr, free_space;
250 int dest_before;
251 int last_loc, last_inserted_loc, location;
252 int i, j;
253 struct block_head * blkh;
254 struct item_head * ih;
255
256 RFALSE( last_first != LAST_TO_FIRST && last_first != FIRST_TO_LAST,
257 "vs-10090: bad last_first parameter %d", last_first);
258 RFALSE( B_NR_ITEMS (src) - first < cpy_num,
259 "vs-10100: too few items in source %d, required %d from %d",
260 B_NR_ITEMS(src), cpy_num, first);
261 RFALSE( cpy_num < 0, "vs-10110: can not copy negative amount of items");
262 RFALSE( ! dest_bi, "vs-10120: can not copy negative amount of items");
263
264 dest = dest_bi->bi_bh;
265
266 RFALSE( ! dest, "vs-10130: can not copy negative amount of items");
267
268 if (cpy_num == 0)
269 return;
270
271 blkh = B_BLK_HEAD(dest);
272 nr = blkh_nr_item( blkh );
273 free_space = blkh_free_space(blkh);
274
275 /* we will insert items before 0-th or nr-th item in dest buffer. It depends of last_first parameter */
276 dest_before = (last_first == LAST_TO_FIRST) ? 0 : nr;
277
278 /* location of head of first new item */
279 ih = B_N_PITEM_HEAD (dest, dest_before);
280
281 RFALSE( blkh_free_space(blkh) < cpy_num * IH_SIZE,
282 "vs-10140: not enough free space for headers %d (needed %d)",
283 B_FREE_SPACE (dest), cpy_num * IH_SIZE);
284
285 /* prepare space for headers */
286 memmove (ih + cpy_num, ih, (nr-dest_before) * IH_SIZE);
287
288 /* copy item headers */
289 memcpy (ih, B_N_PITEM_HEAD (src, first), cpy_num * IH_SIZE);
290
291 free_space -= (IH_SIZE * cpy_num);
292 set_blkh_free_space( blkh, free_space );
293
294 /* location of unmovable item */
295 j = location = (dest_before == 0) ? dest->b_size : ih_location(ih-1);
296 for (i = dest_before; i < nr + cpy_num; i ++) {
297 location -= ih_item_len( ih + i - dest_before );
298 put_ih_location( ih + i - dest_before, location );
299 }
300
301 /* prepare space for items */
302 last_loc = ih_location( &(ih[nr+cpy_num-1-dest_before]) );
303 last_inserted_loc = ih_location( &(ih[cpy_num-1]) );
304
305 /* check free space */
306 RFALSE( free_space < j - last_inserted_loc,
307 "vs-10150: not enough free space for items %d (needed %d)",
308 free_space, j - last_inserted_loc);
309
310 memmove (dest->b_data + last_loc,
311 dest->b_data + last_loc + j - last_inserted_loc,
312 last_inserted_loc - last_loc);
313
314 /* copy items */
315 memcpy (dest->b_data + last_inserted_loc, B_N_PITEM(src,(first + cpy_num - 1)),
316 j - last_inserted_loc);
317
318 /* sizes, item number */
319 set_blkh_nr_item( blkh, nr + cpy_num );
320 set_blkh_free_space( blkh, free_space - (j - last_inserted_loc) );
321
322 do_balance_mark_leaf_dirty (dest_bi->tb, dest, 0);
323
324 if (dest_bi->bi_parent) {
325 struct disk_child *t_dc;
326 t_dc = B_N_CHILD (dest_bi->bi_parent, dest_bi->bi_position);
327 RFALSE( dc_block_number(t_dc) != dest->b_blocknr,
328 "vs-10160: block number in bh does not match to field in disk_child structure %lu and %lu",
329 ( long unsigned ) dest->b_blocknr,
330 ( long unsigned ) dc_block_number(t_dc));
331 put_dc_size( t_dc, dc_size(t_dc) + (j - last_inserted_loc + IH_SIZE * cpy_num ) );
332
333 do_balance_mark_internal_dirty (dest_bi->tb, dest_bi->bi_parent, 0);
334 }
335}
336
337
338/* This function splits the (liquid) item into two items (useful when
339 shifting part of an item into another node.) */
340static void leaf_item_bottle (struct buffer_info * dest_bi, struct buffer_head * src, int last_first,
341 int item_num, int cpy_bytes)
342{
343 struct buffer_head * dest = dest_bi->bi_bh;
344 struct item_head * ih;
345
346 RFALSE( cpy_bytes == -1, "vs-10170: bytes == - 1 means: do not split item");
347
348 if ( last_first == FIRST_TO_LAST ) {
349 /* if ( if item in position item_num in buffer SOURCE is directory item ) */
350 if (is_direntry_le_ih (ih = B_N_PITEM_HEAD(src,item_num)))
351 leaf_copy_dir_entries (dest_bi, src, FIRST_TO_LAST, item_num, 0, cpy_bytes);
352 else {
353 struct item_head n_ih;
354
355 /* copy part of the body of the item number 'item_num' of SOURCE to the end of the DEST
356 part defined by 'cpy_bytes'; create new item header; change old item_header (????);
357 n_ih = new item_header;
358 */
359 memcpy (&n_ih, ih, IH_SIZE);
360 put_ih_item_len( &n_ih, cpy_bytes );
361 if (is_indirect_le_ih (ih)) {
362 RFALSE( cpy_bytes == ih_item_len(ih) && get_ih_free_space(ih),
363 "vs-10180: when whole indirect item is bottle to left neighbor, it must have free_space==0 (not %lu)",
364 ( long unsigned ) get_ih_free_space (ih));
365 set_ih_free_space (&n_ih, 0);
366 }
367
368 RFALSE( op_is_left_mergeable (&(ih->ih_key), src->b_size),
369 "vs-10190: bad mergeability of item %h", ih);
370 n_ih.ih_version = ih->ih_version; /* JDM Endian safe, both le */
371 leaf_insert_into_buf (dest_bi, B_NR_ITEMS(dest), &n_ih, B_N_PITEM (src, item_num), 0);
372 }
373 } else {
374 /* if ( if item in position item_num in buffer SOURCE is directory item ) */
375 if (is_direntry_le_ih(ih = B_N_PITEM_HEAD (src, item_num)))
376 leaf_copy_dir_entries (dest_bi, src, LAST_TO_FIRST, item_num, I_ENTRY_COUNT(ih) - cpy_bytes, cpy_bytes);
377 else {
378 struct item_head n_ih;
379
380 /* copy part of the body of the item number 'item_num' of SOURCE to the begin of the DEST
381 part defined by 'cpy_bytes'; create new item header;
382 n_ih = new item_header;
383 */
384 memcpy (&n_ih, ih, SHORT_KEY_SIZE);
385
386 n_ih.ih_version = ih->ih_version; /* JDM Endian safe, both le */
387
388 if (is_direct_le_ih (ih)) {
389 set_le_ih_k_offset (&n_ih, le_ih_k_offset (ih) + ih_item_len(ih) - cpy_bytes);
390 set_le_ih_k_type (&n_ih, TYPE_DIRECT);
391 set_ih_free_space (&n_ih, MAX_US_INT);
392 } else {
393 /* indirect item */
394 RFALSE( !cpy_bytes && get_ih_free_space (ih),
395 "vs-10200: ih->ih_free_space must be 0 when indirect item will be appended");
396 set_le_ih_k_offset (&n_ih, le_ih_k_offset (ih) + (ih_item_len(ih) - cpy_bytes) / UNFM_P_SIZE * dest->b_size);
397 set_le_ih_k_type (&n_ih, TYPE_INDIRECT);
398 set_ih_free_space (&n_ih, get_ih_free_space (ih));
399 }
400
401 /* set item length */
402 put_ih_item_len( &n_ih, cpy_bytes );
403
404 n_ih.ih_version = ih->ih_version; /* JDM Endian safe, both le */
405
406 leaf_insert_into_buf (dest_bi, 0, &n_ih, B_N_PITEM(src,item_num) + ih_item_len(ih) - cpy_bytes, 0);
407 }
408 }
409}
410
411
412/* If cpy_bytes equals minus one than copy cpy_num whole items from SOURCE to DEST.
413 If cpy_bytes not equal to minus one than copy cpy_num-1 whole items from SOURCE to DEST.
414 From last item copy cpy_num bytes for regular item and cpy_num directory entries for
415 directory item. */
416static int leaf_copy_items (struct buffer_info * dest_bi, struct buffer_head * src, int last_first, int cpy_num,
417 int cpy_bytes)
418{
419 struct buffer_head * dest;
420 int pos, i, src_nr_item, bytes;
421
422 dest = dest_bi->bi_bh;
423 RFALSE( !dest || !src, "vs-10210: !dest || !src");
424 RFALSE( last_first != FIRST_TO_LAST && last_first != LAST_TO_FIRST,
425 "vs-10220:last_first != FIRST_TO_LAST && last_first != LAST_TO_FIRST");
426 RFALSE( B_NR_ITEMS(src) < cpy_num,
427 "vs-10230: No enough items: %d, req. %d", B_NR_ITEMS(src), cpy_num);
428 RFALSE( cpy_num < 0,"vs-10240: cpy_num < 0 (%d)", cpy_num);
429
430 if ( cpy_num == 0 )
431 return 0;
432
433 if ( last_first == FIRST_TO_LAST ) {
434 /* copy items to left */
435 pos = 0;
436 if ( cpy_num == 1 )
437 bytes = cpy_bytes;
438 else
439 bytes = -1;
440
441 /* copy the first item or it part or nothing to the end of the DEST (i = leaf_copy_boundary_item(DEST,SOURCE,0,bytes)) */
442 i = leaf_copy_boundary_item (dest_bi, src, FIRST_TO_LAST, bytes);
443 cpy_num -= i;
444 if ( cpy_num == 0 )
445 return i;
446 pos += i;
447 if ( cpy_bytes == -1 )
448 /* copy first cpy_num items starting from position 'pos' of SOURCE to end of DEST */
449 leaf_copy_items_entirely (dest_bi, src, FIRST_TO_LAST, pos, cpy_num);
450 else {
451 /* copy first cpy_num-1 items starting from position 'pos-1' of the SOURCE to the end of the DEST */
452 leaf_copy_items_entirely (dest_bi, src, FIRST_TO_LAST, pos, cpy_num-1);
453
454 /* copy part of the item which number is cpy_num+pos-1 to the end of the DEST */
455 leaf_item_bottle (dest_bi, src, FIRST_TO_LAST, cpy_num+pos-1, cpy_bytes);
456 }
457 } else {
458 /* copy items to right */
459 src_nr_item = B_NR_ITEMS (src);
460 if ( cpy_num == 1 )
461 bytes = cpy_bytes;
462 else
463 bytes = -1;
464
465 /* copy the last item or it part or nothing to the begin of the DEST (i = leaf_copy_boundary_item(DEST,SOURCE,1,bytes)); */
466 i = leaf_copy_boundary_item (dest_bi, src, LAST_TO_FIRST, bytes);
467
468 cpy_num -= i;
469 if ( cpy_num == 0 )
470 return i;
471
472 pos = src_nr_item - cpy_num - i;
473 if ( cpy_bytes == -1 ) {
474 /* starting from position 'pos' copy last cpy_num items of SOURCE to begin of DEST */
475 leaf_copy_items_entirely (dest_bi, src, LAST_TO_FIRST, pos, cpy_num);
476 } else {
477 /* copy last cpy_num-1 items starting from position 'pos+1' of the SOURCE to the begin of the DEST; */
478 leaf_copy_items_entirely (dest_bi, src, LAST_TO_FIRST, pos+1, cpy_num-1);
479
480 /* copy part of the item which number is pos to the begin of the DEST */
481 leaf_item_bottle (dest_bi, src, LAST_TO_FIRST, pos, cpy_bytes);
482 }
483 }
484 return i;
485}
486
487
488/* there are types of coping: from S[0] to L[0], from S[0] to R[0],
489 from R[0] to L[0]. for each of these we have to define parent and
490 positions of destination and source buffers */
491static void leaf_define_dest_src_infos (int shift_mode, struct tree_balance * tb, struct buffer_info * dest_bi,
492 struct buffer_info * src_bi, int * first_last,
493 struct buffer_head * Snew)
494{
495 memset (dest_bi, 0, sizeof (struct buffer_info));
496 memset (src_bi, 0, sizeof (struct buffer_info));
497
498 /* define dest, src, dest parent, dest position */
499 switch (shift_mode) {
500 case LEAF_FROM_S_TO_L: /* it is used in leaf_shift_left */
501 src_bi->tb = tb;
502 src_bi->bi_bh = PATH_PLAST_BUFFER (tb->tb_path);
503 src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, 0);
504 src_bi->bi_position = PATH_H_B_ITEM_ORDER (tb->tb_path, 0); /* src->b_item_order */
505 dest_bi->tb = tb;
506 dest_bi->bi_bh = tb->L[0];
507 dest_bi->bi_parent = tb->FL[0];
508 dest_bi->bi_position = get_left_neighbor_position (tb, 0);
509 *first_last = FIRST_TO_LAST;
510 break;
511
512 case LEAF_FROM_S_TO_R: /* it is used in leaf_shift_right */
513 src_bi->tb = tb;
514 src_bi->bi_bh = PATH_PLAST_BUFFER (tb->tb_path);
515 src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, 0);
516 src_bi->bi_position = PATH_H_B_ITEM_ORDER (tb->tb_path, 0);
517 dest_bi->tb = tb;
518 dest_bi->bi_bh = tb->R[0];
519 dest_bi->bi_parent = tb->FR[0];
520 dest_bi->bi_position = get_right_neighbor_position (tb, 0);
521 *first_last = LAST_TO_FIRST;
522 break;
523
524 case LEAF_FROM_R_TO_L: /* it is used in balance_leaf_when_delete */
525 src_bi->tb = tb;
526 src_bi->bi_bh = tb->R[0];
527 src_bi->bi_parent = tb->FR[0];
528 src_bi->bi_position = get_right_neighbor_position (tb, 0);
529 dest_bi->tb = tb;
530 dest_bi->bi_bh = tb->L[0];
531 dest_bi->bi_parent = tb->FL[0];
532 dest_bi->bi_position = get_left_neighbor_position (tb, 0);
533 *first_last = FIRST_TO_LAST;
534 break;
535
536 case LEAF_FROM_L_TO_R: /* it is used in balance_leaf_when_delete */
537 src_bi->tb = tb;
538 src_bi->bi_bh = tb->L[0];
539 src_bi->bi_parent = tb->FL[0];
540 src_bi->bi_position = get_left_neighbor_position (tb, 0);
541 dest_bi->tb = tb;
542 dest_bi->bi_bh = tb->R[0];
543 dest_bi->bi_parent = tb->FR[0];
544 dest_bi->bi_position = get_right_neighbor_position (tb, 0);
545 *first_last = LAST_TO_FIRST;
546 break;
547
548 case LEAF_FROM_S_TO_SNEW:
549 src_bi->tb = tb;
550 src_bi->bi_bh = PATH_PLAST_BUFFER (tb->tb_path);
551 src_bi->bi_parent = PATH_H_PPARENT (tb->tb_path, 0);
552 src_bi->bi_position = PATH_H_B_ITEM_ORDER (tb->tb_path, 0);
553 dest_bi->tb = tb;
554 dest_bi->bi_bh = Snew;
555 dest_bi->bi_parent = NULL;
556 dest_bi->bi_position = 0;
557 *first_last = LAST_TO_FIRST;
558 break;
559
560 default:
561 reiserfs_panic (NULL, "vs-10250: leaf_define_dest_src_infos: shift type is unknown (%d)", shift_mode);
562 }
563 RFALSE( src_bi->bi_bh == 0 || dest_bi->bi_bh == 0,
564 "vs-10260: mode==%d, source (%p) or dest (%p) buffer is initialized incorrectly",
565 shift_mode, src_bi->bi_bh, dest_bi->bi_bh);
566}
567
568
569
570
571/* copy mov_num items and mov_bytes of the (mov_num-1)th item to
572 neighbor. Delete them from source */
573int leaf_move_items (int shift_mode, struct tree_balance * tb, int mov_num, int mov_bytes, struct buffer_head * Snew)
574{
575 int ret_value;
576 struct buffer_info dest_bi, src_bi;
577 int first_last;
578
579 leaf_define_dest_src_infos (shift_mode, tb, &dest_bi, &src_bi, &first_last, Snew);
580
581 ret_value = leaf_copy_items (&dest_bi, src_bi.bi_bh, first_last, mov_num, mov_bytes);
582
583 leaf_delete_items (&src_bi, first_last, (first_last == FIRST_TO_LAST) ? 0 : (B_NR_ITEMS(src_bi.bi_bh) - mov_num), mov_num, mov_bytes);
584
585
586 return ret_value;
587}
588
589
590/* Shift shift_num items (and shift_bytes of last shifted item if shift_bytes != -1)
591 from S[0] to L[0] and replace the delimiting key */
592int leaf_shift_left (struct tree_balance * tb, int shift_num, int shift_bytes)
593{
594 struct buffer_head * S0 = PATH_PLAST_BUFFER (tb->tb_path);
595 int i;
596
597 /* move shift_num (and shift_bytes bytes) items from S[0] to left neighbor L[0] */
598 i = leaf_move_items (LEAF_FROM_S_TO_L, tb, shift_num, shift_bytes, NULL);
599
600 if ( shift_num ) {
601 if (B_NR_ITEMS (S0) == 0) { /* number of items in S[0] == 0 */
602
603 RFALSE( shift_bytes != -1,
604 "vs-10270: S0 is empty now, but shift_bytes != -1 (%d)",
605 shift_bytes);
606#ifdef CONFIG_REISERFS_CHECK
607 if (tb->tb_mode == M_PASTE || tb->tb_mode == M_INSERT) {
608 print_cur_tb ("vs-10275");
609 reiserfs_panic (tb->tb_sb, "vs-10275: leaf_shift_left: balance condition corrupted (%c)", tb->tb_mode);
610 }
611#endif
612
613 if (PATH_H_POSITION (tb->tb_path, 1) == 0)
614 replace_key (tb, tb->CFL[0], tb->lkey[0], PATH_H_PPARENT (tb->tb_path, 0), 0);
615
616 } else {
617 /* replace lkey in CFL[0] by 0-th key from S[0]; */
618 replace_key (tb, tb->CFL[0], tb->lkey[0], S0, 0);
619
620 RFALSE( (shift_bytes != -1 &&
621 !(is_direntry_le_ih (B_N_PITEM_HEAD (S0, 0))
622 && !I_ENTRY_COUNT (B_N_PITEM_HEAD (S0, 0)))) &&
623 (!op_is_left_mergeable (B_N_PKEY (S0, 0), S0->b_size)),
624 "vs-10280: item must be mergeable");
625 }
626 }
627
628 return i;
629}
630
631
632
633
634
635/* CLEANING STOPPED HERE */
636
637
638
639
640/* Shift shift_num (shift_bytes) items from S[0] to the right neighbor, and replace the delimiting key */
641int leaf_shift_right(
642 struct tree_balance * tb,
643 int shift_num,
644 int shift_bytes
645 )
646{
647 // struct buffer_head * S0 = PATH_PLAST_BUFFER (tb->tb_path);
648 int ret_value;
649
650 /* move shift_num (and shift_bytes) items from S[0] to right neighbor R[0] */
651 ret_value = leaf_move_items (LEAF_FROM_S_TO_R, tb, shift_num, shift_bytes, NULL);
652
653 /* replace rkey in CFR[0] by the 0-th key from R[0] */
654 if (shift_num) {
655 replace_key (tb, tb->CFR[0], tb->rkey[0], tb->R[0], 0);
656
657 }
658
659 return ret_value;
660}
661
662
663
664static void leaf_delete_items_entirely (struct buffer_info * bi,
665 int first, int del_num);
666/* If del_bytes == -1, starting from position 'first' delete del_num items in whole in buffer CUR.
667 If not.
668 If last_first == 0. Starting from position 'first' delete del_num-1 items in whole. Delete part of body of
669 the first item. Part defined by del_bytes. Don't delete first item header
670 If last_first == 1. Starting from position 'first+1' delete del_num-1 items in whole. Delete part of body of
671 the last item . Part defined by del_bytes. Don't delete last item header.
672*/
673void leaf_delete_items (struct buffer_info * cur_bi, int last_first,
674 int first, int del_num, int del_bytes)
675{
676 struct buffer_head * bh;
677 int item_amount = B_NR_ITEMS (bh = cur_bi->bi_bh);
678
679 RFALSE( !bh, "10155: bh is not defined");
680 RFALSE( del_num < 0, "10160: del_num can not be < 0. del_num==%d", del_num);
681 RFALSE( first < 0 || first + del_num > item_amount,
682 "10165: invalid number of first item to be deleted (%d) or "
683 "no so much items (%d) to delete (only %d)",
684 first, first + del_num, item_amount);
685
686 if ( del_num == 0 )
687 return;
688
689 if ( first == 0 && del_num == item_amount && del_bytes == -1 ) {
690 make_empty_node (cur_bi);
691 do_balance_mark_leaf_dirty (cur_bi->tb, bh, 0);
692 return;
693 }
694
695 if ( del_bytes == -1 )
696 /* delete del_num items beginning from item in position first */
697 leaf_delete_items_entirely (cur_bi, first, del_num);
698 else {
699 if ( last_first == FIRST_TO_LAST ) {
700 /* delete del_num-1 items beginning from item in position first */
701 leaf_delete_items_entirely (cur_bi, first, del_num-1);
702
703 /* delete the part of the first item of the bh
704 do not delete item header
705 */
706 leaf_cut_from_buffer (cur_bi, 0, 0, del_bytes);
707 } else {
708 struct item_head * ih;
709 int len;
710
711 /* delete del_num-1 items beginning from item in position first+1 */
712 leaf_delete_items_entirely (cur_bi, first+1, del_num-1);
713
714 if (is_direntry_le_ih (ih = B_N_PITEM_HEAD(bh, B_NR_ITEMS(bh)-1))) /* the last item is directory */
715 /* len = numbers of directory entries in this item */
716 len = ih_entry_count(ih);
717 else
718 /* len = body len of item */
719 len = ih_item_len(ih);
720
721 /* delete the part of the last item of the bh
722 do not delete item header
723 */
724 leaf_cut_from_buffer (cur_bi, B_NR_ITEMS(bh)-1, len - del_bytes, del_bytes);
725 }
726 }
727}
728
729
730/* insert item into the leaf node in position before */
731void leaf_insert_into_buf (struct buffer_info * bi, int before,
732 struct item_head * inserted_item_ih,
733 const char * inserted_item_body,
734 int zeros_number)
735{
736 struct buffer_head * bh = bi->bi_bh;
737 int nr, free_space;
738 struct block_head * blkh;
739 struct item_head * ih;
740 int i;
741 int last_loc, unmoved_loc;
742 char * to;
743
744
745 blkh = B_BLK_HEAD(bh);
746 nr = blkh_nr_item(blkh);
747 free_space = blkh_free_space( blkh );
748
749 /* check free space */
750 RFALSE( free_space < ih_item_len(inserted_item_ih) + IH_SIZE,
751 "vs-10170: not enough free space in block %z, new item %h",
752 bh, inserted_item_ih);
753 RFALSE( zeros_number > ih_item_len(inserted_item_ih),
754 "vs-10172: zero number == %d, item length == %d",
755 zeros_number, ih_item_len(inserted_item_ih));
756
757
758 /* get item new item must be inserted before */
759 ih = B_N_PITEM_HEAD (bh, before);
760
761 /* prepare space for the body of new item */
762 last_loc = nr ? ih_location( &(ih[nr - before - 1]) ) : bh->b_size;
763 unmoved_loc = before ? ih_location( ih-1 ) : bh->b_size;
764
765
766 memmove (bh->b_data + last_loc - ih_item_len(inserted_item_ih),
767 bh->b_data + last_loc, unmoved_loc - last_loc);
768
769 to = bh->b_data + unmoved_loc - ih_item_len(inserted_item_ih);
770 memset (to, 0, zeros_number);
771 to += zeros_number;
772
773 /* copy body to prepared space */
774 if (inserted_item_body)
775 memmove (to, inserted_item_body, ih_item_len(inserted_item_ih) - zeros_number);
776 else
777 memset(to, '\0', ih_item_len(inserted_item_ih) - zeros_number);
778
779 /* insert item header */
780 memmove (ih + 1, ih, IH_SIZE * (nr - before));
781 memmove (ih, inserted_item_ih, IH_SIZE);
782
783 /* change locations */
784 for (i = before; i < nr + 1; i ++)
785 {
786 unmoved_loc -= ih_item_len( &(ih[i-before]));
787 put_ih_location( &(ih[i-before]), unmoved_loc );
788 }
789
790 /* sizes, free space, item number */
791 set_blkh_nr_item( blkh, blkh_nr_item(blkh) + 1 );
792 set_blkh_free_space( blkh,
793 free_space - (IH_SIZE + ih_item_len(inserted_item_ih ) ) );
794 do_balance_mark_leaf_dirty (bi->tb, bh, 1);
795
796 if (bi->bi_parent) {
797 struct disk_child *t_dc;
798 t_dc = B_N_CHILD (bi->bi_parent, bi->bi_position);
799 put_dc_size( t_dc, dc_size(t_dc) + (IH_SIZE + ih_item_len(inserted_item_ih)));
800 do_balance_mark_internal_dirty (bi->tb, bi->bi_parent, 0);
801 }
802}
803
804
805/* paste paste_size bytes to affected_item_num-th item.
806 When item is a directory, this only prepare space for new entries */
807void leaf_paste_in_buffer (struct buffer_info * bi, int affected_item_num,
808 int pos_in_item, int paste_size,
809 const char * body,
810 int zeros_number)
811{
812 struct buffer_head * bh = bi->bi_bh;
813 int nr, free_space;
814 struct block_head * blkh;
815 struct item_head * ih;
816 int i;
817 int last_loc, unmoved_loc;
818
819 blkh = B_BLK_HEAD(bh);
820 nr = blkh_nr_item(blkh);
821 free_space = blkh_free_space(blkh);
822
823
824 /* check free space */
825 RFALSE( free_space < paste_size,
826 "vs-10175: not enough free space: needed %d, available %d",
827 paste_size, free_space);
828
829#ifdef CONFIG_REISERFS_CHECK
830 if (zeros_number > paste_size) {
831 print_cur_tb ("10177");
832 reiserfs_panic ( NULL, "vs-10177: leaf_paste_in_buffer: ero number == %d, paste_size == %d",
833 zeros_number, paste_size);
834 }
835#endif /* CONFIG_REISERFS_CHECK */
836
837
838 /* item to be appended */
839 ih = B_N_PITEM_HEAD(bh, affected_item_num);
840
841 last_loc = ih_location( &(ih[nr - affected_item_num - 1]) );
842 unmoved_loc = affected_item_num ? ih_location( ih-1 ) : bh->b_size;
843
844 /* prepare space */
845 memmove (bh->b_data + last_loc - paste_size, bh->b_data + last_loc,
846 unmoved_loc - last_loc);
847
848
849 /* change locations */
850 for (i = affected_item_num; i < nr; i ++)
851 put_ih_location( &(ih[i-affected_item_num]),
852 ih_location( &(ih[i-affected_item_num])) - paste_size );
853
854 if ( body ) {
855 if (!is_direntry_le_ih (ih)) {
856 if (!pos_in_item) {
857 /* shift data to right */
858 memmove (bh->b_data + ih_location(ih) + paste_size,
859 bh->b_data + ih_location(ih), ih_item_len(ih));
860 /* paste data in the head of item */
861 memset (bh->b_data + ih_location(ih), 0, zeros_number);
862 memcpy (bh->b_data + ih_location(ih) + zeros_number, body, paste_size - zeros_number);
863 } else {
864 memset (bh->b_data + unmoved_loc - paste_size, 0, zeros_number);
865 memcpy (bh->b_data + unmoved_loc - paste_size + zeros_number, body, paste_size - zeros_number);
866 }
867 }
868 }
869 else
870 memset(bh->b_data + unmoved_loc - paste_size, '\0', paste_size);
871
872 put_ih_item_len( ih, ih_item_len(ih) + paste_size );
873
874 /* change free space */
875 set_blkh_free_space( blkh, free_space - paste_size );
876
877 do_balance_mark_leaf_dirty (bi->tb, bh, 0);
878
879 if (bi->bi_parent) {
880 struct disk_child *t_dc = B_N_CHILD (bi->bi_parent, bi->bi_position);
881 put_dc_size( t_dc, dc_size(t_dc) + paste_size );
882 do_balance_mark_internal_dirty (bi->tb, bi->bi_parent, 0);
883 }
884}
885
886
887/* cuts DEL_COUNT entries beginning from FROM-th entry. Directory item
888 does not have free space, so it moves DEHs and remaining records as
889 necessary. Return value is size of removed part of directory item
890 in bytes. */
891static int leaf_cut_entries (
892 struct buffer_head * bh,
893 struct item_head * ih,
894 int from,
895 int del_count
896 )
897{
898 char * item;
899 struct reiserfs_de_head * deh;
900 int prev_record_offset; /* offset of record, that is (from-1)th */
901 char * prev_record; /* */
902 int cut_records_len; /* length of all removed records */
903 int i;
904
905
906 /* make sure, that item is directory and there are enough entries to
907 remove */
908 RFALSE( !is_direntry_le_ih (ih), "10180: item is not directory item");
909 RFALSE( I_ENTRY_COUNT(ih) < from + del_count,
910 "10185: item contains not enough entries: entry_cout = %d, from = %d, to delete = %d",
911 I_ENTRY_COUNT(ih), from, del_count);
912
913 if (del_count == 0)
914 return 0;
915
916 /* first byte of item */
917 item = bh->b_data + ih_location(ih);
918
919 /* entry head array */
920 deh = B_I_DEH (bh, ih);
921
922 /* first byte of remaining entries, those are BEFORE cut entries
923 (prev_record) and length of all removed records (cut_records_len) */
924 prev_record_offset = (from ? deh_location( &(deh[from - 1])) : ih_item_len(ih));
925 cut_records_len = prev_record_offset/*from_record*/ -
926 deh_location( &(deh[from + del_count - 1]));
927 prev_record = item + prev_record_offset;
928
929
930 /* adjust locations of remaining entries */
931 for (i = I_ENTRY_COUNT(ih) - 1; i > from + del_count - 1; i --)
932 put_deh_location( &(deh[i]),
933 deh_location( &deh[i] ) - (DEH_SIZE * del_count ) );
934
935 for (i = 0; i < from; i ++)
936 put_deh_location( &(deh[i]),
937 deh_location( &deh[i] ) - (DEH_SIZE * del_count + cut_records_len) );
938
939 put_ih_entry_count( ih, ih_entry_count(ih) - del_count );
940
941 /* shift entry head array and entries those are AFTER removed entries */
942 memmove ((char *)(deh + from),
943 deh + from + del_count,
944 prev_record - cut_records_len - (char *)(deh + from + del_count));
945
946 /* shift records, those are BEFORE removed entries */
947 memmove (prev_record - cut_records_len - DEH_SIZE * del_count,
948 prev_record, item + ih_item_len(ih) - prev_record);
949
950 return DEH_SIZE * del_count + cut_records_len;
951}
952
953
954/* when cut item is part of regular file
955 pos_in_item - first byte that must be cut
956 cut_size - number of bytes to be cut beginning from pos_in_item
957
958 when cut item is part of directory
959 pos_in_item - number of first deleted entry
960 cut_size - count of deleted entries
961 */
962void leaf_cut_from_buffer (struct buffer_info * bi, int cut_item_num,
963 int pos_in_item, int cut_size)
964{
965 int nr;
966 struct buffer_head * bh = bi->bi_bh;
967 struct block_head * blkh;
968 struct item_head * ih;
969 int last_loc, unmoved_loc;
970 int i;
971
972 blkh = B_BLK_HEAD(bh);
973 nr = blkh_nr_item(blkh);
974
975 /* item head of truncated item */
976 ih = B_N_PITEM_HEAD (bh, cut_item_num);
977
978 if (is_direntry_le_ih (ih)) {
979 /* first cut entry ()*/
980 cut_size = leaf_cut_entries (bh, ih, pos_in_item, cut_size);
981 if (pos_in_item == 0) {
982 /* change key */
983 RFALSE( cut_item_num,
984 "when 0-th enrty of item is cut, that item must be first in the node, not %d-th", cut_item_num);
985 /* change item key by key of first entry in the item */
986 set_le_ih_k_offset (ih, deh_offset(B_I_DEH (bh, ih)));
987 /*memcpy (&ih->ih_key.k_offset, &(B_I_DEH (bh, ih)->deh_offset), SHORT_KEY_SIZE);*/
988 }
989 } else {
990 /* item is direct or indirect */
991 RFALSE( is_statdata_le_ih (ih), "10195: item is stat data");
992 RFALSE( pos_in_item && pos_in_item + cut_size != ih_item_len(ih),
993 "10200: invalid offset (%lu) or trunc_size (%lu) or ih_item_len (%lu)",
994 ( long unsigned ) pos_in_item, ( long unsigned ) cut_size,
995 ( long unsigned ) ih_item_len (ih));
996
997 /* shift item body to left if cut is from the head of item */
998 if (pos_in_item == 0) {
999 memmove( bh->b_data + ih_location(ih),
1000 bh->b_data + ih_location(ih) + cut_size,
1001 ih_item_len(ih) - cut_size);
1002
1003 /* change key of item */
1004 if (is_direct_le_ih (ih))
1005 set_le_ih_k_offset (ih, le_ih_k_offset (ih) + cut_size);
1006 else {
1007 set_le_ih_k_offset (ih, le_ih_k_offset (ih) + (cut_size / UNFM_P_SIZE) * bh->b_size);
1008 RFALSE( ih_item_len(ih) == cut_size && get_ih_free_space (ih),
1009 "10205: invalid ih_free_space (%h)", ih);
1010 }
1011 }
1012 }
1013
1014
1015 /* location of the last item */
1016 last_loc = ih_location( &(ih[nr - cut_item_num - 1]) );
1017
1018 /* location of the item, which is remaining at the same place */
1019 unmoved_loc = cut_item_num ? ih_location(ih-1) : bh->b_size;
1020
1021
1022 /* shift */
1023 memmove (bh->b_data + last_loc + cut_size, bh->b_data + last_loc,
1024 unmoved_loc - last_loc - cut_size);
1025
1026 /* change item length */
1027 put_ih_item_len( ih, ih_item_len(ih) - cut_size );
1028
1029 if (is_indirect_le_ih (ih)) {
1030 if (pos_in_item)
1031 set_ih_free_space (ih, 0);
1032 }
1033
1034 /* change locations */
1035 for (i = cut_item_num; i < nr; i ++)
1036 put_ih_location( &(ih[i-cut_item_num]), ih_location( &ih[i-cut_item_num]) + cut_size );
1037
1038 /* size, free space */
1039 set_blkh_free_space( blkh, blkh_free_space(blkh) + cut_size );
1040
1041 do_balance_mark_leaf_dirty (bi->tb, bh, 0);
1042
1043 if (bi->bi_parent) {
1044 struct disk_child *t_dc;
1045 t_dc = B_N_CHILD (bi->bi_parent, bi->bi_position);
1046 put_dc_size( t_dc, dc_size(t_dc) - cut_size );
1047 do_balance_mark_internal_dirty (bi->tb, bi->bi_parent, 0);
1048 }
1049}
1050
1051
1052/* delete del_num items from buffer starting from the first'th item */
1053static void leaf_delete_items_entirely (struct buffer_info * bi,
1054 int first, int del_num)
1055{
1056 struct buffer_head * bh = bi->bi_bh;
1057 int nr;
1058 int i, j;
1059 int last_loc, last_removed_loc;
1060 struct block_head * blkh;
1061 struct item_head * ih;
1062
1063 RFALSE( bh == NULL, "10210: buffer is 0");
1064 RFALSE( del_num < 0, "10215: del_num less than 0 (%d)", del_num);
1065
1066 if (del_num == 0)
1067 return;
1068
1069 blkh = B_BLK_HEAD(bh);
1070 nr = blkh_nr_item(blkh);
1071
1072 RFALSE( first < 0 || first + del_num > nr,
1073 "10220: first=%d, number=%d, there is %d items", first, del_num, nr);
1074
1075 if (first == 0 && del_num == nr) {
1076 /* this does not work */
1077 make_empty_node (bi);
1078
1079 do_balance_mark_leaf_dirty (bi->tb, bh, 0);
1080 return;
1081 }
1082
1083 ih = B_N_PITEM_HEAD (bh, first);
1084
1085 /* location of unmovable item */
1086 j = (first == 0) ? bh->b_size : ih_location(ih-1);
1087
1088 /* delete items */
1089 last_loc = ih_location( &(ih[nr-1-first]) );
1090 last_removed_loc = ih_location( &(ih[del_num-1]) );
1091
1092 memmove (bh->b_data + last_loc + j - last_removed_loc,
1093 bh->b_data + last_loc, last_removed_loc - last_loc);
1094
1095 /* delete item headers */
1096 memmove (ih, ih + del_num, (nr - first - del_num) * IH_SIZE);
1097
1098 /* change item location */
1099 for (i = first; i < nr - del_num; i ++)
1100 put_ih_location( &(ih[i-first]), ih_location( &(ih[i-first]) ) + (j - last_removed_loc) );
1101
1102 /* sizes, item number */
1103 set_blkh_nr_item( blkh, blkh_nr_item(blkh) - del_num );
1104 set_blkh_free_space( blkh, blkh_free_space(blkh) + (j - last_removed_loc + IH_SIZE * del_num) );
1105
1106 do_balance_mark_leaf_dirty (bi->tb, bh, 0);
1107
1108 if (bi->bi_parent) {
1109 struct disk_child *t_dc = B_N_CHILD (bi->bi_parent, bi->bi_position);
1110 put_dc_size( t_dc, dc_size(t_dc) -
1111 (j - last_removed_loc + IH_SIZE * del_num));
1112 do_balance_mark_internal_dirty (bi->tb, bi->bi_parent, 0);
1113 }
1114}
1115
1116
1117
1118
1119
1120/* paste new_entry_count entries (new_dehs, records) into position before to item_num-th item */
1121void leaf_paste_entries (
1122 struct buffer_head * bh,
1123 int item_num,
1124 int before,
1125 int new_entry_count,
1126 struct reiserfs_de_head * new_dehs,
1127 const char * records,
1128 int paste_size
1129 )
1130{
1131 struct item_head * ih;
1132 char * item;
1133 struct reiserfs_de_head * deh;
1134 char * insert_point;
1135 int i, old_entry_num;
1136
1137 if (new_entry_count == 0)
1138 return;
1139
1140 ih = B_N_PITEM_HEAD(bh, item_num);
1141
1142 /* make sure, that item is directory, and there are enough records in it */
1143 RFALSE( !is_direntry_le_ih (ih), "10225: item is not directory item");
1144 RFALSE( I_ENTRY_COUNT (ih) < before,
1145 "10230: there are no entry we paste entries before. entry_count = %d, before = %d",
1146 I_ENTRY_COUNT (ih), before);
1147
1148
1149 /* first byte of dest item */
1150 item = bh->b_data + ih_location(ih);
1151
1152 /* entry head array */
1153 deh = B_I_DEH (bh, ih);
1154
1155 /* new records will be pasted at this point */
1156 insert_point = item + (before ? deh_location( &(deh[before - 1])) : (ih_item_len(ih) - paste_size));
1157
1158 /* adjust locations of records that will be AFTER new records */
1159 for (i = I_ENTRY_COUNT(ih) - 1; i >= before; i --)
1160 put_deh_location( &(deh[i]),
1161 deh_location(&(deh[i])) + (DEH_SIZE * new_entry_count ));
1162
1163 /* adjust locations of records that will be BEFORE new records */
1164 for (i = 0; i < before; i ++)
1165 put_deh_location( &(deh[i]), deh_location(&(deh[i])) + paste_size );
1166
1167 old_entry_num = I_ENTRY_COUNT(ih);
1168 put_ih_entry_count( ih, ih_entry_count(ih) + new_entry_count );
1169
1170 /* prepare space for pasted records */
1171 memmove (insert_point + paste_size, insert_point, item + (ih_item_len(ih) - paste_size) - insert_point);
1172
1173 /* copy new records */
1174 memcpy (insert_point + DEH_SIZE * new_entry_count, records,
1175 paste_size - DEH_SIZE * new_entry_count);
1176
1177 /* prepare space for new entry heads */
1178 deh += before;
1179 memmove ((char *)(deh + new_entry_count), deh, insert_point - (char *)deh);
1180
1181 /* copy new entry heads */
1182 deh = (struct reiserfs_de_head *)((char *)deh);
1183 memcpy (deh, new_dehs, DEH_SIZE * new_entry_count);
1184
1185 /* set locations of new records */
1186 for (i = 0; i < new_entry_count; i ++)
1187 {
1188 put_deh_location( &(deh[i]),
1189 deh_location( &(deh[i] )) +
1190 (- deh_location( &(new_dehs[new_entry_count - 1])) +
1191 insert_point + DEH_SIZE * new_entry_count - item));
1192 }
1193
1194
1195 /* change item key if necessary (when we paste before 0-th entry */
1196 if (!before)
1197 {
1198 set_le_ih_k_offset (ih, deh_offset(new_dehs));
1199/* memcpy (&ih->ih_key.k_offset,
1200 &new_dehs->deh_offset, SHORT_KEY_SIZE);*/
1201 }
1202
1203#ifdef CONFIG_REISERFS_CHECK
1204 {
1205 int prev, next;
1206 /* check record locations */
1207 deh = B_I_DEH (bh, ih);
1208 for (i = 0; i < I_ENTRY_COUNT(ih); i ++) {
1209 next = (i < I_ENTRY_COUNT(ih) - 1) ? deh_location( &(deh[i + 1])) : 0;
1210 prev = (i != 0) ? deh_location( &(deh[i - 1]) ) : 0;
1211
1212 if (prev && prev <= deh_location( &(deh[i])))
1213 reiserfs_warning (NULL, "vs-10240: leaf_paste_entries: directory item (%h) corrupted (prev %a, cur(%d) %a)",
1214 ih, deh + i - 1, i, deh + i);
1215 if (next && next >= deh_location( &(deh[i])))
1216 reiserfs_warning (NULL, "vs-10250: leaf_paste_entries: directory item (%h) corrupted (cur(%d) %a, next %a)",
1217 ih, i, deh + i, deh + i + 1);
1218 }
1219 }
1220#endif
1221
1222}