diff options
Diffstat (limited to 'fs/reiserfs/namei.c')
-rw-r--r-- | fs/reiserfs/namei.c | 2574 |
1 files changed, 1330 insertions, 1244 deletions
diff --git a/fs/reiserfs/namei.c b/fs/reiserfs/namei.c index 4a333255f27..a20bbc1642d 100644 --- a/fs/reiserfs/namei.c +++ b/fs/reiserfs/namei.c @@ -25,86 +25,85 @@ // directory item contains array of entry headers. This performs // binary search through that array -static int bin_search_in_dir_item (struct reiserfs_dir_entry * de, loff_t off) +static int bin_search_in_dir_item(struct reiserfs_dir_entry *de, loff_t off) { - struct item_head * ih = de->de_ih; - struct reiserfs_de_head * deh = de->de_deh; - int rbound, lbound, j; - - lbound = 0; - rbound = I_ENTRY_COUNT (ih) - 1; - - for (j = (rbound + lbound) / 2; lbound <= rbound; j = (rbound + lbound) / 2) { - if (off < deh_offset (deh + j)) { - rbound = j - 1; - continue; + struct item_head *ih = de->de_ih; + struct reiserfs_de_head *deh = de->de_deh; + int rbound, lbound, j; + + lbound = 0; + rbound = I_ENTRY_COUNT(ih) - 1; + + for (j = (rbound + lbound) / 2; lbound <= rbound; + j = (rbound + lbound) / 2) { + if (off < deh_offset(deh + j)) { + rbound = j - 1; + continue; + } + if (off > deh_offset(deh + j)) { + lbound = j + 1; + continue; + } + // this is not name found, but matched third key component + de->de_entry_num = j; + return NAME_FOUND; } - if (off > deh_offset (deh + j)) { - lbound = j + 1; - continue; - } - // this is not name found, but matched third key component - de->de_entry_num = j; - return NAME_FOUND; - } - de->de_entry_num = lbound; - return NAME_NOT_FOUND; + de->de_entry_num = lbound; + return NAME_NOT_FOUND; } - // comment? maybe something like set de to point to what the path points to? -static inline void set_de_item_location (struct reiserfs_dir_entry * de, struct path * path) +static inline void set_de_item_location(struct reiserfs_dir_entry *de, + struct path *path) { - de->de_bh = get_last_bh (path); - de->de_ih = get_ih (path); - de->de_deh = B_I_DEH (de->de_bh, de->de_ih); - de->de_item_num = PATH_LAST_POSITION (path); -} - + de->de_bh = get_last_bh(path); + de->de_ih = get_ih(path); + de->de_deh = B_I_DEH(de->de_bh, de->de_ih); + de->de_item_num = PATH_LAST_POSITION(path); +} // de_bh, de_ih, de_deh (points to first element of array), de_item_num is set -inline void set_de_name_and_namelen (struct reiserfs_dir_entry * de) +inline void set_de_name_and_namelen(struct reiserfs_dir_entry *de) { - struct reiserfs_de_head * deh = de->de_deh + de->de_entry_num; + struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num; - if (de->de_entry_num >= ih_entry_count (de->de_ih)) - BUG (); + if (de->de_entry_num >= ih_entry_count(de->de_ih)) + BUG(); - de->de_entrylen = entry_length (de->de_bh, de->de_ih, de->de_entry_num); - de->de_namelen = de->de_entrylen - (de_with_sd (deh) ? SD_SIZE : 0); - de->de_name = B_I_PITEM (de->de_bh, de->de_ih) + deh_location(deh); - if (de->de_name[de->de_namelen - 1] == 0) - de->de_namelen = strlen (de->de_name); + de->de_entrylen = entry_length(de->de_bh, de->de_ih, de->de_entry_num); + de->de_namelen = de->de_entrylen - (de_with_sd(deh) ? SD_SIZE : 0); + de->de_name = B_I_PITEM(de->de_bh, de->de_ih) + deh_location(deh); + if (de->de_name[de->de_namelen - 1] == 0) + de->de_namelen = strlen(de->de_name); } - // what entry points to -static inline void set_de_object_key (struct reiserfs_dir_entry * de) +static inline void set_de_object_key(struct reiserfs_dir_entry *de) { - if (de->de_entry_num >= ih_entry_count (de->de_ih)) - BUG (); - de->de_dir_id = deh_dir_id( &(de->de_deh[de->de_entry_num])); - de->de_objectid = deh_objectid( &(de->de_deh[de->de_entry_num])); + if (de->de_entry_num >= ih_entry_count(de->de_ih)) + BUG(); + de->de_dir_id = deh_dir_id(&(de->de_deh[de->de_entry_num])); + de->de_objectid = deh_objectid(&(de->de_deh[de->de_entry_num])); } - -static inline void store_de_entry_key (struct reiserfs_dir_entry * de) +static inline void store_de_entry_key(struct reiserfs_dir_entry *de) { - struct reiserfs_de_head * deh = de->de_deh + de->de_entry_num; - - if (de->de_entry_num >= ih_entry_count (de->de_ih)) - BUG (); - - /* store key of the found entry */ - de->de_entry_key.version = KEY_FORMAT_3_5; - de->de_entry_key.on_disk_key.k_dir_id = le32_to_cpu (de->de_ih->ih_key.k_dir_id); - de->de_entry_key.on_disk_key.k_objectid = le32_to_cpu (de->de_ih->ih_key.k_objectid); - set_cpu_key_k_offset (&(de->de_entry_key), deh_offset (deh)); - set_cpu_key_k_type (&(de->de_entry_key), TYPE_DIRENTRY); + struct reiserfs_de_head *deh = de->de_deh + de->de_entry_num; + + if (de->de_entry_num >= ih_entry_count(de->de_ih)) + BUG(); + + /* store key of the found entry */ + de->de_entry_key.version = KEY_FORMAT_3_5; + de->de_entry_key.on_disk_key.k_dir_id = + le32_to_cpu(de->de_ih->ih_key.k_dir_id); + de->de_entry_key.on_disk_key.k_objectid = + le32_to_cpu(de->de_ih->ih_key.k_objectid); + set_cpu_key_k_offset(&(de->de_entry_key), deh_offset(deh)); + set_cpu_key_k_type(&(de->de_entry_key), TYPE_DIRENTRY); } - /* 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. @@ -117,58 +116,60 @@ entry position in the item */ /* The function is NOT SCHEDULE-SAFE! */ -int search_by_entry_key (struct super_block * sb, const struct cpu_key * key, - struct path * path, struct reiserfs_dir_entry * de) +int search_by_entry_key(struct super_block *sb, const struct cpu_key *key, + struct path *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_warning (sb, "vs-7000: search_by_entry_key: search_by_key returned item position == 0"); - pathrelse(path) ; - return IO_ERROR ; + int retval; + + retval = search_item(sb, key, path); + switch (retval) { + case ITEM_NOT_FOUND: + if (!PATH_LAST_POSITION(path)) { + reiserfs_warning(sb, + "vs-7000: search_by_entry_key: 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_warning(sb, + "vs-7002: search_by_entry_key: no path to here"); + return IO_ERROR; } - PATH_LAST_POSITION (path) --; - - case ITEM_FOUND: - break; - - case IO_ERROR: - return retval; - default: - pathrelse (path); - reiserfs_warning (sb, "vs-7002: search_by_entry_key: no path to here"); - return IO_ERROR; - } - - set_de_item_location (de, path); + 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: search_by_entry_key: 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 componen t 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; + 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: search_by_entry_key: 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 componen t 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; } - - /* Keyed 32-bit hash function using TEA in a Davis-Meyer function */ /* The third component is hashed, and you can choose from more than @@ -176,197 +177,210 @@ int search_by_entry_key (struct super_block * sb, const struct cpu_key * key, but are thought about. This function should be moved to hashes.c Jedi, please do so. -Hans */ -static __u32 get_third_component (struct super_block * s, - const char * name, int len) +static __u32 get_third_component(struct super_block *s, + const char *name, int len) { - __u32 res; - - if (!len || (len == 1 && name[0] == '.')) - return DOT_OFFSET; - if (len == 2 && name[0] == '.' && name[1] == '.') - return DOT_DOT_OFFSET; - - res = REISERFS_SB(s)->s_hash_function (name, len); - - // take bits from 7-th to 30-th including both bounds - res = GET_HASH_VALUE(res); - if (res == 0) - // needed to have no names before "." and ".." those have hash - // value == 0 and generation conters 1 and 2 accordingly - res = 128; - return res + MAX_GENERATION_NUMBER; + __u32 res; + + if (!len || (len == 1 && name[0] == '.')) + return DOT_OFFSET; + if (len == 2 && name[0] == '.' && name[1] == '.') + return DOT_DOT_OFFSET; + + res = REISERFS_SB(s)->s_hash_function(name, len); + + // take bits from 7-th to 30-th including both bounds + res = GET_HASH_VALUE(res); + if (res == 0) + // needed to have no names before "." and ".." those have hash + // value == 0 and generation conters 1 and 2 accordingly + res = 128; + return res + MAX_GENERATION_NUMBER; } - -static int reiserfs_match (struct reiserfs_dir_entry * de, - const char * name, int namelen) +static int reiserfs_match(struct reiserfs_dir_entry *de, + const char *name, int namelen) { - int retval = NAME_NOT_FOUND; + int retval = NAME_NOT_FOUND; - if ((namelen == de->de_namelen) && - !memcmp(de->de_name, name, de->de_namelen)) - retval = (de_visible (de->de_deh + de->de_entry_num) ? NAME_FOUND : NAME_FOUND_INVISIBLE); + if ((namelen == de->de_namelen) && + !memcmp(de->de_name, name, de->de_namelen)) + retval = + (de_visible(de->de_deh + de->de_entry_num) ? NAME_FOUND : + NAME_FOUND_INVISIBLE); - return retval; + return retval; } - /* de's de_bh, de_ih, de_deh, de_item_num, de_entry_num are set already */ /* used when hash collisions exist */ - -static int linear_search_in_dir_item (struct cpu_key * key, struct reiserfs_dir_entry * de, - const char * name, int namelen) +static int linear_search_in_dir_item(struct cpu_key *key, + struct reiserfs_dir_entry *de, + const char *name, int namelen) { - struct reiserfs_de_head * deh = de->de_deh; - int retval; - int i; + struct reiserfs_de_head *deh = de->de_deh; + int retval; + int i; - i = de->de_entry_num; + i = de->de_entry_num; - if (i == I_ENTRY_COUNT (de->de_ih) || - GET_HASH_VALUE (deh_offset (deh + i)) != GET_HASH_VALUE (cpu_key_k_offset (key))) { - i --; - } + if (i == I_ENTRY_COUNT(de->de_ih) || + GET_HASH_VALUE(deh_offset(deh + i)) != + GET_HASH_VALUE(cpu_key_k_offset(key))) { + i--; + } - RFALSE( de->de_deh != B_I_DEH (de->de_bh, de->de_ih), - "vs-7010: array of entry headers not found"); + RFALSE(de->de_deh != B_I_DEH(de->de_bh, de->de_ih), + "vs-7010: array of entry headers not found"); - deh += i; + deh += i; - for (; i >= 0; i --, deh --) { - if (GET_HASH_VALUE (deh_offset (deh)) != - GET_HASH_VALUE (cpu_key_k_offset (key))) { - // hash value does not match, no need to check whole name - return NAME_NOT_FOUND; - } - - /* mark, that this generation number is used */ - if (de->de_gen_number_bit_string) - set_bit (GET_GENERATION_NUMBER (deh_offset (deh)), (unsigned long *)de->de_gen_number_bit_string); + for (; i >= 0; i--, deh--) { + if (GET_HASH_VALUE(deh_offset(deh)) != + GET_HASH_VALUE(cpu_key_k_offset(key))) { + // hash value does not match, no need to check whole name + return NAME_NOT_FOUND; + } + + /* mark, that this generation number is used */ + if (de->de_gen_number_bit_string) + set_bit(GET_GENERATION_NUMBER(deh_offset(deh)), + (unsigned long *)de->de_gen_number_bit_string); - // calculate pointer to name and namelen - de->de_entry_num = i; - set_de_name_and_namelen (de); + // calculate pointer to name and namelen + de->de_entry_num = i; + set_de_name_and_namelen(de); - if ((retval = reiserfs_match (de, name, namelen)) != NAME_NOT_FOUND) { - // de's de_name, de_namelen, de_recordlen are set. Fill the rest: + if ((retval = + reiserfs_match(de, name, namelen)) != NAME_NOT_FOUND) { + // de's de_name, de_namelen, de_recordlen are set. Fill the rest: - // key of pointed object - set_de_object_key (de); + // key of pointed object + set_de_object_key(de); - store_de_entry_key (de); + store_de_entry_key(de); - // retval can be NAME_FOUND or NAME_FOUND_INVISIBLE - return retval; + // retval can be NAME_FOUND or NAME_FOUND_INVISIBLE + return retval; + } } - } - - if (GET_GENERATION_NUMBER (le_ih_k_offset (de->de_ih)) == 0) - /* we have reached left most entry in the node. In common we - have to go to the left neighbor, but if generation counter - is 0 already, we know for sure, that there is no name with - the same hash value */ - // FIXME: this work correctly only because hash value can not - // be 0. Btw, in case of Yura's hash it is probably possible, - // so, this is a bug - return NAME_NOT_FOUND; - RFALSE( de->de_item_num, - "vs-7015: two diritems of the same directory in one node?"); + if (GET_GENERATION_NUMBER(le_ih_k_offset(de->de_ih)) == 0) + /* we have reached left most entry in the node. In common we + have to go to the left neighbor, but if generation counter + is 0 already, we know for sure, that there is no name with + the same hash value */ + // FIXME: this work correctly only because hash value can not + // be 0. Btw, in case of Yura's hash it is probably possible, + // so, this is a bug + return NAME_NOT_FOUND; - return GOTO_PREVIOUS_ITEM; -} + RFALSE(de->de_item_num, + "vs-7015: two diritems of the same directory in one node?"); + return GOTO_PREVIOUS_ITEM; +} // may return NAME_FOUND, NAME_FOUND_INVISIBLE, NAME_NOT_FOUND // FIXME: should add something like IOERROR -static int reiserfs_find_entry (struct inode * dir, const char * name, int namelen, - struct path * path_to_entry, struct reiserfs_dir_entry * de) +static int reiserfs_find_entry(struct inode *dir, const char *name, int namelen, + struct path *path_to_entry, + struct reiserfs_dir_entry *de) { - struct cpu_key key_to_search; - int retval; - - - if (namelen > REISERFS_MAX_NAME (dir->i_sb->s_blocksize)) - return NAME_NOT_FOUND; - - /* we will search for this key in the tree */ - make_cpu_key (&key_to_search, dir, - get_third_component (dir->i_sb, name, namelen), TYPE_DIRENTRY, 3); - - while (1) { - retval = search_by_entry_key (dir->i_sb, &key_to_search, path_to_entry, de); - if (retval == IO_ERROR) { - reiserfs_warning (dir->i_sb, "zam-7001: io error in %s", - __FUNCTION__); - return IO_ERROR; - } - - /* 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 */ - path_to_entry->pos_in_item = de->de_entry_num; - return retval; - } - - /* there is left neighboring item of this directory and given entry can be there */ - set_cpu_key_k_offset (&key_to_search, le_ih_k_offset (de->de_ih) - 1); - pathrelse (path_to_entry); - - } /* while (1) */ + struct cpu_key key_to_search; + int retval; + + if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize)) + return NAME_NOT_FOUND; + + /* we will search for this key in the tree */ + make_cpu_key(&key_to_search, dir, + get_third_component(dir->i_sb, name, namelen), + TYPE_DIRENTRY, 3); + + while (1) { + retval = + search_by_entry_key(dir->i_sb, &key_to_search, + path_to_entry, de); + if (retval == IO_ERROR) { + reiserfs_warning(dir->i_sb, "zam-7001: io error in %s", + __FUNCTION__); + return IO_ERROR; + } + + /* 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 */ + path_to_entry->pos_in_item = de->de_entry_num; + return retval; + } + + /* there is left neighboring item of this directory and given entry can be there */ + set_cpu_key_k_offset(&key_to_search, + le_ih_k_offset(de->de_ih) - 1); + pathrelse(path_to_entry); + + } /* while (1) */ } - -static struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dentry, struct nameidata *nd) +static struct dentry *reiserfs_lookup(struct inode *dir, struct dentry *dentry, + struct nameidata *nd) { - int retval; - struct inode * inode = NULL; - struct reiserfs_dir_entry de; - INITIALIZE_PATH (path_to_entry); - - if (REISERFS_MAX_NAME (dir->i_sb->s_blocksize) < dentry->d_name.len) - return ERR_PTR(-ENAMETOOLONG); - - reiserfs_write_lock(dir->i_sb); - de.de_gen_number_bit_string = NULL; - retval = reiserfs_find_entry (dir, dentry->d_name.name, dentry->d_name.len, &path_to_entry, &de); - pathrelse (&path_to_entry); - if (retval == NAME_FOUND) { - /* Hide the .reiserfs_priv directory */ - if (reiserfs_xattrs (dir->i_sb) && - !old_format_only(dir->i_sb) && - REISERFS_SB(dir->i_sb)->priv_root && - REISERFS_SB(dir->i_sb)->priv_root->d_inode && - de.de_objectid == le32_to_cpu (INODE_PKEY(REISERFS_SB(dir->i_sb)->priv_root->d_inode)->k_objectid)) { - reiserfs_write_unlock (dir->i_sb); - return ERR_PTR (-EACCES); + int retval; + struct inode *inode = NULL; + struct reiserfs_dir_entry de; + INITIALIZE_PATH(path_to_entry); + + if (REISERFS_MAX_NAME(dir->i_sb->s_blocksize) < dentry->d_name.len) + return ERR_PTR(-ENAMETOOLONG); + + reiserfs_write_lock(dir->i_sb); + de.de_gen_number_bit_string = NULL; + retval = + reiserfs_find_entry(dir, dentry->d_name.name, dentry->d_name.len, + &path_to_entry, &de); + pathrelse(&path_to_entry); + if (retval == NAME_FOUND) { + /* Hide the .reiserfs_priv directory */ + if (reiserfs_xattrs(dir->i_sb) && + !old_format_only(dir->i_sb) && + REISERFS_SB(dir->i_sb)->priv_root && + REISERFS_SB(dir->i_sb)->priv_root->d_inode && + de.de_objectid == + le32_to_cpu(INODE_PKEY + (REISERFS_SB(dir->i_sb)->priv_root->d_inode)-> + k_objectid)) { + reiserfs_write_unlock(dir->i_sb); + return ERR_PTR(-EACCES); + } + + inode = + reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); + if (!inode || IS_ERR(inode)) { + reiserfs_write_unlock(dir->i_sb); + return ERR_PTR(-EACCES); + } + + /* Propogate the priv_object flag so we know we're in the priv tree */ + if (is_reiserfs_priv_object(dir)) + reiserfs_mark_inode_private(inode); + } + reiserfs_write_unlock(dir->i_sb); + if (retval == IO_ERROR) { + return ERR_PTR(-EIO); } - inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); - if (!inode || IS_ERR(inode)) { - reiserfs_write_unlock(dir->i_sb); - return ERR_PTR(-EACCES); - } - - /* Propogate the priv_object flag so we know we're in the priv tree */ - if (is_reiserfs_priv_object (dir)) - reiserfs_mark_inode_private (inode); - } - reiserfs_write_unlock(dir->i_sb); - if ( retval == IO_ERROR ) { - return ERR_PTR(-EIO); - } - - if (inode) - return d_splice_alias(inode, dentry); - - d_add(dentry, inode); - return NULL; -} + if (inode) + return d_splice_alias(inode, dentry); + d_add(dentry, inode); + return NULL; +} /* ** looks up the dentry of the parent directory for child. @@ -374,40 +388,38 @@ static struct dentry * reiserfs_lookup (struct inode * dir, struct dentry * dent */ struct dentry *reiserfs_get_parent(struct dentry *child) { - int retval; - struct inode * inode = NULL; - struct reiserfs_dir_entry de; - INITIALIZE_PATH (path_to_entry); - struct dentry *parent; - struct inode *dir = child->d_inode ; - - - if (dir->i_nlink == 0) { - return ERR_PTR(-ENOENT); - } - de.de_gen_number_bit_string = NULL; - - reiserfs_write_lock(dir->i_sb); - retval = reiserfs_find_entry (dir, "..", 2, &path_to_entry, &de); - pathrelse (&path_to_entry); - if (retval != NAME_FOUND) { + int retval; + struct inode *inode = NULL; + struct reiserfs_dir_entry de; + INITIALIZE_PATH(path_to_entry); + struct dentry *parent; + struct inode *dir = child->d_inode; + + if (dir->i_nlink == 0) { + return ERR_PTR(-ENOENT); + } + de.de_gen_number_bit_string = NULL; + + reiserfs_write_lock(dir->i_sb); + retval = reiserfs_find_entry(dir, "..", 2, &path_to_entry, &de); + pathrelse(&path_to_entry); + if (retval != NAME_FOUND) { + reiserfs_write_unlock(dir->i_sb); + return ERR_PTR(-ENOENT); + } + inode = reiserfs_iget(dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); reiserfs_write_unlock(dir->i_sb); - return ERR_PTR(-ENOENT); - } - inode = reiserfs_iget (dir->i_sb, (struct cpu_key *)&(de.de_dir_id)); - reiserfs_write_unlock(dir->i_sb); - - if (!inode || IS_ERR(inode)) { - return ERR_PTR(-EACCES); - } - parent = d_alloc_anon(inode); - if (!parent) { - iput(inode); - parent = ERR_PTR(-ENOMEM); - } - return parent; -} + if (!inode || IS_ERR(inode)) { + return ERR_PTR(-EACCES); + } + parent = d_alloc_anon(inode); + if (!parent) { + iput(inode); + parent = ERR_PTR(-ENOMEM); + } + return parent; +} /* add entry to the directory (entry can be hidden). @@ -415,132 +427,143 @@ insert definition of when hidden directories are used here -Hans Does not mark dir inode dirty, do it after successesfull call to it */ -static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct inode * dir, - const char * name, int namelen, struct inode * inode, - int visible) +static int reiserfs_add_entry(struct reiserfs_transaction_handle *th, + struct inode *dir, const char *name, int namelen, + struct inode *inode, int visible) { - struct cpu_key entry_key; - struct reiserfs_de_head * deh; - INITIALIZE_PATH (path); - struct reiserfs_dir_entry de; - int bit_string [MAX_GENERATION_NUMBER / (sizeof(int) * 8) + 1]; - int gen_number; - char small_buf[32+DEH_SIZE] ; /* 48 bytes now and we avoid kmalloc - if we create file with short name */ - char * buffer; - int buflen, paste_size; - int retval; - - BUG_ON (!th->t_trans_id); - - /* cannot allow items to be added into a busy deleted directory */ - if (!namelen) - return -EINVAL; - - if (namelen > REISERFS_MAX_NAME (dir->i_sb->s_blocksize)) - return -ENAMETOOLONG; - - /* each entry has unique key. compose it */ - make_cpu_key (&entry_key, dir, - get_third_component (dir->i_sb, name, namelen), TYPE_DIRENTRY, 3); - - /* get memory for composing the entry */ - buflen = DEH_SIZE + ROUND_UP (namelen); - if (buflen > sizeof (small_buf)) { - buffer = reiserfs_kmalloc (buflen, GFP_NOFS, dir->i_sb); - if (buffer == 0) - return -ENOMEM; - } else - buffer = small_buf; - - paste_size = (get_inode_sd_version (dir) == STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen; - - /* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */ - deh = (struct reiserfs_de_head *)buffer; - deh->deh_location = 0; /* JDM Endian safe if 0 */ - put_deh_offset( deh, cpu_key_k_offset( &entry_key ) ); - deh->deh_state = 0; /* JDM Endian safe if 0 */ - /* put key (ino analog) to de */ - deh->deh_dir_id = INODE_PKEY (inode)->k_dir_id; /* safe: k_dir_id is le */ - deh->deh_objectid = INODE_PKEY (inode)->k_objectid; /* safe: k_objectid is le */ - - /* copy name */ - memcpy ((char *)(deh + 1), name, namelen); - /* padd by 0s to the 4 byte boundary */ - padd_item ((char *)(deh + 1), ROUND_UP (namelen), namelen); - - /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */ - mark_de_without_sd (deh); - visible ? mark_de_visible (deh) : mark_de_hidden (deh); - - /* find the proper place for the new entry */ - memset (bit_string, 0, sizeof (bit_string)); - de.de_gen_number_bit_string = (char *)bit_string; - retval = reiserfs_find_entry (dir, name, namelen, &path, &de); - if( retval != NAME_NOT_FOUND ) { - if (buffer != small_buf) - reiserfs_kfree (buffer, buflen, dir->i_sb); - pathrelse (&path); + struct cpu_key entry_key; + struct reiserfs_de_head *deh; + INITIALIZE_PATH(path); + struct reiserfs_dir_entry de; + int bit_string[MAX_GENERATION_NUMBER / (sizeof(int) * 8) + 1]; + int gen_number; + char small_buf[32 + DEH_SIZE]; /* 48 bytes now and we avoid kmalloc + if we create file with short name */ + char *buffer; + int buflen, paste_size; + int retval; + + BUG_ON(!th->t_trans_id); + + /* cannot allow items to be added into a busy deleted directory */ + if (!namelen) + return -EINVAL; + + if (namelen > REISERFS_MAX_NAME(dir->i_sb->s_blocksize)) + return -ENAMETOOLONG; + + /* each entry has unique key. compose it */ + make_cpu_key(&entry_key, dir, + get_third_component(dir->i_sb, name, namelen), + TYPE_DIRENTRY, 3); + + /* get memory for composing the entry */ + buflen = DEH_SIZE + ROUND_UP(namelen); + if (buflen > sizeof(small_buf)) { + buffer = reiserfs_kmalloc(buflen, GFP_NOFS, dir->i_sb); + if (buffer == 0) + return -ENOMEM; + } else + buffer = small_buf; + + paste_size = + (get_inode_sd_version(dir) == + STAT_DATA_V1) ? (DEH_SIZE + namelen) : buflen; + + /* fill buffer : directory entry head, name[, dir objectid | , stat data | ,stat data, dir objectid ] */ + deh = (struct reiserfs_de_head *)buffer; + deh->deh_location = 0; /* JDM Endian safe if 0 */ + put_deh_offset(deh, cpu_key_k_offset(&entry_key)); + deh->deh_state = 0; /* JDM Endian safe if 0 */ + /* put key (ino analog) to de */ + deh->deh_dir_id = INODE_PKEY(inode)->k_dir_id; /* safe: k_dir_id is le */ + deh->deh_objectid = INODE_PKEY(inode)->k_objectid; /* safe: k_objectid is le */ + + /* copy name */ + memcpy((char *)(deh + 1), name, namelen); + /* padd by 0s to the 4 byte boundary */ + padd_item((char *)(deh + 1), ROUND_UP(namelen), namelen); + + /* entry is ready to be pasted into tree, set 'visibility' and 'stat data in entry' attributes */ + mark_de_without_sd(deh); + visible ? mark_de_visible(deh) : mark_de_hidden(deh); + + /* find the proper place for the new entry */ + memset(bit_string, 0, sizeof(bit_string)); + de.de_gen_number_bit_string = (char *)bit_string; + retval = reiserfs_find_entry(dir, name, namelen, &path, &de); + if (retval != NAME_NOT_FOUND) { + if (buffer != small_buf) + reiserfs_kfree(buffer, buflen, dir->i_sb); + pathrelse(&path); + + if (retval == IO_ERROR) { + return -EIO; + } + + if (retval != NAME_FOUND) { + reiserfs_warning(dir->i_sb, + "zam-7002:%s: \"reiserfs_find_entry\" " + "has returned unexpected value (%d)", + __FUNCTION__, retval); + } + + return -EEXIST; + } - if ( retval == IO_ERROR ) { - return -EIO; + gen_number = + find_first_zero_bit((unsigned long *)bit_string, + MAX_GENERATION_NUMBER + 1); + if (gen_number > MAX_GENERATION_NUMBER) { + /* there is no free generation number */ + reiserfs_warning(dir->i_sb, + "reiserfs_add_entry: Congratulations! we have got hash function screwed up"); + if (buffer != small_buf) + reiserfs_kfree(buffer, buflen, dir->i_sb); + pathrelse(&path); + return -EBUSY; + } + /* adjust offset of directory enrty */ + put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number)); + set_cpu_key_k_offset(&entry_key, deh_offset(deh)); + + /* update max-hash-collisions counter in reiserfs_sb_info */ + PROC_INFO_MAX(th->t_super, max_hash_collisions, gen_number); + + if (gen_number != 0) { /* we need to re-search for the insertion point */ + if (search_by_entry_key(dir->i_sb, &entry_key, &path, &de) != + NAME_NOT_FOUND) { + reiserfs_warning(dir->i_sb, + "vs-7032: reiserfs_add_entry: " + "entry with this key (%K) already exists", + &entry_key); + + if (buffer != small_buf) + reiserfs_kfree(buffer, buflen, dir->i_sb); + pathrelse(&path); + return -EBUSY; + } } - if (retval != NAME_FOUND) { - reiserfs_warning (dir->i_sb, "zam-7002:%s: \"reiserfs_find_entry\" " - "has returned unexpected value (%d)", - __FUNCTION__, retval); - } - - return -EEXIST; - } - - gen_number = find_first_zero_bit ((unsigned long *)bit_string, MAX_GENERATION_NUMBER + 1); - if (gen_number > MAX_GENERATION_NUMBER) { - /* there is no free generation number */ - reiserfs_warning (dir->i_sb, "reiserfs_add_entry: Congratulations! we have got hash function screwed up"); - if (buffer != small_buf) - reiserfs_kfree (buffer, buflen, dir->i_sb); - pathrelse (&path); - return -EBUSY; - } - /* adjust offset of directory enrty */ - put_deh_offset(deh, SET_GENERATION_NUMBER(deh_offset(deh), gen_number)); - set_cpu_key_k_offset (&entry_key, deh_offset(deh)); - - /* update max-hash-collisions counter in reiserfs_sb_info */ - PROC_INFO_MAX( th -> t_super, max_hash_collisions, gen_number ); - - if (gen_number != 0) { /* we need to re-search for the insertion point */ - if (search_by_entry_key (dir->i_sb, &entry_key, &path, &de) != NAME_NOT_FOUND) { - reiserfs_warning (dir->i_sb, "vs-7032: reiserfs_add_entry: " - "entry with this key (%K) already exists", - &entry_key); - - if (buffer != small_buf) - reiserfs_kfree (buffer, buflen, dir->i_sb); - pathrelse (&path); - return -EBUSY; + /* perform the insertion of the entry that we have prepared */ + retval = + reiserfs_paste_into_item(th, &path, &entry_key, dir, buffer, + paste_size); + if (buffer != small_buf) + reiserfs_kfree(buffer, buflen, dir->i_sb); + if (retval) { + reiserfs_check_path(&path); + return retval; } - } - - /* perform the insertion of the entry that we have prepared */ - retval = reiserfs_paste_into_item (th, &path, &entry_key, dir, buffer, paste_size); - if (buffer != small_buf) - reiserfs_kfree (buffer, buflen, dir->i_sb); - if (retval) { - reiserfs_check_path(&path) ; - return retval; - } - dir->i_size += paste_size; - dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; - if (!S_ISDIR (inode->i_mode) && visible) - // reiserfs_mkdir or reiserfs_rename will do that by itself - reiserfs_update_sd (th, dir); + dir->i_size += paste_size; + dir->i_mtime = dir->i_ctime = CURRENT_TIME_SEC; + if (!S_ISDIR(inode->i_mode) && visible) + // reiserfs_mkdir or reiserfs_rename will do that by itself + reiserfs_update_sd(th, dir); - reiserfs_check_path(&path) ; - return 0; + reiserfs_check_path(&path); + return 0; } /* quota utility function, call if you've had to abort after calling @@ -548,12 +571,13 @@ static int reiserfs_add_entry (struct reiserfs_transaction_handle *th, struct in ** This should only be called on inodes that do not have stat data ** inserted into the tree yet. */ -static int drop_new_inode(struct inode *inode) { - DQUOT_DROP(inode); - make_bad_inode(inode) ; - inode->i_flags |= S_NOQUOTA; - iput(inode) ; - return 0 ; +static int drop_new_inode(struct inode *inode) +{ + DQUOT_DROP(inode); + make_bad_inode(inode); + inode->i_flags |= S_NOQUOTA; + iput(inode); + return 0; } /* utility function that does setup for reiserfs_new_inode. @@ -561,905 +585,968 @@ static int drop_new_inode(struct inode *inode) { ** outside of a transaction, so we had to pull some bits of ** reiserfs_new_inode out into this func. */ -static int new_inode_init(struct inode *inode, struct inode *dir, int mode) { - - /* the quota init calls have to know who to charge the quota to, so - ** we have to set uid and gid here - */ - inode->i_uid = current->fsuid; - inode->i_mode = mode; - - if (dir->i_mode & S_ISGID) { - inode->i_gid = dir->i_gid; - if (S_ISDIR(mode)) - inode->i_mode |= S_ISGID; - } else { - inode->i_gid = current->fsgid; - } - DQUOT_INIT(inode); - return 0 ; +static int new_inode_init(struct inode *inode, struct inode *dir, int mode) +{ + + /* the quota init calls have to know who to charge the quota to, so + ** we have to set uid and gid here + */ + inode->i_uid = current->fsuid; + inode->i_mode = mode; + + if (dir->i_mode & S_ISGID) { + inode->i_gid = dir->i_gid; + if (S_ISDIR(mode)) + inode->i_mode |= S_ISGID; + } else { + inode->i_gid = current->fsgid; + } + DQUOT_INIT(inode); + return 0; } -static int reiserfs_create (struct inode * dir, struct dentry *dentry, int mode, - struct nameidata *nd) +static int reiserfs_create(struct inode *dir, struct dentry *dentry, int mode, + struct nameidata *nd) { - int retval; - struct inode * inode; - /* We need blocks for transaction + (user+group)*(quotas for new inode + update of quota for directory owner) */ - int jbegin_count = JOURNAL_PER_BALANCE_CNT * 2 + 2 * (REISERFS_QUOTA_INIT_BLOCKS(dir->i_sb)+REISERFS_QUOTA_TRANS_BLOCKS(dir->i_sb)); - struct reiserfs_transaction_handle th ; - int locked; - - if (!(inode = new_inode(dir->i_sb))) { - return -ENOMEM ; - } - new_inode_init(inode, dir, mode); - - locked = reiserfs_cache_default_acl (dir); - - reiserfs_write_lock(dir->i_sb); - - if (locked) - reiserfs_write_lock_xattrs (dir->i_sb); - - retval = journal_begin(&th, dir->i_sb, jbegin_count); - if (retval) { - drop_new_inode (inode); - goto out_failed; - } - - retval = reiserfs_new_inode (&th, dir, mode, NULL, 0/*i_size*/, dentry, inode); - if (retval) - goto out_failed; - - if (locked) { - reiserfs_write_unlock_xattrs (dir->i_sb); - locked = 0; - } - - inode->i_op = &reiserfs_file_inode_operations; - inode->i_fop = &reiserfs_file_operations; - inode->i_mapping->a_ops = &reiserfs_address_space_operations ; - - retval = reiserfs_add_entry (&th, dir, dentry->d_name.name, dentry->d_name.len, - inode, 1/*visible*/); - if (retval) { - int err; - inode->i_nlink--; - reiserfs_update_sd (&th, inode); - err = journal_end(&th, dir->i_sb, jbegin_count) ; - if (err) - retval = err; - iput (inode); |