ext4: remove i_mutex lock in ext4_evict_inode to fix lockdep complaining

The i_mutex lock and flush_completed_IO() added by commit 2581fdc810
in ext4_evict_inode() causes lockdep complaining about potential
deadlock in several places. In most/all of these LOCKDEP complaints
it looks like it's a false positive, since many of the potential
circular locking cases can't take place by the time the
ext4_evict_inode() is called; but since at the very least it may mask
real problems, we need to address this.

This change removes the flush_completed_IO() and i_mutex lock in
ext4_evict_inode(). Instead, we take a different approach to resolve
the software lockup that commit 2581fdc810 intends to fix. Rather
than having ext4-dio-unwritten thread wait for grabing the i_mutex
lock of an inode, we use mutex_trylock() instead, and simply requeue
the work item if we fail to grab the inode's i_mutex lock.

This should speed up work queue processing in general and also
prevents the following deadlock scenario: During page fault,
shrink_icache_memory is called that in turn evicts another inode B.
Inode B has some pending io_end work so it calls ext4_ioend_wait()
that waits for inode B's i_ioend_count to become zero. However, inode
B's ioend work was queued behind some of inode A's ioend work on the
same cpu's ext4-dio-unwritten workqueue. As the ext4-dio-unwritten
thread on that cpu is processing inode A's ioend work, it tries to
grab inode A's i_mutex lock. Since the i_mutex lock of inode A is
still hold before the page fault happened, we enter a deadlock.

Signed-off-by: Jiaying Zhang <jiayingz@google.com>
Signed-off-by: "Theodore Ts'o" <tytso@mit.edu>

authored by Jiaying Zhang and committed by Theodore Ts'o 8c0bec21 fcb8ce5c

Changed files
+18 -4
fs
+1
fs/ext4/ext4.h
··· 175 175 */ 176 176 #define EXT4_IO_END_UNWRITTEN 0x0001 177 177 #define EXT4_IO_END_ERROR 0x0002 178 + #define EXT4_IO_END_QUEUED 0x0004 178 179 179 180 struct ext4_io_page { 180 181 struct page *p_page;
-3
fs/ext4/inode.c
··· 121 121 122 122 trace_ext4_evict_inode(inode); 123 123 124 - mutex_lock(&inode->i_mutex); 125 - ext4_flush_completed_IO(inode); 126 - mutex_unlock(&inode->i_mutex); 127 124 ext4_ioend_wait(inode); 128 125 129 126 if (inode->i_nlink) {
+17 -1
fs/ext4/page-io.c
··· 142 142 unsigned long flags; 143 143 int ret; 144 144 145 - mutex_lock(&inode->i_mutex); 145 + if (!mutex_trylock(&inode->i_mutex)) { 146 + /* 147 + * Requeue the work instead of waiting so that the work 148 + * items queued after this can be processed. 149 + */ 150 + queue_work(EXT4_SB(inode->i_sb)->dio_unwritten_wq, &io->work); 151 + /* 152 + * To prevent the ext4-dio-unwritten thread from keeping 153 + * requeueing end_io requests and occupying cpu for too long, 154 + * yield the cpu if it sees an end_io request that has already 155 + * been requeued. 156 + */ 157 + if (io->flag & EXT4_IO_END_QUEUED) 158 + yield(); 159 + io->flag |= EXT4_IO_END_QUEUED; 160 + return; 161 + } 146 162 ret = ext4_end_io_nolock(io); 147 163 if (ret < 0) { 148 164 mutex_unlock(&inode->i_mutex);