@@ -1222,6 +1222,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
12221222 ext4_lblk_t offsets [4 ], offsets2 [4 ];
12231223 Indirect chain [4 ], chain2 [4 ];
12241224 Indirect * partial , * partial2 ;
1225+ Indirect * p = NULL , * p2 = NULL ;
12251226 ext4_lblk_t max_block ;
12261227 __le32 nr = 0 , nr2 = 0 ;
12271228 int n = 0 , n2 = 0 ;
@@ -1263,7 +1264,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
12631264 }
12641265
12651266
1266- partial = ext4_find_shared (inode , n , offsets , chain , & nr );
1267+ partial = p = ext4_find_shared (inode , n , offsets , chain , & nr );
12671268 if (nr ) {
12681269 if (partial == chain ) {
12691270 /* Shared branch grows from the inode */
@@ -1288,13 +1289,11 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
12881289 partial -> p + 1 ,
12891290 (__le32 * )partial -> bh -> b_data + addr_per_block ,
12901291 (chain + n - 1 ) - partial );
1291- BUFFER_TRACE (partial -> bh , "call brelse" );
1292- brelse (partial -> bh );
12931292 partial -- ;
12941293 }
12951294
12961295end_range :
1297- partial2 = ext4_find_shared (inode , n2 , offsets2 , chain2 , & nr2 );
1296+ partial2 = p2 = ext4_find_shared (inode , n2 , offsets2 , chain2 , & nr2 );
12981297 if (nr2 ) {
12991298 if (partial2 == chain2 ) {
13001299 /*
@@ -1324,16 +1323,14 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
13241323 (__le32 * )partial2 -> bh -> b_data ,
13251324 partial2 -> p ,
13261325 (chain2 + n2 - 1 ) - partial2 );
1327- BUFFER_TRACE (partial2 -> bh , "call brelse" );
1328- brelse (partial2 -> bh );
13291326 partial2 -- ;
13301327 }
13311328 goto do_indirects ;
13321329 }
13331330
13341331 /* Punch happened within the same level (n == n2) */
1335- partial = ext4_find_shared (inode , n , offsets , chain , & nr );
1336- partial2 = ext4_find_shared (inode , n2 , offsets2 , chain2 , & nr2 );
1332+ partial = p = ext4_find_shared (inode , n , offsets , chain , & nr );
1333+ partial2 = p2 = ext4_find_shared (inode , n2 , offsets2 , chain2 , & nr2 );
13371334
13381335 /* Free top, but only if partial2 isn't its subtree. */
13391336 if (nr ) {
@@ -1390,11 +1387,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
13901387 partial -> p + 1 ,
13911388 partial2 -> p ,
13921389 (chain + n - 1 ) - partial );
1393- BUFFER_TRACE (partial -> bh , "call brelse" );
1394- brelse (partial -> bh );
1395- BUFFER_TRACE (partial2 -> bh , "call brelse" );
1396- brelse (partial2 -> bh );
1397- return 0 ;
1390+ goto cleanup ;
13981391 }
13991392
14001393 /*
@@ -1409,28 +1402,36 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14091402 partial -> p + 1 ,
14101403 (__le32 * )partial -> bh -> b_data + addr_per_block ,
14111404 (chain + n - 1 ) - partial );
1412- BUFFER_TRACE (partial -> bh , "call brelse" );
1413- brelse (partial -> bh );
14141405 partial -- ;
14151406 }
14161407 if (partial2 > chain2 && depth2 <= depth ) {
14171408 ext4_free_branches (handle , inode , partial2 -> bh ,
14181409 (__le32 * )partial2 -> bh -> b_data ,
14191410 partial2 -> p ,
14201411 (chain2 + n2 - 1 ) - partial2 );
1421- BUFFER_TRACE (partial2 -> bh , "call brelse" );
1422- brelse (partial2 -> bh );
14231412 partial2 -- ;
14241413 }
14251414 }
1415+
1416+ cleanup :
1417+ while (p && p > chain ) {
1418+ BUFFER_TRACE (p -> bh , "call brelse" );
1419+ brelse (p -> bh );
1420+ p -- ;
1421+ }
1422+ while (p2 && p2 > chain2 ) {
1423+ BUFFER_TRACE (p2 -> bh , "call brelse" );
1424+ brelse (p2 -> bh );
1425+ p2 -- ;
1426+ }
14261427 return 0 ;
14271428
14281429do_indirects :
14291430 /* Kill the remaining (whole) subtrees */
14301431 switch (offsets [0 ]) {
14311432 default :
14321433 if (++ n >= n2 )
1433- return 0 ;
1434+ break ;
14341435 nr = i_data [EXT4_IND_BLOCK ];
14351436 if (nr ) {
14361437 ext4_free_branches (handle , inode , NULL , & nr , & nr + 1 , 1 );
@@ -1439,7 +1440,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14391440 /* fall through */
14401441 case EXT4_IND_BLOCK :
14411442 if (++ n >= n2 )
1442- return 0 ;
1443+ break ;
14431444 nr = i_data [EXT4_DIND_BLOCK ];
14441445 if (nr ) {
14451446 ext4_free_branches (handle , inode , NULL , & nr , & nr + 1 , 2 );
@@ -1448,7 +1449,7 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14481449 /* fall through */
14491450 case EXT4_DIND_BLOCK :
14501451 if (++ n >= n2 )
1451- return 0 ;
1452+ break ;
14521453 nr = i_data [EXT4_TIND_BLOCK ];
14531454 if (nr ) {
14541455 ext4_free_branches (handle , inode , NULL , & nr , & nr + 1 , 3 );
@@ -1458,5 +1459,5 @@ int ext4_ind_remove_space(handle_t *handle, struct inode *inode,
14581459 case EXT4_TIND_BLOCK :
14591460 ;
14601461 }
1461- return 0 ;
1462+ goto cleanup ;
14621463}
0 commit comments