]>
Commit | Line | Data |
---|---|---|
7d777456 GKH |
1 | From 492c93e8097f0bf58b2884064af85242fabe5d71 Mon Sep 17 00:00:00 2001 |
2 | From: Dmitry Monakhov <dmonakhov@openvz.org> | |
3 | Date: Sun, 30 May 2010 22:49:31 -0400 | |
4 | Subject: ext4: fix error handling in migrate | |
5 | ||
6 | commit f39490bcd1691d65dc33689222a12e1fc13dd824 upstream (as of v2.6.33-git11) | |
7 | ||
8 | Set i_nlink to zero for temporary inode from very beginning. | |
9 | otherwise we may fail to start new journal handle and this | |
10 | inode will be unreferenced but with i_nlink == 1 | |
11 | Since we hold inode reference it can not be pruned. | |
12 | ||
13 | Also add missed journal_start retval check. | |
14 | ||
15 | Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org> | |
16 | Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> | |
17 | Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> | |
18 | --- | |
19 | fs/ext4/migrate.c | 29 ++++++++++++++--------------- | |
20 | 1 file changed, 14 insertions(+), 15 deletions(-) | |
21 | ||
22 | --- a/fs/ext4/migrate.c | |
23 | +++ b/fs/ext4/migrate.c | |
24 | @@ -494,14 +494,10 @@ int ext4_ext_migrate(struct inode *inode | |
25 | } | |
26 | i_size_write(tmp_inode, i_size_read(inode)); | |
27 | /* | |
28 | - * We don't want the inode to be reclaimed | |
29 | - * if we got interrupted in between. We have | |
30 | - * this tmp inode carrying reference to the | |
31 | - * data blocks of the original file. We set | |
32 | - * the i_nlink to zero at the last stage after | |
33 | - * switching the original file to extent format | |
34 | + * Set the i_nlink to zero so it will be deleted later | |
35 | + * when we drop inode reference. | |
36 | */ | |
37 | - tmp_inode->i_nlink = 1; | |
38 | + tmp_inode->i_nlink = 0; | |
39 | ||
40 | ext4_ext_tree_init(handle, tmp_inode); | |
41 | ext4_orphan_add(handle, tmp_inode); | |
42 | @@ -528,6 +524,16 @@ int ext4_ext_migrate(struct inode *inode | |
43 | up_read((&EXT4_I(inode)->i_data_sem)); | |
44 | ||
45 | handle = ext4_journal_start(inode, 1); | |
46 | + if (IS_ERR(handle)) { | |
47 | + /* | |
48 | + * It is impossible to update on-disk structures without | |
49 | + * a handle, so just rollback in-core changes and live other | |
50 | + * work to orphan_list_cleanup() | |
51 | + */ | |
52 | + ext4_orphan_del(NULL, tmp_inode); | |
53 | + retval = PTR_ERR(handle); | |
54 | + goto out; | |
55 | + } | |
56 | ||
57 | ei = EXT4_I(inode); | |
58 | i_data = ei->i_data; | |
59 | @@ -609,15 +615,8 @@ err_out: | |
60 | ||
61 | /* Reset the extent details */ | |
62 | ext4_ext_tree_init(handle, tmp_inode); | |
63 | - | |
64 | - /* | |
65 | - * Set the i_nlink to zero so that | |
66 | - * generic_drop_inode really deletes the | |
67 | - * inode | |
68 | - */ | |
69 | - tmp_inode->i_nlink = 0; | |
70 | - | |
71 | ext4_journal_stop(handle); | |
72 | +out: | |
73 | unlock_new_inode(tmp_inode); | |
74 | iput(tmp_inode); | |
75 |