Skip to content

Commit 5a90f8d

Browse files
author
Andreas Gruenbacher
committed
gfs2: Don't start unnecessary transactions during log flush
Commit 8d39197 ("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: 8d39197 ("gfs2: Remove __gfs2_writepage()") Signed-off-by: Andreas Gruenbacher <[email protected]>
1 parent d50a64e commit 5a90f8d

File tree

3 files changed

+38
-1
lines changed

3 files changed

+38
-1
lines changed

fs/gfs2/aops.c

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,37 @@ static int __gfs2_jdata_write_folio(struct folio *folio,
117117
return gfs2_write_jdata_folio(folio, wbc);
118118
}
119119

120+
/**
121+
* gfs2_jdata_writeback - Write jdata folios to the log
122+
* @mapping: The mapping to write
123+
* @wbc: The writeback control
124+
*
125+
* Returns: errno
126+
*/
127+
int gfs2_jdata_writeback(struct address_space *mapping, struct writeback_control *wbc)
128+
{
129+
struct inode *inode = mapping->host;
130+
struct gfs2_inode *ip = GFS2_I(inode);
131+
struct gfs2_sbd *sdp = GFS2_SB(mapping->host);
132+
struct folio *folio = NULL;
133+
int error;
134+
135+
BUG_ON(current->journal_info);
136+
if (gfs2_assert_withdraw(sdp, ip->i_gl->gl_state == LM_ST_EXCLUSIVE))
137+
return 0;
138+
139+
while ((folio = writeback_iter(mapping, wbc, folio, &error))) {
140+
if (folio_test_checked(folio)) {
141+
folio_redirty_for_writepage(wbc, folio);
142+
folio_unlock(folio);
143+
continue;
144+
}
145+
error = __gfs2_jdata_write_folio(folio, wbc);
146+
}
147+
148+
return error;
149+
}
150+
120151
/**
121152
* gfs2_writepages - Write a bunch of dirty pages back to disk
122153
* @mapping: The mapping to write

fs/gfs2/aops.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
#include "incore.h"
1010

1111
void adjust_fs_space(struct inode *inode);
12+
int gfs2_jdata_writeback(struct address_space *mapping, struct writeback_control *wbc);
1213

1314
#endif /* __AOPS_DOT_H__ */

fs/gfs2/log.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include "dir.h"
3232
#include "trace_gfs2.h"
3333
#include "trans.h"
34+
#include "aops.h"
3435

3536
static void gfs2_log_shutdown(struct gfs2_sbd *sdp);
3637

@@ -131,7 +132,11 @@ __acquires(&sdp->sd_ail_lock)
131132
if (!mapping)
132133
continue;
133134
spin_unlock(&sdp->sd_ail_lock);
134-
ret = mapping->a_ops->writepages(mapping, wbc);
135+
BUG_ON(GFS2_SB(mapping->host) != sdp);
136+
if (gfs2_is_jdata(GFS2_I(mapping->host)))
137+
ret = gfs2_jdata_writeback(mapping, wbc);
138+
else
139+
ret = mapping->a_ops->writepages(mapping, wbc);
135140
if (need_resched()) {
136141
blk_finish_plug(plug);
137142
cond_resched();

0 commit comments

Comments
 (0)