1 From 03bd8b9b896c8e940f282f540e6b4de90d666b7c Mon Sep 17 00:00:00 2001
2 From: Dmitry Monakhov <dmonakhov@openvz.org>
3 Date: Wed, 26 Sep 2012 12:32:19 -0400
4 Subject: ext4: move_extent code cleanup
6 From: Dmitry Monakhov <dmonakhov@openvz.org>
8 commit 03bd8b9b896c8e940f282f540e6b4de90d666b7c upstream.
10 - Remove usless checks, because it is too late to check that inode != NULL
11 at the moment it was referenced several times.
12 - Double lock routines looks very ugly and locking ordering relays on
13 order of i_ino, but other kernel code rely on order of pointers.
14 Let's make them simple and clean.
15 - check that inodes belongs to the same SB as soon as possible.
17 Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
18 Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
19 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
22 fs/ext4/move_extent.c | 167 ++++++++++++++------------------------------------
23 1 file changed, 47 insertions(+), 120 deletions(-)
25 --- a/fs/ext4/move_extent.c
26 +++ b/fs/ext4/move_extent.c
27 @@ -141,55 +141,21 @@ mext_next_extent(struct inode *inode, st
31 - * mext_check_null_inode - NULL check for two inodes
33 - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0.
36 -mext_check_null_inode(struct inode *inode1, struct inode *inode2,
37 - const char *function, unsigned int line)
41 - if (inode1 == NULL) {
42 - __ext4_error(inode2->i_sb, function, line,
43 - "Both inodes should not be NULL: "
44 - "inode1 NULL inode2 %lu", inode2->i_ino);
46 - } else if (inode2 == NULL) {
47 - __ext4_error(inode1->i_sb, function, line,
48 - "Both inodes should not be NULL: "
49 - "inode1 %lu inode2 NULL", inode1->i_ino);
56 * double_down_write_data_sem - Acquire two inodes' write lock of i_data_sem
58 - * @orig_inode: original inode structure
59 - * @donor_inode: donor inode structure
60 - * Acquire write lock of i_data_sem of the two inodes (orig and donor) by
62 + * Acquire write lock of i_data_sem of the two inodes
65 -double_down_write_data_sem(struct inode *orig_inode, struct inode *donor_inode)
66 +double_down_write_data_sem(struct inode *first, struct inode *second)
68 - struct inode *first = orig_inode, *second = donor_inode;
69 + if (first < second) {
70 + down_write(&EXT4_I(first)->i_data_sem);
71 + down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING);
73 + down_write(&EXT4_I(second)->i_data_sem);
74 + down_write_nested(&EXT4_I(first)->i_data_sem, SINGLE_DEPTH_NESTING);
77 - * Use the inode number to provide the stable locking order instead
78 - * of its address, because the C language doesn't guarantee you can
79 - * compare pointers that don't come from the same array.
81 - if (donor_inode->i_ino < orig_inode->i_ino) {
82 - first = donor_inode;
83 - second = orig_inode;
86 - down_write(&EXT4_I(first)->i_data_sem);
87 - down_write_nested(&EXT4_I(second)->i_data_sem, SINGLE_DEPTH_NESTING);
91 @@ -969,14 +935,6 @@ mext_check_arguments(struct inode *orig_
95 - /* Files should be in the same ext4 FS */
96 - if (orig_inode->i_sb != donor_inode->i_sb) {
97 - ext4_debug("ext4 move extent: The argument files "
98 - "should be in same FS [ino:orig %lu, donor %lu]\n",
99 - orig_inode->i_ino, donor_inode->i_ino);
103 /* Ext4 move extent supports only extent based file */
104 if (!(ext4_test_inode_flag(orig_inode, EXT4_INODE_EXTENTS))) {
105 ext4_debug("ext4 move extent: orig file is not extents "
106 @@ -1072,35 +1030,19 @@ mext_check_arguments(struct inode *orig_
107 * @inode1: the inode structure
108 * @inode2: the inode structure
110 - * Lock two inodes' i_mutex by i_ino order.
111 - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0.
112 + * Lock two inodes' i_mutex
116 mext_inode_double_lock(struct inode *inode1, struct inode *inode2)
120 - BUG_ON(inode1 == NULL && inode2 == NULL);
122 - ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__);
126 - if (inode1 == inode2) {
127 - mutex_lock(&inode1->i_mutex);
131 - if (inode1->i_ino < inode2->i_ino) {
132 + BUG_ON(inode1 == inode2);
133 + if (inode1 < inode2) {
134 mutex_lock_nested(&inode1->i_mutex, I_MUTEX_PARENT);
135 mutex_lock_nested(&inode2->i_mutex, I_MUTEX_CHILD);
137 mutex_lock_nested(&inode2->i_mutex, I_MUTEX_PARENT);
138 mutex_lock_nested(&inode1->i_mutex, I_MUTEX_CHILD);
146 @@ -1109,28 +1051,13 @@ out:
147 * @inode1: the inode that is released first
148 * @inode2: the inode that is released second
150 - * If inode1 or inode2 is NULL, return -EIO. Otherwise, return 0.
155 mext_inode_double_unlock(struct inode *inode1, struct inode *inode2)
159 - BUG_ON(inode1 == NULL && inode2 == NULL);
161 - ret = mext_check_null_inode(inode1, inode2, __func__, __LINE__);
166 - mutex_unlock(&inode1->i_mutex);
168 - if (inode2 && inode2 != inode1)
169 - mutex_unlock(&inode2->i_mutex);
173 + mutex_unlock(&inode1->i_mutex);
174 + mutex_unlock(&inode2->i_mutex);
178 @@ -1187,16 +1114,23 @@ ext4_move_extents(struct file *o_filp, s
179 ext4_lblk_t block_end, seq_start, add_blocks, file_end, seq_blocks = 0;
180 ext4_lblk_t rest_blocks;
181 pgoff_t orig_page_offset = 0, seq_end_page;
182 - int ret1, ret2, depth, last_extent = 0;
183 + int ret, depth, last_extent = 0;
184 int blocks_per_page = PAGE_CACHE_SIZE >> orig_inode->i_blkbits;
185 int data_offset_in_page;
186 int block_len_in_page;
189 - /* orig and donor should be different file */
190 - if (orig_inode->i_ino == donor_inode->i_ino) {
191 + if (orig_inode->i_sb != donor_inode->i_sb) {
192 + ext4_debug("ext4 move extent: The argument files "
193 + "should be in same FS [ino:orig %lu, donor %lu]\n",
194 + orig_inode->i_ino, donor_inode->i_ino);
198 + /* orig and donor should be different inodes */
199 + if (orig_inode == donor_inode) {
200 ext4_debug("ext4 move extent: The argument files should not "
201 - "be same file [ino:orig %lu, donor %lu]\n",
202 + "be same inode [ino:orig %lu, donor %lu]\n",
203 orig_inode->i_ino, donor_inode->i_ino);
206 @@ -1210,16 +1144,14 @@ ext4_move_extents(struct file *o_filp, s
209 /* Protect orig and donor inodes against a truncate */
210 - ret1 = mext_inode_double_lock(orig_inode, donor_inode);
213 + mext_inode_double_lock(orig_inode, donor_inode);
215 /* Protect extent tree against block allocations via delalloc */
216 double_down_write_data_sem(orig_inode, donor_inode);
217 /* Check the filesystem environment whether move_extent can be done */
218 - ret1 = mext_check_arguments(orig_inode, donor_inode, orig_start,
219 + ret = mext_check_arguments(orig_inode, donor_inode, orig_start,
225 file_end = (i_size_read(orig_inode) - 1) >> orig_inode->i_blkbits;
226 @@ -1227,13 +1159,13 @@ ext4_move_extents(struct file *o_filp, s
227 if (file_end < block_end)
228 len -= block_end - file_end;
230 - ret1 = get_ext_path(orig_inode, block_start, &orig_path);
232 + ret = get_ext_path(orig_inode, block_start, &orig_path);
236 /* Get path structure to check the hole */
237 - ret1 = get_ext_path(orig_inode, block_start, &holecheck_path);
239 + ret = get_ext_path(orig_inode, block_start, &holecheck_path);
243 depth = ext_depth(orig_inode);
244 @@ -1252,13 +1184,13 @@ ext4_move_extents(struct file *o_filp, s
245 last_extent = mext_next_extent(orig_inode,
246 holecheck_path, &ext_cur);
247 if (last_extent < 0) {
248 - ret1 = last_extent;
252 last_extent = mext_next_extent(orig_inode, orig_path,
254 if (last_extent < 0) {
255 - ret1 = last_extent;
259 seq_start = le32_to_cpu(ext_cur->ee_block);
260 @@ -1272,7 +1204,7 @@ ext4_move_extents(struct file *o_filp, s
261 if (le32_to_cpu(ext_cur->ee_block) > block_end) {
262 ext4_debug("ext4 move extent: The specified range of file "
263 "may be the hole\n");
269 @@ -1292,7 +1224,7 @@ ext4_move_extents(struct file *o_filp, s
270 last_extent = mext_next_extent(orig_inode, holecheck_path,
272 if (last_extent < 0) {
273 - ret1 = last_extent;
277 add_blocks = ext4_ext_get_actual_len(ext_cur);
278 @@ -1349,18 +1281,18 @@ ext4_move_extents(struct file *o_filp, s
281 block_len_in_page, uninit,
285 /* Count how many blocks we have exchanged */
286 *moved_len += block_len_in_page;
290 if (*moved_len > len) {
291 EXT4_ERROR_INODE(orig_inode,
292 "We replaced blocks too much! "
293 "sum of replaced: %llu requested: %llu",
300 @@ -1374,22 +1306,22 @@ ext4_move_extents(struct file *o_filp, s
303 double_down_write_data_sem(orig_inode, donor_inode);
308 /* Decrease buffer counter */
310 ext4_ext_drop_refs(holecheck_path);
311 - ret1 = get_ext_path(orig_inode, seq_start, &holecheck_path);
313 + ret = get_ext_path(orig_inode, seq_start, &holecheck_path);
316 depth = holecheck_path->p_depth;
318 /* Decrease buffer counter */
320 ext4_ext_drop_refs(orig_path);
321 - ret1 = get_ext_path(orig_inode, seq_start, &orig_path);
323 + ret = get_ext_path(orig_inode, seq_start, &orig_path);
327 ext_cur = holecheck_path[depth].p_ext;
328 @@ -1412,12 +1344,7 @@ out:
329 kfree(holecheck_path);
331 double_up_write_data_sem(orig_inode, donor_inode);
332 - ret2 = mext_inode_double_unlock(orig_inode, donor_inode);
333 + mext_inode_double_unlock(orig_inode, donor_inode);