mirror of https://gitee.com/openkylin/linux.git
Btrfs: Invalidate dcache entry after creating snapshot and
We need to invalidate an existing dcache entry after creating a new snapshot or subvolume, because a negative dache entry will stop us from accessing the new snapshot or subvolume. --- ctree.h | 23 +++++++++++++++++++++++ inode.c | 4 ++++ transaction.c | 4 ++++ 3 files changed, 31 insertions(+) Signed-off-by: Chris Mason <chris.mason@oracle.com>
This commit is contained in:
parent
48ec2cf873
commit
3b96362cc8
|
@ -1544,6 +1544,9 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *root, struct btrfs_path *path,
|
struct btrfs_root *root, struct btrfs_path *path,
|
||||||
u64 isize);
|
u64 isize);
|
||||||
/* inode.c */
|
/* inode.c */
|
||||||
|
void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name,
|
||||||
|
int namelen);
|
||||||
|
|
||||||
int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
|
int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
|
||||||
size_t size, struct bio *bio);
|
size_t size, struct bio *bio);
|
||||||
|
|
||||||
|
|
|
@ -2642,6 +2642,31 @@ static void btrfs_truncate(struct inode *inode)
|
||||||
btrfs_throttle(root);
|
btrfs_throttle(root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Invalidate a single dcache entry at the root of the filesystem.
|
||||||
|
* Needed after creation of snapshot or subvolume.
|
||||||
|
*/
|
||||||
|
void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name,
|
||||||
|
int namelen)
|
||||||
|
{
|
||||||
|
struct dentry *alias, *entry;
|
||||||
|
struct qstr qstr;
|
||||||
|
|
||||||
|
alias = d_find_alias(root->fs_info->sb->s_root->d_inode);
|
||||||
|
if (alias) {
|
||||||
|
qstr.name = name;
|
||||||
|
qstr.len = namelen;
|
||||||
|
/* change me if btrfs ever gets a d_hash operation */
|
||||||
|
qstr.hash = full_name_hash(qstr.name, qstr.len);
|
||||||
|
entry = d_lookup(alias, &qstr);
|
||||||
|
dput(alias);
|
||||||
|
if (entry) {
|
||||||
|
d_invalidate(entry);
|
||||||
|
dput(entry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static int noinline create_subvol(struct btrfs_root *root, char *name,
|
static int noinline create_subvol(struct btrfs_root *root, char *name,
|
||||||
int namelen)
|
int namelen)
|
||||||
{
|
{
|
||||||
|
@ -2761,6 +2786,10 @@ static int noinline create_subvol(struct btrfs_root *root, char *name,
|
||||||
ret = btrfs_update_inode(trans, new_root, inode);
|
ret = btrfs_update_inode(trans, new_root, inode);
|
||||||
if (ret)
|
if (ret)
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
/* Invalidate existing dcache entry for new subvolume. */
|
||||||
|
btrfs_invalidate_dcache_root(root, name, namelen);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
nr = trans->blocks_used;
|
nr = trans->blocks_used;
|
||||||
err = btrfs_commit_transaction(trans, new_root);
|
err = btrfs_commit_transaction(trans, new_root);
|
||||||
|
|
|
@ -560,6 +560,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
||||||
struct btrfs_root *root = pending->root;
|
struct btrfs_root *root = pending->root;
|
||||||
struct extent_buffer *tmp;
|
struct extent_buffer *tmp;
|
||||||
int ret;
|
int ret;
|
||||||
|
int namelen;
|
||||||
u64 objectid;
|
u64 objectid;
|
||||||
|
|
||||||
new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
|
new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS);
|
||||||
|
@ -595,8 +596,9 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
||||||
* insert the directory item
|
* insert the directory item
|
||||||
*/
|
*/
|
||||||
key.offset = (u64)-1;
|
key.offset = (u64)-1;
|
||||||
|
namelen = strlen(pending->name);
|
||||||
ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root,
|
ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root,
|
||||||
pending->name, strlen(pending->name),
|
pending->name, namelen,
|
||||||
root->fs_info->sb->s_root->d_inode->i_ino,
|
root->fs_info->sb->s_root->d_inode->i_ino,
|
||||||
&key, BTRFS_FT_DIR);
|
&key, BTRFS_FT_DIR);
|
||||||
|
|
||||||
|
@ -606,6 +608,10 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
|
||||||
ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root,
|
ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root,
|
||||||
pending->name, strlen(pending->name), objectid,
|
pending->name, strlen(pending->name), objectid,
|
||||||
root->fs_info->sb->s_root->d_inode->i_ino);
|
root->fs_info->sb->s_root->d_inode->i_ino);
|
||||||
|
|
||||||
|
/* Invalidate existing dcache entry for new snapshot. */
|
||||||
|
btrfs_invalidate_dcache_root(root, pending->name, namelen);
|
||||||
|
|
||||||
fail:
|
fail:
|
||||||
kfree(new_root_item);
|
kfree(new_root_item);
|
||||||
return ret;
|
return ret;
|
||||||
|
|
Loading…
Reference in New Issue