forked from mirrors/linux
		
	ext4: remove messy logic from ext4_ext_rm_leaf
- Both callers(truncate and punch_hole) already aligned left end point
  so we no longer need split logic here.
- Remove dead duplicated code.
- Call ext4_ext_dirty only after we have updated eh_entries, otherwise
  we'll loose entries update. Regression caused by d583fb87a3
  266'th testcase in xfstests (http://patchwork.ozlabs.org/patch/120872)
Signed-off-by: Dmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>
			
			
This commit is contained in:
		
							parent
							
								
									1939dd84b3
								
							
						
					
					
						commit
						750c9c47a5
					
				
					 1 changed files with 12 additions and 91 deletions
				
			
		| 
						 | 
					@ -2311,13 +2311,12 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 | 
				
			||||||
	int err = 0, correct_index = 0;
 | 
						int err = 0, correct_index = 0;
 | 
				
			||||||
	int depth = ext_depth(inode), credits;
 | 
						int depth = ext_depth(inode), credits;
 | 
				
			||||||
	struct ext4_extent_header *eh;
 | 
						struct ext4_extent_header *eh;
 | 
				
			||||||
	ext4_lblk_t a, b, block;
 | 
						ext4_lblk_t a, b;
 | 
				
			||||||
	unsigned num;
 | 
						unsigned num;
 | 
				
			||||||
	ext4_lblk_t ex_ee_block;
 | 
						ext4_lblk_t ex_ee_block;
 | 
				
			||||||
	unsigned short ex_ee_len;
 | 
						unsigned short ex_ee_len;
 | 
				
			||||||
	unsigned uninitialized = 0;
 | 
						unsigned uninitialized = 0;
 | 
				
			||||||
	struct ext4_extent *ex;
 | 
						struct ext4_extent *ex;
 | 
				
			||||||
	struct ext4_map_blocks map;
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* the header must be checked already in ext4_ext_remove_space() */
 | 
						/* the header must be checked already in ext4_ext_remove_space() */
 | 
				
			||||||
	ext_debug("truncate since %u in leaf\n", start);
 | 
						ext_debug("truncate since %u in leaf\n", start);
 | 
				
			||||||
