Skip to content

Commit 02f448f

Browse files
committed
Merge: gfs2: Mount failure after successful recovery
MR: https://gitlab.com/redhat/centos-stream/src/kernel/centos-stream-9/-/merge_requests/6879 JIRA: https://issues.redhat.com/browse/RHEL-91331 This set of patches fixes an occasional failure to mount a filesystem after it has been successfully recovered. What's happening is that due to incorrect cache invalidation, gfs2_find_jhead() fails to find the log head written during recovery. This is fixed by only looking up the log head before recovery and then updating it instead of looking it up a second time after recovery. Signed-off-by: Andreas Gruenbacher <[email protected]> Approved-by: Andrew Price <[email protected]> Approved-by: Abhi Das <[email protected]> Approved-by: CKI KWF Bot <[email protected]> Merged-by: Augusto Caringi <[email protected]>
2 parents 8e82ce0 + 82da495 commit 02f448f

File tree

8 files changed

+29
-43
lines changed

8 files changed

+29
-43
lines changed

fs/gfs2/glops.c

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -593,14 +593,13 @@ static int freeze_go_xmote_bh(struct gfs2_glock *gl)
593593
if (test_bit(SDF_JOURNAL_LIVE, &sdp->sd_flags)) {
594594
j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
595595

596-
error = gfs2_find_jhead(sdp->sd_jdesc, &head, false);
596+
error = gfs2_find_jhead(sdp->sd_jdesc, &head);
597597
if (gfs2_assert_withdraw_delayed(sdp, !error))
598598
return error;
599599
if (gfs2_assert_withdraw_delayed(sdp, head.lh_flags &
600600
GFS2_LOG_HEAD_UNMOUNT))
601601
return -EIO;
602-
sdp->sd_log_sequence = head.lh_sequence + 1;
603-
gfs2_log_pointers_init(sdp, head.lh_blkno);
602+
gfs2_log_pointers_init(sdp, &head);
604603
}
605604
return 0;
606605
}

fs/gfs2/log.h

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,17 +44,6 @@ __releases(&sdp->sd_log_lock)
4444
spin_unlock(&sdp->sd_log_lock);
4545
}
4646

47-
static inline void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
48-
unsigned int value)
49-
{
50-
if (++value == sdp->sd_jdesc->jd_blocks) {
51-
value = 0;
52-
}
53-
sdp->sd_log_tail = value;
54-
sdp->sd_log_flush_tail = value;
55-
sdp->sd_log_head = value;
56-
}
57-
5847
static inline void gfs2_ordered_add_inode(struct gfs2_inode *ip)
5948
{
6049
struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);

fs/gfs2/lops.c

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -500,15 +500,13 @@ static struct bio *gfs2_chain_bio(struct bio *prev, unsigned int nr_iovecs)
500500
* gfs2_find_jhead - find the head of a log
501501
* @jd: The journal descriptor
502502
* @head: The log descriptor for the head of the log is returned here
503-
* @keep_cache: If set inode pages will not be truncated
504503
*
505504
* Do a search of a journal by reading it in large chunks using bios and find
506505
* the valid log entry with the highest sequence number. (i.e. the log head)
507506
*
508507
* Returns: 0 on success, errno otherwise
509508
*/
510-
int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head,
511-
bool keep_cache)
509+
int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
512510
{
513511
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
514512
struct address_space *mapping = jd->jd_inode->i_mapping;
@@ -598,8 +596,7 @@ int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head,
598596
if (!ret)
599597
ret = filemap_check_wb_err(mapping, since);
600598

601-
if (!keep_cache)
602-
truncate_inode_pages(mapping, 0);
599+
truncate_inode_pages(mapping, 0);
603600

604601
return ret;
605602
}

fs/gfs2/lops.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ void gfs2_log_write(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
2020
void gfs2_log_submit_bio(struct bio **biop, blk_opf_t opf);
2121
void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
2222
int gfs2_find_jhead(struct gfs2_jdesc *jd,
23-
struct gfs2_log_header_host *head, bool keep_cache);
23+
struct gfs2_log_header_host *head);
2424
void gfs2_drain_revokes(struct gfs2_sbd *sdp);
2525

2626
static inline unsigned int buf_limit(struct gfs2_sbd *sdp)

fs/gfs2/recovery.c

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -263,16 +263,12 @@ static void clean_journal(struct gfs2_jdesc *jd,
263263
struct gfs2_log_header_host *head)
264264
{
265265
struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
266-
u32 lblock = head->lh_blkno;
267266

268-
gfs2_replay_incr_blk(jd, &lblock);
269-
gfs2_write_log_header(sdp, jd, head->lh_sequence + 1, 0, lblock,
267+
gfs2_replay_incr_blk(jd, &head->lh_blkno);
268+
head->lh_sequence++;
269+
gfs2_write_log_header(sdp, jd, head->lh_sequence, 0, head->lh_blkno,
270270
GFS2_LOG_HEAD_UNMOUNT | GFS2_LOG_HEAD_RECOVERY,
271271
REQ_PREFLUSH | REQ_FUA | REQ_META | REQ_SYNC);
272-
if (jd->jd_jid == sdp->sd_lockstruct.ls_jid) {
273-
sdp->sd_log_flush_head = lblock;
274-
gfs2_log_incr_head(sdp);
275-
}
276272
}
277273

278274

@@ -457,7 +453,7 @@ void gfs2_recover_func(struct work_struct *work)
457453
if (error)
458454
goto fail_gunlock_ji;
459455

460-
error = gfs2_find_jhead(jd, &head, true);
456+
error = gfs2_find_jhead(jd, &head);
461457
if (error)
462458
goto fail_gunlock_ji;
463459
t_jhd = ktime_get();
@@ -533,6 +529,9 @@ void gfs2_recover_func(struct work_struct *work)
533529
ktime_ms_delta(t_rep, t_tlck));
534530
}
535531

532+
if (jd->jd_jid == sdp->sd_lockstruct.ls_jid)
533+
gfs2_log_pointers_init(sdp, &head);
534+
536535
gfs2_recovery_done(sdp, jd->jd_jid, LM_RD_SUCCESS);
537536

538537
if (jlocked) {
@@ -580,3 +579,13 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd, bool wait)
580579
return wait ? jd->jd_recover_error : 0;
581580
}
582581

582+
void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
583+
struct gfs2_log_header_host *head)
584+
{
585+
sdp->sd_log_sequence = head->lh_sequence + 1;
586+
gfs2_replay_incr_blk(sdp->sd_jdesc, &head->lh_blkno);
587+
sdp->sd_log_tail = head->lh_blkno;
588+
sdp->sd_log_flush_head = head->lh_blkno;
589+
sdp->sd_log_flush_tail = head->lh_blkno;
590+
sdp->sd_log_head = head->lh_blkno;
591+
}

fs/gfs2/recovery.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@ void gfs2_recover_func(struct work_struct *work);
2929
int __get_log_header(struct gfs2_sbd *sdp,
3030
const struct gfs2_log_header *lh, unsigned int blkno,
3131
struct gfs2_log_header_host *head);
32+
void gfs2_log_pointers_init(struct gfs2_sbd *sdp,
33+
struct gfs2_log_header_host *head);
3234

3335
#endif /* __RECOVERY_DOT_H__ */
3436

fs/gfs2/super.c

Lines changed: 4 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -134,28 +134,18 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp)
134134
{
135135
struct gfs2_inode *ip = GFS2_I(sdp->sd_jdesc->jd_inode);
136136
struct gfs2_glock *j_gl = ip->i_gl;
137-
struct gfs2_log_header_host head;
138137
int error;
139138

140139
j_gl->gl_ops->go_inval(j_gl, DIO_METADATA);
141140
if (gfs2_withdrawn(sdp))
142141
return -EIO;
143142

144-
error = gfs2_find_jhead(sdp->sd_jdesc, &head, false);
145-
if (error) {
146-
gfs2_consist(sdp);
147-
return error;
148-
}
149-
150-
if (!(head.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) {
151-
gfs2_consist(sdp);
143+
if (sdp->sd_log_sequence == 0) {
144+
fs_err(sdp, "unknown status of our own journal jid %d",
145+
sdp->sd_lockstruct.ls_jid);
152146
return -EIO;
153147
}
154148

155-
/* Initialize some head of the log stuff */
156-
sdp->sd_log_sequence = head.lh_sequence + 1;
157-
gfs2_log_pointers_init(sdp, head.lh_blkno);
158-
159149
error = gfs2_quota_init(sdp);
160150
if (!error && gfs2_withdrawn(sdp))
161151
error = -EIO;
@@ -370,7 +360,7 @@ static int gfs2_lock_fs_check_clean(struct gfs2_sbd *sdp)
370360
error = gfs2_jdesc_check(jd);
371361
if (error)
372362
break;
373-
error = gfs2_find_jhead(jd, &lh, false);
363+
error = gfs2_find_jhead(jd, &lh);
374364
if (error)
375365
break;
376366
if (!(lh.lh_flags & GFS2_LOG_HEAD_UNMOUNT)) {

fs/gfs2/util.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,7 @@ int check_journal_clean(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
7272
"mount.\n");
7373
goto out_unlock;
7474
}
75-
error = gfs2_find_jhead(jd, &head, false);
75+
error = gfs2_find_jhead(jd, &head);
7676
if (error) {
7777
if (verbose)
7878
fs_err(sdp, "Error parsing journal for spectator "

0 commit comments

Comments
 (0)