revert-mm-fix-blkdev-size-calculation-in-generic_write_checks
[linux-2.6/linux-trees-mm.git] / fs / reiser4 / plugin / dir_plugin_common.c
blob8a2cbb869125a0bfdccda66efb87c23ff761e5b5
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, reiser4_key * key);
13 void check_light_weight(struct inode *inode, struct inode *parent);
15 /* this is common implementation of get_parent method of dir plugin
16 this is used by NFS kernel server to "climb" up directory tree to
17 check permissions
19 struct dentry *get_parent_common(struct inode *child)
21 struct super_block *s;
22 struct inode *parent;
23 struct dentry dotdot;
24 struct dentry *dentry;
25 reiser4_key key;
26 int result;
29 * lookup dotdot entry.
32 s = child->i_sb;
33 memset(&dotdot, 0, sizeof(dotdot));
34 dotdot.d_name.name = "..";
35 dotdot.d_name.len = 2;
36 dotdot.d_op = &get_super_private(s)->ops.dentry;
38 result = reiser4_lookup_name(child, &dotdot, &key);
39 if (result != 0)
40 return ERR_PTR(result);
42 parent = reiser4_iget(s, &key, 1);
43 if (!IS_ERR(parent)) {
45 * FIXME-NIKITA dubious: attributes are inherited from @child
46 * to @parent. But:
48 * (*) this is the only this we can do
50 * (*) attributes of light-weight object are inherited
51 * from a parent through which object was looked up first,
52 * so it is ambiguous anyway.
55 check_light_weight(parent, child);
56 reiser4_iget_complete(parent);
57 dentry = d_alloc_anon(parent);
58 if (dentry == NULL) {
59 iput(parent);
60 dentry = ERR_PTR(RETERR(-ENOMEM));
61 } else
62 dentry->d_op = &get_super_private(s)->ops.dentry;
63 } else if (PTR_ERR(parent) == -ENOENT)
64 dentry = ERR_PTR(RETERR(-ESTALE));
65 else
66 dentry = (void *)parent;
67 return dentry;
70 /* this is common implementation of is_name_acceptable method of dir
71 plugin
73 int is_name_acceptable_common(const struct inode *inode, /* directory to check */
74 const char *name UNUSED_ARG, /* name to check */
75 int len /* @name's length */ )
77 assert("nikita-733", inode != NULL);
78 assert("nikita-734", name != NULL);
79 assert("nikita-735", len > 0);
81 return len <= reiser4_max_filename_len(inode);
84 /* there is no common implementation of build_entry_key method of dir
85 plugin. See plugin/dir/hashed_dir.c:build_entry_key_hashed() or
86 plugin/dir/seekable.c:build_entry_key_seekable() for example
89 /* this is common implementation of build_readdir_key method of dir
90 plugin
91 see reiser4_readdir_common for more details
93 int build_readdir_key_common(struct file *dir /* directory being read */ ,
94 reiser4_key * result /* where to store key */ )
96 reiser4_file_fsdata *fdata;
97 struct inode *inode;
99 assert("nikita-1361", dir != NULL);
100 assert("nikita-1362", result != NULL);
101 assert("nikita-1363", dir->f_dentry != NULL);
102 inode = dir->f_dentry->d_inode;
103 assert("nikita-1373", inode != NULL);
105 fdata = reiser4_get_file_fsdata(dir);
106 if (IS_ERR(fdata))
107 return PTR_ERR(fdata);
108 assert("nikita-1364", fdata != NULL);
109 return extract_key_from_de_id(get_inode_oid(inode),
110 &fdata->dir.readdir.position.
111 dir_entry_key, result);
115 void reiser4_adjust_dir_file(struct inode *, const struct dentry *, int offset,
116 int adj);
118 /* this is common implementation of add_entry method of dir plugin
120 int reiser4_add_entry_common(struct inode *object, /* directory to add new name
121 * in */
122 struct dentry *where, /* new name */
123 reiser4_object_create_data * data, /* parameters of
124 * new object */
125 reiser4_dir_entry_desc * entry /* parameters of
126 * new directory
127 * entry */)
129 int result;
130 coord_t *coord;
131 lock_handle lh;
132 struct reiser4_dentry_fsdata *fsdata;
133 reiser4_block_nr reserve;
135 assert("nikita-1114", object != NULL);
136 assert("nikita-1250", where != NULL);
138 fsdata = reiser4_get_dentry_fsdata(where);
139 if (unlikely(IS_ERR(fsdata)))
140 return PTR_ERR(fsdata);
142 reserve = inode_dir_plugin(object)->estimate.add_entry(object);
143 if (reiser4_grab_space(reserve, BA_CAN_COMMIT))
144 return RETERR(-ENOSPC);
146 init_lh(&lh);
147 coord = &fsdata->dec.entry_coord;
148 coord_clear_iplug(coord);
150 /* check for this entry in a directory. This is plugin method. */
151 result = reiser4_find_entry(object, where, &lh, ZNODE_WRITE_LOCK,
152 entry);
153 if (likely(result == -ENOENT)) {
154 /* add new entry. Just pass control to the directory
155 item plugin. */
156 assert("nikita-1709", inode_dir_item_plugin(object));
157 assert("nikita-2230", coord->node == lh.node);
158 reiser4_seal_done(&fsdata->dec.entry_seal);
159 result =
160 inode_dir_item_plugin(object)->s.dir.add_entry(object,
161 coord, &lh,
162 where,
163 entry);
164 if (result == 0) {
165 reiser4_adjust_dir_file(object, where,
166 fsdata->dec.pos + 1, +1);
167 INODE_INC_FIELD(object, i_size);
169 } else if (result == 0) {
170 assert("nikita-2232", coord->node == lh.node);
171 result = RETERR(-EEXIST);
173 done_lh(&lh);
175 return result;
179 * rem_entry - remove entry from directory item
180 * @dir:
181 * @dentry:
182 * @entry:
183 * @coord:
184 * @lh:
186 * Checks that coordinate @coord is set properly and calls item plugin
187 * method to cut entry.
189 static int
190 rem_entry(struct inode *dir, struct dentry *dentry,
191 reiser4_dir_entry_desc * entry, coord_t * coord, lock_handle * lh)
193 item_plugin *iplug;
194 struct inode *child;
196 iplug = inode_dir_item_plugin(dir);
197 child = dentry->d_inode;
198 assert("nikita-3399", child != NULL);
200 /* check that we are really destroying an entry for @child */
201 if (REISER4_DEBUG) {
202 int result;
203 reiser4_key key;
205 result = iplug->s.dir.extract_key(coord, &key);
206 if (result != 0)
207 return result;
208 if (get_key_objectid(&key) != get_inode_oid(child)) {
209 warning("nikita-3397",
210 "rem_entry: %#llx != %#llx\n",
211 get_key_objectid(&key),
212 (unsigned long long)get_inode_oid(child));
213 return RETERR(-EIO);
216 return iplug->s.dir.rem_entry(dir, &dentry->d_name, coord, lh, entry);
220 * reiser4_rem_entry_common - remove entry from a directory
221 * @dir: directory to remove entry from
222 * @where: name that is being removed
223 * @entry: description of entry being removed
225 * This is common implementation of rem_entry method of dir plugin.
227 int reiser4_rem_entry_common(struct inode *dir,
228 struct dentry *dentry,
229 reiser4_dir_entry_desc *entry)
231 int result;
232 coord_t *coord;
233 lock_handle lh;
234 struct reiser4_dentry_fsdata *fsdata;
235 __u64 tograb;
237 assert("nikita-1124", dir != NULL);
238 assert("nikita-1125", dentry != NULL);
240 tograb = inode_dir_plugin(dir)->estimate.rem_entry(dir);
241 result = reiser4_grab_space(tograb, BA_CAN_COMMIT | BA_RESERVED);
242 if (result != 0)
243 return RETERR(-ENOSPC);
245 init_lh(&lh);
247 /* check for this entry in a directory. This is plugin method. */
248 result = reiser4_find_entry(dir, dentry, &lh, ZNODE_WRITE_LOCK, entry);
249 fsdata = reiser4_get_dentry_fsdata(dentry);
250 if (IS_ERR(fsdata)) {
251 done_lh(&lh);
252 return PTR_ERR(fsdata);
255 coord = &fsdata->dec.entry_coord;
257 assert("nikita-3404",
258 get_inode_oid(dentry->d_inode) != get_inode_oid(dir) ||
259 dir->i_size <= 1);
261 coord_clear_iplug(coord);
262 if (result == 0) {
263 /* remove entry. Just pass control to the directory item
264 plugin. */
265 assert("vs-542", inode_dir_item_plugin(dir));
266 reiser4_seal_done(&fsdata->dec.entry_seal);
267 reiser4_adjust_dir_file(dir, dentry, fsdata->dec.pos, -1);
268 result =
269 WITH_COORD(coord,
270 rem_entry(dir, dentry, entry, coord, &lh));
271 if (result == 0) {
272 if (dir->i_size >= 1)
273 INODE_DEC_FIELD(dir, i_size);
274 else {
275 warning("nikita-2509", "Dir %llu is runt",
276 (unsigned long long)
277 get_inode_oid(dir));
278 result = RETERR(-EIO);
281 assert("nikita-3405", dentry->d_inode->i_nlink != 1 ||
282 dentry->d_inode->i_size != 2 ||
283 inode_dir_plugin(dentry->d_inode) == NULL);
286 done_lh(&lh);
288 return result;
291 static reiser4_block_nr estimate_init(struct inode *parent,
292 struct inode *object);
293 static int create_dot_dotdot(struct inode *object, struct inode *parent);
295 /* this is common implementation of init method of dir plugin
296 create "." and ".." entries
298 int reiser4_dir_init_common(struct inode *object, /* new directory */
299 struct inode *parent, /* parent directory */
300 reiser4_object_create_data * data /* info passed
301 * to us, this
302 * is filled by
303 * reiser4()
304 * syscall in
305 * particular */)
307 reiser4_block_nr reserve;
309 assert("nikita-680", object != NULL);
310 assert("nikita-681", S_ISDIR(object->i_mode));
311 assert("nikita-682", parent != NULL);
312 assert("nikita-684", data != NULL);
313 assert("nikita-686", data->id == DIRECTORY_FILE_PLUGIN_ID);
314 assert("nikita-687", object->i_mode & S_IFDIR);
316 reserve = estimate_init(parent, object);
317 if (reiser4_grab_space(reserve, BA_CAN_COMMIT))
318 return RETERR(-ENOSPC);
320 return create_dot_dotdot(object, parent);
323 /* this is common implementation of done method of dir plugin
324 remove "." entry
326 int reiser4_dir_done_common(struct inode *object /* object being deleted */ )
328 int result;
329 reiser4_block_nr reserve;
330 struct dentry goodby_dots;
331 reiser4_dir_entry_desc entry;
333 assert("nikita-1449", object != NULL);
335 if (reiser4_inode_get_flag(object, REISER4_NO_SD))
336 return 0;
338 /* of course, this can be rewritten to sweep everything in one
339 reiser4_cut_tree(). */
340 memset(&entry, 0, sizeof entry);
342 /* FIXME: this done method is called from reiser4_delete_dir_common which
343 * reserved space already */
344 reserve = inode_dir_plugin(object)->estimate.rem_entry(object);
345 if (reiser4_grab_space(reserve, BA_CAN_COMMIT | BA_RESERVED))
346 return RETERR(-ENOSPC);
348 memset(&goodby_dots, 0, sizeof goodby_dots);
349 entry.obj = goodby_dots.d_inode = object;
350 goodby_dots.d_name.name = ".";
351 goodby_dots.d_name.len = 1;
352 result = reiser4_rem_entry_common(object, &goodby_dots, &entry);
353 reiser4_free_dentry_fsdata(&goodby_dots);
354 if (unlikely(result != 0 && result != -ENOMEM && result != -ENOENT))
355 /* only worth a warning
357 "values of \x0eB\x0f will give rise to dom!\n"
358 -- v6src/s2/mv.c:89
360 warning("nikita-2252", "Cannot remove dot of %lli: %i",
361 (unsigned long long)get_inode_oid(object), result);
362 return 0;
365 /* this is common implementation of attach method of dir plugin
367 int reiser4_attach_common(struct inode *child UNUSED_ARG,
368 struct inode *parent UNUSED_ARG)
370 assert("nikita-2647", child != NULL);
371 assert("nikita-2648", parent != NULL);
373 return 0;
376 /* this is common implementation of detach method of dir plugin
377 remove "..", decrease nlink on parent
379 int reiser4_detach_common(struct inode *object, struct inode *parent)
381 int result;
382 struct dentry goodby_dots;
383 reiser4_dir_entry_desc entry;
385 assert("nikita-2885", object != NULL);
386 assert("nikita-2886", !reiser4_inode_get_flag(object, REISER4_NO_SD));
388 memset(&entry, 0, sizeof entry);
390 /* NOTE-NIKITA this only works if @parent is -the- parent of
391 @object, viz. object whose key is stored in dotdot
392 entry. Wouldn't work with hard-links on directories. */
393 memset(&goodby_dots, 0, sizeof goodby_dots);
394 entry.obj = goodby_dots.d_inode = parent;
395 goodby_dots.d_name.name = "..";
396 goodby_dots.d_name.len = 2;
397 result = reiser4_rem_entry_common(object, &goodby_dots, &entry);
398 reiser4_free_dentry_fsdata(&goodby_dots);
399 if (result == 0) {
400 /* the dot should be the only entry remaining at this time... */
401 assert("nikita-3400",
402 object->i_size == 1 && object->i_nlink <= 2);
403 #if 0
404 /* and, together with the only name directory can have, they
405 * provides for the last 2 remaining references. If we get
406 * here as part of error handling during mkdir, @object
407 * possibly has no name yet, so its nlink == 1. If we get here
408 * from rename (targeting empty directory), it has no name
409 * already, so its nlink == 1. */
410 assert("nikita-3401",
411 object->i_nlink == 2 || object->i_nlink == 1);
412 #endif
414 /* decrement nlink of directory removed ".." pointed
415 to */
416 reiser4_del_nlink(parent, NULL, 0);
418 return result;
421 /* this is common implementation of estimate.add_entry method of
422 dir plugin
423 estimation of adding entry which supposes that entry is inserting a
424 unit into item
426 reiser4_block_nr estimate_add_entry_common(const struct inode * inode)
428 return estimate_one_insert_into_item(reiser4_tree_by_inode(inode));
431 /* this is common implementation of estimate.rem_entry method of dir
432 plugin
434 reiser4_block_nr estimate_rem_entry_common(const struct inode * inode)
436 return estimate_one_item_removal(reiser4_tree_by_inode(inode));
439 /* this is common implementation of estimate.unlink method of dir
440 plugin
442 reiser4_block_nr
443 dir_estimate_unlink_common(const struct inode * parent,
444 const struct inode * object)
446 reiser4_block_nr res;
448 /* hashed_rem_entry(object) */
449 res = inode_dir_plugin(object)->estimate.rem_entry(object);
450 /* del_nlink(parent) */
451 res += 2 * inode_file_plugin(parent)->estimate.update(parent);
453 return res;
457 * helper for inode_ops ->lookup() and dir plugin's ->get_parent()
458 * methods: if @inode is a light-weight file, setup its credentials
459 * that are not stored in the stat-data in this case
461 void check_light_weight(struct inode *inode, struct inode *parent)
463 if (reiser4_inode_get_flag(inode, REISER4_LIGHT_WEIGHT)) {
464 inode->i_uid = parent->i_uid;
465 inode->i_gid = parent->i_gid;
466 /* clear light-weight flag. If inode would be read by any
467 other name, [ug]id wouldn't change. */
468 reiser4_inode_clr_flag(inode, REISER4_LIGHT_WEIGHT);
472 /* looks for name specified in @dentry in directory @parent and if name is
473 found - key of object found entry points to is stored in @entry->key */
474 int reiser4_lookup_name(struct inode *parent, /* inode of directory to lookup for
475 * name in */
476 struct dentry *dentry, /* name to look for */
477 reiser4_key * key /* place to store key */ )
479 int result;
480 coord_t *coord;
481 lock_handle lh;
482 const char *name;
483 int len;
484 reiser4_dir_entry_desc entry;
485 struct reiser4_dentry_fsdata *fsdata;
487 assert("nikita-1247", parent != NULL);
488 assert("nikita-1248", dentry != NULL);
489 assert("nikita-1123", dentry->d_name.name != NULL);
490 assert("vs-1486",
491 dentry->d_op == &get_super_private(parent->i_sb)->ops.dentry);
493 name = dentry->d_name.name;
494 len = dentry->d_name.len;
496 if (!inode_dir_plugin(parent)->is_name_acceptable(parent, name, len))
497 /* some arbitrary error code to return */
498 return RETERR(-ENAMETOOLONG);
500 fsdata = reiser4_get_dentry_fsdata(dentry);
501 if (IS_ERR(fsdata))
502 return PTR_ERR(fsdata);
504 coord = &fsdata->dec.entry_coord;
505 coord_clear_iplug(coord);
506 init_lh(&lh);
508 /* find entry in a directory. This is plugin method. */
509 result = reiser4_find_entry(parent, dentry, &lh, ZNODE_READ_LOCK,
510 &entry);
511 if (result == 0) {
512 /* entry was found, extract object key from it. */
513 result =
514 WITH_COORD(coord,
515 item_plugin_by_coord(coord)->s.dir.
516 extract_key(coord, key));
518 done_lh(&lh);
519 return result;
523 /* helper for reiser4_dir_init_common(): estimate number of blocks to reserve */
524 static reiser4_block_nr
525 estimate_init(struct inode *parent, struct inode *object)
527 reiser4_block_nr res = 0;
529 assert("vpf-321", parent != NULL);
530 assert("vpf-322", object != NULL);
532 /* hashed_add_entry(object) */
533 res += inode_dir_plugin(object)->estimate.add_entry(object);
534 /* reiser4_add_nlink(object) */
535 res += inode_file_plugin(object)->estimate.update(object);
536 /* hashed_add_entry(object) */
537 res += inode_dir_plugin(object)->estimate.add_entry(object);
538 /* reiser4_add_nlink(parent) */
539 res += inode_file_plugin(parent)->estimate.update(parent);
541 return 0;
544 /* helper function for reiser4_dir_init_common(). Create "." and ".." */
545 static int create_dot_dotdot(struct inode *object /* object to create dot and
546 * dotdot for */ ,
547 struct inode *parent /* parent of @object */)
549 int result;
550 struct dentry dots_entry;
551 reiser4_dir_entry_desc entry;
553 assert("nikita-688", object != NULL);
554 assert("nikita-689", S_ISDIR(object->i_mode));
555 assert("nikita-691", parent != NULL);
557 /* We store dot and dotdot as normal directory entries. This is
558 not necessary, because almost all information stored in them
559 is already in the stat-data of directory, the only thing
560 being missed is objectid of grand-parent directory that can
561 easily be added there as extension.
563 But it is done the way it is done, because not storing dot
564 and dotdot will lead to the following complications:
566 . special case handling in ->lookup().
567 . addition of another extension to the sd.
568 . dependency on key allocation policy for stat data.
572 memset(&entry, 0, sizeof entry);
573 memset(&dots_entry, 0, sizeof dots_entry);
574 entry.obj = dots_entry.d_inode = object;
575 dots_entry.d_name.name = ".";
576 dots_entry.d_name.len = 1;
577 result = reiser4_add_entry_common(object, &dots_entry, NULL, &entry);
578 reiser4_free_dentry_fsdata(&dots_entry);
580 if (result == 0) {
581 result = reiser4_add_nlink(object, object, 0);
582 if (result == 0) {
583 entry.obj = dots_entry.d_inode = parent;
584 dots_entry.d_name.name = "..";
585 dots_entry.d_name.len = 2;
586 result = reiser4_add_entry_common(object,
587 &dots_entry, NULL, &entry);
588 reiser4_free_dentry_fsdata(&dots_entry);
589 /* if creation of ".." failed, iput() will delete
590 object with ".". */
591 if (result == 0) {
592 result = reiser4_add_nlink(parent, object, 0);
593 if (result != 0)
595 * if we failed to bump i_nlink, try
596 * to remove ".."
598 reiser4_detach_common(object, parent);
603 if (result != 0) {
605 * in the case of error, at least update stat-data so that,
606 * ->i_nlink updates are not lingering.
608 reiser4_update_sd(object);
609 reiser4_update_sd(parent);
612 return result;
616 * return 0 iff @coord contains a directory entry for the file with the name
617 * @name.
619 static int
620 check_item(const struct inode *dir, const coord_t * coord, const char *name)
622 item_plugin *iplug;
623 char buf[DE_NAME_BUF_LEN];
625 iplug = item_plugin_by_coord(coord);
626 if (iplug == NULL) {
627 warning("nikita-1135", "Cannot get item plugin");
628 print_coord("coord", coord, 1);
629 return RETERR(-EIO);
630 } else if (item_id_by_coord(coord) !=
631 item_id_by_plugin(inode_dir_item_plugin(dir))) {
632 /* item id of current item does not match to id of items a
633 directory is built of */
634 warning("nikita-1136", "Wrong item plugin");
635 print_coord("coord", coord, 1);
636 return RETERR(-EIO);
638 assert("nikita-1137", iplug->s.dir.extract_name);
640 /* Compare name stored in this entry with name we are looking for.
642 NOTE-NIKITA Here should go code for support of something like
643 unicode, code tables, etc.
645 return !!strcmp(name, iplug->s.dir.extract_name(coord, buf));
648 static int
649 check_entry(const struct inode *dir, coord_t * coord, const struct qstr *name)
651 return WITH_COORD(coord, check_item(dir, coord, name->name));
655 * argument package used by entry_actor to scan entries with identical keys.
657 struct entry_actor_args {
658 /* name we are looking for */
659 const char *name;
660 /* key of directory entry. entry_actor() scans through sequence of
661 * items/units having the same key */
662 reiser4_key *key;
663 /* how many entries with duplicate key was scanned so far. */
664 int non_uniq;
665 #if REISER4_USE_COLLISION_LIMIT
666 /* scan limit */
667 int max_non_uniq;
668 #endif
669 /* return parameter: set to true, if ->name wasn't found */
670 int not_found;
671 /* what type of lock to take when moving to the next node during
672 * scan */
673 znode_lock_mode mode;
675 /* last coord that was visited during scan */
676 coord_t last_coord;
677 /* last node locked during scan */
678 lock_handle last_lh;
679 /* inode of directory */
680 const struct inode *inode;
683 /* Function called by reiser4_find_entry() to look for given name
684 in the directory. */
685 static int entry_actor(reiser4_tree * tree UNUSED_ARG /* tree being scanned */ ,
686 coord_t * coord /* current coord */ ,
687 lock_handle * lh /* current lock handle */ ,
688 void *entry_actor_arg /* argument to scan */ )
690 reiser4_key unit_key;
691 struct entry_actor_args *args;
693 assert("nikita-1131", tree != NULL);
694 assert("nikita-1132", coord != NULL);
695 assert("nikita-1133", entry_actor_arg != NULL);
697 args = entry_actor_arg;
698 ++args->non_uniq;
699 #if REISER4_USE_COLLISION_LIMIT
700 if (args->non_uniq > args->max_non_uniq) {
701 args->not_found = 1;
702 /* hash collision overflow. */
703 return RETERR(-EBUSY);
705 #endif
708 * did we just reach the end of the sequence of items/units with
709 * identical keys?
711 if (!keyeq(args->key, unit_key_by_coord(coord, &unit_key))) {
712 assert("nikita-1791",
713 keylt(args->key, unit_key_by_coord(coord, &unit_key)));
714 args->not_found = 1;
715 args->last_coord.between = AFTER_UNIT;
716 return 0;
719 coord_dup(&args->last_coord, coord);
721 * did scan just moved to the next node?
723 if (args->last_lh.node != lh->node) {
724 int lock_result;
727 * if so, lock new node with the mode requested by the caller
729 done_lh(&args->last_lh);
730 assert("nikita-1896", znode_is_any_locked(lh->node));
731 lock_result = longterm_lock_znode(&args->last_lh, lh->node,
732 args->mode, ZNODE_LOCK_HIPRI);
733 if (lock_result != 0)
734 return lock_result;
736 return check_item(args->inode, coord, args->name);
739 /* Look for given @name within directory @dir.
741 This is called during lookup, creation and removal of directory
742 entries and on reiser4_rename_common
744 First calculate key that directory entry for @name would have. Search
745 for this key in the tree. If such key is found, scan all items with
746 the same key, checking name in each directory entry along the way.
748 int reiser4_find_entry(struct inode *dir, /* directory to scan */
749 struct dentry *de, /* name to search for */
750 lock_handle * lh, /* resulting lock handle */
751 znode_lock_mode mode, /* required lock mode */
752 reiser4_dir_entry_desc * entry /* parameters of found
753 directory entry */)
755 const struct qstr *name;
756 seal_t *seal;
757 coord_t *coord;
758 int result;
759 __u32 flags;
760 struct de_location *dec;
761 struct reiser4_dentry_fsdata *fsdata;
763 assert("nikita-1130", lh != NULL);
764 assert("nikita-1128", dir != NULL);
766 name = &de->d_name;
767 assert("nikita-1129", name != NULL);
769 /* dentry private data don't require lock, because dentry
770 manipulations are protected by i_mutex on parent.
772 This is not so for inodes, because there is no -the- parent in
773 inode case.
775 fsdata = reiser4_get_dentry_fsdata(de);
776 if (IS_ERR(fsdata))
777 return PTR_ERR(fsdata);
778 dec = &fsdata->dec;
780 coord = &dec->entry_coord;
781 coord_clear_iplug(coord);
782 seal = &dec->entry_seal;
783 /* compose key of directory entry for @name */
784 inode_dir_plugin(dir)->build_entry_key(dir, name, &entry->key);
786 if (reiser4_seal_is_set(seal)) {
787 /* check seal */
788 result = reiser4_seal_validate(seal, coord, &entry->key,
789 lh, mode, ZNODE_LOCK_LOPRI);
790 if (result == 0) {
791 /* key was found. Check that it is really item we are
792 looking for. */
793 result = check_entry(dir, coord, name);
794 if (result == 0)
795 return 0;
798 flags = (mode == ZNODE_WRITE_LOCK) ? CBK_FOR_INSERT : 0;
800 * find place in the tree where directory item should be located.
802 result = reiser4_object_lookup(dir, &entry->key, coord, lh, mode,
803 FIND_EXACT, LEAF_LEVEL, LEAF_LEVEL,
804 flags, NULL /*ra_info */ );
805 if (result == CBK_COORD_FOUND) {
806 struct entry_actor_args arg;
808 /* fast path: no hash collisions */
809 result = check_entry(dir, coord, name);
810 if (result == 0) {
811 reiser4_seal_init(seal, coord, &entry->key);
812 dec->pos = 0;
813 } else if (result > 0) {
814 /* Iterate through all units with the same keys. */
815 arg.name = name->name;
816 arg.key = &entry->key;
817 arg.not_found = 0;
818 arg.non_uniq = 0;
819 #if REISER4_USE_COLLISION_LIMIT
820 arg.max_non_uniq = max_hash_collisions(dir);
821 assert("nikita-2851", arg.max_non_uniq > 1);
822 #endif
823 arg.mode = mode;
824 arg.inode = dir;
825 coord_init_zero(&arg.last_coord);
826 init_lh(&arg.last_lh);
828 result = reiser4_iterate_tree
829 (reiser4_tree_by_inode(dir),
830 coord, lh,
831 entry_actor, &arg, mode, 1);
832 /* if end of the tree or extent was reached during
833 scanning. */
834 if (arg.not_found || (result == -E_NO_NEIGHBOR)) {
835 /* step back */
836 done_lh(lh);
838 result = zload(arg.last_coord.node);
839 if (result == 0) {
840 coord_clear_iplug(&arg.last_coord);
841 coord_dup(coord, &arg.last_coord);
842 move_lh(lh, &arg.last_lh);
843 result = RETERR(-ENOENT);
844 zrelse(arg.last_coord.node);
845 --arg.non_uniq;
849 done_lh(&arg.last_lh);
850 if (result == 0)
851 reiser4_seal_init(seal, coord, &entry->key);
853 if (result == 0 || result == -ENOENT) {
854 assert("nikita-2580", arg.non_uniq > 0);
855 dec->pos = arg.non_uniq - 1;
858 } else
859 dec->pos = -1;
860 return result;
864 Local variables:
865 c-indentation-style: "K&R"
866 mode-name: "LC"
867 c-basic-offset: 8
868 tab-width: 8
869 fill-column: 120
870 scroll-step: 1
871 End: