mirror of
git://git.yoctoproject.org/linux-yocto.git
synced 2025-10-22 23:13:01 +02:00
gfs2: Don't start unnecessary transactions during log flush
[ Upstream commit5a90f8d499
] Commit8d391972ae
("gfs2: Remove __gfs2_writepage()") changed the log flush code in gfs2_ail1_start_one() to call aops->writepages() instead of aops->writepage(). For jdata inodes, this means that we will now try to reserve log space and start a transaction before we can determine that the pages in question have already been journaled. When this happens in the context of gfs2_logd(), it can now appear that not enough log space is available for freeing up log space, and we will lock up. Fix that by issuing journal writes directly instead of going through aops->writepages() in the log flush code. Fixes:8d391972ae
("gfs2: Remove __gfs2_writepage()") Signed-off-by: Andreas Gruenbacher <agruenba@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
519aed5bda
commit
9468bcd92d
|
@ -117,6 +117,37 @@ static int __gfs2_jdata_write_folio(struct folio *folio,
|
|||
return gfs2_write_jdata_folio(folio, wbc);
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_jdata_writeback - Write jdata folios to the log
|
||||
* @mapping: The mapping to write
|
||||
* @wbc: The writeback control
|
||||
*
|
||||
* Returns: errno
|
||||
*/
|
||||
int gfs2_jdata_writeback(struct address_space *mapping, struct writeback_control *wbc)
|
||||
{
|
||||
struct inode *inode = mapping->host;
|
||||
struct gfs2_inode *ip = GFS2_I(inode);
|
||||
struct gfs2_sbd *sdp = GFS2_SB(mapping->host);
|
||||
struct folio *folio = NULL;
|
||||
int error;
|
||||
|
||||
BUG_ON(current->journal_info);
|
||||
if (gfs2_assert_withdraw(sdp, ip->i_gl->gl_state == LM_ST_EXCLUSIVE))
|
||||
return 0;
|
||||
|
||||
while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
|
||||
if (folio_test_checked(folio)) {
|
||||
folio_redirty_for_writepage(wbc, folio);
|
||||
folio_unlock(folio);
|
||||
continue;
|
||||
}
|
||||
error = __gfs2_jdata_write_folio(folio, wbc);
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/**
|
||||
* gfs2_writepages - Write a bunch of dirty pages back to disk
|
||||
* @mapping: The mapping to write
|
||||
|
|
|
@ -9,5 +9,6 @@
|
|||
#include "incore.h"
|
||||
|
||||
void adjust_fs_space(struct inode *inode);
|
||||
int gfs2_jdata_writeback(struct address_space *mapping, struct writeback_control *wbc);
|
||||
|
||||
#endif /* __AOPS_DOT_H__ */
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include "dir.h"
|
||||
#include "trace_gfs2.h"
|
||||
#include "trans.h"
|
||||
#include "aops.h"
|
||||
|
||||
static void gfs2_log_shutdown(struct gfs2_sbd *sdp);
|
||||
|
||||
|
@ -131,7 +132,11 @@ __acquires(&sdp->sd_ail_lock)
|
|||
if (!mapping)
|
||||
continue;
|
||||
spin_unlock(&sdp->sd_ail_lock);
|
||||
ret = mapping->a_ops->writepages(mapping, wbc);
|
||||
BUG_ON(GFS2_SB(mapping->host) != sdp);
|
||||
if (gfs2_is_jdata(GFS2_I(mapping->host)))
|
||||
ret = gfs2_jdata_writeback(mapping, wbc);
|
||||
else
|
||||
ret = mapping->a_ops->writepages(mapping, wbc);
|
||||
if (need_resched()) {
|
||||
blk_finish_plug(plug);
|
||||
cond_resched();
|
||||
|
|
Loading…
Reference in New Issue
Block a user