|
@@ -5329,8 +5329,9 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
|
|
stop = le32_to_cpu(extent->ee_block);
|
|
stop = le32_to_cpu(extent->ee_block);
|
|
|
|
|
|
/*
|
|
/*
|
|
- * In case of left shift, Don't start shifting extents until we make
|
|
|
|
- * sure the hole is big enough to accommodate the shift.
|
|
|
|
|
|
+ * For left shifts, make sure the hole on the left is big enough to
|
|
|
|
+ * accommodate the shift. For right shifts, make sure the last extent
|
|
|
|
+ * won't be shifted beyond EXT_MAX_BLOCKS.
|
|
*/
|
|
*/
|
|
if (SHIFT == SHIFT_LEFT) {
|
|
if (SHIFT == SHIFT_LEFT) {
|
|
path = ext4_find_extent(inode, start - 1, &path,
|
|
path = ext4_find_extent(inode, start - 1, &path,
|
|
@@ -5350,9 +5351,14 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
|
|
|
|
|
|
if ((start == ex_start && shift > ex_start) ||
|
|
if ((start == ex_start && shift > ex_start) ||
|
|
(shift > start - ex_end)) {
|
|
(shift > start - ex_end)) {
|
|
- ext4_ext_drop_refs(path);
|
|
|
|
- kfree(path);
|
|
|
|
- return -EINVAL;
|
|
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto out;
|
|
|
|
+ }
|
|
|
|
+ } else {
|
|
|
|
+ if (shift > EXT_MAX_BLOCKS -
|
|
|
|
+ (stop + ext4_ext_get_actual_len(extent))) {
|
|
|
|
+ ret = -EINVAL;
|
|
|
|
+ goto out;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|