Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 1f555cfa authored by Dmitry Monakhov's avatar Dmitry Monakhov Committed by Theodore Ts'o
Browse files

ext4: serialize truncate with owerwrite DIO workers



Jan Kara have spotted interesting issue:
There are  potential data corruption issue with  direct IO overwrites
racing with truncate:
 Like:
  dio write                      truncate_task
  ->ext4_ext_direct_IO
   ->overwrite == 1
    ->down_read(&EXT4_I(inode)->i_data_sem);
    ->mutex_unlock(&inode->i_mutex);
                               ->ext4_setattr()
                                ->inode_dio_wait()
                                ->truncate_setsize()
                                ->ext4_truncate()
                                 ->down_write(&EXT4_I(inode)->i_data_sem);
    ->__blockdev_direct_IO
     ->ext4_get_block
     ->submit_io()
    ->up_read(&EXT4_I(inode)->i_data_sem);
                                 # truncate data blocks, allocate them to
                                 # other inode - bad stuff happens because
                                 # dio is still in flight.

In order to serialize with truncate dio worker should grab extra i_dio_count
reference before drop i_mutex.

Reviewed-by: default avatarJan Kara <jack@suse.cz>
Signed-off-by: default avatarDmitry Monakhov <dmonakhov@openvz.org>
Signed-off-by: default avatar"Theodore Ts'o" <tytso@mit.edu>
parent 1b65007e
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -3010,6 +3010,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
		overwrite = *((int *)iocb->private);

		if (overwrite) {
			atomic_inc(&inode->i_dio_count);
			down_read(&EXT4_I(inode)->i_data_sem);
			mutex_unlock(&inode->i_mutex);
		}
@@ -3107,6 +3108,7 @@ static ssize_t ext4_ext_direct_IO(int rw, struct kiocb *iocb,
	retake_lock:
		/* take i_mutex locking again if we do a ovewrite dio */
		if (overwrite) {
			inode_dio_done(inode);
			up_read(&EXT4_I(inode)->i_data_sem);
			mutex_lock(&inode->i_mutex);
		}