aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
Diffstat (limited to 'fs')
-rw-r--r--fs/btrfs/ctree.h3
-rw-r--r--fs/btrfs/inode.c29
-rw-r--r--fs/btrfs/transaction.c8
3 files changed, 39 insertions, 1 deletions
diff --git a/fs/btrfs/ctree.h b/fs/btrfs/ctree.h
index 7b73a9c3d868..ad4eacca7f59 100644
--- a/fs/btrfs/ctree.h
+++ b/fs/btrfs/ctree.h
@@ -1544,6 +1544,9 @@ int btrfs_csum_truncate(struct btrfs_trans_handle *trans,
1544 struct btrfs_root *root, struct btrfs_path *path, 1544 struct btrfs_root *root, struct btrfs_path *path,
1545 u64 isize); 1545 u64 isize);
1546/* inode.c */ 1546/* inode.c */
1547void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name,
1548 int namelen);
1549
1547int btrfs_merge_bio_hook(struct page *page, unsigned long offset, 1550int btrfs_merge_bio_hook(struct page *page, unsigned long offset,
1548 size_t size, struct bio *bio); 1551 size_t size, struct bio *bio);
1549 1552
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)
2642 btrfs_throttle(root); 2642 btrfs_throttle(root);
2643} 2643}
2644 2644
2645/*
2646 * Invalidate a single dcache entry at the root of the filesystem.
2647 * Needed after creation of snapshot or subvolume.
2648 */
2649void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name,
2650 int namelen)
2651{
2652 struct dentry *alias, *entry;
2653 struct qstr qstr;
2654
2655 alias = d_find_alias(root->fs_info->sb->s_root->d_inode);
2656 if (alias) {
2657 qstr.name = name;
2658 qstr.len = namelen;
2659 /* change me if btrfs ever gets a d_hash operation */
2660 qstr.hash = full_name_hash(qstr.name, qstr.len);
2661 entry = d_lookup(alias, &qstr);
2662 dput(alias);
2663 if (entry) {
2664 d_invalidate(entry);
2665 dput(entry);
2666 }
2667 }
2668}
2669
2645static int noinline create_subvol(struct btrfs_root *root, char *name, 2670static int noinline create_subvol(struct btrfs_root *root, char *name,
2646 int namelen) 2671 int namelen)
2647{ 2672{
@@ -2761,6 +2786,10 @@ static int noinline create_subvol(struct btrfs_root *root, char *name,
2761 ret = btrfs_update_inode(trans, new_root, inode); 2786 ret = btrfs_update_inode(trans, new_root, inode);
2762 if (ret) 2787 if (ret)
2763 goto fail; 2788 goto fail;
2789
2790 /* Invalidate existing dcache entry for new subvolume. */
2791 btrfs_invalidate_dcache_root(root, name, namelen);
2792
2764fail: 2793fail:
2765 nr = trans->blocks_used; 2794 nr = trans->blocks_used;
2766 err = btrfs_commit_transaction(trans, new_root); 2795 err = btrfs_commit_transaction(trans, new_root);
diff --git a/fs/btrfs/transaction.c b/fs/btrfs/transaction.c
index 1cb084efd6ed..f04684f7fea3 100644
--- a/fs/btrfs/transaction.c
+++ b/fs/btrfs/transaction.c
@@ -560,6 +560,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
560 struct btrfs_root *root = pending->root; 560 struct btrfs_root *root = pending->root;
561 struct extent_buffer *tmp; 561 struct extent_buffer *tmp;
562 int ret; 562 int ret;
563 int namelen;
563 u64 objectid; 564 u64 objectid;
564 565
565 new_root_item = kmalloc(sizeof(*new_root_item), GFP_NOFS); 566 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,
595 * insert the directory item 596 * insert the directory item
596 */ 597 */
597 key.offset = (u64)-1; 598 key.offset = (u64)-1;
599 namelen = strlen(pending->name);
598 ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root, 600 ret = btrfs_insert_dir_item(trans, root->fs_info->tree_root,
599 pending->name, strlen(pending->name), 601 pending->name, namelen,
600 root->fs_info->sb->s_root->d_inode->i_ino, 602 root->fs_info->sb->s_root->d_inode->i_ino,
601 &key, BTRFS_FT_DIR); 603 &key, BTRFS_FT_DIR);
602 604
@@ -606,6 +608,10 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
606 ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root, 608 ret = btrfs_insert_inode_ref(trans, root->fs_info->tree_root,
607 pending->name, strlen(pending->name), objectid, 609 pending->name, strlen(pending->name), objectid,
608 root->fs_info->sb->s_root->d_inode->i_ino); 610 root->fs_info->sb->s_root->d_inode->i_ino);
611
612 /* Invalidate existing dcache entry for new snapshot. */
613 btrfs_invalidate_dcache_root(root, pending->name, namelen);
614
609fail: 615fail:
610 kfree(new_root_item); 616 kfree(new_root_item);
611 return ret; 617 return ret;