diff options
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r-- | fs/btrfs/inode.c | 50 |
1 files changed, 32 insertions, 18 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 3e3620e69bb9..e163b1b74707 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c | |||
@@ -3038,8 +3038,7 @@ struct inode *btrfs_iget(struct super_block *s, struct btrfs_key *location, | |||
3038 | return inode; | 3038 | return inode; |
3039 | } | 3039 | } |
3040 | 3040 | ||
3041 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | 3041 | struct inode *btrfs_lookup_dentry(struct inode *dir, struct dentry *dentry) |
3042 | struct nameidata *nd) | ||
3043 | { | 3042 | { |
3044 | struct inode * inode; | 3043 | struct inode * inode; |
3045 | struct btrfs_inode *bi = BTRFS_I(dir); | 3044 | struct btrfs_inode *bi = BTRFS_I(dir); |
@@ -3067,13 +3066,21 @@ static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | |||
3067 | inode = btrfs_iget(dir->i_sb, &location, sub_root, &new); | 3066 | inode = btrfs_iget(dir->i_sb, &location, sub_root, &new); |
3068 | if (IS_ERR(inode)) | 3067 | if (IS_ERR(inode)) |
3069 | return ERR_CAST(inode); | 3068 | return ERR_CAST(inode); |
3070 | |||
3071 | /* the inode and parent dir are two different roots */ | ||
3072 | if (new && root != sub_root) { | ||
3073 | igrab(inode); | ||
3074 | sub_root->inode = inode; | ||
3075 | } | ||
3076 | } | 3069 | } |
3070 | return inode; | ||
3071 | } | ||
3072 | |||
3073 | static struct dentry *btrfs_lookup(struct inode *dir, struct dentry *dentry, | ||
3074 | struct nameidata *nd) | ||
3075 | { | ||
3076 | struct inode *inode; | ||
3077 | |||
3078 | if (dentry->d_name.len > BTRFS_NAME_LEN) | ||
3079 | return ERR_PTR(-ENAMETOOLONG); | ||
3080 | |||
3081 | inode = btrfs_lookup_dentry(dir, dentry); | ||
3082 | if (IS_ERR(inode)) | ||
3083 | return ERR_CAST(inode); | ||
3077 | 3084 | ||
3078 | return d_splice_alias(inode, dentry); | 3085 | return d_splice_alias(inode, dentry); |
3079 | } | 3086 | } |
@@ -3129,7 +3136,6 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
3129 | return 0; | 3136 | return 0; |
3130 | filp->f_pos = 2; | 3137 | filp->f_pos = 2; |
3131 | } | 3138 | } |
3132 | |||
3133 | path = btrfs_alloc_path(); | 3139 | path = btrfs_alloc_path(); |
3134 | path->reada = 2; | 3140 | path->reada = 2; |
3135 | 3141 | ||
@@ -3159,6 +3165,7 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
3159 | path->slots[0]++; | 3165 | path->slots[0]++; |
3160 | } | 3166 | } |
3161 | } | 3167 | } |
3168 | |||
3162 | advance = 1; | 3169 | advance = 1; |
3163 | item = btrfs_item_nr(leaf, slot); | 3170 | item = btrfs_item_nr(leaf, slot); |
3164 | btrfs_item_key_to_cpu(leaf, &found_key, slot); | 3171 | btrfs_item_key_to_cpu(leaf, &found_key, slot); |
@@ -3194,16 +3201,25 @@ static int btrfs_real_readdir(struct file *filp, void *dirent, | |||
3194 | 3201 | ||
3195 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; | 3202 | d_type = btrfs_filetype_table[btrfs_dir_type(leaf, di)]; |
3196 | btrfs_dir_item_key_to_cpu(leaf, di, &location); | 3203 | btrfs_dir_item_key_to_cpu(leaf, di, &location); |
3204 | |||
3205 | /* is this a reference to our own snapshot? If so | ||
3206 | * skip it | ||
3207 | */ | ||
3208 | if (location.type == BTRFS_ROOT_ITEM_KEY && | ||
3209 | location.objectid == root->root_key.objectid) { | ||
3210 | over = 0; | ||
3211 | goto skip; | ||
3212 | } | ||
3197 | over = filldir(dirent, name_ptr, name_len, | 3213 | over = filldir(dirent, name_ptr, name_len, |
3198 | found_key.offset, location.objectid, | 3214 | found_key.offset, location.objectid, |
3199 | d_type); | 3215 | d_type); |
3200 | 3216 | ||
3217 | skip: | ||
3201 | if (name_ptr != tmp_name) | 3218 | if (name_ptr != tmp_name) |
3202 | kfree(name_ptr); | 3219 | kfree(name_ptr); |
3203 | 3220 | ||
3204 | if (over) | 3221 | if (over) |
3205 | goto nopos; | 3222 | goto nopos; |
3206 | |||
3207 | di_len = btrfs_dir_name_len(leaf, di) + | 3223 | di_len = btrfs_dir_name_len(leaf, di) + |
3208 | btrfs_dir_data_len(leaf, di) + sizeof(*di); | 3224 | btrfs_dir_data_len(leaf, di) + sizeof(*di); |
3209 | di_cur += di_len; | 3225 | di_cur += di_len; |
@@ -3318,8 +3334,7 @@ out: | |||
3318 | * helper to find a free sequence number in a given directory. This current | 3334 | * helper to find a free sequence number in a given directory. This current |
3319 | * code is very simple, later versions will do smarter things in the btree | 3335 | * code is very simple, later versions will do smarter things in the btree |
3320 | */ | 3336 | */ |
3321 | static int btrfs_set_inode_index(struct inode *dir, struct inode *inode, | 3337 | int btrfs_set_inode_index(struct inode *dir, u64 *index) |
3322 | u64 *index) | ||
3323 | { | 3338 | { |
3324 | int ret = 0; | 3339 | int ret = 0; |
3325 | 3340 | ||
@@ -3365,7 +3380,7 @@ static struct inode *btrfs_new_inode(struct btrfs_trans_handle *trans, | |||
3365 | return ERR_PTR(-ENOMEM); | 3380 | return ERR_PTR(-ENOMEM); |
3366 | 3381 | ||
3367 | if (dir) { | 3382 | if (dir) { |
3368 | ret = btrfs_set_inode_index(dir, inode, index); | 3383 | ret = btrfs_set_inode_index(dir, index); |
3369 | if (ret) | 3384 | if (ret) |
3370 | return ERR_PTR(ret); | 3385 | return ERR_PTR(ret); |
3371 | } | 3386 | } |
@@ -3651,7 +3666,7 @@ static int btrfs_link(struct dentry *old_dentry, struct inode *dir, | |||
3651 | err = btrfs_check_free_space(root, 1, 0); | 3666 | err = btrfs_check_free_space(root, 1, 0); |
3652 | if (err) | 3667 | if (err) |
3653 | goto fail; | 3668 | goto fail; |
3654 | err = btrfs_set_inode_index(dir, inode, &index); | 3669 | err = btrfs_set_inode_index(dir, &index); |
3655 | if (err) | 3670 | if (err) |
3656 | goto fail; | 3671 | goto fail; |
3657 | 3672 | ||
@@ -4349,13 +4364,13 @@ out: | |||
4349 | * Invalidate a single dcache entry at the root of the filesystem. | 4364 | * Invalidate a single dcache entry at the root of the filesystem. |
4350 | * Needed after creation of snapshot or subvolume. | 4365 | * Needed after creation of snapshot or subvolume. |
4351 | */ | 4366 | */ |
4352 | void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name, | 4367 | void btrfs_invalidate_dcache_root(struct inode *dir, char *name, |
4353 | int namelen) | 4368 | int namelen) |
4354 | { | 4369 | { |
4355 | struct dentry *alias, *entry; | 4370 | struct dentry *alias, *entry; |
4356 | struct qstr qstr; | 4371 | struct qstr qstr; |
4357 | 4372 | ||
4358 | alias = d_find_alias(root->fs_info->sb->s_root->d_inode); | 4373 | alias = d_find_alias(dir); |
4359 | if (alias) { | 4374 | if (alias) { |
4360 | qstr.name = name; | 4375 | qstr.name = name; |
4361 | qstr.len = namelen; | 4376 | qstr.len = namelen; |
@@ -4387,7 +4402,6 @@ int btrfs_create_subvol_root(struct btrfs_root *new_root, struct dentry *dentry, | |||
4387 | return PTR_ERR(inode); | 4402 | return PTR_ERR(inode); |
4388 | inode->i_op = &btrfs_dir_inode_operations; | 4403 | inode->i_op = &btrfs_dir_inode_operations; |
4389 | inode->i_fop = &btrfs_dir_file_operations; | 4404 | inode->i_fop = &btrfs_dir_file_operations; |
4390 | new_root->inode = inode; | ||
4391 | 4405 | ||
4392 | inode->i_nlink = 1; | 4406 | inode->i_nlink = 1; |
4393 | btrfs_i_size_write(inode, 0); | 4407 | btrfs_i_size_write(inode, 0); |
@@ -4590,7 +4604,7 @@ static int btrfs_rename(struct inode * old_dir, struct dentry *old_dentry, | |||
4590 | } | 4604 | } |
4591 | 4605 | ||
4592 | } | 4606 | } |
4593 | ret = btrfs_set_inode_index(new_dir, old_inode, &index); | 4607 | ret = btrfs_set_inode_index(new_dir, &index); |
4594 | if (ret) | 4608 | if (ret) |
4595 | goto out_fail; | 4609 | goto out_fail; |
4596 | 4610 | ||