Commit b5a7e970 authored by Theodore Ts'o's avatar Theodore Ts'o

ext4: fix ext4_end_io_dio() racing against fsync()

We need to make sure iocb->private is cleared *before* we put the
io_end structure on i_completed_io_list.  Otherwise fsync() could
potentially run on another CPU and free the iocb structure out from
under us.
Reported-by: default avatarKent Overstreet <koverstreet@google.com>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
Cc: stable@kernel.org
parent dc47ce90
...@@ -2781,10 +2781,11 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, ...@@ -2781,10 +2781,11 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
iocb->private, io_end->inode->i_ino, iocb, offset, iocb->private, io_end->inode->i_ino, iocb, offset,
size); size);
iocb->private = NULL;
/* if not aio dio with unwritten extents, just free io and return */ /* if not aio dio with unwritten extents, just free io and return */
if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
ext4_free_io_end(io_end); ext4_free_io_end(io_end);
iocb->private = NULL;
out: out:
if (is_async) if (is_async)
aio_complete(iocb, ret, 0); aio_complete(iocb, ret, 0);
...@@ -2807,7 +2808,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset, ...@@ -2807,7 +2808,6 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
/* queue the work to convert unwritten extents to written */ /* queue the work to convert unwritten extents to written */
iocb->private = NULL;
queue_work(wq, &io_end->work); queue_work(wq, &io_end->work);
/* XXX: probably should move into the real I/O completion handler */ /* XXX: probably should move into the real I/O completion handler */
......
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