Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3b96362c authored by Sven Wegener's avatar Sven Wegener Committed by Chris Mason
Browse files

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: default avatarChris Mason <chris.mason@oracle.com>
parent 48ec2cf8
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -1544,6 +1544,9 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
			struct btrfs_root *root, struct btrfs_path *path,
			u64 isize);
/* 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,
			 size_t size, struct bio *bio);

+29 −0
Original line number Diff line number Diff line
@@ -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);
+7 −1
Original line number Diff line number Diff line
@@ -560,6 +560,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
	struct btrfs_root *root = pending->root;
	struct extent_buffer *tmp;
	int ret;
	int namelen;
	u64 objectid;

	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
	 */
	key.offset = (u64)-1;
	namelen = strlen(pending->name);
	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,
				    &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,
			     pending->name, strlen(pending->name), objectid,
			     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:
	kfree(new_root_item);
	return ret;