On Fri, Jul 03, 2020 at 11:53:25AM +0200, Andreas Gruenbacher wrote: > So far, gfs2 has taken the inode glocks inside the ->readpage and > ->readahead address space operations. Since commit d4388340ae0b ("fs: > convert mpage_readpages to mpage_readahead"), gfs2_readahead is passed > the pages to read ahead locked. With that, the current holder of the > inode glock may be trying to lock one of those pages while > gfs2_readahead is trying to take the inode glock, resulting in a > deadlock. > > Fix that by moving the lock taking to the higher-level ->read_iter file > and ->fault vm operations. This also gets rid of an ugly lock inversion > workaround in gfs2_readpage. > > Signed-off-by: Andreas Gruenbacher <agruenba@xxxxxxxxxx> Reviewed-by: Matthew Wilcox (Oracle) <willy@xxxxxxxxxxxxx> > -/** > - * __gfs2_readpage - readpage > - * @file: The file to read a page for > - * @page: The page to read > - * > - * This is the core of gfs2's readpage. It's used by the internal file > - * reading code as in that case we already hold the glock. Also it's > - * called by gfs2_readpage() once the required lock has been granted. > - */ > - > static int __gfs2_readpage(void *file, struct page *page) You could go a little further and rename this function to plain gfs2_readpage(). gfs2_internal_read() should switch from read_cache_page() to read_mapping_page(). > { > struct gfs2_inode *ip = GFS2_I(page->mapping->host); > struct gfs2_sbd *sdp = GFS2_SB(page->mapping->host); > - > int error; > > if (i_blocksize(page->mapping->host) == PAGE_SIZE && > @@ -505,36 +494,11 @@ static int __gfs2_readpage(void *file, struct page *page) > * gfs2_readpage - read a page of a file > * @file: The file to read > * @page: The page of the file > - * > - * This deals with the locking required. We have to unlock and > - * relock the page in order to get the locking in the right > - * order. > */ I'd drop the kernel-doc comments on method implementations entirely, unless there's something useful to say ... which there isn't any more (yay!) > @@ -598,16 +562,9 @@ static void gfs2_readahead(struct readahead_control *rac) > { > struct inode *inode = rac->mapping->host; > struct gfs2_inode *ip = GFS2_I(inode); > - struct gfs2_holder gh; > > - gfs2_holder_init(ip->i_gl, LM_ST_SHARED, 0, &gh); > - if (gfs2_glock_nq(&gh)) > - goto out_uninit; > if (!gfs2_is_stuffed(ip)) > mpage_readahead(rac, gfs2_block_map); I think you probably want to make this: if (i_blocksize(page->mapping->host) == PAGE_SIZE && !page_has_buffers(page)) error = iomap_readahead(rac, &gfs2_iomap_ops); else if (!gfs2_is_stuffed(ip)) error = mpage_readahead(rac, gfs2_block_map); ... but I understand not wanting to make that change at this point in the release cycle. I'm happy for the patches to go in as-is, just wanted to point out these improvements that could be made.