mm-only debug patch...
[mmotm.git] / fs / reiser4 / plugin / dir_plugin_common.c
blob4eb6165348894814a9b50ec02bda178230a27b57
1 /* Copyright 2005 by Hans Reiser, licensing governed by
2 reiser4/README */
4 /* this file contains typical implementations for most of methods of
5 directory plugin
6 */
8 #include "../inode.h"
10 int reiser4_find_entry(struct inode *dir, struct dentry *name,
11 lock_handle * , znode_lock_mode, reiser4_dir_entry_desc *);
12 int reiser4_lookup_name(struct inode *parent, struct dentry *dentry,
13 reiser4_key * key);
14 void check_light_weight(struct inode *inode, struct inode *parent);
16 /* this is common implementation of get_parent method of dir plugin
17 this is used by NFS kernel server to "climb" up directory tree to
18 check permissions
20 struct dentry *get_parent_common(struct inode *child)
22 struct super_block *s;
23 struct inode *parent;
24 struct dentry dotdot;
25 struct dentry *dentry;
26 reiser4_key key;
27 int result;
30 * lookup dotdot entry.
33 s = child->i_sb;
34 memset(&dotdot, 0, sizeof(dotdot));
35 dotdot.d_name.name = "..";
36 dotdot.d_name.len = 2;
37 dotdot.d_op = &get_super_private(s)->ops.dentry;
39 result = reiser4_lookup_name(child, &dotdot, &key);
40 if (result != 0)
41 return ERR_PTR(result);
43 parent = reiser4_iget(s, &key, 1);
44 if (!IS_ERR(parent)) {
46 * FIXME-NIKITA dubious: attributes are inherited from @child
47 * to @parent. But:
49 * (*) this is the only this we can do
51 * (*) attributes of light-weight object are inherited
52 * from a parent through which object was looked up first,
53 * so it is ambiguous anyway.
56 check_light_weight(parent, child);
57 reiser4_iget_complete(parent);
58 dentry = d_obtain_alias(parent);
59 if (!IS_ERR(dentry))
60 dentry->d_op = &get_super_private(s)->ops.dentry;
61 } else if (PTR_ERR(parent) == -ENOENT)
62 dentry = ERR_PTR(RETERR(-ESTALE));
63 else
64 dentry = (void *)parent;
65 return dentry;
68 /* this is common implementation of is_name_acceptable method of dir
69 plugin
71 int is_name_acceptable_common(const struct inode *inode, /* directory to check*/
72 const char *name UNUSED_ARG, /* name to check */
73 int len/* @name's length */)
75 assert("nikita-733", inode != NULL);
76 assert("nikita-734", name != NULL);
77 assert("nikita-735", len > 0);
79 return len <= reiser4_max_filename_len(inode);
82 /* there is no common implementation of build_entry_key method of dir
83 plugin. See plugin/dir/hashed_dir.c:build_entry_key_hashed() or
84 plugin/dir/seekable.c:build_entry_key_seekable() for example
87 /* this is common implementation of build_readdir_key method of dir
88 plugin
89 see reiser4_readdir_common for more details
91 int build_readdir_key_common(struct file *dir /* directory being read */ ,
92 reiser4_key * result/* where to store key */)
94 reiser4_file_fsdata *fdata;
95 struct inode *inode;
97 assert("nikita-1361", dir != NULL);
98 assert("nikita-1362", result != NULL);
99 assert("nikita-1363", dir->f_dentry != NULL);
100 inode = dir->f_dentry->d_inode;
101 assert("nikita-1373", inode != NULL);
103 fdata = reiser4_get_file_fsdata(dir);
104 if (IS_ERR(fdata))
105 return PTR_ERR(fdata);
106 assert("nikita-1364", fdata != NULL);
107 return extract_key_from_de_id(get_inode_oid(inode),
108 &fdata->dir.readdir.position.
109 dir_entry_key, result);
113 void reiser4_adjust_dir_file(struct inode *, const struct dentry *, int offset,
114 int adj);
116 /* this is common implementation of add_entry method of dir plugin
118 int reiser4_add_entry_common(struct inode *object, /* directory to add new name
119 * in */
120 struct dentry *where, /* new name */
121 reiser4_object_create_data * data, /* parameters of
122 * new object */
123 reiser4_dir_entry_desc * entry /* parameters of
124 * new directory
125 * entry */)
127 int result;
128 coord_t *coord;
129 lock_handle lh;
130 struct reiser4_dentry_fsdata *fsdata;
131 reiser4_block_nr reserve;
133 assert("nikita-1114", object != NULL);
134 assert("nikita-1250", where != NULL);
136 fsdata = reiser4_get_dentry_fsdata(where);
137 if (unlikely(IS_ERR(fsdata)))
138 return PTR_ERR(fsdata);
140 reserve = inode_dir_plugin(object)->estimate.add_entry(object);
141 if (reiser4_grab_space(reserve, BA_CAN_COMMIT))
142 return RETERR(-ENOSPC);
144 init_lh(&lh);
145 coord = &fsdata->dec.entry_coord;
146 coord_clear_iplug(coord);
148 /* check for this entry in a directory. This is plugin method. */
149 result = reiser4_find_entry(object, where, &lh, ZNODE_WRITE_LOCK,
150 entry);
151 if (likely(result == -ENOENT)) {
152 /* add new entry. Just pass control to the directory
153 item plugin. */
154 assert("nikita-1709", inode_dir_item_plugin(object));
155 assert("nikita-2230", coord->node == lh.node);
156 reiser4_seal_done(&fsdata->dec.entry_seal);
157 result =
158 inode_dir_item_plugin(object)->s.dir.add_entry(object,
159 coord, &lh,
160 where,
161 entry);
162 if (result == 0) {
163 reiser4_adjust_dir_file(object, where,
164 fsdata->dec.pos + 1, +1);
165 INODE_INC_FIELD(object, i_size);
167 } else if (result == 0) {
168 assert("nikita-2232", coord->node == lh.node);
169 result = RETERR(-EEXIST);
171 done_lh(&lh);
173 return result;
177 * rem_entry - remove entry from directory item
178 * @dir:
179 * @dentry:
180 * @entry:
181 * @coord:
182 * @lh:
184 * Checks that coordinate @coord is set properly and calls item plugin
185 * method to cut entry.
187 static int
188 rem_entry(struct inode *dir, struct dentry *dentry,
189 reiser4_dir_entry_desc * entry, coord_t *coord, lock_handle * lh)
191 item_plugin *iplug;
192 struct inode *child;
194 iplug = inode_dir_item_plugin(dir);
195 child = dentry->d_inode;
196 assert("nikita-3399", child != NULL);
198 /* check that we are really destroying an entry for @child */
199 if (REISER4_DEBUG) {
200 int result;
201 reiser4_key key;
203 result = iplug->s.dir.extract_key(coord, &key);
204 if (result != 0)
205 return result;
206 if (get_key_objectid(&key) != get_inode_oid(child)) {
207 warning("nikita-3397",
208 "rem_entry: %#llx != %#llx\n",
209 get_key_objectid(&key),
210 (unsigned long long)get_inode_oid(child));
211 return RETERR(-EIO);
214 return iplug->s.dir.rem_entry(dir, &dentry->d_name, coord, lh, entry);
218 * reiser4_rem_entry_common - remove entry from a directory
219 * @dir: directory to remove entry from
220 * @where: name that is being removed
221 * @entry: description of entry being removed
223 * This is common implementation of rem_entry method of dir plugin.
225 int reiser4_rem_entry_common(struct inode *dir,
226 struct dentry *dentry,
227 reiser4_dir_entry_desc * entry)
229 int result;
230 coord_t *coord;
231 lock_handle lh;
232 struct reiser4_dentry_fsdata *fsdata;
233 __u64 tograb;
235 assert("nikita-1124", dir != NULL);
236 assert("nikita-1125", dentry != NULL);
238 tograb = inode_dir_plugin(dir)->estimate.rem_entry(dir);
239 result = reiser4_grab_space(tograb, BA_CAN_COMMIT | BA_RESERVED);
240 if (result != 0)
241 return RETERR(-ENOSPC);
243 init_lh(&lh);
245 /* check for this entry in a directory. This is plugin method. */
246 result = reiser4_find_entry(dir, dentry, &lh, ZNODE_WRITE_LOCK, entry);
247 fsdata = reiser4_get_dentry_fsdata(dentry);
248 if (IS_ERR(fsdata)) {
249 done_lh(&lh);
250 return PTR_ERR(fsdata);
253 coord = &fsdata->dec.entry_coord;
255 assert("nikita-3404",
256 get_inode_oid(dentry->d_inode) != get_inode_oid(dir) ||
257 dir->i_size <= 1);
259 coord_clear_iplug(coord);
260 if (result == 0) {
261 /* remove entry. Just pass control to the directory item
262 plugin. */
263 assert("vs-542", inode_dir_item_plugin(dir));
264 reiser4_seal_done(&fsdata->dec.entry_seal);
265 reiser4_adjust_dir_file(dir, dentry, fsdata->dec.pos, -1);
266 result =
267 WITH_COORD(coord,
268 rem_entry(dir, dentry, entry, coord, &lh));
269 if (result == 0) {
270 if (dir->i_size >= 1)
271 INODE_DEC_FIELD(dir, i_size);
272 else {
273 warning("nikita-2509", "Dir %llu is runt",
274 (unsigned long long)
275 get_inode_oid(dir));
276 result = RETERR(-EIO);
279 assert("nikita-3405", dentry->d_inode->i_nlink != 1 ||
280 dentry->d_inode->i_size != 2 ||
281 inode_dir_plugin(dentry->d_inode) == NULL);
284 done_lh(&lh);
286 return result;
289 static reiser4_block_nr estimate_init(struct inode *parent,
290 struct inode *object);
291 static int create_dot_dotdot(struct inode *object, struct inode *parent);
293 /* this is common implementation of init method of dir plugin
294 create "." and ".." entries
296 int reiser4_dir_init_common(struct inode *object, /* new directory */
297 struct inode *parent, /* parent directory */
298 reiser4_object_create_data * data /* info passed
299 * to us, this
300 * is filled by
301 * reiser4()
302 * syscall in
303 * particular */)
305 reiser4_block_nr reserve;
307 assert("nikita-680", object != NULL);
308 assert("nikita-681", S_ISDIR(object->i_mode));
309 assert("nikita-682", parent != NULL);
310 assert("nikita-684", data != NULL);
311 assert("nikita-686", data->id == DIRECTORY_FILE_PLUGIN_ID);
312 assert("nikita-687", object->i_mode & S_IFDIR);
314 reserve = estimate_init(parent, object);
315 if (reiser4_grab_space(reserve, BA_CAN_COMMIT))
316 return RETERR(-ENOSPC);
318 return create_dot_dotdot(object, parent);
321 /* this is common implementation of done method of dir plugin
322 remove "." entry
324 int reiser4_dir_done_common(struct inode *object/* object being deleted */)
326 int result;
327 reiser4_block_nr reserve;
328 struct dentry goodby_dots;
329 reiser4_dir_entry_desc entry;
331 assert("nikita-1449", object != NULL);
333 if (reiser4_inode_get_flag(object, REISER4_NO_SD))
334 return 0;
336 /* of course, this can be rewritten to sweep everything in one
337 reiser4_cut_tree(). */
338 memset(&entry, 0, sizeof entry);
340 /* FIXME: this done method is called from reiser4_delete_dir_common
341 * which reserved space already */
342 reserve = inode_dir_plugin(object)->estimate.rem_entry(object);
343 if (reiser4_grab_space(reserve, BA_CAN_COMMIT | BA_RESERVED))
344 return RETERR(-ENOSPC);
346 memset(&goodby_dots, 0, sizeof goodby_dots);
347 entry.obj = goodby_dots.d_inode = object;
348 goodby_dots.d_name.name = ".";
349 goodby_dots.d_name.len = 1;
350 result = reiser4_rem_entry_common(object, &goodby_dots, &entry);
351 reiser4_free_dentry_fsdata(&goodby_dots);
352 if (unlikely(result != 0 && result != -ENOMEM && result != -ENOENT))
353 warning("nikita-2252", "Cannot remove dot of %lli: %i",
354 (unsigned long long)get_inode_oid(object), result);
355 return 0;
358 /* this is common implementation of attach method of dir plugin
360 int reiser4_attach_common(struct inode *child UNUSED_ARG,
361 struct inode *parent UNUSED_ARG)
363 assert("nikita-2647", child != NULL);
364 assert("nikita-2648", parent != NULL);
366 return 0;
369 /* this is common implementation of detach method of dir plugin
370 remove "..", decrease nlink on parent
372 int reiser4_detach_common(struct inode *object, struct inode *parent)
374 int result;
375 struct dentry goodby_dots;
376 reiser4_dir_entry_desc entry;
378 assert("nikita-2885", object != NULL);
379 assert("nikita-2886", !reiser4_inode_get_flag(object, REISER4_NO_SD));
381 memset(&entry, 0, sizeof entry);
383 /* NOTE-NIKITA this only works if @parent is -the- parent of
384 @object, viz. object whose key is stored in dotdot
385 entry. Wouldn't work with hard-links on directories. */
386 memset(&goodby_dots, 0, sizeof goodby_dots);
387 entry.obj = goodby_dots.d_inode = parent;
388 goodby_dots.d_name.name = "..";
389 goodby_dots.d_name.len = 2;
390 result = reiser4_rem_entry_common(object, &goodby_dots, &entry);
391 reiser4_free_dentry_fsdata(&goodby_dots);
392 if (result == 0) {
393 /* the dot should be the only entry remaining at this time... */
394 assert("nikita-3400",
395 object->i_size == 1 && object->i_nlink <= 2);
396 #if 0
397 /* and, together with the only name directory can have, they
398 * provides for the last 2 remaining references. If we get
399 * here as part of error handling during mkdir, @object
400 * possibly has no name yet, so its nlink == 1. If we get here
401 * from rename (targeting empty directory), it has no name
402 * already, so its nlink == 1. */
403 assert("nikita-3401",
404 object->i_nlink == 2 || object->i_nlink == 1);
405 #endif
407 /* decrement nlink of directory removed ".." pointed
408 to */
409 reiser4_del_nlink(parent, NULL, 0);
411 return result;
414 /* this is common implementation of estimate.add_entry method of
415 dir plugin
416 estimation of adding entry which supposes that entry is inserting a
417 unit into item
419 reiser4_block_nr estimate_add_entry_common(const struct inode *inode)
421 return estimate_one_insert_into_item(reiser4_tree_by_inode(inode));
424 /* this is common implementation of estimate.rem_entry method of dir
425 plugin
427 reiser4_block_nr estimate_rem_entry_common(const struct inode *inode)
429 return estimate_one_item_removal(reiser4_tree_by_inode(inode));
432 /* this is common implementation of estimate.unlink method of dir
433 plugin
435 reiser4_block_nr
436 dir_estimate_unlink_common(const struct inode *parent,
437 const struct inode *object)
439 reiser4_block_nr res;
441 /* hashed_rem_entry(object) */
442 res = inode_dir_plugin(object)->estimate.rem_entry(object);
443 /* del_nlink(parent) */
444 res += 2 * inode_file_plugin(parent)->estimate.update(parent);
446 return res;
450 * helper for inode_ops ->lookup() and dir plugin's ->get_parent()
451 * methods: if @inode is a light-weight file, setup its credentials
452 * that are not stored in the stat-data in this case
454 void check_light_weight(struct inode *inode, struct inode *parent)
456 if (reiser4_inode_get_flag(inode, REISER4_LIGHT_WEIGHT)) {
457 inode->i_uid = parent->i_uid;
458 inode->i_gid = parent->i_gid;
459 /* clear light-weight flag. If inode would be read by any
460 other name, [ug]id wouldn't change. */
461 reiser4_inode_clr_flag(inode, REISER4_LIGHT_WEIGHT);
465 /* looks for name specified in @dentry in directory @parent and if name is
466 found - key of object found entry points to is stored in @entry->key */
467 int reiser4_lookup_name(struct inode *parent, /* inode of directory to lookup
468 * for name in */
469 struct dentry *dentry, /* name to look for */
470 reiser4_key * key/* place to store key */)
472 int result;
473 coord_t *coord;
474 lock_handle lh;
475 const char *name;
476 int len;
477 reiser4_dir_entry_desc entry;
478 struct reiser4_dentry_fsdata *fsdata;
480 assert("nikita-1247", parent != NULL);
481 assert("nikita-1248", dentry != NULL);
482 assert("nikita-1123", dentry->d_name.name != NULL);
483 assert("vs-1486",
484 dentry->d_op == &get_super_private(parent->i_sb)->ops.dentry);
486 name = dentry->d_name.name;
487 len = dentry->d_name.len;
489 if (!inode_dir_plugin(parent)->is_name_acceptable(parent, name, len))
490 /* some arbitrary error code to return */
491 return RETERR(-ENAMETOOLONG);
493 fsdata = reiser4_get_dentry_fsdata(dentry);
494 if (IS_ERR(fsdata))
495 return PTR_ERR(fsdata);
497 coord = &fsdata->dec.entry_coord;
498 coord_clear_iplug(coord);
499 init_lh(&lh);
501 /* find entry in a directory. This is plugin method. */
502 result = reiser4_find_entry(parent, dentry, &lh, ZNODE_READ_LOCK,
503 &entry);
504 if (result == 0) {
505 /* entry was found, extract object key from it. */
506 result =
507 WITH_COORD(coord,
508 item_plugin_by_coord(coord)->s.dir.
509 extract_key(coord, key));
511 done_lh(&lh);
512 return result;
516 /* helper for reiser4_dir_init_common(): estimate number of blocks to reserve */
517 static reiser4_block_nr
518 estimate_init(struct inode *parent, struct inode *object)
520 reiser4_block_nr res = 0;
522 assert("vpf-321", parent != NULL);
523 assert("vpf-322", object != NULL);
525 /* hashed_add_entry(object) */
526 res += inode_dir_plugin(object)->estimate.add_entry(object);
527 /* reiser4_add_nlink(object) */
528 res += inode_file_plugin(object)->estimate.update(object);
529 /* hashed_add_entry(object) */
530 res += inode_dir_plugin(object)->estimate.add_entry(object);
531 /* reiser4_add_nlink(parent) */
532 res += inode_file_plugin(parent)->estimate.update(parent);
534 return 0;
537 /* helper function for reiser4_dir_init_common(). Create "." and ".." */
538 static int create_dot_dotdot(struct inode *object/* object to create dot and
539 * dotdot for */ ,
540 struct inode *parent/* parent of @object */)
542 int result;
543 struct dentry dots_entry;
544 reiser4_dir_entry_desc entry;
546 assert("nikita-688", object != NULL);
547 assert("nikita-689", S_ISDIR(object->i_mode));
548 assert("nikita-691", parent != NULL);
550 /* We store dot and dotdot as normal directory entries. This is
551 not necessary, because almost all information stored in them
552 is already in the stat-data of directory, the only thing
553 being missed is objectid of grand-parent directory that can
554 easily be added there as extension.
556 But it is done the way it is done, because not storing dot
557 and dotdot will lead to the following complications:
559 . special case handling in ->lookup().
560 . addition of another extension to the sd.
561 . dependency on key allocation policy for stat data.
565 memset(&entry, 0, sizeof entry);
566 memset(&dots_entry, 0, sizeof dots_entry);
567 entry.obj = dots_entry.d_inode = object;
568 dots_entry.d_name.name = ".";
569 dots_entry.d_name.len = 1;
570 result = reiser4_add_entry_common(object, &dots_entry, NULL, &entry);
571 reiser4_free_dentry_fsdata(&dots_entry);
573 if (result == 0) {
574 result = reiser4_add_nlink(object, object, 0);
575 if (result == 0) {
576 entry.obj = dots_entry.d_inode = parent;
577 dots_entry.d_name.name = "..";
578 dots_entry.d_name.len = 2;
579 result = reiser4_add_entry_common(object,
580 &dots_entry, NULL, &entry);
581 reiser4_free_dentry_fsdata(&dots_entry);
582 /* if creation of ".." failed, iput() will delete
583 object with ".". */
584 if (result == 0) {
585 result = reiser4_add_nlink(parent, object, 0);
586 if (result != 0)
588 * if we failed to bump i_nlink, try
589 * to remove ".."
591 reiser4_detach_common(object, parent);
596 if (result != 0) {
598 * in the case of error, at least update stat-data so that,
599 * ->i_nlink updates are not lingering.
601 reiser4_update_sd(object);
602 reiser4_update_sd(parent);
605 return result;
609 * return 0 iff @coord contains a directory entry for the file with the name
610 * @name.
612 static int
613 check_item(const struct inode *dir, const coord_t *coord, const char *name)
615 item_plugin *iplug;
616 char buf[DE_NAME_BUF_LEN];
618 iplug = item_plugin_by_coord(coord);
619 if (iplug == NULL) {
620 warning("nikita-1135", "Cannot get item plugin");
621 print_coord("coord", coord, 1);
622 return RETERR(-EIO);
623 } else if (item_id_by_coord(coord) !=
624 item_id_by_plugin(inode_dir_item_plugin(dir))) {
625 /* item id of current item does not match to id of items a
626 directory is built of */
627 warning("nikita-1136", "Wrong item plugin");
628 print_coord("coord", coord, 1);
629 return RETERR(-EIO);
631 assert("nikita-1137", iplug->s.dir.extract_name);
633 /* Compare name stored in this entry with name we are looking for.
635 NOTE-NIKITA Here should go code for support of something like
636 unicode, code tables, etc.
638 return !!strcmp(name, iplug->s.dir.extract_name(coord, buf));
641 static int
642 check_entry(const struct inode *dir, coord_t *coord, const struct qstr *name)
644 return WITH_COORD(coord, check_item(dir, coord, name->name));
648 * argument package used by entry_actor to scan entries with identical keys.
650 struct entry_actor_args {
651 /* name we are looking for */
652 const char *name;
653 /* key of directory entry. entry_actor() scans through sequence of
654 * items/units having the same key */
655 reiser4_key *key;
656 /* how many entries with duplicate key was scanned so far. */
657 int non_uniq;
658 #if REISER4_USE_COLLISION_LIMIT
659 /* scan limit */
660 int max_non_uniq;
661 #endif
662 /* return parameter: set to true, if ->name wasn't found */
663 int not_found;
664 /* what type of lock to take when moving to the next node during
665 * scan */
666 znode_lock_mode mode;
668 /* last coord that was visited during scan */
669 coord_t last_coord;
670 /* last node locked during scan */
671 lock_handle last_lh;
672 /* inode of directory */
673 const struct inode *inode;
676 /* Function called by reiser4_find_entry() to look for given name
677 in the directory. */
678 static int entry_actor(reiser4_tree * tree UNUSED_ARG /* tree being scanned */ ,
679 coord_t *coord /* current coord */ ,
680 lock_handle * lh /* current lock handle */ ,
681 void *entry_actor_arg/* argument to scan */)
683 reiser4_key unit_key;
684 struct entry_actor_args *args;
686 assert("nikita-1131", tree != NULL);
687 assert("nikita-1132", coord != NULL);
688 assert("nikita-1133", entry_actor_arg != NULL);
690 args = entry_actor_arg;
691 ++args->non_uniq;
692 #if REISER4_USE_COLLISION_LIMIT
693 if (args->non_uniq > args->max_non_uniq) {
694 args->not_found = 1;
695 /* hash collision overflow. */
696 return RETERR(-EBUSY);
698 #endif
701 * did we just reach the end of the sequence of items/units with
702 * identical keys?
704 if (!keyeq(args->key, unit_key_by_coord(coord, &unit_key))) {
705 assert("nikita-1791",
706 keylt(args->key, unit_key_by_coord(coord, &unit_key)));
707 args->not_found = 1;
708 args->last_coord.between = AFTER_UNIT;
709 return 0;
712 coord_dup(&args->last_coord, coord);
714 * did scan just moved to the next node?
716 if (args->last_lh.node != lh->node) {
717 int lock_result;
720 * if so, lock new node with the mode requested by the caller
722 done_lh(&args->last_lh);
723 assert("nikita-1896", znode_is_any_locked(lh->node));
724 lock_result = longterm_lock_znode(&args->last_lh, lh->node,
725 args->mode, ZNODE_LOCK_HIPRI);
726 if (lock_result != 0)
727 return lock_result;
729 return check_item(args->inode, coord, args->name);
732 /* Look for given @name within directory @dir.
734 This is called during lookup, creation and removal of directory
735 entries and on reiser4_rename_common
737 First calculate key that directory entry for @name would have. Search
738 for this key in the tree. If such key is found, scan all items with
739 the same key, checking name in each directory entry along the way.
741 int reiser4_find_entry(struct inode *dir, /* directory to scan */
742 struct dentry *de, /* name to search for */
743 lock_handle * lh, /* resulting lock handle */
744 znode_lock_mode mode, /* required lock mode */
745 reiser4_dir_entry_desc * entry /* parameters of found
746 directory entry */)
748 const struct qstr *name;
749 seal_t *seal;
750 coord_t *coord;
751 int result;
752 __u32 flags;
753 struct de_location *dec;
754 struct reiser4_dentry_fsdata *fsdata;
756 assert("nikita-1130", lh != NULL);
757 assert("nikita-1128", dir != NULL);
759 name = &de->d_name;
760 assert("nikita-1129", name != NULL);
762 /* dentry private data don't require lock, because dentry
763 manipulations are protected by i_mutex on parent.
765 This is not so for inodes, because there is no -the- parent in
766 inode case.
768 fsdata = reiser4_get_dentry_fsdata(de);
769 if (IS_ERR(fsdata))
770 return PTR_ERR(fsdata);
771 dec = &fsdata->dec;
773 coord = &dec->entry_coord;
774 coord_clear_iplug(coord);
775 seal = &dec->entry_seal;
776 /* compose key of directory entry for @name */
777 inode_dir_plugin(dir)->build_entry_key(dir, name, &entry->key);
779 if (reiser4_seal_is_set(seal)) {
780 /* check seal */
781 result = reiser4_seal_validate(seal, coord, &entry->key,
782 lh, mode, ZNODE_LOCK_LOPRI);
783 if (result == 0) {
784 /* key was found. Check that it is really item we are
785 looking for. */
786 result = check_entry(dir, coord, name);
787 if (result == 0)
788 return 0;
791 flags = (mode == ZNODE_WRITE_LOCK) ? CBK_FOR_INSERT : 0;
793 * find place in the tree where directory item should be located.
795 result = reiser4_object_lookup(dir, &entry->key, coord, lh, mode,
796 FIND_EXACT, LEAF_LEVEL, LEAF_LEVEL,
797 flags, NULL/*ra_info */);
798 if (result == CBK_COORD_FOUND) {
799 struct entry_actor_args arg;
801 /* fast path: no hash collisions */
802 result = check_entry(dir, coord, name);
803 if (result == 0) {
804 reiser4_seal_init(seal, coord, &entry->key);
805 dec->pos = 0;
806 } else if (result > 0) {
807 /* Iterate through all units with the same keys. */
808 arg.name = name->name;
809 arg.key = &entry->key;
810 arg.not_found = 0;
811 arg.non_uniq = 0;
812 #if REISER4_USE_COLLISION_LIMIT
813 arg.max_non_uniq = max_hash_collisions(dir);
814 assert("nikita-2851", arg.max_non_uniq > 1);
815 #endif
816 arg.mode = mode;
817 arg.inode = dir;
818 coord_init_zero(&arg.last_coord);
819 init_lh(&arg.last_lh);
821 result = reiser4_iterate_tree
822 (reiser4_tree_by_inode(dir),
823 coord, lh,
824 entry_actor, &arg, mode, 1);
825 /* if end of the tree or extent was reached during
826 scanning. */
827 if (arg.not_found || (result == -E_NO_NEIGHBOR)) {
828 /* step back */
829 done_lh(lh);
831 result = zload(arg.last_coord.node);
832 if (result == 0) {
833 coord_clear_iplug(&arg.last_coord);
834 coord_dup(coord, &arg.last_coord);
835 move_lh(lh, &arg.last_lh);
836 result = RETERR(-ENOENT);
837 zrelse(arg.last_coord.node);
838 --arg.non_uniq;
842 done_lh(&arg.last_lh);
843 if (result == 0)
844 reiser4_seal_init(seal, coord, &entry->key);
846 if (result == 0 || result == -ENOENT) {
847 assert("nikita-2580", arg.non_uniq > 0);
848 dec->pos = arg.non_uniq - 1;
851 } else
852 dec->pos = -1;
853 return result;
857 Local variables:
858 c-indentation-style: "K&R"
859 mode-name: "LC"
860 c-basic-offset: 8
861 tab-width: 8
862 fill-column: 120
863 scroll-step: 1
864 End: