diff options
Diffstat (limited to 'fs/ext4')
| -rw-r--r-- | fs/ext4/ext4.h | 1 | ||||
| -rw-r--r-- | fs/ext4/inode.c | 3 | ||||
| -rw-r--r-- | fs/ext4/page-io.c | 18 | 
3 files changed, 18 insertions, 4 deletions
| diff --git a/fs/ext4/ext4.h b/fs/ext4/ext4.h index e717dfd2f2b4..b7d7bd0f066e 100644 --- a/fs/ext4/ext4.h +++ b/fs/ext4/ext4.h @@ -175,6 +175,7 @@ struct mpage_da_data {   */  #define	EXT4_IO_END_UNWRITTEN	0x0001  #define EXT4_IO_END_ERROR	0x0002 +#define EXT4_IO_END_QUEUED	0x0004  struct ext4_io_page {  	struct page	*p_page; diff --git a/fs/ext4/inode.c b/fs/ext4/inode.c index c4da98a959ae..18d2558b7624 100644 --- a/fs/ext4/inode.c +++ b/fs/ext4/inode.c @@ -121,9 +121,6 @@ void ext4_evict_inode(struct inode *inode)  	trace_ext4_evict_inode(inode); -	mutex_lock(&inode->i_mutex); -	ext4_flush_completed_IO(inode); -	mutex_unlock(&inode->i_mutex);  	ext4_ioend_wait(inode);  	if (inode->i_nlink) { diff --git a/fs/ext4/page-io.c b/fs/ext4/page-io.c index 78839af7ce29..92f38ee13f8a 100644 --- a/fs/ext4/page-io.c +++ b/fs/ext4/page-io.c @@ -142,7 +142,23 @@ static void ext4_end_io_work(struct work_struct *work)  	unsigned long		flags;  	int			ret; -	mutex_lock(&inode->i_mutex); +	if (!mutex_trylock(&inode->i_mutex)) { +		/* +		 * Requeue the work instead of waiting so that the work +		 * items queued after this can be processed. +		 */ +		queue_work(EXT4_SB(inode->i_sb)->dio_unwritten_wq, &io->work); +		/* +		 * To prevent the ext4-dio-unwritten thread from keeping +		 * requeueing end_io requests and occupying cpu for too long, +		 * yield the cpu if it sees an end_io request that has already +		 * been requeued. +		 */ +		if (io->flag & EXT4_IO_END_QUEUED) +			yield(); +		io->flag |= EXT4_IO_END_QUEUED; +		return; +	}  	ret = ext4_end_io_nolock(io);  	if (ret < 0) {  		mutex_unlock(&inode->i_mutex); | 
