1/*-
2 * Copyright 2000 Hans Reiser
3 * See README for licensing and copyright details
4 *
5 * Ported to FreeBSD by Jean-S�bastien P�dron <jspedron@club-internet.fr>
6 *
7 * $FreeBSD$
8 */
9
10#include <gnu/fs/reiserfs/reiserfs_fs.h>
11
12/* Minimal possible key. It is never in the tree. */
13const struct key MIN_KEY = {
14	0,
15	0,
16	{ {0, 0}, }
17};
18
19/* Maximal possible key. It is never in the tree. */
20const struct key MAX_KEY = {
21	0xffffffff,
22	0xffffffff,
23	{ {0xffffffff, 0xffffffff }, }
24};
25
26/* Does the buffer contain a disk block which is in the tree. */
27int
28B_IS_IN_TREE(const struct buf *p_s_bp)
29{
30
31	return (B_LEVEL(p_s_bp) != FREE_LEVEL);
32}
33
34/* To gets item head in le form */
35void
36copy_item_head(struct item_head *p_v_to, const struct item_head *p_v_from)
37{
38
39	memcpy(p_v_to, p_v_from, IH_SIZE);
40}
41
42/*
43 * k1 is pointer to on-disk structure which is stored in little-endian
44 * form. k2 is pointer to cpu variable. For key of items of the same
45 * object this returns 0.
46 * Returns: -1 if key1 < key2, 0 if key1 == key2 or 1 if key1 > key2
47 */
48/*inline*/ int
49comp_short_keys(const struct key *le_key, const struct cpu_key *cpu_key)
50{
51	const uint32_t *p_s_le_u32, *p_s_cpu_u32;
52	int n_key_length = REISERFS_SHORT_KEY_LEN;
53
54	p_s_le_u32  = (const uint32_t *)le_key;
55	p_s_cpu_u32 = (const uint32_t *)&cpu_key->on_disk_key;
56	for(; n_key_length--; ++p_s_le_u32, ++p_s_cpu_u32) {
57		if (le32toh(*p_s_le_u32) < *p_s_cpu_u32)
58			return (-1);
59		if (le32toh(*p_s_le_u32) > *p_s_cpu_u32)
60			return (1);
61	}
62
63	return (0);
64}
65
66/*
67 * k1 is pointer to on-disk structure which is stored in little-endian
68 * form. k2 is pointer to cpu variable. Compare keys using all 4 key
69 * fields.
70 * Returns: -1 if key1 < key2, 0 if key1 = key2 or 1 if key1 > key2
71 */
72/*inline*/ int
73comp_keys(const struct key *le_key, const struct cpu_key *cpu_key)
74{
75	int retval;
76
77	retval = comp_short_keys(le_key, cpu_key);
78	if (retval)
79		return retval;
80
81	if (le_key_k_offset(le_key_version(le_key), le_key) <
82	    cpu_key_k_offset(cpu_key))
83		return (-1);
84	if (le_key_k_offset(le_key_version(le_key), le_key) >
85	    cpu_key_k_offset(cpu_key))
86		return (1);
87
88	if (cpu_key->key_length == 3)
89		return (0);
90
91	/* This part is needed only when tail conversion is in progress */
92	if (le_key_k_type(le_key_version(le_key), le_key) <
93	    cpu_key_k_type(cpu_key))
94		return (-1);
95
96	if (le_key_k_type(le_key_version(le_key), le_key) >
97	    cpu_key_k_type(cpu_key))
98		return (1);
99
100	return (0);
101}
102
103/* Release all buffers in the path. */
104void
105pathrelse(struct path *p_s_search_path)
106{
107	struct buf *bp;
108	int n_path_offset = p_s_search_path->path_length;
109
110	while (n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET) {
111		bp = PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--);
112		free(bp->b_data, M_REISERFSPATH);
113		free(bp, M_REISERFSPATH);
114	}
115
116	p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
117}
118
119/*
120 * This does not say which one is bigger, it only returns 1 if keys
121 * are not equal, 0 otherwise
122 */
123int
124comp_le_keys(const struct key *k1, const struct key *k2)
125{
126
127	return (memcmp(k1, k2, sizeof(struct key)));
128}
129
130/*
131 * Binary search toolkit function. Search for an item in the array by
132 * the item key.
133 * Returns: 1 if found,  0 if not found;
134 *          *p_n_pos = number of the searched element if found, else the
135 *          number of the first element that is larger than p_v_key.
136 */
137/*
138 * For those not familiar with binary search: n_lbound is the leftmost
139 * item that it could be, n_rbound the rightmost item that it could be.
140 * We examine the item halfway between n_lbound and n_rbound, and that
141 * tells us either that we can increase n_lbound, or decrease n_rbound,
142 * or that we have found it, or if n_lbound <= n_rbound that there are
143 * no possible items, and we have not found it. With each examination we
144 * cut the number of possible items it could be by one more than half
145 * rounded down, or we find it.
146 */
147int
148bin_search(const void *p_v_key,  /* Key to search for. */
149    const void *p_v_base, /* First item in the array. */
150    int p_n_num,          /* Number of items in the array. */
151    int p_n_width,        /* Item size in the array. searched. Lest the
152			     reader be confused, note that this is crafted
153			     as a general function, and when it is applied
154			     specifically to the array of item headers in
155			     a node, p_n_width is actually the item header
156			     size not the item size. */
157    int *p_n_pos)         /* Number of the searched for element. */
158{
159	int n_rbound, n_lbound, n_j;
160
161	for (n_j = ((n_rbound = p_n_num - 1) + (n_lbound = 0)) / 2;
162	    n_lbound <= n_rbound; n_j = (n_rbound + n_lbound) / 2) {
163		switch (COMP_KEYS((const struct key *)
164		    ((const char *)p_v_base + n_j * p_n_width),
165		    (const struct cpu_key *)p_v_key)) {
166		case -1:
167			n_lbound = n_j + 1;
168			continue;
169		case 1:
170			n_rbound = n_j - 1;
171			continue;
172		case 0:
173			*p_n_pos = n_j;
174			return (ITEM_FOUND); /* Key found in the array. */
175		}
176	}
177
178	/*
179	 * bin_search did not find given key, it returns position of key,
180	 * that is minimal and greater than the given one.
181	 */
182	*p_n_pos = n_lbound;
183	return (ITEM_NOT_FOUND);
184}
185
186/*
187 * Get delimiting key of the buffer by looking for it in the buffers in
188 * the path, starting from the bottom of the path, and going upwards. We
189 * must check the path's validity at each step. If the key is not in the
190 * path, there is no delimiting key in the tree (buffer is first or last
191 * buffer in tree), and in this case we return a special key, either
192 * MIN_KEY or MAX_KEY.
193 */
194const struct key *
195get_lkey(const struct path *p_s_chk_path,
196    const struct reiserfs_sb_info *p_s_sbi)
197{
198	struct buf *p_s_parent;
199	int n_position, n_path_offset = p_s_chk_path->path_length;
200
201	/* While not higher in path than first element. */
202	while (n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
203		/* Parent at the path is not in the tree now. */
204		if (!B_IS_IN_TREE(p_s_parent =
205		    PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)))
206			return (&MAX_KEY);
207
208		/* Check whether position in the parent is correct. */
209		if ((n_position = PATH_OFFSET_POSITION(p_s_chk_path,
210		    n_path_offset)) > B_NR_ITEMS(p_s_parent))
211			return (&MAX_KEY);
212
213		/*
214		 * Check whether parent at the path really points to
215		 * the child.
216		 */
217		if (B_N_CHILD_NUM(p_s_parent, n_position) !=
218		    (PATH_OFFSET_PBUFFER(p_s_chk_path,
219					 n_path_offset + 1)->b_blkno
220		     / btodb(p_s_sbi->s_blocksize)))
221			return (&MAX_KEY);
222
223		/*
224		 * Return delimiting key if position in the parent is not
225		 * equal to zero.
226		 */
227		if (n_position)
228			return (B_N_PDELIM_KEY(p_s_parent, n_position - 1));
229	}
230
231	/* Return MIN_KEY if we are in the root of the buffer tree. */
232	if ((PATH_OFFSET_PBUFFER(p_s_chk_path,
233	    FIRST_PATH_ELEMENT_OFFSET)->b_blkno
234	    / btodb(p_s_sbi->s_blocksize)) == SB_ROOT_BLOCK(p_s_sbi))
235		return (&MIN_KEY);
236
237	return (&MAX_KEY);
238}
239
240/* Get delimiting key of the buffer at the path and its right neighbor. */
241const struct key *
242get_rkey(const struct path *p_s_chk_path,
243    const struct reiserfs_sb_info *p_s_sbi)
244{
245	struct buf *p_s_parent;
246	int n_position, n_path_offset = p_s_chk_path->path_length;
247
248	while (n_path_offset-- > FIRST_PATH_ELEMENT_OFFSET) {
249		/* Parent at the path is not in the tree now. */
250		if (!B_IS_IN_TREE(p_s_parent =
251		    PATH_OFFSET_PBUFFER(p_s_chk_path, n_path_offset)))
252			return (&MIN_KEY);
253
254		/* Check whether position in the parent is correct. */
255		if ((n_position = PATH_OFFSET_POSITION(p_s_chk_path,
256		    n_path_offset)) >
257		    B_NR_ITEMS(p_s_parent))
258			return (&MIN_KEY);
259
260		/*
261		 * Check whether parent at the path really points to the
262		 * child.
263		 */
264		if (B_N_CHILD_NUM(p_s_parent, n_position) !=
265		    (PATH_OFFSET_PBUFFER(p_s_chk_path,
266					 n_path_offset + 1)->b_blkno
267		     / btodb(p_s_sbi->s_blocksize)))
268			return (&MIN_KEY);
269
270		/*
271		 * Return delimiting key if position in the parent is not
272		 * the last one.
273		 */
274		if (n_position != B_NR_ITEMS(p_s_parent))
275			return (B_N_PDELIM_KEY(p_s_parent, n_position));
276	}
277
278	/* Return MAX_KEY if we are in the root of the buffer tree. */
279	if ((PATH_OFFSET_PBUFFER(p_s_chk_path,
280	    FIRST_PATH_ELEMENT_OFFSET)->b_blkno
281	    / btodb(p_s_sbi->s_blocksize)) == SB_ROOT_BLOCK(p_s_sbi))
282		return (&MAX_KEY);
283
284	return (&MIN_KEY);
285}
286
287int
288reiserfs_check_path(struct path *p)
289{
290
291	if (p->path_length != ILLEGAL_PATH_ELEMENT_OFFSET)
292		reiserfs_log(LOG_WARNING, "path not properly relsed\n");
293	return (0);
294}
295
296/*
297 * Check whether a key is contained in the tree rooted from a buffer at
298 * a path. This works by looking at the left and right delimiting keys
299 * for the buffer in the last path_element in the path. These delimiting
300 * keys are stored at least one level above that buffer in the tree.
301 * If the buffer is the first or last node in the tree order then one
302 * of the delimiting keys may be absent, and in this case get_lkey and
303 * get_rkey return a special key which is MIN_KEY or MAX_KEY.
304 */
305static inline int
306key_in_buffer(
307    struct path *p_s_chk_path,         /* Path which should be checked. */
308    const struct cpu_key *p_s_key,     /* Key which should be checked. */
309    struct reiserfs_sb_info  *p_s_sbi) /* Super block pointer. */
310{
311
312	if (COMP_KEYS(get_lkey(p_s_chk_path, p_s_sbi), p_s_key) == 1)
313		/* left delimiting key is bigger, that the key we look for */
314		return (0);
315
316	if (COMP_KEYS(get_rkey(p_s_chk_path, p_s_sbi), p_s_key) != 1)
317		/* p_s_key must be less than right delimitiing key */
318		return (0);
319
320	return (1);
321}
322
323#if 0
324/* XXX Il ne semble pas y avoir de compteur de r�f�rence dans struct buf */
325inline void
326decrement_bcount(struct buf *p_s_bp)
327{
328
329	if (p_s_bp) {
330		if (atomic_read(&(p_s_bp->b_count))) {
331			put_bh(p_s_bp);
332			return;
333		}
334	}
335}
336#endif
337
338/* Decrement b_count field of the all buffers in the path. */
339void
340decrement_counters_in_path(struct path *p_s_search_path)
341{
342
343	pathrelse(p_s_search_path);
344#if 0
345	int n_path_offset = p_s_search_path->path_length;
346
347	while (n_path_offset > ILLEGAL_PATH_ELEMENT_OFFSET) {
348		struct buf *bp;
349
350		bp = PATH_OFFSET_PBUFFER(p_s_search_path, n_path_offset--);
351		decrement_bcount(bp);
352	}
353
354	p_s_search_path->path_length = ILLEGAL_PATH_ELEMENT_OFFSET;
355#endif
356}
357
358static int
359is_leaf(char *buf, int blocksize, struct buf *bp)
360{
361	struct item_head *ih;
362	struct block_head *blkh;
363	int used_space, prev_location, i, nr;
364
365	blkh = (struct block_head *)buf;
366	if (blkh_level(blkh) != DISK_LEAF_NODE_LEVEL) {
367		reiserfs_log(LOG_WARNING, "this should be caught earlier");
368		return (0);
369	}
370
371	nr = blkh_nr_item(blkh);
372	if (nr < 1 || nr >
373	    ((blocksize - BLKH_SIZE) / (IH_SIZE + MIN_ITEM_LEN))) {
374		/* Item number is too big or too small */
375		reiserfs_log(LOG_WARNING, "nr_item seems wrong\n");
376		return (0);
377	}
378
379	ih = (struct item_head *)(buf + BLKH_SIZE) + nr - 1;
380	used_space = BLKH_SIZE + IH_SIZE * nr + (blocksize - ih_location(ih));
381	if (used_space != blocksize - blkh_free_space(blkh)) {
382		/*
383		 * Free space does not match to calculated amount of
384		 * use space
385		 */
386		reiserfs_log(LOG_WARNING, "free space seems wrong\n");
387		return (0);
388	}
389
390	/* FIXME: it is_leaf will hit performance too much - we may have
391	 * return 1 here */
392
393	/* Check tables of item heads */
394	ih = (struct item_head *)(buf + BLKH_SIZE);
395	prev_location = blocksize;
396	for (i = 0; i < nr; i++, ih++) {
397		if (le_ih_k_type(ih) == TYPE_ANY) {
398			reiserfs_log(LOG_WARNING,
399			    "wrong item type for item\n");
400			return (0);
401		}
402		if (ih_location(ih) >= blocksize ||
403		    ih_location(ih) < IH_SIZE * nr) {
404			reiserfs_log(LOG_WARNING,
405			    "item location seems wrong\n");
406			return (0);
407		}
408		if (ih_item_len(ih) < 1 ||
409		    ih_item_len(ih) > MAX_ITEM_LEN(blocksize)) {
410			reiserfs_log(LOG_WARNING, "item length seems wrong\n");
411			return (0);
412		}
413		if (prev_location - ih_location(ih) != ih_item_len(ih)) {
414			reiserfs_log(LOG_WARNING,
415			    "item location seems wrong (second one)\n");
416			return (0);
417		}
418		prev_location = ih_location(ih);
419	}
420
421	/* One may imagine much more checks */
422	return 1;
423}
424
425/* Returns 1 if buf looks like an internal node, 0 otherwise */
426static int
427is_internal(char *buf, int blocksize, struct buf *bp)
428{
429	int nr, used_space;
430	struct block_head *blkh;
431
432	blkh = (struct block_head *)buf;
433	nr   = blkh_level(blkh);
434	if (nr <= DISK_LEAF_NODE_LEVEL || nr > MAX_HEIGHT) {
435		/* This level is not possible for internal nodes */
436		reiserfs_log(LOG_WARNING, "this should be caught earlier\n");
437		return (0);
438	}
439
440	nr = blkh_nr_item(blkh);
441	if (nr > (blocksize - BLKH_SIZE - DC_SIZE) / (KEY_SIZE + DC_SIZE)) {
442		/*
443		 * For internal which is not root we might check min
444		 * number of keys
445		 */
446		reiserfs_log(LOG_WARNING, "number of key seems wrong\n");
447		return (0);
448	}
449
450	used_space = BLKH_SIZE + KEY_SIZE * nr + DC_SIZE * (nr + 1);
451	if (used_space != blocksize - blkh_free_space(blkh)) {
452		reiserfs_log(LOG_WARNING,
453		    "is_internal: free space seems wrong\n");
454		return (0);
455	}
456
457	/* One may imagine much more checks */
458	return (1);
459}
460
461/*
462 * Make sure that bh contains formatted node of reiserfs tree of
463 * 'level'-th level
464 */
465static int
466is_tree_node(struct buf *bp, int level)
467{
468	if (B_LEVEL(bp) != level) {
469		reiserfs_log(LOG_WARNING,
470		    "node level (%d) doesn't match to the "
471		    "expected one (%d)\n", B_LEVEL (bp), level);
472		return (0);
473	}
474
475	if (level == DISK_LEAF_NODE_LEVEL)
476		return (is_leaf(bp->b_data, bp->b_bcount, bp));
477
478	return (is_internal(bp->b_data, bp->b_bcount, bp));
479}
480
481int
482search_by_key(struct reiserfs_sb_info *p_s_sbi,
483    const struct cpu_key * p_s_key, /* Key to search. */
484    struct path * p_s_search_path,  /* This structure was allocated and
485				       initialized by the calling function.
486				       It is filled up by this function. */
487    int n_stop_level)               /* How far down the tree to search. To
488				       stop at leaf level - set to
489				       DISK_LEAF_NODE_LEVEL */
490{
491	int error;
492	int n_node_level, n_retval;
493	int n_block_number, expected_level, fs_gen;
494	struct path_element *p_s_last_element;
495	struct buf *p_s_bp, *tmp_bp;
496
497	/*
498	 * As we add each node to a path we increase its count. This means that
499	 * we must be careful to release all nodes in a path before we either
500	 * discard the path struct or re-use the path struct, as we do here.
501	 */
502	decrement_counters_in_path(p_s_search_path);
503
504	/*
505	 * With each iteration of this loop we search through the items in the
506	 * current node, and calculate the next current node(next path element)
507	 * for the next iteration of this loop...
508	 */
509	n_block_number = SB_ROOT_BLOCK(p_s_sbi);
510	expected_level = -1;
511
512	reiserfs_log(LOG_DEBUG, "root block: #%d\n", n_block_number);
513
514	while (1) {
515		/* Prep path to have another element added to it. */
516		reiserfs_log(LOG_DEBUG, "path element #%d\n",
517		    p_s_search_path->path_length);
518		p_s_last_element = PATH_OFFSET_PELEMENT(p_s_search_path,
519		    ++p_s_search_path->path_length);
520		fs_gen = get_generation(p_s_sbi);
521
522		/*
523		 * Read the next tree node, and set the last element in the
524		 * path to have a pointer to it.
525		 */
526		reiserfs_log(LOG_DEBUG, "reading block #%d\n",
527		    n_block_number);
528		if ((error = bread(p_s_sbi->s_devvp,
529		    n_block_number * btodb(p_s_sbi->s_blocksize),
530		    p_s_sbi->s_blocksize, NOCRED, &tmp_bp)) != 0) {
531			reiserfs_log(LOG_DEBUG, "error reading block\n");
532			p_s_search_path->path_length--;
533			pathrelse(p_s_search_path);
534			return (IO_ERROR);
535		}
536		reiserfs_log(LOG_DEBUG, "blkno = %ju, lblkno = %ju\n",
537		    (intmax_t)tmp_bp->b_blkno, (intmax_t)tmp_bp->b_lblkno);
538
539		/*
540		 * As i didn't found a way to handle the lock correctly,
541		 * i copy the data into a fake buffer
542		 */
543		reiserfs_log(LOG_DEBUG, "allocating p_s_bp\n");
544		p_s_bp = malloc(sizeof *p_s_bp, M_REISERFSPATH, M_WAITOK);
545		if (!p_s_bp) {
546			reiserfs_log(LOG_DEBUG, "error allocating memory\n");
547			p_s_search_path->path_length--;
548			pathrelse(p_s_search_path);
549			brelse(tmp_bp);
550			return (IO_ERROR);
551		}
552		reiserfs_log(LOG_DEBUG, "copying struct buf\n");
553		bcopy(tmp_bp, p_s_bp, sizeof(struct buf));
554
555		reiserfs_log(LOG_DEBUG, "allocating p_s_bp->b_data\n");
556		p_s_bp->b_data = malloc(p_s_sbi->s_blocksize,
557		    M_REISERFSPATH, M_WAITOK);
558		if (!p_s_bp->b_data) {
559			reiserfs_log(LOG_DEBUG, "error allocating memory\n");
560			p_s_search_path->path_length--;
561			pathrelse(p_s_search_path);
562			free(p_s_bp, M_REISERFSPATH);
563			brelse(tmp_bp);
564			return (IO_ERROR);
565		}
566		reiserfs_log(LOG_DEBUG, "copying buffer data\n");
567		bcopy(tmp_bp->b_data, p_s_bp->b_data, p_s_sbi->s_blocksize);
568		brelse(tmp_bp);
569		tmp_bp = NULL;
570
571		reiserfs_log(LOG_DEBUG, "...done\n");
572		p_s_last_element->pe_buffer = p_s_bp;
573
574		if (expected_level == -1)
575			expected_level = SB_TREE_HEIGHT(p_s_sbi);
576		expected_level--;
577		reiserfs_log(LOG_DEBUG, "expected level: %d (%d)\n",
578		    expected_level, SB_TREE_HEIGHT(p_s_sbi));
579
580		/* XXX */
581		/*
582		 * It is possible that schedule occurred. We must check
583		 * whether the key to search is still in the tree rooted
584		 * from the current buffer. If not then repeat search
585		 * from the root.
586		 */
587		if (fs_changed(fs_gen, p_s_sbi) &&
588		    (!B_IS_IN_TREE(p_s_bp) ||
589		     B_LEVEL(p_s_bp) != expected_level ||
590		     !key_in_buffer(p_s_search_path, p_s_key, p_s_sbi))) {
591			reiserfs_log(LOG_DEBUG,
592			    "the key isn't in the tree anymore\n");
593			decrement_counters_in_path(p_s_search_path);
594
595			/*
596			 * Get the root block number so that we can repeat
597			 * the search starting from the root.
598			 */
599			n_block_number = SB_ROOT_BLOCK(p_s_sbi);
600			expected_level = -1;
601
602			/* Repeat search from the root */
603			continue;
604		}
605
606		/*
607		 * Make sure, that the node contents look like a node of
608		 * certain level
609		 */
610		if (!is_tree_node(p_s_bp, expected_level)) {
611			reiserfs_log(LOG_WARNING,
612			    "invalid format found in block %ju. Fsck?",
613			    (intmax_t)p_s_bp->b_blkno);
614			pathrelse (p_s_search_path);
615			return (IO_ERROR);
616		}
617
618		/* Ok, we have acquired next formatted node in the tree */
619		n_node_level = B_LEVEL(p_s_bp);
620		reiserfs_log(LOG_DEBUG, "block info:\n");
621		reiserfs_log(LOG_DEBUG, "  node level:  %d\n",
622		    n_node_level);
623		reiserfs_log(LOG_DEBUG, "  nb of items: %d\n",
624		    B_NR_ITEMS(p_s_bp));
625		reiserfs_log(LOG_DEBUG, "  free space:  %d bytes\n",
626		    B_FREE_SPACE(p_s_bp));
627		reiserfs_log(LOG_DEBUG, "bin_search with :\n"
628		    "  p_s_key = (objectid=%d, dirid=%d)\n"
629		    "  B_NR_ITEMS(p_s_bp) = %d\n"
630		    "  p_s_last_element->pe_position = %d (path_length = %d)\n",
631		    p_s_key->on_disk_key.k_objectid,
632		    p_s_key->on_disk_key.k_dir_id,
633		    B_NR_ITEMS(p_s_bp),
634		    p_s_last_element->pe_position,
635		    p_s_search_path->path_length);
636		n_retval = bin_search(p_s_key, B_N_PITEM_HEAD(p_s_bp, 0),
637		    B_NR_ITEMS(p_s_bp),
638		    (n_node_level == DISK_LEAF_NODE_LEVEL) ? IH_SIZE : KEY_SIZE,
639		    &(p_s_last_element->pe_position));
640		reiserfs_log(LOG_DEBUG, "bin_search result: %d\n",
641		    n_retval);
642		if (n_node_level == n_stop_level) {
643			reiserfs_log(LOG_DEBUG, "stop level reached (%s)\n",
644			    n_retval == ITEM_FOUND ? "found" : "not found");
645			return (n_retval);
646		}
647
648		/* We are not in the stop level */
649		if (n_retval == ITEM_FOUND)
650			/*
651			 * Item has been found, so we choose the pointer
652			 * which is to the right of the found one
653			 */
654			p_s_last_element->pe_position++;
655
656		/*
657		 * If item was not found we choose the position which is
658		 * to the left of the found item. This requires no code,
659		 * bin_search did it already.
660		 */
661
662		/*
663		 * So we have chosen a position in the current node which
664		 * is an internal node. Now we calculate child block number
665		 * by position in the node.
666		 */
667		n_block_number = B_N_CHILD_NUM(p_s_bp,
668		    p_s_last_element->pe_position);
669	}
670
671	reiserfs_log(LOG_DEBUG, "done\n");
672	return (0);
673}
674
675/*
676 * Form the path to an item and position in this item which contains
677 * file byte defined by p_s_key. If there is no such item corresponding
678 * to the key, we point the path to the item with maximal key less than
679 * p_s_key, and *p_n_pos_in_item is set to one past the last entry/byte
680 * in the item. If searching for entry in a directory item, and it is
681 * not found, *p_n_pos_in_item is set to one entry more than the entry
682 * with maximal key which is less than the sought key.
683 *
684 * Note that if there is no entry in this same node which is one more,
685 * then we point to an imaginary entry. For direct items, the position
686 * is in units of bytes, for indirect items the position is in units
687 * of blocknr entries, for directory items the position is in units of
688 * directory entries.
689 */
690
691/* The function is NOT SCHEDULE-SAFE! */
692int
693search_for_position_by_key(struct reiserfs_sb_info *p_s_sbi,
694    const struct cpu_key *p_cpu_key, /* Key to search (cpu variable) */
695    struct path *p_s_search_path)    /* Filled up by this function.  */
696{
697	int retval, n_blk_size;
698	off_t item_offset, offset;
699	struct item_head *p_le_ih; /* Pointer to on-disk structure */
700	struct reiserfs_dir_entry de;
701
702	/* If searching for directory entry. */
703	if (is_direntry_cpu_key(p_cpu_key))
704		return (search_by_entry_key(p_s_sbi, p_cpu_key,
705		    p_s_search_path, &de));
706
707	/* If not searching for directory entry. */
708
709	/* If item is found. */
710	retval = search_item(p_s_sbi, p_cpu_key, p_s_search_path);
711	if (retval == IO_ERROR)
712		return (retval);
713	if (retval == ITEM_FOUND) {
714		if (ih_item_len(B_N_PITEM_HEAD(
715		    PATH_PLAST_BUFFER(p_s_search_path),
716		    PATH_LAST_POSITION(p_s_search_path))) == 0) {
717			reiserfs_log(LOG_WARNING, "item length equals zero\n");
718		}
719
720		pos_in_item(p_s_search_path) = 0;
721		return (POSITION_FOUND);
722	}
723
724	if (PATH_LAST_POSITION(p_s_search_path) == 0) {
725		reiserfs_log(LOG_WARNING, "position equals zero\n");
726	}
727
728	/* Item is not found. Set path to the previous item. */
729	p_le_ih = B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_search_path),
730	    --PATH_LAST_POSITION(p_s_search_path));
731	n_blk_size = p_s_sbi->s_blocksize;
732
733	if (comp_short_keys(&(p_le_ih->ih_key), p_cpu_key)) {
734		return (FILE_NOT_FOUND);
735	}
736
737	item_offset = le_ih_k_offset(p_le_ih);
738	offset = cpu_key_k_offset(p_cpu_key);
739
740	/* Needed byte is contained in the item pointed to by the path.*/
741	if (item_offset <= offset &&
742	    item_offset + op_bytes_number(p_le_ih, n_blk_size) > offset) {
743		pos_in_item(p_s_search_path) = offset - item_offset;
744		if (is_indirect_le_ih(p_le_ih)) {
745			pos_in_item(p_s_search_path) /= n_blk_size;
746		}
747		return (POSITION_FOUND);
748	}
749
750	/* Needed byte is not contained in the item pointed to by the
751	 * path. Set pos_in_item out of the item. */
752	if (is_indirect_le_ih(p_le_ih))
753		pos_in_item(p_s_search_path) =
754		    ih_item_len(p_le_ih) / UNFM_P_SIZE;
755	else
756		pos_in_item(p_s_search_path) =
757		    ih_item_len(p_le_ih);
758
759	return (POSITION_NOT_FOUND);
760}
761