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