Beispiel #1
0
/* first calls search_by_key, then, if item is not found looks for the entry inside directory item indicated by
   search_by_key. (We assign a key to each directory item, and place multiple entries in a single directory item.)
   Fills the path to the entry, and to the entry position in the item */
int search_by_entry_key (struct super_block * sb, struct key * key, struct path * path, int * pos_in_item, int * repeat)
{
  /* search for a directory item using key of entry */
  if (search_by_key (sb, key, path, repeat, DISK_LEAF_NODE_LEVEL, READ_BLOCKS) == ITEM_FOUND) {
    *pos_in_item = 0;
    return POSITION_FOUND;
  }
#ifdef REISERFS_CHECK
  if (!PATH_LAST_POSITION (path))
    reiserfs_panic (sb, "vs-7000: search_by_entry_key: search_by_key returned item position == 0");
#endif /* REISERFS_CHECK */
  PATH_LAST_POSITION (path) --;

#ifdef REISERFS_CHECK
  {
    struct item_head * ih = B_N_PITEM_HEAD (PATH_PLAST_BUFFER (path), PATH_LAST_POSITION (path));

    if (!I_IS_DIRECTORY_ITEM (ih) || COMP_SHORT_KEYS (&(ih->ih_key), key)) {
      print_block (PATH_PLAST_BUFFER (path), 0, -1, -1);
      reiserfs_panic (sb, "vs-7005: search_by_entry_key: found item %h is not directory item or "
		      "does not belong to the same directory as key %k", ih, key);
    }
  }
#endif /* REISERFS_CHECK */

  /* binary search in directory item by third component of the key */
  return bin_search_in_dir_item (PATH_PITEM_HEAD (path), B_I_DEH (PATH_PLAST_BUFFER (path), PATH_PITEM_HEAD (path)), key, pos_in_item);
}
Beispiel #2
0
static int reiserfs_find_entry (struct inode * dir, const char * name, int namelen, struct path * path_to_entry, struct reiserfs_dir_entry * de)
{
  struct key key_to_search;
  int repeat;
  int retval;

  if (!dir || !dir->i_sb)
    return POSITION_NOT_FOUND;

  if ((unsigned int)namelen > REISERFS_MAX_NAME_LEN (dir->i_sb->s_blocksize))
    return POSITION_NOT_FOUND;

  /* there are no entries having the same third component of key, so
     fourth key component is not used */
  copy_key (&key_to_search, INODE_PKEY (dir));
  key_to_search.k_offset = get_third_component (name, namelen);
  key_to_search.k_uniqueness = DIRENTRY_UNIQUENESS;

  while (1) {
    /* search for a directory item using the formed key */
    if (search_by_key (dir->i_sb, &key_to_search, path_to_entry, &repeat, DISK_LEAF_NODE_LEVEL, READ_BLOCKS) == ITEM_NOT_FOUND) {
      /* take previous item */
#ifdef REISERFS_CHECK
      if (!PATH_LAST_POSITION (path_to_entry))
	reiserfs_panic (dir->i_sb, "vs-7010: reiserfs_find_entry: search_by_key returned bad position == 0");
#endif /* REISERFS_CHECK */
      PATH_LAST_POSITION (path_to_entry) --;
    }
    
    de->de_bh = PATH_PLAST_BUFFER (path_to_entry);
    de->de_item_num = PATH_LAST_POSITION (path_to_entry);
    de->de_ih = B_N_PITEM_HEAD (de->de_bh, de->de_item_num);
    de->de_deh = B_I_DEH (de->de_bh, de->de_ih);

#ifdef REISERFS_CHECK
    if (!I_IS_DIRECTORY_ITEM (de->de_ih) || COMP_SHORT_KEYS (&(de->de_ih->ih_key), INODE_PKEY (dir)))
      reiserfs_panic (dir->i_sb, "vs-7020: reiserfs_find_entry: item must be an item of the same directory item as inode");
#endif /* REISERFS_CHECK */

    /* we do not check whether bin_search_in_dir_item found the given key, even if so, we still have
       to compare names */
    bin_search_in_dir_item (de->de_ih, de->de_deh, &key_to_search, &(de->de_entry_num));

    /* compare names for all entries having given hash value */
    retval = linear_search_in_dir_item (&key_to_search, de, name, namelen);
    if (retval != GOTO_PREVIOUS_ITEM)
      /* there is no need to scan directory anymore. Given entry found or does not exist */
      return retval;

    /* there is left neighboring item of this directory and given entry can be there */
    key_to_search.k_offset = de->de_ih->ih_key.k_offset - 1;
    pathrelse (path_to_entry);

  } /* while (1) */
}
Beispiel #3
0
/* This works by looking at the left and right delimiting keys for the buffer in the last path_element in
   the path.  These delimiting keys are stored at least one level above that buffer in the tree. If the
   buffer is the first or last node in the tree order then one of the delimiting keys may be absent, and in
   this case get_lkey and get_rkey return a special key which is MIN_KEY or MAX_KEY. */
static inline int key_in_buffer(struct treepath *chk_path,	/* Path which should be checked.  */
				const struct cpu_key *key,	/* Key which should be checked.   */
				struct super_block *sb
    )
{

	RFALSE(!key || chk_path->path_length < FIRST_PATH_ELEMENT_OFFSET
	       || chk_path->path_length > MAX_HEIGHT,
	       "PAP-5050: pointer to the key(%p) is NULL or invalid path length(%d)",
	       key, chk_path->path_length);
	RFALSE(!PATH_PLAST_BUFFER(chk_path)->b_bdev,
	       "PAP-5060: device must not be NODEV");

	if (comp_keys(get_lkey(chk_path, sb), key) == 1)
		/* left delimiting key is bigger, that the key we look for */
		return 0;
	/*  if ( comp_keys(key, get_rkey(chk_path, sb)) != -1 ) */
	if (comp_keys(get_rkey(chk_path, sb), key) != 1)
		/* key must be less than right delimitiing key */
		return 0;
	return 1;
}
Beispiel #4
0
/* Check whether a key is contained in the tree rooted from a buffer at a
   path.  This works by looking at the left and right delimiting keys for the
   buffer in the last path_element in the path.  These delimiting keys are
   stored at least one level above that buffer in the tree. If the buffer is
   the first or last node in the tree order then one of the delimiting keys
   may be absent, and in this case get_lkey and get_rkey return a special key
   which is MIN_KEY or MAX_KEY. */
static  inline  int key_in_buffer (
    struct path         * p_s_chk_path, /* Path which should be checked.  */
    struct key          * p_s_key,      /* Key which should be checked.   */
    struct super_block  * p_s_sb        /* Super block pointer.           */
    ) {

#ifdef CONFIG_REISERFS_CHECK
    if ( ! p_s_key || p_s_chk_path->path_length < FIRST_PATH_ELEMENT_OFFSET ||
	 p_s_chk_path->path_length > MAX_HEIGHT )
	reiserfs_panic(p_s_sb, "PAP-5050: key_in_buffer:  pointer to the key(%p) is NULL or illegal path length(%d)",
		       p_s_key, p_s_chk_path->path_length);
  
    if ( PATH_PLAST_BUFFER(p_s_chk_path)->b_dev == NODEV )
	reiserfs_panic(p_s_sb, "PAP-5060: key_in_buffer: device must not be NODEV");
#endif

    if ( COMP_KEYS(get_lkey(p_s_chk_path, p_s_sb), p_s_key) == 1 )
	return 0;
    if ( COMP_KEYS(p_s_key, get_rkey(p_s_chk_path, p_s_sb)) != -1 )
	return 0;
    return 1;
}
Beispiel #5
0
/* The function is NOT SCHEDULE-SAFE! */
int
search_for_position_by_key(struct reiserfs_sb_info *p_s_sbi,
    const struct cpu_key *p_cpu_key, /* Key to search (cpu variable) */
    struct path *p_s_search_path)    /* Filled up by this function.  */
{
	int retval, n_blk_size;
	off_t item_offset, offset;
	struct item_head *p_le_ih; /* Pointer to on-disk structure */
	struct reiserfs_dir_entry de;

	/* If searching for directory entry. */
	if (is_direntry_cpu_key(p_cpu_key))
		return (search_by_entry_key(p_s_sbi, p_cpu_key,
		    p_s_search_path, &de));

	/* If not searching for directory entry. */

	/* If item is found. */
	retval = search_item(p_s_sbi, p_cpu_key, p_s_search_path);
	if (retval == IO_ERROR)
		return (retval);
	if (retval == ITEM_FOUND) {
		if (ih_item_len(B_N_PITEM_HEAD(
		    PATH_PLAST_BUFFER(p_s_search_path),
		    PATH_LAST_POSITION(p_s_search_path))) == 0) {
			reiserfs_log(LOG_WARNING, "item length equals zero\n");
		}

		pos_in_item(p_s_search_path) = 0;
		return (POSITION_FOUND);
	}

	if (PATH_LAST_POSITION(p_s_search_path) == 0) {
		reiserfs_log(LOG_WARNING, "position equals zero\n");
	}

	/* Item is not found. Set path to the previous item. */
	p_le_ih = B_N_PITEM_HEAD(PATH_PLAST_BUFFER(p_s_search_path),
	    --PATH_LAST_POSITION(p_s_search_path));
	n_blk_size = p_s_sbi->s_blocksize;

	if (comp_short_keys(&(p_le_ih->ih_key), p_cpu_key)) {
		return (FILE_NOT_FOUND);
	}

	item_offset = le_ih_k_offset(p_le_ih);
	offset = cpu_key_k_offset(p_cpu_key);

	/* Needed byte is contained in the item pointed to by the path.*/
	if (item_offset <= offset &&
	    item_offset + op_bytes_number(p_le_ih, n_blk_size) > offset) {
		pos_in_item(p_s_search_path) = offset - item_offset;
		if (is_indirect_le_ih(p_le_ih)) {
			pos_in_item(p_s_search_path) /= n_blk_size;
		}
		return (POSITION_FOUND);
	}

	/* Needed byte is not contained in the item pointed to by the
	 * path. Set pos_in_item out of the item. */
	if (is_indirect_le_ih(p_le_ih))
		pos_in_item(p_s_search_path) =
		    ih_item_len(p_le_ih) / UNFM_P_SIZE;
	else
		pos_in_item(p_s_search_path) =
		    ih_item_len(p_le_ih);

	return (POSITION_NOT_FOUND);
}