summaryrefslogtreecommitdiffstats
path: root/fs/btrfs/inode.c
diff options
context:
space:
mode:
authorSven Wegener2008-06-10 03:57:42 +0200
committerChris Mason2008-09-25 17:04:03 +0200
commit3b96362cc8d314c935c335d5c3c42eb93c23166b (patch)
tree6d69302c9589d64ccb76f61b833f1a7151f9c841 /fs/btrfs/inode.c
parentBtrfs: Fix race in running_transaction checks (diff)
downloadkernel-qcow2-linux-3b96362cc8d314c935c335d5c3c42eb93c23166b.tar.gz
kernel-qcow2-linux-3b96362cc8d314c935c335d5c3c42eb93c23166b.tar.xz
kernel-qcow2-linux-3b96362cc8d314c935c335d5c3c42eb93c23166b.zip
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>
Diffstat (limited to 'fs/btrfs/inode.c')
-rw-r--r--fs/btrfs/inode.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c
index 1569fb864515..31aa4ba06fce 100644
--- a/fs/btrfs/inode.c
+++ b/fs/btrfs/inode.c
@@ -2642,6 +2642,31 @@ static void btrfs_truncate(struct inode *inode)
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,
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);
if (ret)
goto fail;
+
+ /* Invalidate existing dcache entry for new subvolume. */
+ btrfs_invalidate_dcache_root(root, name, namelen);
+
fail:
nr = trans->blocks_used;
err = btrfs_commit_transaction(trans, new_root);