diff options
Diffstat (limited to 'fs')
-rw-r--r-- | fs/btrfs/ctree.h | 3 | ||||
-rw-r--r-- | fs/btrfs/inode.c | 29 | ||||
-rw-r--r-- | fs/btrfs/transaction.c | 8 |
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 */ |
1547 | void btrfs_invalidate_dcache_root(struct btrfs_root *root, char *name, | ||
1548 | int namelen); | ||
1549 | |||
1547 | int btrfs_merge_bio_hook(struct page *page, unsigned long offset, | 1550 | int 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 | */ | ||
2649 | void 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 | |||
2645 | static int noinline create_subvol(struct btrfs_root *root, char *name, | 2670 | static 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 | |||
2764 | fail: | 2793 | fail: |
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 | |||
609 | fail: | 615 | fail: |
610 | kfree(new_root_item); | 616 | kfree(new_root_item); |
611 | return ret; | 617 | return ret; |