]>
Commit | Line | Data |
---|---|---|
8de80845 GKH |
1 | From 2e4bfab97055aa6acdd0637913bd705c2d6506d6 Mon Sep 17 00:00:00 2001 |
2 | From: Yan, Zheng <zheng.yan@oracle.com> | |
3 | Date: Thu, 12 Nov 2009 09:37:02 +0000 | |
4 | Subject: Btrfs: Avoid orphan inodes cleanup during committing transaction | |
5 | ||
6 | From: Yan, Zheng <zheng.yan@oracle.com> | |
7 | ||
8 | commit 2e4bfab97055aa6acdd0637913bd705c2d6506d6 upstream. | |
9 | ||
10 | btrfs_lookup_dentry may trigger orphan cleanup, so it's not good | |
11 | to call it while committing a transaction. | |
12 | ||
13 | Signed-off-by: Yan Zheng <zheng.yan@oracle.com> | |
14 | Signed-off-by: Chris Mason <chris.mason@oracle.com> | |
15 | Acked-by: Jeff Mahoney <jeffm@suse.com> | |
16 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
17 | ||
18 | --- | |
19 | fs/btrfs/ioctl.c | 29 +++++++++++++++++------------ | |
20 | fs/btrfs/transaction.c | 4 ---- | |
21 | 2 files changed, 17 insertions(+), 16 deletions(-) | |
22 | ||
23 | --- a/fs/btrfs/ioctl.c | |
24 | +++ b/fs/btrfs/ioctl.c | |
25 | @@ -237,7 +237,6 @@ static noinline int create_subvol(struct | |
26 | u64 objectid; | |
27 | u64 new_dirid = BTRFS_FIRST_FREE_OBJECTID; | |
28 | u64 index = 0; | |
29 | - unsigned long nr = 1; | |
30 | ||
31 | /* | |
32 | * 1 - inode item | |
33 | @@ -342,24 +341,21 @@ static noinline int create_subvol(struct | |
34 | ||
35 | d_instantiate(dentry, btrfs_lookup_dentry(dir, dentry)); | |
36 | fail: | |
37 | - nr = trans->blocks_used; | |
38 | err = btrfs_commit_transaction(trans, root); | |
39 | if (err && !ret) | |
40 | ret = err; | |
41 | ||
42 | btrfs_unreserve_metadata_space(root, 6); | |
43 | - btrfs_btree_balance_dirty(root, nr); | |
44 | return ret; | |
45 | } | |
46 | ||
47 | static int create_snapshot(struct btrfs_root *root, struct dentry *dentry, | |
48 | char *name, int namelen) | |
49 | { | |
50 | + struct inode *inode; | |
51 | struct btrfs_pending_snapshot *pending_snapshot; | |
52 | struct btrfs_trans_handle *trans; | |
53 | - int ret = 0; | |
54 | - int err; | |
55 | - unsigned long nr = 0; | |
56 | + int ret; | |
57 | ||
58 | if (!root->ref_cows) | |
59 | return -EINVAL; | |
60 | @@ -372,20 +368,20 @@ static int create_snapshot(struct btrfs_ | |
61 | */ | |
62 | ret = btrfs_reserve_metadata_space(root, 6); | |
63 | if (ret) | |
64 | - goto fail_unlock; | |
65 | + goto fail; | |
66 | ||
67 | pending_snapshot = kzalloc(sizeof(*pending_snapshot), GFP_NOFS); | |
68 | if (!pending_snapshot) { | |
69 | ret = -ENOMEM; | |
70 | btrfs_unreserve_metadata_space(root, 6); | |
71 | - goto fail_unlock; | |
72 | + goto fail; | |
73 | } | |
74 | pending_snapshot->name = kmalloc(namelen + 1, GFP_NOFS); | |
75 | if (!pending_snapshot->name) { | |
76 | ret = -ENOMEM; | |
77 | kfree(pending_snapshot); | |
78 | btrfs_unreserve_metadata_space(root, 6); | |
79 | - goto fail_unlock; | |
80 | + goto fail; | |
81 | } | |
82 | memcpy(pending_snapshot->name, name, namelen); | |
83 | pending_snapshot->name[namelen] = '\0'; | |
84 | @@ -395,10 +391,19 @@ static int create_snapshot(struct btrfs_ | |
85 | pending_snapshot->root = root; | |
86 | list_add(&pending_snapshot->list, | |
87 | &trans->transaction->pending_snapshots); | |
88 | - err = btrfs_commit_transaction(trans, root); | |
89 | + ret = btrfs_commit_transaction(trans, root); | |
90 | + BUG_ON(ret); | |
91 | + btrfs_unreserve_metadata_space(root, 6); | |
92 | ||
93 | -fail_unlock: | |
94 | - btrfs_btree_balance_dirty(root, nr); | |
95 | + inode = btrfs_lookup_dentry(dentry->d_parent->d_inode, dentry); | |
96 | + if (IS_ERR(inode)) { | |
97 | + ret = PTR_ERR(inode); | |
98 | + goto fail; | |
99 | + } | |
100 | + BUG_ON(!inode); | |
101 | + d_instantiate(dentry, inode); | |
102 | + ret = 0; | |
103 | +fail: | |
104 | return ret; | |
105 | } | |
106 | ||
107 | --- a/fs/btrfs/transaction.c | |
108 | +++ b/fs/btrfs/transaction.c | |
109 | @@ -796,7 +796,6 @@ static noinline int create_pending_snaps | |
110 | memcpy(&pending->root_key, &key, sizeof(key)); | |
111 | fail: | |
112 | kfree(new_root_item); | |
113 | - btrfs_unreserve_metadata_space(root, 6); | |
114 | return ret; | |
115 | } | |
116 | ||
117 | @@ -808,7 +807,6 @@ static noinline int finish_pending_snaps | |
118 | u64 index = 0; | |
119 | struct btrfs_trans_handle *trans; | |
120 | struct inode *parent_inode; | |
121 | - struct inode *inode; | |
122 | struct btrfs_root *parent_root; | |
123 | ||
124 | parent_inode = pending->dentry->d_parent->d_inode; | |
125 | @@ -840,8 +838,6 @@ static noinline int finish_pending_snaps | |
126 | ||
127 | BUG_ON(ret); | |
128 | ||
129 | - inode = btrfs_lookup_dentry(parent_inode, pending->dentry); | |
130 | - d_instantiate(pending->dentry, inode); | |
131 | fail: | |
132 | btrfs_end_transaction(trans, fs_info->fs_root); | |
133 | return ret; |