aboutsummaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2011-12-12 10:53:02 -0500
committerTheodore Ts'o <tytso@mit.edu>2011-12-12 10:53:02 -0500
commitb5a7e97039a80fae673ccc115ce595d5b88fb4ee (patch)
treeb8533e2cb3fc30da051487257cd24af6edeea83e /fs
parentdc47ce90c3a822cd7c9e9339fe4d5f61dcb26b50 (diff)
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: Kent Overstreet <koverstreet@google.com> Signed-off-by: "Theodore Ts'o" <tytso@mit.edu> Cc: stable@kernel.org
Diffstat (limited to 'fs')
-rw-r--r--fs/ext4/inode.c4
1 files changed, 2 insertions, 2 deletions
diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c
index 848f436df29f..d2c86633811f 100644
--- a/fs/ext4/inode.c
+++ b/fs/ext4/inode.c
@@ -2781,10 +2781,11 @@ static void ext4_end_io_dio(struct kiocb *iocb, loff_t offset,
2781 iocb->private, io_end->inode->i_ino, iocb, offset, 2781 iocb->private, io_end->inode->i_ino, iocb, offset,
2782 size); 2782 size);
2783 2783
2784 iocb->private = NULL;
2785
2784 /* if not aio dio with unwritten extents, just free io and return */ 2786 /* if not aio dio with unwritten extents, just free io and return */
2785 if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) { 2787 if (!(io_end->flag & EXT4_IO_END_UNWRITTEN)) {
2786 ext4_free_io_end(io_end); 2788 ext4_free_io_end(io_end);
2787 iocb->private = NULL;
2788out: 2789out:
2789 if (is_async) 2790 if (is_async)
2790 aio_complete(iocb, ret, 0); 2791 aio_complete(iocb, ret, 0);
@@ -2807,7 +2808,6 @@ out:
2807 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags); 2808 spin_unlock_irqrestore(&ei->i_completed_io_lock, flags);
2808 2809
2809 /* queue the work to convert unwritten extents to written */ 2810 /* queue the work to convert unwritten extents to written */
2810 iocb->private = NULL;
2811 queue_work(wq, &io_end->work); 2811 queue_work(wq, &io_end->work);
2812 2812
2813 /* XXX: probably should move into the real I/O completion handler */ 2813 /* XXX: probably should move into the real I/O completion handler */