/* 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); }
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) */ }
static char * item_type (struct item_head * ih) { static char * types[] = { "SD", "DIR", "DRCT", "IND", "???" }; if (I_IS_STAT_DATA_ITEM(ih)) return types[0]; if (I_IS_DIRECTORY_ITEM(ih)) return types[1]; if (I_IS_DIRECT_ITEM(ih)) return types[2]; if (I_IS_INDIRECT_ITEM(ih)) return types[3]; return types[4]; }
void print_directory_item (FILE * fp, reiserfs_filsys_t fs, struct buffer_head * bh, struct item_head * ih) { int i; int namelen; struct reiserfs_de_head * deh; char * name; /* static char namebuf [80];*/ if (!I_IS_DIRECTORY_ITEM (ih)) return; //printk ("\n%2%-25s%-30s%-15s%-15s%-15s\n", " Name", "length", "Object key", "Hash", "Gen number", "Status"); reiserfs_warning (fp, "%3s: %-25s%s%-22s%-12s%s\n", "###", "Name", "length", " Object key", " Hash", "Gen number"); deh = B_I_DEH (bh, ih); for (i = 0; i < ih_entry_count (ih); i ++, deh ++) { if (dir_entry_bad_location (deh, ih, i == 0 ? 1 : 0)) { reiserfs_warning (fp, "%3d: wrong entry location %u, deh_offset %u\n", i, deh_location (deh), deh_offset (deh)); continue; } if (i && dir_entry_bad_location (deh - 1, ih, ((i - 1) == 0) ? 1 : 0)) /* previous entry has bad location so we can not calculate entry length */ namelen = 25; else namelen = name_length (ih, deh, i); name = name_in_entry (deh, i); reiserfs_warning (fp, "%3d: \"%-25.*s\"(%3d)%20K%12d%5d, loc %u, state %x %s\n", i, namelen, name, namelen, /* this gets converted in print_short_key() */ (struct key *)&(deh->deh_dir_id), GET_HASH_VALUE (deh_offset(deh)), GET_GENERATION_NUMBER (deh_offset(deh)), deh_location (deh), deh_state(deh), fs ? (is_properly_hashed (fs, name, namelen, deh_offset (deh)) ? "" : "(BROKEN)") : "??"); } }