| 
						 | 
					@ -2360,86 +2359,18 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 | 
				
			||||||
			ex_ee_block = le32_to_cpu(ex->ee_block);
 | 
								ex_ee_block = le32_to_cpu(ex->ee_block);
 | 
				
			||||||
			ex_ee_len = ext4_ext_get_actual_len(ex);
 | 
								ex_ee_len = ext4_ext_get_actual_len(ex);
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		} else if (a != ex_ee_block &&
 | 
							} else if (b != ex_ee_block + ex_ee_len - 1) {
 | 
				
			||||||
			b != ex_ee_block + ex_ee_len - 1) {
 | 
								EXT4_ERROR_INODE(inode,"  bad truncate %u:%u\n",
 | 
				
			||||||
			/*
 | 
										 start, end);
 | 
				
			||||||
			 * If this is a truncate, then this condition should
 | 
								err = -EIO;
 | 
				
			||||||
			 * never happen because at least one of the end points
 | 
								goto out;
 | 
				
			||||||
			 * needs to be on the edge of the extent.
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			if (end == EXT_MAX_BLOCKS - 1) {
 | 
					 | 
				
			||||||
				ext_debug("  bad truncate %u:%u\n",
 | 
					 | 
				
			||||||
						start, end);
 | 
					 | 
				
			||||||
				block = 0;
 | 
					 | 
				
			||||||
				num = 0;
 | 
					 | 
				
			||||||
				err = -EIO;
 | 
					 | 
				
			||||||
				goto out;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			/*
 | 
					 | 
				
			||||||
			 * else this is a hole punch, so the extent needs to
 | 
					 | 
				
			||||||
			 * be split since neither edge of the hole is on the
 | 
					 | 
				
			||||||
			 * extent edge
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			else{
 | 
					 | 
				
			||||||
				map.m_pblk = ext4_ext_pblock(ex);
 | 
					 | 
				
			||||||
				map.m_lblk = ex_ee_block;
 | 
					 | 
				
			||||||
				map.m_len = b - ex_ee_block;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				err = ext4_split_extent(handle,
 | 
					 | 
				
			||||||
					inode, path, &map, 0,
 | 
					 | 
				
			||||||
					EXT4_GET_BLOCKS_PUNCH_OUT_EXT |
 | 
					 | 
				
			||||||
					EXT4_GET_BLOCKS_PRE_IO);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if (err < 0)
 | 
					 | 
				
			||||||
					goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				ex_ee_len = ext4_ext_get_actual_len(ex);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				b = ex_ee_block+ex_ee_len - 1 < end ?
 | 
					 | 
				
			||||||
					ex_ee_block+ex_ee_len - 1 : end;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				/* Then remove tail of this extent */
 | 
					 | 
				
			||||||
				block = ex_ee_block;
 | 
					 | 
				
			||||||
				num = a - block;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else if (a != ex_ee_block) {
 | 
							} else if (a != ex_ee_block) {
 | 
				
			||||||
			/* remove tail of the extent */
 | 
								/* remove tail of the extent */
 | 
				
			||||||
			block = ex_ee_block;
 | 
								num = a - ex_ee_block;
 | 
				
			||||||
			num = a - block;
 | 
					 | 
				
			||||||
		} else if (b != ex_ee_block + ex_ee_len - 1) {
 | 
					 | 
				
			||||||
			/* remove head of the extent */
 | 
					 | 
				
			||||||
			block = b;
 | 
					 | 
				
			||||||
			num =  ex_ee_block + ex_ee_len - b;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			/*
 | 
					 | 
				
			||||||
			 * If this is a truncate, this condition
 | 
					 | 
				
			||||||
			 * should never happen
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			if (end == EXT_MAX_BLOCKS - 1) {
 | 
					 | 
				
			||||||
				ext_debug("  bad truncate %u:%u\n",
 | 
					 | 
				
			||||||
					start, end);
 | 
					 | 
				
			||||||
				err = -EIO;
 | 
					 | 
				
			||||||
				goto out;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		} else {
 | 
							} else {
 | 
				
			||||||
			/* remove whole extent: excellent! */
 | 
								/* remove whole extent: excellent! */
 | 
				
			||||||
			block = ex_ee_block;
 | 
					 | 
				
			||||||
			num = 0;
 | 
								num = 0;
 | 
				
			||||||
			if (a != ex_ee_block) {
 | 
					 | 
				
			||||||
				ext_debug("  bad truncate %u:%u\n",
 | 
					 | 
				
			||||||
					start, end);
 | 
					 | 
				
			||||||
				err = -EIO;
 | 
					 | 
				
			||||||
				goto out;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if (b != ex_ee_block + ex_ee_len - 1) {
 | 
					 | 
				
			||||||
				ext_debug("  bad truncate %u:%u\n",
 | 
					 | 
				
			||||||
					start, end);
 | 
					 | 
				
			||||||
				err = -EIO;
 | 
					 | 
				
			||||||
				goto out;
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * 3 for leaf, sb, and inode plus 2 (bmap and group
 | 
							 * 3 for leaf, sb, and inode plus 2 (bmap and group
 | 
				
			||||||
		 * descriptor) for each block group; assume two block
 | 
							 * descriptor) for each block group; assume two block
 | 
				
			||||||
| 
						 | 
					@ -2466,19 +2397,10 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			goto out;
 | 
								goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (num == 0) {
 | 
							if (num == 0)
 | 
				
			||||||
			/* this extent is removed; mark slot entirely unused */
 | 
								/* this extent is removed; mark slot entirely unused */
 | 
				
			||||||
			ext4_ext_store_pblock(ex, 0);
 | 
								ext4_ext_store_pblock(ex, 0);
 | 
				
			||||||
		} else if (block != ex_ee_block) {
 | 
					 | 
				
			||||||
			/*
 | 
					 | 
				
			||||||
			 * If this was a head removal, then we need to update
 | 
					 | 
				
			||||||
			 * the physical block since it is now at a different
 | 
					 | 
				
			||||||
			 * location
 | 
					 | 
				
			||||||
			 */
 | 
					 | 
				
			||||||
			ext4_ext_store_pblock(ex, ext4_ext_pblock(ex) + (b-a));
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ex->ee_block = cpu_to_le32(block);
 | 
					 | 
				
			||||||
		ex->ee_len = cpu_to_le16(num);
 | 
							ex->ee_len = cpu_to_le16(num);
 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * Do not mark uninitialized if all the blocks in the
 | 
							 * Do not mark uninitialized if all the blocks in the
 | 
				
			||||||
| 
						 | 
					@ -2486,11 +2408,6 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 | 
				
			||||||
		 */
 | 
							 */
 | 
				
			||||||
		if (uninitialized && num)
 | 
							if (uninitialized && num)
 | 
				
			||||||
			ext4_ext_mark_uninitialized(ex);
 | 
								ext4_ext_mark_uninitialized(ex);
 | 
				
			||||||
 | 
					 | 
				
			||||||
		err = ext4_ext_dirty(handle, inode, path + depth);
 | 
					 | 
				
			||||||
		if (err)
 | 
					 | 
				
			||||||
			goto out;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		/*
 | 
							/*
 | 
				
			||||||
		 * If the extent was completely released,
 | 
							 * If the extent was completely released,
 | 
				
			||||||
		 * we need to remove it from the leaf
 | 
							 * we need to remove it from the leaf
 | 
				
			||||||
| 
						 | 
					@ -2513,6 +2430,10 @@ ext4_ext_rm_leaf(handle_t *handle, struct inode *inode,
 | 
				
			||||||
		} else
 | 
							} else
 | 
				
			||||||
			*partial_cluster = 0;
 | 
								*partial_cluster = 0;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							err = ext4_ext_dirty(handle, inode, path + depth);
 | 
				
			||||||
 | 
							if (err)
 | 
				
			||||||
 | 
								goto out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ext_debug("new extent: %u:%u:%llu\n", block, num,
 | 
							ext_debug("new extent: %u:%u:%llu\n", block, num,
 | 
				
			||||||
				ext4_ext_pblock(ex));
 | 
									ext4_ext_pblock(ex));
 | 
				
			||||||
		ex--;
 | 
							ex--;
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue