예제 #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);
}
예제 #2
0
파일: namei.c 프로젝트: AlexShiLucky/linux
/* The function is NOT SCHEDULE-SAFE! */
int search_by_entry_key(struct super_block *sb, const struct cpu_key *key,
			struct treepath *path, struct reiserfs_dir_entry *de)
{
	int retval;

	retval = search_item(sb, key, path);
	switch (retval) {
	case ITEM_NOT_FOUND:
		if (!PATH_LAST_POSITION(path)) {
			reiserfs_error(sb, "vs-7000", "search_by_key "
				       "returned item position == 0");
			pathrelse(path);
			return IO_ERROR;
		}
		PATH_LAST_POSITION(path)--;

	case ITEM_FOUND:
		break;

	case IO_ERROR:
		return retval;

	default:
		pathrelse(path);
		reiserfs_error(sb, "vs-7002", "no path to here");
		return IO_ERROR;
	}

	set_de_item_location(de, path);

#ifdef CONFIG_REISERFS_CHECK
	if (!is_direntry_le_ih(de->de_ih) ||
	    COMP_SHORT_KEYS(&de->de_ih->ih_key, key)) {
		print_block(de->de_bh, 0, -1, -1);
		reiserfs_panic(sb, "vs-7005", "found item %h is not directory "
			       "item or does not belong to the same directory "
			       "as key %K", de->de_ih, key);
	}
#endif				/* CONFIG_REISERFS_CHECK */

	/*
	 * binary search in directory item by third component of the
	 * key. sets de->de_entry_num of de
	 */
	retval = bin_search_in_dir_item(de, cpu_key_k_offset(key));
	path->pos_in_item = de->de_entry_num;
	if (retval != NAME_NOT_FOUND) {
		/*
		 * ugly, but rename needs de_bh, de_deh, de_name,
		 * de_namelen, de_objectid set
		 */
		set_de_name_and_namelen(de);
		set_de_object_key(de);
	}
	return retval;
}
예제 #3
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) */
}
예제 #4
0
/*
 * We assign a key to each directory item, and place multiple entries in
 * a single directory item. A directory item has a key equal to the key
 * of the first directory entry in it.
 *
 * This function first calls search_by_key, then, if item whose first
 * entry matches is not found it looks for the entry inside directory
 * item found by search_by_key. Fills the path to the entry, and to the
 * entry position in the item
 */
int
search_by_entry_key(struct reiserfs_sb_info *sbi,
    const struct cpu_key *key, struct path *path,
    struct reiserfs_dir_entry *de)
{
	int retval;

	reiserfs_log(LOG_DEBUG, "searching in (objectid=%d,dirid=%d)\n",
	    key->on_disk_key.k_objectid, key->on_disk_key.k_dir_id);
	retval = search_item(sbi, key, path);
	switch (retval) {
	case ITEM_NOT_FOUND:
		if (!PATH_LAST_POSITION(path)) {
			reiserfs_log(LOG_DEBUG,
			    "search_by_key returned item position == 0");
			pathrelse(path);
			return (IO_ERROR);
		}
		PATH_LAST_POSITION(path)--;
		reiserfs_log(LOG_DEBUG, "search_by_key did not found it\n");
		break;
	case ITEM_FOUND:
		reiserfs_log(LOG_DEBUG, "search_by_key found it\n");
		break;
	case IO_ERROR:
		return (retval);
	default:
		pathrelse(path);
		reiserfs_log(LOG_DEBUG, "no path to here");
		return (IO_ERROR);
	}

	reiserfs_log(LOG_DEBUG, "set item location\n");
	set_de_item_location(de, path);

	/*
	 * Binary search in directory item by third component of the
	 * key. Sets de->de_entry_num of de
	 */
	reiserfs_log(LOG_DEBUG, "bin_search_in_dir_item\n");
	retval = bin_search_in_dir_item(de, cpu_key_k_offset(key));
	path->pos_in_item = de->de_entry_num;
	if (retval != NAME_NOT_FOUND) {
		/*
		 * Ugly, but rename needs de_bp, de_deh, de_name, de_namelen,
		 * de_objectid set
		 */
		set_de_name_and_namelen(de);
		set_de_object_key(de);
		reiserfs_log(LOG_DEBUG, "set (objectid=%d,dirid=%d)\n",
		    de->de_objectid, de->de_dir_id);
	}

	return (retval);
}