1 /* Copyright 2001, 2002, 2003 by Hans Reiser, licensing governed by reiser4/README */
3 /* Directory entry implementation */
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
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
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)
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
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"
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>
76 #define CHECKME(coord) \
78 const char *message; \
81 coord_dup_nocheck(&dup, (coord)); \
83 assert("nikita-2871", cde_check(&dup, &message) == 0); \
86 #define CHECKME(coord) noop
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
);
120 impossible("nikita-1308", "Wrong idx");
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 */ )
139 doffset
= &header_at(coord
, idx
)->offset
;
140 offset
= le16_to_cpu(get_unaligned(doffset
));
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 */ ,
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
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 */ )
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
);
187 while (right
- left
>= REISER4_SEQ_SEARCH_BREAK
) {
190 median
= (left
+ right
) >> 1;
192 header
= header_at(coord
, median
);
193 *last
= de_id_key_cmp(&header
->hash
, entry_key
);
205 } while (median
>= 0 &&
206 de_id_key_cmp(&header
->hash
,
207 entry_key
) == EQUAL_TO
);
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
)
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
231 int size
/* total size of new units' data */ ,
232 unsigned int data_size
/* free space already reserved
233 * in the item for insertion */ )
236 cde_unit_header
*header
;
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
);
251 dent
= address(coord
, size
);
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 */
273 put_unaligned(cpu_to_le16((__u16
) entries
), &formatted_at(coord
)->num_of_entries
);
275 /* [ 0 ... pos ] entries were shifted by no * ( sizeof *header )
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
);
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
297 *pos
= find(coord
, &dir_entry
->key
, &cmp_res
);
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
,
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
317 cde_unit_header
*header
;
318 directory_entry_format
*dent
;
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
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
]);
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
;
352 e
= (struct cde_entry_data
*) data
->data
;
354 assert("nikita-1288", e
!= NULL
);
355 assert("nikita-1289", e
->num_of_entries
>= 0);
359 result
= sizeof(cde_item_format
);
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
) {
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
))
376 ((reiser4_item_data
*) data
)->length
= result
;
380 /* ->nr_units() method for this item plugin. */
381 pos_in_node_t
nr_units_cde(const coord_t
* coord
/* coord of item */ )
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
);
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 */ )
412 assert("nikita-1339", p1
!= NULL
);
413 assert("nikita-1340", p2
!= NULL
);
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()));
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
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
));
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
462 int reiser4_check_cde(const coord_t
* coord
/* coord of item to check */,
463 const char **error
/* where to store error message */)
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";
481 item_start
= item_body_by_coord(coord
);
482 item_end
= item_start
+ item_length_by_coord(coord
);
484 coord_dup(&c
, coord
);
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";
495 entry
= entry_at(coord
, i
);
496 if ((char *)entry
< item_start
+ sizeof(cde_item_format
)) {
497 *error
= "CDE header is too low";
501 if ((char *)(entry
+ 1) > item_end
) {
502 *error
= "CDE header is too high";
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 */
517 put_unaligned(cpu_to_le16(0), &formatted_at(coord
)->num_of_entries
);
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 */ )
529 reiser4_key utmost_key
;
531 assert("nikita-1293", coord
!= NULL
);
532 assert("nikita-1294", key
!= NULL
);
536 if (keygt(item_key_by_coord(coord
, &utmost_key
), key
)) {
538 coord
->between
= BEFORE_UNIT
;
539 return CBK_COORD_NOTFOUND
;
541 pos
= find(coord
, key
, &last_comp
);
543 coord
->unit_pos
= (int)pos
;
546 coord
->between
= AT_UNIT
;
547 return CBK_COORD_FOUND
;
549 coord
->between
= BEFORE_UNIT
;
550 return RETERR(-ENOENT
);
553 impossible("nikita-1298", "Broken find");
557 coord
->unit_pos
= units(coord
) - 1;
558 coord
->between
= AFTER_UNIT
;
560 FIND_MAX_NOT_MORE_THAN
) ? CBK_COORD_FOUND
:
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
569 carry_plugin_info
* info UNUSED_ARG
/* todo carry queue */ )
571 struct cde_entry_data
*e
;
576 e
= (struct cde_entry_data
*) data
->data
;
579 for (i
= 0; i
< e
->num_of_entries
; ++i
) {
583 phantom_size
= data
->length
;
584 if (units(coord
) == 0)
585 phantom_size
-= sizeof(cde_item_format
);
588 expand(coord
, e
->entry
+ i
, phantom_size
, &pos
, data
->arg
);
591 result
= paste_entry(coord
, e
->entry
+ i
, pos
, data
->arg
);
599 /* amount of space occupied by all entries starting from @idx both headers and
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
,
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 */ )
634 /* pend == SHIFT_LEFT <==> shifting to the left */
635 if (pend
== SHIFT_LEFT
) {
636 for (shift
= min((int)want
- 1, units(coord
)); shift
>= 0;
638 *size
= part_size(coord
, shift
);
640 *size
-= sizeof(cde_item_format
);
641 if (*size
<= free_space
)
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;
653 *size
= total_size
- part_size(coord
, shift
);
655 *size
+= sizeof(cde_item_format
);
656 if (*size
<= free_space
)
659 shift
= units(coord
) - shift
- 1;
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 */ )
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
);
695 assert("nikita-1309", (int)(from
+ count
) == units(source
));
697 memmove(item_body_by_coord(target
),
698 (char *)item_body_by_coord(target
) + free_space
,
699 item_length_by_coord(target
) - free_space
);
707 offset_of(source
, (int)(from
+ count
)) - offset_of(source
,
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 */
719 offset_of(target
, pos_in_target
) - offset_of(source
, (int)from
);
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
));
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
));
734 for (i
= pos_in_target
; i
< (int)(pos_in_target
+ count
); ++i
)
735 adj_offset(target
, i
, data_delta
);
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
)
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
);
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
);
779 unit_key_by_coord(&next
, new_first
);
782 size
= item_length_by_coord(coord
);
783 if (count
== (unsigned)units(coord
)) {
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
));
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
;
804 memmove(entry_from
, entry_to
,
805 (unsigned)(address(coord
, size
) - entry_to
));
807 entry_delta
= entry_to
- entry_from
;
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
);
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
),
827 memset(item_body_by_coord(coord
), 0,
828 (unsigned)header_delta
+ entry_delta
);
830 /* freed space is already at the end of item */
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
;
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
);
876 znode_make_dirty(coord
->node
);
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
)
896 result
= data
->length
;
898 result
-= sizeof(cde_item_format
);
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
;
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
;
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
);
939 result
= insert_by_coord(coord
, &data
, &dir_entry
->key
, lh
, 0);
941 result
= reiser4_resize_item(coord
, &data
, &dir_entry
->key
,
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
951 reiser4_dir_entry_desc
* entry UNUSED_ARG
/* parameters of
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
));
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
981 coord_dup(&shadow
, coord
);
983 kill_node_content(coord
, &shadow
, NULL
, NULL
, NULL
, NULL
, NULL
, 0);
985 /* NOTE-NIKITA quota plugin? */
986 DQUOT_FREE_SPACE_NODIRTY(dir
, length
);
991 /* ->s.dir.max_name_len() method for this item plugin */
992 int max_name_len_cde(const struct inode
*dir
/* directory */ )
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.
1002 c-indentation-style: "K&R"