revert-mm-fix-blkdev-size-calculation-in-generic_write_checks
[linux-2.6/linux-trees-mm.git] / fs / reiser4 / plugin / item / cde.c
bloba5a9cdeec1d0f818a1ec2984f1d1c4bc2eff01d8
1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */
3 /* Directory entry implementation */
5 /* DESCRIPTION:
7 This is "compound" directory item plugin implementation. This directory
8 item type is compound (as opposed to the "simple directory item" in
9 fs/reiser4/plugin/item/sde.[ch]), because it consists of several directory
10 entries.
12 The reason behind this decision is disk space efficiency: all directory
13 entries inside the same directory have identical fragment in their
14 keys. This, of course, depends on key assignment policy. In our default key
15 assignment policy, all directory entries have the same locality which is
16 equal to the object id of their directory.
18 Composing directory item out of several directory entries for the same
19 directory allows us to store said key fragment only once. That is, this is
20 some ad hoc form of key compression (stem compression) that is implemented
21 here, because general key compression is not supposed to be implemented in
22 v4.0.
24 Another decision that was made regarding all directory item plugins, is
25 that they will store entry keys unaligned. This is for that sake of disk
26 space efficiency again.
28 In should be noted, that storing keys unaligned increases CPU consumption,
29 at least on some architectures.
31 Internal on-disk structure of the compound directory item is the following:
33 HEADER cde_item_format. Here number of entries is stored.
34 ENTRY_HEADER_0 cde_unit_header. Here part of entry key and
35 ENTRY_HEADER_1 offset of entry body are stored.
36 ENTRY_HEADER_2 (basically two last parts of key)
37 ...
38 ENTRY_HEADER_N
39 ENTRY_BODY_0 directory_entry_format. Here part of stat data key and
40 ENTRY_BODY_1 NUL-terminated name are stored.
41 ENTRY_BODY_2 (part of statadta key in the
42 sence that since all SDs have
43 zero offset, this offset is not
44 stored on disk).
45 ...
46 ENTRY_BODY_N
48 When it comes to the balancing, each directory entry in compound directory
49 item is unit, that is, something that can be cut from one item and pasted
50 into another item of the same type. Handling of unit cut and paste is major
51 reason for the complexity of code below.
55 #include "../../forward.h"
56 #include "../../debug.h"
57 #include "../../dformat.h"
58 #include "../../kassign.h"
59 #include "../../key.h"
60 #include "../../coord.h"
61 #include "sde.h"
62 #include "cde.h"
63 #include "item.h"
64 #include "../node/node.h"
65 #include "../plugin.h"
66 #include "../../znode.h"
67 #include "../../carry.h"
68 #include "../../tree.h"
69 #include "../../inode.h"
71 #include <linux/fs.h> /* for struct inode */
72 #include <linux/dcache.h> /* for struct dentry */
73 #include <linux/quotaops.h>
75 #if 0
76 #define CHECKME(coord) \
77 ({ \
78 const char *message; \
79 coord_t dup; \
81 coord_dup_nocheck(&dup, (coord)); \
82 dup.unit_pos = 0; \
83 assert("nikita-2871", cde_check(&dup, &message) == 0); \
85 #else
86 #define CHECKME(coord) noop
87 #endif
89 /* return body of compound directory item at @coord */
90 static inline cde_item_format *formatted_at(const coord_t * coord)
92 assert("nikita-1282", coord != NULL);
93 return item_body_by_coord(coord);
96 /* return entry header at @coord */
97 static inline cde_unit_header *header_at(const coord_t *
98 coord /* coord of item */ ,
99 int idx /* index of unit */ )
101 assert("nikita-1283", coord != NULL);
102 return &formatted_at(coord)->entry[idx];
105 /* return number of units in compound directory item at @coord */
106 static int units(const coord_t * coord /* coord of item */ )
108 return le16_to_cpu(get_unaligned(&formatted_at(coord)->num_of_entries));
111 /* return offset of the body of @idx-th entry in @coord */
112 static unsigned int offset_of(const coord_t * coord /* coord of item */ ,
113 int idx /* index of unit */ )
115 if (idx < units(coord))
116 return le16_to_cpu(get_unaligned(&header_at(coord, idx)->offset));
117 else if (idx == units(coord))
118 return item_length_by_coord(coord);
119 else
120 impossible("nikita-1308", "Wrong idx");
121 return 0;
124 /* set offset of the body of @idx-th entry in @coord */
125 static void set_offset(const coord_t * coord /* coord of item */ ,
126 int idx /* index of unit */ ,
127 unsigned int offset /* new offset */ )
129 put_unaligned(cpu_to_le16((__u16) offset), &header_at(coord, idx)->offset);
132 static void adj_offset(const coord_t * coord /* coord of item */ ,
133 int idx /* index of unit */ ,
134 int delta /* offset change */ )
136 d16 *doffset;
137 __u16 offset;
139 doffset = &header_at(coord, idx)->offset;
140 offset = le16_to_cpu(get_unaligned(doffset));
141 offset += delta;
142 put_unaligned(cpu_to_le16((__u16) offset), doffset);
145 /* return pointer to @offset-th byte from the beginning of @coord */
146 static char *address(const coord_t * coord /* coord of item */ ,
147 int offset)
149 return ((char *)item_body_by_coord(coord)) + offset;
152 /* return pointer to the body of @idx-th entry in @coord */
153 static directory_entry_format *entry_at(const coord_t * coord /* coord of
154 * item */ ,
155 int idx /* index of unit */ )
157 return (directory_entry_format *) address(coord,
158 (int)offset_of(coord, idx));
161 /* return number of unit referenced by @coord */
162 static int idx_of(const coord_t * coord /* coord of item */ )
164 assert("nikita-1285", coord != NULL);
165 return coord->unit_pos;
168 /* find position where entry with @entry_key would be inserted into @coord */
169 static int find(const coord_t * coord /* coord of item */ ,
170 const reiser4_key * entry_key /* key to look for */ ,
171 cmp_t * last /* result of last comparison */ )
173 int entries;
175 int left;
176 int right;
178 cde_unit_header *header;
180 assert("nikita-1295", coord != NULL);
181 assert("nikita-1296", entry_key != NULL);
182 assert("nikita-1297", last != NULL);
184 entries = units(coord);
185 left = 0;
186 right = entries - 1;
187 while (right - left >= REISER4_SEQ_SEARCH_BREAK) {
188 int median;
190 median = (left + right) >> 1;
192 header = header_at(coord, median);
193 *last = de_id_key_cmp(&header->hash, entry_key);
194 switch (*last) {
195 case LESS_THAN:
196 left = median;
197 break;
198 case GREATER_THAN:
199 right = median;
200 break;
201 case EQUAL_TO:{
202 do {
203 median--;
204 header--;
205 } while (median >= 0 &&
206 de_id_key_cmp(&header->hash,
207 entry_key) == EQUAL_TO);
208 return median + 1;
212 header = header_at(coord, left);
213 for (; left < entries; ++left, ++header) {
214 prefetch(header + 1);
215 *last = de_id_key_cmp(&header->hash, entry_key);
216 if (*last != LESS_THAN)
217 break;
219 if (left < entries)
220 return left;
221 else
222 return RETERR(-ENOENT);
226 /* expand @coord as to accommodate for insertion of @no new entries starting
227 from @pos, with total bodies size @size. */
228 static int expand_item(const coord_t * coord /* coord of item */ ,
229 int pos /* unit position */ , int no /* number of new
230 * units*/ ,
231 int size /* total size of new units' data */ ,
232 unsigned int data_size /* free space already reserved
233 * in the item for insertion */ )
235 int entries;
236 cde_unit_header *header;
237 char *dent;
238 int i;
240 assert("nikita-1310", coord != NULL);
241 assert("nikita-1311", pos >= 0);
242 assert("nikita-1312", no > 0);
243 assert("nikita-1313", data_size >= no * sizeof(directory_entry_format));
244 assert("nikita-1343",
245 item_length_by_coord(coord) >=
246 (int)(size + data_size + no * sizeof *header));
248 entries = units(coord);
250 if (pos == entries)
251 dent = address(coord, size);
252 else
253 dent = (char *)entry_at(coord, pos);
254 /* place where new header will be in */
255 header = header_at(coord, pos);
256 /* free space for new entry headers */
257 memmove(header + no, header,
258 (unsigned)(address(coord, size) - (char *)header));
259 /* if adding to the end initialise first new header */
260 if (pos == entries) {
261 set_offset(coord, pos, (unsigned)size);
264 /* adjust entry pointer and size */
265 dent = dent + no * sizeof *header;
266 size += no * sizeof *header;
267 /* free space for new entries */
268 memmove(dent + data_size, dent,
269 (unsigned)(address(coord, size) - dent));
271 /* increase counter */
272 entries += no;
273 put_unaligned(cpu_to_le16((__u16) entries), &formatted_at(coord)->num_of_entries);
275 /* [ 0 ... pos ] entries were shifted by no * ( sizeof *header )
276 bytes. */
277 for (i = 0; i <= pos; ++i)
278 adj_offset(coord, i, no * sizeof *header);
279 /* [ pos + no ... +\infty ) entries were shifted by ( no *
280 sizeof *header + data_size ) bytes */
281 for (i = pos + no; i < entries; ++i)
282 adj_offset(coord, i, no * sizeof *header + data_size);
283 return 0;
286 /* insert new @entry into item */
287 static int expand(const coord_t * coord /* coord of item */ ,
288 struct cde_entry * entry /* entry to insert */ ,
289 int len /* length of @entry data */ ,
290 int *pos /* position to insert */ ,
291 reiser4_dir_entry_desc * dir_entry /* parameters for new
292 * entry */ )
294 cmp_t cmp_res;
295 int datasize;
297 *pos = find(coord, &dir_entry->key, &cmp_res);
298 if (*pos < 0)
299 *pos = units(coord);
301 datasize = sizeof(directory_entry_format);
302 if (is_longname(entry->name->name, entry->name->len))
303 datasize += entry->name->len + 1;
305 expand_item(coord, *pos, 1, item_length_by_coord(coord) - len,
306 datasize);
307 return 0;
310 /* paste body of @entry into item */
311 static int paste_entry(const coord_t * coord /* coord of item */ ,
312 struct cde_entry * entry /* new entry */ ,
313 int pos /* position to insert */ ,
314 reiser4_dir_entry_desc * dir_entry /* parameters for
315 * new entry */ )
317 cde_unit_header *header;
318 directory_entry_format *dent;
319 const char *name;
320 int len;
322 header = header_at(coord, pos);
323 dent = entry_at(coord, pos);
325 build_de_id_by_key(&dir_entry->key, &header->hash);
326 build_inode_key_id(entry->obj, &dent->id);
327 /* AUDIT unsafe strcpy() operation! It should be replaced with
328 much less CPU hungry
329 memcpy( ( char * ) dent -> name, entry -> name -> name , entry -> name -> len );
331 Also a more major thing is that there should be a way to figure out
332 amount of space in dent -> name and be able to check that we are
333 not going to overwrite more than we supposed to */
334 name = entry->name->name;
335 len = entry->name->len;
336 if (is_longname(name, len)) {
337 strcpy((unsigned char *)dent->name, name);
338 put_unaligned(0, &dent->name[len]);
340 return 0;
343 /* estimate how much space is necessary in item to insert/paste set of entries
344 described in @data. */
345 int estimate_cde(const coord_t * coord /* coord of item */ ,
346 const reiser4_item_data * data /* parameters for new item */ )
348 struct cde_entry_data *e;
349 int result;
350 int i;
352 e = (struct cde_entry_data *) data->data;
354 assert("nikita-1288", e != NULL);
355 assert("nikita-1289", e->num_of_entries >= 0);
357 if (coord == NULL)
358 /* insert */
359 result = sizeof(cde_item_format);
360 else
361 /* paste */
362 result = 0;
364 result += e->num_of_entries *
365 (sizeof(cde_unit_header) + sizeof(directory_entry_format));
366 for (i = 0; i < e->num_of_entries; ++i) {
367 const char *name;
368 int len;
370 name = e->entry[i].name->name;
371 len = e->entry[i].name->len;
372 assert("nikita-2054", strlen(name) == len);
373 if (is_longname(name, len))
374 result += len + 1;
376 ((reiser4_item_data *) data)->length = result;
377 return result;
380 /* ->nr_units() method for this item plugin. */
381 pos_in_node_t nr_units_cde(const coord_t * coord /* coord of item */ )
383 return units(coord);
386 /* ->unit_key() method for this item plugin. */
387 reiser4_key *unit_key_cde(const coord_t * coord /* coord of item */ ,
388 reiser4_key * key /* resulting key */ )
390 assert("nikita-1452", coord != NULL);
391 assert("nikita-1345", idx_of(coord) < units(coord));
392 assert("nikita-1346", key != NULL);
394 item_key_by_coord(coord, key);
395 extract_key_from_de_id(extract_dir_id_from_key(key),
396 &header_at(coord, idx_of(coord))->hash, key);
397 return key;
400 /* mergeable_cde(): implementation of ->mergeable() item method.
402 Two directory items are mergeable iff they are from the same
403 directory. That simple.
406 int mergeable_cde(const coord_t * p1 /* coord of first item */ ,
407 const coord_t * p2 /* coord of second item */ )
409 reiser4_key k1;
410 reiser4_key k2;
412 assert("nikita-1339", p1 != NULL);
413 assert("nikita-1340", p2 != NULL);
415 return
416 (item_plugin_by_coord(p1) == item_plugin_by_coord(p2)) &&
417 (extract_dir_id_from_key(item_key_by_coord(p1, &k1)) ==
418 extract_dir_id_from_key(item_key_by_coord(p2, &k2)));
422 /* ->max_key_inside() method for this item plugin. */
423 reiser4_key *max_key_inside_cde(const coord_t * coord /* coord of item */ ,
424 reiser4_key * result /* resulting key */ )
426 assert("nikita-1342", coord != NULL);
428 item_key_by_coord(coord, result);
429 set_key_ordering(result, get_key_ordering(reiser4_max_key()));
430 set_key_fulloid(result, get_key_fulloid(reiser4_max_key()));
431 set_key_offset(result, get_key_offset(reiser4_max_key()));
432 return result;
435 /* @data contains data which are to be put into tree */
436 int can_contain_key_cde(const coord_t * coord /* coord of item */ ,
437 const reiser4_key * key /* key to check */ ,
438 const reiser4_item_data * data /* parameters of new
439 * item/unit being
440 * created */ )
442 reiser4_key item_key;
444 /* FIXME-VS: do not rely on anything but iplug field of @data. Only
445 data->iplug is initialized */
446 assert("vs-457", data && data->iplug);
447 /* assert( "vs-553", data -> user == 0 );*/
448 item_key_by_coord(coord, &item_key);
450 return (item_plugin_by_coord(coord) == data->iplug) &&
451 (extract_dir_id_from_key(&item_key) ==
452 extract_dir_id_from_key(key));
455 #if REISER4_DEBUG
456 /* cde_check ->check() method for compressed directory items
458 used for debugging, every item should have here the most complete
459 possible check of the consistency of the item that the inventor can
460 construct
462 int reiser4_check_cde(const coord_t * coord /* coord of item to check */,
463 const char **error /* where to store error message */)
465 int i;
466 int result;
467 char *item_start;
468 char *item_end;
469 reiser4_key key;
471 coord_t c;
473 assert("nikita-1357", coord != NULL);
474 assert("nikita-1358", error != NULL);
476 if (!ergo(coord->item_pos != 0,
477 is_dot_key(item_key_by_coord(coord, &key)))) {
478 *error = "CDE doesn't start with dot";
479 return -1;
481 item_start = item_body_by_coord(coord);
482 item_end = item_start + item_length_by_coord(coord);
484 coord_dup(&c, coord);
485 result = 0;
486 for (i = 0; i < units(coord); ++i) {
487 directory_entry_format *entry;
489 if ((char *)(header_at(coord, i) + 1) >
490 item_end - units(coord) * sizeof *entry) {
491 *error = "CDE header is out of bounds";
492 result = -1;
493 break;
495 entry = entry_at(coord, i);
496 if ((char *)entry < item_start + sizeof(cde_item_format)) {
497 *error = "CDE header is too low";
498 result = -1;
499 break;
501 if ((char *)(entry + 1) > item_end) {
502 *error = "CDE header is too high";
503 result = -1;
504 break;
508 return result;
510 #endif
512 /* ->init() method for this item plugin. */
513 int init_cde(coord_t * coord /* coord of item */ ,
514 coord_t * from UNUSED_ARG, reiser4_item_data * data /* structure used for insertion */
515 UNUSED_ARG)
517 put_unaligned(cpu_to_le16(0), &formatted_at(coord)->num_of_entries);
518 return 0;
521 /* ->lookup() method for this item plugin. */
522 lookup_result lookup_cde(const reiser4_key * key /* key to search for */ ,
523 lookup_bias bias /* search bias */ ,
524 coord_t * coord /* coord of item to lookup in */ )
526 cmp_t last_comp;
527 int pos;
529 reiser4_key utmost_key;
531 assert("nikita-1293", coord != NULL);
532 assert("nikita-1294", key != NULL);
534 CHECKME(coord);
536 if (keygt(item_key_by_coord(coord, &utmost_key), key)) {
537 coord->unit_pos = 0;
538 coord->between = BEFORE_UNIT;
539 return CBK_COORD_NOTFOUND;
541 pos = find(coord, key, &last_comp);
542 if (pos >= 0) {
543 coord->unit_pos = (int)pos;
544 switch (last_comp) {
545 case EQUAL_TO:
546 coord->between = AT_UNIT;
547 return CBK_COORD_FOUND;
548 case GREATER_THAN:
549 coord->between = BEFORE_UNIT;
550 return RETERR(-ENOENT);
551 case LESS_THAN:
552 default:
553 impossible("nikita-1298", "Broken find");
554 return RETERR(-EIO);
556 } else {
557 coord->unit_pos = units(coord) - 1;
558 coord->between = AFTER_UNIT;
559 return (bias ==
560 FIND_MAX_NOT_MORE_THAN) ? CBK_COORD_FOUND :
561 CBK_COORD_NOTFOUND;
565 /* ->paste() method for this item plugin. */
566 int paste_cde(coord_t * coord /* coord of item */ ,
567 reiser4_item_data * data /* parameters of new unit being
568 * inserted */ ,
569 carry_plugin_info * info UNUSED_ARG /* todo carry queue */ )
571 struct cde_entry_data *e;
572 int result;
573 int i;
575 CHECKME(coord);
576 e = (struct cde_entry_data *) data->data;
578 result = 0;
579 for (i = 0; i < e->num_of_entries; ++i) {
580 int pos;
581 int phantom_size;
583 phantom_size = data->length;
584 if (units(coord) == 0)
585 phantom_size -= sizeof(cde_item_format);
587 result =
588 expand(coord, e->entry + i, phantom_size, &pos, data->arg);
589 if (result != 0)
590 break;
591 result = paste_entry(coord, e->entry + i, pos, data->arg);
592 if (result != 0)
593 break;
595 CHECKME(coord);
596 return result;
599 /* amount of space occupied by all entries starting from @idx both headers and
600 bodies. */
601 static unsigned int part_size(const coord_t * coord /* coord of item */ ,
602 int idx /* index of unit */ )
604 assert("nikita-1299", coord != NULL);
605 assert("nikita-1300", idx < (int)units(coord));
607 return sizeof(cde_item_format) +
608 (idx + 1) * sizeof(cde_unit_header) + offset_of(coord,
609 idx + 1) -
610 offset_of(coord, 0);
613 /* how many but not more than @want units of @source can be merged with
614 item in @target node. If pend == append - we try to append last item
615 of @target by first units of @source. If pend == prepend - we try to
616 "prepend" first item in @target by last units of @source. @target
617 node has @free_space bytes of free space. Total size of those units
618 are returned via @size */
619 int can_shift_cde(unsigned free_space /* free space in item */ ,
620 coord_t * coord /* coord of source item */ ,
621 znode * target /* target node */ ,
622 shift_direction pend /* shift direction */ ,
623 unsigned *size /* resulting number of shifted bytes */ ,
624 unsigned want /* maximal number of bytes to shift */ )
626 int shift;
628 CHECKME(coord);
629 if (want == 0) {
630 *size = 0;
631 return 0;
634 /* pend == SHIFT_LEFT <==> shifting to the left */
635 if (pend == SHIFT_LEFT) {
636 for (shift = min((int)want - 1, units(coord)); shift >= 0;
637 --shift) {
638 *size = part_size(coord, shift);
639 if (target != NULL)
640 *size -= sizeof(cde_item_format);
641 if (*size <= free_space)
642 break;
644 shift = shift + 1;
645 } else {
646 int total_size;
648 assert("nikita-1301", pend == SHIFT_RIGHT);
650 total_size = item_length_by_coord(coord);
651 for (shift = units(coord) - want - 1; shift < units(coord) - 1;
652 ++shift) {
653 *size = total_size - part_size(coord, shift);
654 if (target == NULL)
655 *size += sizeof(cde_item_format);
656 if (*size <= free_space)
657 break;
659 shift = units(coord) - shift - 1;
661 if (shift == 0)
662 *size = 0;
663 CHECKME(coord);
664 return shift;
667 /* ->copy_units() method for this item plugin. */
668 void copy_units_cde(coord_t * target /* coord of target item */ ,
669 coord_t * source /* coord of source item */ ,
670 unsigned from /* starting unit */ ,
671 unsigned count /* how many units to copy */ ,
672 shift_direction where_is_free_space /* shift direction */ ,
673 unsigned free_space /* free space in item */ )
675 char *header_from;
676 char *header_to;
678 char *entry_from;
679 char *entry_to;
681 int pos_in_target;
682 int data_size;
683 int data_delta;
684 int i;
686 assert("nikita-1303", target != NULL);
687 assert("nikita-1304", source != NULL);
688 assert("nikita-1305", (int)from < units(source));
689 assert("nikita-1307", (int)(from + count) <= units(source));
691 if (where_is_free_space == SHIFT_LEFT) {
692 assert("nikita-1453", from == 0);
693 pos_in_target = units(target);
694 } else {
695 assert("nikita-1309", (int)(from + count) == units(source));
696 pos_in_target = 0;
697 memmove(item_body_by_coord(target),
698 (char *)item_body_by_coord(target) + free_space,
699 item_length_by_coord(target) - free_space);
702 CHECKME(target);
703 CHECKME(source);
705 /* expand @target */
706 data_size =
707 offset_of(source, (int)(from + count)) - offset_of(source,
708 (int)from);
710 if (units(target) == 0)
711 free_space -= sizeof(cde_item_format);
713 expand_item(target, pos_in_target, (int)count,
714 (int)(item_length_by_coord(target) - free_space),
715 (unsigned)data_size);
717 /* copy first @count units of @source into @target */
718 data_delta =
719 offset_of(target, pos_in_target) - offset_of(source, (int)from);
721 /* copy entries */
722 entry_from = (char *)entry_at(source, (int)from);
723 entry_to = (char *)entry_at(source, (int)(from + count));
724 memmove(entry_at(target, pos_in_target), entry_from,
725 (unsigned)(entry_to - entry_from));
727 /* copy headers */
728 header_from = (char *)header_at(source, (int)from);
729 header_to = (char *)header_at(source, (int)(from + count));
730 memmove(header_at(target, pos_in_target), header_from,
731 (unsigned)(header_to - header_from));
733 /* update offsets */
734 for (i = pos_in_target; i < (int)(pos_in_target + count); ++i)
735 adj_offset(target, i, data_delta);
736 CHECKME(target);
737 CHECKME(source);
740 /* ->cut_units() method for this item plugin. */
741 int cut_units_cde(coord_t * coord /* coord of item */ ,
742 pos_in_node_t from /* start unit pos */ ,
743 pos_in_node_t to /* stop unit pos */ ,
744 struct carry_cut_data *cdata UNUSED_ARG,
745 reiser4_key * smallest_removed, reiser4_key * new_first)
747 char *header_from;
748 char *header_to;
750 char *entry_from;
751 char *entry_to;
753 int size;
754 int entry_delta;
755 int header_delta;
756 int i;
758 unsigned count;
760 CHECKME(coord);
762 count = to - from + 1;
764 assert("nikita-1454", coord != NULL);
765 assert("nikita-1455", (int)(from + count) <= units(coord));
767 if (smallest_removed)
768 unit_key_by_coord(coord, smallest_removed);
770 if (new_first) {
771 coord_t next;
773 /* not everything is cut from item head */
774 assert("vs-1527", from == 0);
775 assert("vs-1528", to < units(coord) - 1);
777 coord_dup(&next, coord);
778 next.unit_pos++;
779 unit_key_by_coord(&next, new_first);
782 size = item_length_by_coord(coord);
783 if (count == (unsigned)units(coord)) {
784 return size;
787 header_from = (char *)header_at(coord, (int)from);
788 header_to = (char *)header_at(coord, (int)(from + count));
790 entry_from = (char *)entry_at(coord, (int)from);
791 entry_to = (char *)entry_at(coord, (int)(from + count));
793 /* move headers */
794 memmove(header_from, header_to,
795 (unsigned)(address(coord, size) - header_to));
797 header_delta = header_to - header_from;
799 entry_from -= header_delta;
800 entry_to -= header_delta;
801 size -= header_delta;
803 /* copy entries */
804 memmove(entry_from, entry_to,
805 (unsigned)(address(coord, size) - entry_to));
807 entry_delta = entry_to - entry_from;
808 size -= entry_delta;
810 /* update offsets */
812 for (i = 0; i < (int)from; ++i)
813 adj_offset(coord, i, -header_delta);
815 for (i = from; i < units(coord) - (int)count; ++i)
816 adj_offset(coord, i, -header_delta - entry_delta);
818 put_unaligned(cpu_to_le16((__u16) units(coord) - count),
819 &formatted_at(coord)->num_of_entries);
821 if (from == 0) {
822 /* entries from head was removed - move remaining to right */
823 memmove((char *)item_body_by_coord(coord) +
824 header_delta + entry_delta, item_body_by_coord(coord),
825 (unsigned)size);
826 if (REISER4_DEBUG)
827 memset(item_body_by_coord(coord), 0,
828 (unsigned)header_delta + entry_delta);
829 } else {
830 /* freed space is already at the end of item */
831 if (REISER4_DEBUG)
832 memset((char *)item_body_by_coord(coord) + size, 0,
833 (unsigned)header_delta + entry_delta);
836 return header_delta + entry_delta;
839 int kill_units_cde(coord_t * coord /* coord of item */ ,
840 pos_in_node_t from /* start unit pos */ ,
841 pos_in_node_t to /* stop unit pos */ ,
842 struct carry_kill_data *kdata UNUSED_ARG,
843 reiser4_key * smallest_removed, reiser4_key * new_first)
845 return cut_units_cde(coord, from, to, NULL, smallest_removed, new_first);
848 /* ->s.dir.extract_key() method for this item plugin. */
849 int extract_key_cde(const coord_t * coord /* coord of item */ ,
850 reiser4_key * key /* resulting key */ )
852 directory_entry_format *dent;
854 assert("nikita-1155", coord != NULL);
855 assert("nikita-1156", key != NULL);
857 dent = entry_at(coord, idx_of(coord));
858 return extract_key_from_id(&dent->id, key);
862 update_key_cde(const coord_t * coord, const reiser4_key * key,
863 lock_handle * lh UNUSED_ARG)
865 directory_entry_format *dent;
866 obj_key_id obj_id;
867 int result;
869 assert("nikita-2344", coord != NULL);
870 assert("nikita-2345", key != NULL);
872 dent = entry_at(coord, idx_of(coord));
873 result = build_obj_key_id(key, &obj_id);
874 if (result == 0) {
875 dent->id = obj_id;
876 znode_make_dirty(coord->node);
878 return 0;
881 /* ->s.dir.extract_name() method for this item plugin. */
882 char *extract_name_cde(const coord_t * coord /* coord of item */ , char *buf)
884 directory_entry_format *dent;
886 assert("nikita-1157", coord != NULL);
888 dent = entry_at(coord, idx_of(coord));
889 return extract_dent_name(coord, dent, buf);
892 static int cde_bytes(int pasting, const reiser4_item_data * data)
894 int result;
896 result = data->length;
897 if (!pasting)
898 result -= sizeof(cde_item_format);
899 return result;
902 /* ->s.dir.add_entry() method for this item plugin */
903 int add_entry_cde(struct inode *dir /* directory object */ ,
904 coord_t * coord /* coord of item */ ,
905 lock_handle * lh /* lock handle for insertion */ ,
906 const struct dentry *name /* name to insert */ ,
907 reiser4_dir_entry_desc * dir_entry /* parameters of new
908 * directory entry */ )
910 reiser4_item_data data;
911 struct cde_entry entry;
912 struct cde_entry_data edata;
913 int result;
915 assert("nikita-1656", coord->node == lh->node);
916 assert("nikita-1657", znode_is_write_locked(coord->node));
918 edata.num_of_entries = 1;
919 edata.entry = &entry;
921 entry.dir = dir;
922 entry.obj = dir_entry->obj;
923 entry.name = &name->d_name;
925 data.data = (char *)&edata;
926 data.user = 0; /* &edata is not user space */
927 data.iplug = item_plugin_by_id(COMPOUND_DIR_ID);
928 data.arg = dir_entry;
929 assert("nikita-1302", data.iplug != NULL);
931 result = is_dot_key(&dir_entry->key);
932 data.length = estimate_cde(result ? coord : NULL, &data);
934 /* NOTE-NIKITA quota plugin? */
935 if (DQUOT_ALLOC_SPACE_NODIRTY(dir, cde_bytes(result, &data)))
936 return RETERR(-EDQUOT);
938 if (result)
939 result = insert_by_coord(coord, &data, &dir_entry->key, lh, 0);
940 else
941 result = reiser4_resize_item(coord, &data, &dir_entry->key,
942 lh, 0);
943 return result;
946 /* ->s.dir.rem_entry() */
947 int rem_entry_cde(struct inode *dir /* directory of item */ ,
948 const struct qstr *name, coord_t * coord /* coord of item */ ,
949 lock_handle * lh UNUSED_ARG /* lock handle for
950 * removal */ ,
951 reiser4_dir_entry_desc * entry UNUSED_ARG /* parameters of
952 * directory entry
953 * being removed */ )
955 coord_t shadow;
956 int result;
957 int length;
958 ON_DEBUG(char buf[DE_NAME_BUF_LEN]);
960 assert("nikita-2870", strlen(name->name) == name->len);
961 assert("nikita-2869",
962 !strcmp(name->name, extract_name_cde(coord, buf)));
964 length = sizeof(directory_entry_format) + sizeof(cde_unit_header);
965 if (is_longname(name->name, name->len))
966 length += name->len + 1;
968 if (inode_get_bytes(dir) < length) {
969 warning("nikita-2628", "Dir is broke: %llu: %llu",
970 (unsigned long long)get_inode_oid(dir),
971 inode_get_bytes(dir));
973 return RETERR(-EIO);
976 /* cut_node() is supposed to take pointers to _different_
977 coords, because it will modify them without respect to
978 possible aliasing. To work around this, create temporary copy
979 of @coord.
981 coord_dup(&shadow, coord);
982 result =
983 kill_node_content(coord, &shadow, NULL, NULL, NULL, NULL, NULL, 0);
984 if (result == 0) {
985 /* NOTE-NIKITA quota plugin? */
986 DQUOT_FREE_SPACE_NODIRTY(dir, length);
988 return result;
991 /* ->s.dir.max_name_len() method for this item plugin */
992 int max_name_len_cde(const struct inode *dir /* directory */ )
994 return
995 reiser4_tree_by_inode(dir)->nplug->max_item_size() -
996 sizeof(directory_entry_format) - sizeof(cde_item_format) -
997 sizeof(cde_unit_header) - 2;
1000 /* Make Linus happy.
1001 Local variables:
1002 c-indentation-style: "K&R"
1003 mode-name: "LC"
1004 c-basic-offset: 8
1005 tab-width: 8
1006 fill-column: 120
1007 End: