X-Git-Url: http://ftp.safe.ca/?a=blobdiff_plain;f=fs%2Fext3%2Fnamei.c;h=b45c88bd5f73d23ed41661279e74004ef060e8a1;hb=d8c76e6f45c111c32a4b3e50a2adc9210737b0d8;hp=af193a304ee5868c6bd54db9f8018159940463bb;hpb=9f40668d7d14d4d16cedc2104bfb63a43584dacf;p=safe%2Fjmp%2Flinux-2.6 diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index af193a3..b45c88b 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -15,13 +15,13 @@ * Big-endian to little-endian byte-swapping/bitmaps by * David S. Miller (davem@caip.rutgers.edu), 1995 * Directory entry file type support and forward compatibility hooks - * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 + * for B-tree directories by Theodore Ts'o (tytso@mit.edu), 1998 * Hash Tree Directory indexing (c) - * Daniel Phillips, 2001 + * Daniel Phillips, 2001 * Hash Tree Directory indexing porting - * Christopher Li, 2002 + * Christopher Li, 2002 * Hash Tree Directory indexing cleanup - * Theodore Ts'o, 2002 + * Theodore Ts'o, 2002 */ #include @@ -35,6 +35,7 @@ #include #include #include +#include #include #include "namei.h" @@ -76,7 +77,7 @@ static struct buffer_head *ext3_append(handle_t *handle, #ifdef DX_DEBUG #define dxtrace(command) command #else -#define dxtrace(command) +#define dxtrace(command) #endif struct fake_dirent @@ -169,7 +170,7 @@ static struct ext3_dir_entry_2* dx_pack_dirents (char *base, int size); static void dx_insert_block (struct dx_frame *frame, u32 hash, u32 block); static int ext3_htree_next_block(struct inode *dir, __u32 hash, struct dx_frame *frame, - struct dx_frame *frames, + struct dx_frame *frames, __u32 *start_hash); static struct buffer_head * ext3_dx_find_entry(struct dentry *dentry, struct ext3_dir_entry_2 **res_dir, int *err); @@ -250,7 +251,7 @@ static void dx_show_index (char * label, struct dx_entry *entries) } struct stats -{ +{ unsigned names; unsigned space; unsigned bcount; @@ -278,7 +279,7 @@ static struct stats dx_show_leaf(struct dx_hash_info *hinfo, struct ext3_dir_ent ((char *) de - base)); } space += EXT3_DIR_REC_LEN(de->name_len); - names++; + names++; } de = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); } @@ -464,7 +465,7 @@ static void dx_release (struct dx_frame *frames) */ static int ext3_htree_next_block(struct inode *dir, __u32 hash, struct dx_frame *frame, - struct dx_frame *frames, + struct dx_frame *frames, __u32 *start_hash) { struct dx_frame *p; @@ -632,7 +633,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, } count += ret; hashval = ~0; - ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, + ret = ext3_htree_next_block(dir, HASH_NB_ALWAYS, frame, frames, &hashval); *next_hash = hashval; if (ret < 0) { @@ -649,7 +650,7 @@ int ext3_htree_fill_tree(struct file *dir_file, __u32 start_hash, break; } dx_release(frames); - dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n", + dxtrace(printk("Fill tree: returned %d entries, next hash: %x\n", count, *next_hash)); return count; errout: @@ -870,7 +871,7 @@ restart: bh = ext3_getblk(NULL, dir, b++, 0, &err); bh_use[ra_max] = bh; if (bh) - ll_rw_block(READ, 1, &bh); + ll_rw_block(READ_META, 1, &bh); } } if ((bh = bh_use[ra_ptr++]) == NULL) @@ -1000,15 +1001,17 @@ static struct dentry *ext3_lookup(struct inode * dir, struct dentry *dentry, str if (bh) { unsigned long ino = le32_to_cpu(de->inode); brelse (bh); - inode = iget(dir->i_sb, ino); + if (!ext3_valid_inum(dir->i_sb, ino)) { + ext3_error(dir->i_sb, "ext3_lookup", + "bad inode number: %lu", ino); + inode = NULL; + } else + inode = iget(dir->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); } - if (inode) - return d_splice_alias(inode, dentry); - d_add(dentry, inode); - return NULL; + return d_splice_alias(inode, dentry); } @@ -1031,7 +1034,13 @@ struct dentry *ext3_get_parent(struct dentry *child) return ERR_PTR(-ENOENT); ino = le32_to_cpu(de->inode); brelse(bh); - inode = iget(child->d_inode->i_sb, ino); + + if (!ext3_valid_inum(child->d_inode->i_sb, ino)) { + ext3_error(child->d_inode->i_sb, "ext3_get_parent", + "bad inode number: %lu", ino); + inode = NULL; + } else + inode = iget(child->d_inode->i_sb, ino); if (!inode) return ERR_PTR(-EACCES); @@ -1042,7 +1051,7 @@ struct dentry *ext3_get_parent(struct dentry *child) parent = ERR_PTR(-ENOMEM); } return parent; -} +} #define S_SHIFT 12 static unsigned char ext3_type_by_mode[S_IFMT >> S_SHIFT] = { @@ -1190,7 +1199,7 @@ errout: * add_dirent_to_buf will attempt search the directory block for * space. It will return -ENOSPC if no space is available, and -EIO * and -EEXIST if directory entry already exists. - * + * * NOTE! bh is NOT released in the case where ENOSPC is returned. In * all other cases bh is released. */ @@ -1382,7 +1391,6 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, int dx_fallback=0; #endif unsigned blocksize; - unsigned nlen, rlen; u32 block, blocks; sb = dir->i_sb; @@ -1420,8 +1428,7 @@ static int ext3_add_entry (handle_t *handle, struct dentry *dentry, return retval; de = (struct ext3_dir_entry_2 *) bh->b_data; de->inode = 0; - de->rec_len = cpu_to_le16(rlen = blocksize); - nlen = 0; + de->rec_len = cpu_to_le16(blocksize); return add_dirent_to_buf(handle, dentry, inode, de, bh); } @@ -1566,7 +1573,7 @@ cleanup: * ext3_delete_entry deletes a directory entry by merging it with the * previous entry */ -static int ext3_delete_entry (handle_t *handle, +static int ext3_delete_entry (handle_t *handle, struct inode * dir, struct ext3_dir_entry_2 * de_del, struct buffer_head * bh) @@ -1609,12 +1616,12 @@ static int ext3_delete_entry (handle_t *handle, */ static inline void ext3_inc_count(handle_t *handle, struct inode *inode) { - inode->i_nlink++; + inc_nlink(inode); } static inline void ext3_dec_count(handle_t *handle, struct inode *inode) { - inode->i_nlink--; + drop_nlink(inode); } static int ext3_add_nondir(handle_t *handle, @@ -1637,12 +1644,12 @@ static int ext3_add_nondir(handle_t *handle, * is so far negative - it has no inode. * * If the create succeeds, we fill in the inode information - * with d_instantiate(). + * with d_instantiate(). */ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode, struct nameidata *nd) { - handle_t *handle; + handle_t *handle; struct inode * inode; int err, retries = 0; @@ -1682,7 +1689,7 @@ static int ext3_mknod (struct inode * dir, struct dentry *dentry, retry: handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + - EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 3 + 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -1736,7 +1743,7 @@ retry: inode->i_size = EXT3_I(inode)->i_disksize = inode->i_sb->s_blocksize; dir_block = ext3_bread (handle, inode, 0, 1, &err); if (!dir_block) { - inode->i_nlink--; /* is this nlink == 0? */ + drop_nlink(inode); /* is this nlink == 0? */ ext3_mark_inode_dirty(handle, inode); iput (inode); goto out_stop; @@ -1768,7 +1775,7 @@ retry: iput (inode); goto out_stop; } - dir->i_nlink++; + inc_nlink(dir); ext3_update_dx_flag(dir); ext3_mark_inode_dirty(handle, dir); d_instantiate(dentry, inode); @@ -1807,10 +1814,10 @@ static int empty_dir (struct inode * inode) de1 = (struct ext3_dir_entry_2 *) ((char *) de + le16_to_cpu(de->rec_len)); if (le32_to_cpu(de->inode) != inode->i_ino || - !le32_to_cpu(de1->inode) || + !le32_to_cpu(de1->inode) || strcmp (".", de->name) || strcmp ("..", de1->name)) { - ext3_warning (inode->i_sb, "empty_dir", + ext3_warning (inode->i_sb, "empty_dir", "bad directory (dir #%lu) - no `.' or `..'", inode->i_ino); brelse (bh); @@ -1877,7 +1884,7 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode) * being truncated, or files being unlinked. */ /* @@@ FIXME: Observation from aviro: - * I think I can trigger J_ASSERT in ext3_orphan_add(). We block + * I think I can trigger J_ASSERT in ext3_orphan_add(). We block * here (on lock_super()), so race with ext3_link() which might bump * ->i_nlink. For, say it, character device. Not a regular file, * not a directory, not a symlink and ->i_nlink > 0. @@ -1913,8 +1920,8 @@ int ext3_orphan_add(handle_t *handle, struct inode *inode) if (!err) list_add(&EXT3_I(inode)->i_orphan, &EXT3_SB(sb)->s_orphan); - jbd_debug(4, "superblock will point to %ld\n", inode->i_ino); - jbd_debug(4, "orphan inode %ld will point to %d\n", + jbd_debug(4, "superblock will point to %lu\n", inode->i_ino); + jbd_debug(4, "orphan inode %lu will point to %d\n", inode->i_ino, NEXT_ORPHAN(inode)); out_unlock: unlock_super(sb); @@ -2046,7 +2053,7 @@ static int ext3_rmdir (struct inode * dir, struct dentry *dentry) ext3_orphan_add(handle, inode); inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; ext3_mark_inode_dirty(handle, inode); - dir->i_nlink--; + drop_nlink(dir); ext3_update_dx_flag(dir); ext3_mark_inode_dirty(handle, dir); @@ -2097,7 +2104,7 @@ static int ext3_unlink(struct inode * dir, struct dentry *dentry) dir->i_ctime = dir->i_mtime = CURRENT_TIME_SEC; ext3_update_dx_flag(dir); ext3_mark_inode_dirty(handle, dir); - inode->i_nlink--; + drop_nlink(inode); if (!inode->i_nlink) ext3_orphan_add(handle, inode); inode->i_ctime = dir->i_ctime; @@ -2123,7 +2130,7 @@ static int ext3_symlink (struct inode * dir, retry: handle = ext3_journal_start(dir, EXT3_DATA_TRANS_BLOCKS(dir->i_sb) + - EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 5 + 2*EXT3_QUOTA_INIT_BLOCKS(dir->i_sb)); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2144,7 +2151,8 @@ retry: * We have a transaction open. All is sweetness. It also sets * i_size in generic_commit_write(). */ - err = page_symlink(inode, symname, l); + err = __page_symlink(inode, symname, l, + mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS); if (err) { ext3_dec_count(handle, inode); ext3_mark_inode_dirty(handle, inode); @@ -2220,7 +2228,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, DQUOT_INIT(new_dentry->d_inode); handle = ext3_journal_start(old_dir, 2 * EXT3_DATA_TRANS_BLOCKS(old_dir->i_sb) + - EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); + EXT3_INDEX_EXTRA_TRANS_BLOCKS + 2); if (IS_ERR(handle)) return PTR_ERR(handle); @@ -2318,7 +2326,7 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, } if (new_inode) { - new_inode->i_nlink--; + drop_nlink(new_inode); new_inode->i_ctime = CURRENT_TIME_SEC; } old_dir->i_ctime = old_dir->i_mtime = CURRENT_TIME_SEC; @@ -2329,11 +2337,11 @@ static int ext3_rename (struct inode * old_dir, struct dentry *old_dentry, PARENT_INO(dir_bh->b_data) = cpu_to_le32(new_dir->i_ino); BUFFER_TRACE(dir_bh, "call ext3_journal_dirty_metadata"); ext3_journal_dirty_metadata(handle, dir_bh); - old_dir->i_nlink--; + drop_nlink(old_dir); if (new_inode) { - new_inode->i_nlink--; + drop_nlink(new_inode); } else { - new_dir->i_nlink++; + inc_nlink(new_dir); ext3_update_dx_flag(new_dir); ext3_mark_inode_dirty(handle, new_dir); } @@ -2386,4 +2394,4 @@ struct inode_operations ext3_special_inode_operations = { .removexattr = generic_removexattr, #endif .permission = ext3_permission, -}; +};