aboutsummaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-08-01 19:48:31 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2011-08-01 19:48:31 -0400
commit1b8e94993c4752d98c33903aa836acc15f7e6d5c (patch)
treeb78cba208f0a193ce6ceebbc146021af4425b4e1 /fs/btrfs/inode.c
parent12ff47e7f5fb64c566f62e6cf6a3b291c51bd337 (diff)
parent206d440f64030b6425841bf7cb38e26a5ea0c382 (diff)
Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs-2.6: xfs: Fix build breakage in xfs_iops.c when CONFIG_FS_POSIX_ACL is not set VFS: Reorganise shrink_dcache_for_umount_subtree() after demise of dcache_lock VFS: Remove dentry->d_lock locking from shrink_dcache_for_umount_subtree() VFS: Remove detached-dentry counter from shrink_dcache_for_umount_subtree() switch posix_acl_chmod() to umode_t switch posix_acl_from_mode() to umode_t switch posix_acl_equiv_mode() to umode_t * switch posix_acl_create() to umode_t * block: initialise bd_super in bdget() vfs: avoid call to inode_lru_list_del() if possible vfs: avoid taking inode_hash_lock on pipes and sockets vfs: conditionally call inode_wb_list_del() VFS: Fix automount for negative autofs dentries Btrfs: load the key from the dir item in readdir into a fake dentry devtmpfs: missing initialialization in never-hit case hppfs: missing include
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c47
1 files changed, 45 insertions, 2 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 13e6255182e3..ae762dab37f8 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -3993,12 +3993,19 @@ struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry)
3993 struct btrfs_root *sub_root = root; 3993 struct btrfs_root *sub_root = root;
3994 struct btrfs_key location; 3994 struct btrfs_key location;
3995 int index; 3995 int index;
3996 int ret; 3996 int ret = 0;
3997 3997
3998 if (dentry->d_name.len > BTRFS_NAME_LEN) 3998 if (dentry->d_name.len > BTRFS_NAME_LEN)
3999 return ERR_PTR(-ENAMETOOLONG); 3999 return ERR_PTR(-ENAMETOOLONG);
4000 4000
4001 ret = btrfs_inode_by_name(dir, dentry, &location); 4001 if (unlikely(d_need_lookup(dentry))) {
4002 memcpy(&location, dentry->d_fsdata, sizeof(struct btrfs_key));
4003 kfree(dentry->d_fsdata);
4004 dentry->d_fsdata = NULL;
4005 d_clear_need_lookup(dentry);
4006 } else {
4007 ret = btrfs_inode_by_name(dir, dentry, &location);
4008 }
4002 4009
4003 if (ret < 0) 4010 if (ret < 0)
4004 return ERR_PTR(ret); 4011 return ERR_PTR(ret);
@@ -4053,6 +4060,12 @@ static int btrfs_dentry_delete(const struct dentry *dentry)
4053 return 0; 4060 return 0;
4054} 4061}
4055 4062
4063static void btrfs_dentry_release(struct dentry *dentry)
4064{
4065 if (dentry->d_fsdata)
4066 kfree(dentry->d_fsdata);
4067}
4068
4056static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, 4069static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry,
4057 struct nameidata *nd) 4070 struct nameidata *nd)
4058{ 4071{
@@ -4075,6 +4088,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
4075 struct btrfs_path *path; 4088 struct btrfs_path *path;
4076 struct list_head ins_list; 4089 struct list_head ins_list;
4077 struct list_head del_list; 4090 struct list_head del_list;
4091 struct qstr q;
4078 int ret; 4092 int ret;
4079 struct extent_buffer *leaf; 4093 struct extent_buffer *leaf;
4080 int slot; 4094 int slot;
@@ -4164,6 +4178,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
4164 4178
4165 while (di_cur < di_total) { 4179 while (di_cur < di_total) {
4166 struct btrfs_key location; 4180 struct btrfs_key location;
4181 struct dentry *tmp;
4167 4182
4168 if (verify_dir_item(root, leaf, di)) 4183 if (verify_dir_item(root, leaf, di))
4169 break; 4184 break;
@@ -4184,6 +4199,33 @@ static int btrfs_real_readdir(struct file *filp, void *dirent,
4184 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; 4199 d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)];
4185 btrfs_dir_item_key_to_cpu(leaf, di, &location); 4200 btrfs_dir_item_key_to_cpu(leaf, di, &location);
4186 4201
4202 q.name = name_ptr;
4203 q.len = name_len;
4204 q.hash = full_name_hash(q.name, q.len);
4205 tmp = d_lookup(filp->f_dentry, &q);
4206 if (!tmp) {
4207 struct btrfs_key *newkey;
4208
4209 newkey = kzalloc(sizeof(struct btrfs_key),
4210 GFP_NOFS);
4211 if (!newkey)
4212 goto no_dentry;
4213 tmp = d_alloc(filp->f_dentry, &q);
4214 if (!tmp) {
4215 kfree(newkey);
4216 dput(tmp);
4217 goto no_dentry;
4218 }
4219 memcpy(newkey, &location,
4220 sizeof(struct btrfs_key));
4221 tmp->d_fsdata = newkey;
4222 tmp->d_flags |= DCACHE_NEED_LOOKUP;
4223 d_rehash(tmp);
4224 dput(tmp);
4225 } else {
4226 dput(tmp);
4227 }
4228no_dentry:
4187 /* is this a reference to our own snapshot? If so 4229 /* is this a reference to our own snapshot? If so
4188 * skip it 4230 * skip it
4189 */ 4231 */
@@ -7430,4 +7472,5 @@ static const struct inode_operations btrfs_symlink_inode_operations = {
7430 7472
7431const struct dentry_operations btrfs_dentry_operations = { 7473const struct dentry_operations btrfs_dentry_operations = {
7432 .d_delete = btrfs_dentry_delete, 7474 .d_delete = btrfs_dentry_delete,
7475 .d_release = btrfs_dentry_release,
7433}; 7476};