readahead first lock the folio, then invokes aops->readahead, which locks the two state lock to block subsequent direct I/O. However, direct IO or bchfs_fpunch first lock the two state lock to block subsequent buffered I/O, and then lock the folio to invalidate or truncate it. Therefore, there is a deadlock:
thread1 thread2 lock folio bch2_pagecache_block_get bch2_pagecache_add_get lock folio Reported-by: [email protected] Signed-off-by: Alan Huang <[email protected]> --- fs/bcachefs/fs-io-buffered.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/bcachefs/fs-io-buffered.c b/fs/bcachefs/fs-io-buffered.c index c5ed62a11f23..ed8329c6c00d 100644 --- a/fs/bcachefs/fs-io-buffered.c +++ b/fs/bcachefs/fs-io-buffered.c @@ -290,7 +290,8 @@ void bch2_readahead(struct readahead_control *ractl) * scheduling. */ blk_start_plug(&plug); - bch2_pagecache_add_get(inode); + if (!bch2_pagecache_add_tryget(inode)) + goto out; struct btree_trans *trans = bch2_trans_get(c); while ((folio = readpage_iter_peek(&readpages_iter))) { @@ -317,6 +318,7 @@ void bch2_readahead(struct readahead_control *ractl) bch2_trans_put(trans); bch2_pagecache_add_put(inode); +out: blk_finish_plug(&plug); darray_exit(&readpages_iter.folios); } -- 2.49.0
