Hi Edwin, On Wed, 6 Mar 2019 at 12:08, Edwin Török <[email protected]> wrote: > Hello, > > I've been trying to debug a GFS2 deadlock that we see in our lab quite > frequently with a 4.19 kernel. With 4.4 and older kernels we were not able to > reproduce this. > See below for lockdep dumps and stacktraces.
thanks for the thorough bug report. Does the below fix work for you? Thanks, Andreas -- Prevent page reclaim on the backing device of the filesystem in gfs2_file_write_iter: - In gfs2_file_write_iter, iomap_file_buffered_write grabs the log flush lock (via iomap_apply -> iomap_begin -> gfs2_iomap_begin_write -> gfs2_trans_begin) and holds it for the duration of the write. - It then calls iomap_write_actor -> balance_dirty_pages. - If that triggers writeback on the same filesystem, we would try to grab the log flush lock again (via writeback_sb_inodes -> gfs2_write_inode -> gfs2_log_flush) and deadlock. Prevent that by not setting backing_dev_info in gfs2_file_write_iter. Reported-by: Edwin Török <[email protected]> Fixes: 64bc06bb32ee ("gfs2: iomap buffered write support") Signed-off-by: Andreas Gruenbacher <[email protected]> --- fs/gfs2/file.c | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/fs/gfs2/file.c b/fs/gfs2/file.c index a2dea5bc04276..8c7d296d58608 100644 --- a/fs/gfs2/file.c +++ b/fs/gfs2/file.c @@ -816,16 +816,13 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from) if (ret <= 0) goto out; - /* We can write back this queue in page reclaim */ - current->backing_dev_info = inode_to_bdi(inode); - ret = file_remove_privs(file); if (ret) - goto out2; + goto out; ret = file_update_time(file); if (ret) - goto out2; + goto out; if (iocb->ki_flags & IOCB_DIRECT) { struct address_space *mapping = file->f_mapping; @@ -834,11 +831,11 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from) written = gfs2_file_direct_write(iocb, from); if (written < 0 || !iov_iter_count(from)) - goto out2; + goto out; ret = iomap_file_buffered_write(iocb, from, &gfs2_iomap_ops); if (unlikely(ret < 0)) - goto out2; + goto out; buffered = ret; /* @@ -867,8 +864,6 @@ static ssize_t gfs2_file_write_iter(struct kiocb *iocb, struct iov_iter *from) iocb->ki_pos += ret; } -out2: - current->backing_dev_info = NULL; out: inode_unlock(inode); if (likely(ret > 0)) { -- 2.20.1
