Commit 6fd2152f authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'ext4_for_linus_stable2' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4

Pull ext4 fixes from Ted Ts'o:
 "Fix a regression in the lazytime code that was introduced in v6.1-rc1,
  and a use-after-free that can be triggered by a maliciously corrupted
  file system"

* tag 'ext4_for_linus_stable2' of git://git.kernel.org/pub/scm/linux/kernel/git/tytso/ext4:
  fs: do not update freeing inode i_io_list
  ext4: fix use-after-free in ext4_ext_shift_extents
parents c3eb11fb 4e3c51f4
...@@ -5184,6 +5184,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, ...@@ -5184,6 +5184,7 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
* and it is decreased till we reach start. * and it is decreased till we reach start.
*/ */
again: again:
ret = 0;
if (SHIFT == SHIFT_LEFT) if (SHIFT == SHIFT_LEFT)
iterator = &start; iterator = &start;
else else
...@@ -5227,14 +5228,21 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle, ...@@ -5227,14 +5228,21 @@ ext4_ext_shift_extents(struct inode *inode, handle_t *handle,
ext4_ext_get_actual_len(extent); ext4_ext_get_actual_len(extent);
} else { } else {
extent = EXT_FIRST_EXTENT(path[depth].p_hdr); extent = EXT_FIRST_EXTENT(path[depth].p_hdr);
if (le32_to_cpu(extent->ee_block) > 0) if (le32_to_cpu(extent->ee_block) > start)
*iterator = le32_to_cpu(extent->ee_block) - 1; *iterator = le32_to_cpu(extent->ee_block) - 1;
else else if (le32_to_cpu(extent->ee_block) == start)
/* Beginning is reached, end of the loop */
iterator = NULL; iterator = NULL;
/* Update path extent in case we need to stop */ else {
while (le32_to_cpu(extent->ee_block) < start) extent = EXT_LAST_EXTENT(path[depth].p_hdr);
while (le32_to_cpu(extent->ee_block) >= start)
extent--;
if (extent == EXT_LAST_EXTENT(path[depth].p_hdr))
break;
extent++; extent++;
iterator = NULL;
}
path[depth].p_ext = extent; path[depth].p_ext = extent;
} }
ret = ext4_ext_shift_path_extents(path, shift, inode, ret = ext4_ext_shift_path_extents(path, shift, inode,
......
...@@ -1712,9 +1712,14 @@ static int writeback_single_inode(struct inode *inode, ...@@ -1712,9 +1712,14 @@ static int writeback_single_inode(struct inode *inode,
wb = inode_to_wb_and_lock_list(inode); wb = inode_to_wb_and_lock_list(inode);
spin_lock(&inode->i_lock); spin_lock(&inode->i_lock);
/* /*
* If the inode is now fully clean, then it can be safely removed from * If the inode is freeing, its i_io_list shoudn't be updated
* its writeback list (if any). Otherwise the flusher threads are * as it can be finally deleted at this moment.
* responsible for the writeback lists. */
if (!(inode->i_state & I_FREEING)) {
/*
* If the inode is now fully clean, then it can be safely
* removed from its writeback list (if any). Otherwise the
* flusher threads are responsible for the writeback lists.
*/ */
if (!(inode->i_state & I_DIRTY_ALL)) if (!(inode->i_state & I_DIRTY_ALL))
inode_cgwb_move_to_attached(inode, wb); inode_cgwb_move_to_attached(inode, wb);
...@@ -1723,7 +1728,10 @@ static int writeback_single_inode(struct inode *inode, ...@@ -1723,7 +1728,10 @@ static int writeback_single_inode(struct inode *inode,
redirty_tail_locked(inode, wb); redirty_tail_locked(inode, wb);
else if (inode->i_state & I_DIRTY_TIME) { else if (inode->i_state & I_DIRTY_TIME) {
inode->dirtied_when = jiffies; inode->dirtied_when = jiffies;
inode_io_list_move_locked(inode, wb, &wb->b_dirty_time); inode_io_list_move_locked(inode,
wb,
&wb->b_dirty_time);
}
} }
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment