Skip to contentSkip to conversation

Bz #248176: GFS2: invalid metadata block - REVISED

PATCH New Bob Peterson 3 participants 4 messages Aug 8, 2007 – Aug 10, 2007 GFS2 file system

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 Bz #248176: GFS2: invalid metadata block - REVISED

This is for bugzilla bug #248176: GFS2: invalid metadata block

Patches 1 thru 3 were accepted upstream, but there were problems with 4 and 5. Those issues have been resolved and now the recovery tests are passing without errors. This code has gone through 41 * 3 successful gfs2 recovery tests before it hit an unrelated (openais) problem. I'm continuing to test it.

This is a complete rewrite of patch 5 for bug #248176, written by Steve Whitehouse. This is referred to in the bugzilla record as "new 6" and "a different solution".

The problem was that the journal inodes, although protected by a glock, were not synched with the other nodes because they don't use the inode glock synch operations (i.e. no "glops" were defined). Therefore, journal recovery on a journal-recovering node were causing the blocks to get out of sync with the node that was actually trying to use that journal as it comes back up from a reboot.

There are two possible solutions: (1) To make the journals use the normal inode glock sync operations, or (2) To make the journal operations take effect immediately (i.e. no caching). Although option 1 works, it turns out to be a lot more code. Steve opted for option 2, which is much simpler and therefore less prone to regression errors.

Regards,

Bob Peterson
--

--

fs/gfs2/ops_fstype.c +1 -1
index 58c730b..f0bcaa2 100644
@@ -358,7 +358,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
 
 		ip = GFS2_I(sdp->sd_jdesc->jd_inode);
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-					   LM_FLAG_NOEXP | GL_EXACT,
+					   LM_FLAG_NOEXP | GL_EXACT | GL_NOCACHE,
 					   &sdp->sd_jinode_gh);
 		if (error) {
 			fs_err(sdp, "can't acquire journal inode glock: %d\n",
fs/gfs2/recovery.c +1 -1
index 5ada38c..beb6c7a 100644
@@ -469,7 +469,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
 		};
 
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-					   LM_FLAG_NOEXP, &ji_gh);
+					   LM_FLAG_NOEXP | GL_NOCACHE, &ji_gh);
 		if (error)
 			goto fail_gunlock_j;
 	} else {
#1 lore raw

PATCH 1/1 Bz #248176: GFS2: invalid metadata block - REVISED

Hi,

This one and the previous patch are now both in the -nmw git tree. Thanks,

Steve.

Quoted 60 lines · Bob Peterson

This is for bugzilla bug #248176: GFS2: invalid metadata block

Patches 1 thru 3 were accepted upstream, but there were problems with 4 and 5. Those issues have been resolved and now the recovery tests are passing without errors. This code has gone through 41 * 3 successful gfs2 recovery tests before it hit an unrelated (openais) problem. I'm continuing to test it.

This is a complete rewrite of patch 5 for bug #248176, written by Steve Whitehouse. This is referred to in the bugzilla record as "new 6" and "a different solution".

The problem was that the journal inodes, although protected by a glock, were not synched with the other nodes because they don't use the inode glock synch operations (i.e. no "glops" were defined). Therefore, journal recovery on a journal-recovering node were causing the blocks to get out of sync with the node that was actually trying to use that journal as it comes back up from a reboot.

There are two possible solutions: (1) To make the journals use the normal inode glock sync operations, or (2) To make the journal operations take effect immediately (i.e. no caching). Although option 1 works, it turns out to be a lot more code. Steve opted for option 2, which is much simpler and therefore less prone to regression errors.

Regards,

Bob Peterson
--

--

fs/gfs2/ops_fstype.c +1 -1
index 58c730b..f0bcaa2 100644
@@ -358,7 +358,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
 
 		ip = GFS2_I(sdp->sd_jdesc->jd_inode);
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-					   LM_FLAG_NOEXP | GL_EXACT,
+					   LM_FLAG_NOEXP | GL_EXACT | GL_NOCACHE,
 					   &sdp->sd_jinode_gh);
 		if (error) {
 			fs_err(sdp, "can't acquire journal inode glock: %d\n",
fs/gfs2/recovery.c +1 -1
index 5ada38c..beb6c7a 100644
@@ -469,7 +469,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
 		};
 
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-					   LM_FLAG_NOEXP, &ji_gh);
+					   LM_FLAG_NOEXP | GL_NOCACHE, &ji_gh);
 		if (error)
 			goto fail_gunlock_j;
 	} else {
#2 lore raw

PATCH 1/1 Bz #248176: GFS2: invalid metadata block - REVISED

In reply to Bob Peterson
Quoted 7 lines · Bob Peterson

The problem was that the journal inodes, although protected by a glock, were not synched with the other nodes because they don't use the inode glock synch operations (i.e. no "glops" were defined). Therefore, journal recovery on a journal-recovering node were causing the blocks to get out of sync with the node that was actually trying to use that journal as it comes back up from a reboot.

I don't understand this patch either. Maybe I have worked too long in GFS1 so please educate me on these GFS2 internals. Comment below:

Quoted 33 lines

There are two possible solutions: (1) To make the journals use the normal inode glock sync operations, or (2) To make the journal operations take effect immediately (i.e. no caching). Although option 1 works, it turns out to be a lot more code. Steve opted for option 2, which is much simpler and therefore less prone to regression errors.

Regards,

Bob Peterson
--

--

fs/gfs2/ops_fstype.c +1 -1
index 58c730b..f0bcaa2 100644
@@ -358,7 +358,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
 
 		ip = GFS2_I(sdp->sd_jdesc->jd_inode);
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-					   LM_FLAG_NOEXP | GL_EXACT,
+					   LM_FLAG_NOEXP | GL_EXACT | GL_NOCACHE,
 					   &sdp->sd_jinode_gh);
 		if (error) {
 			fs_err(sdp, "can't acquire journal inode glock: %d\n",
fs/gfs2/recovery.c +0 -0
index 5ada38c..beb6c7a 100644

fs/gfs2/recovery.c int gfs2_recover_journal(struct gfs2_jdesc *jd) · line 475

Quoted 8 lines
fs/gfs2/recovery.c +1 -1
@@ -469,7 +469,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
 		};
 
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-					   LM_FLAG_NOEXP, &ji_gh);
+					   LM_FLAG_NOEXP | GL_NOCACHE, &ji_gh);
 		if (error)
 			goto fail_gunlock_j;
 	} else {

This lock is requested as "SHARED" (read lock). So how does "GL_NOCACHE" help it to "sync" with other nodes regarding to disk blocks sharing as you described above ? For a normal EXCLUSIVE inode glock with nocache, it will force a sync (disk blocks). However, this is a read lock. So what is the problem this patch has solved ?

-- Wendy

#3 lore raw

PATCH 1/1 Bz #248176: GFS2: invalid metadata block - REVISED

Hi,

Quoted 58 lines · Wendy Cheng
Quoted 7 lines · Bob Peterson

The problem was that the journal inodes, although protected by a glock, were not synched with the other nodes because they don't use the inode glock synch operations (i.e. no "glops" were defined). Therefore, journal recovery on a journal-recovering node were causing the blocks to get out of sync with the node that was actually trying to use that journal as it comes back up from a reboot.

I don't understand this patch either. Maybe I have worked too long in GFS1 so please educate me on these GFS2 internals. Comment below:

Quoted 33 lines

There are two possible solutions: (1) To make the journals use the normal inode glock sync operations, or (2) To make the journal operations take effect immediately (i.e. no caching). Although option 1 works, it turns out to be a lot more code. Steve opted for option 2, which is much simpler and therefore less prone to regression errors.

Regards,

Bob Peterson
--

--

fs/gfs2/ops_fstype.c +1 -1
index 58c730b..f0bcaa2 100644
@@ -358,7 +358,7 @@ static int init_journal(struct gfs2_sbd *sdp, int undo)
 
 		ip = GFS2_I(sdp->sd_jdesc->jd_inode);
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-					   LM_FLAG_NOEXP | GL_EXACT,
+					   LM_FLAG_NOEXP | GL_EXACT | GL_NOCACHE,
 					   &sdp->sd_jinode_gh);
 		if (error) {
 			fs_err(sdp, "can't acquire journal inode glock: %d\n",
fs/gfs2/recovery.c +0 -0
index 5ada38c..beb6c7a 100644

fs/gfs2/recovery.c int gfs2_recover_journal(struct gfs2_jdesc *jd) · line 475

Quoted 8 lines
fs/gfs2/recovery.c +1 -1
@@ -469,7 +469,7 @@ int gfs2_recover_journal(struct gfs2_jdesc *jd)
 		};
 
 		error = gfs2_glock_nq_init(ip->i_gl, LM_ST_SHARED,
-					   LM_FLAG_NOEXP, &ji_gh);
+					   LM_FLAG_NOEXP | GL_NOCACHE, &ji_gh);
 		if (error)
 			goto fail_gunlock_j;
 	} else {

This lock is requested as "SHARED" (read lock). So how does "GL_NOCACHE" help it to "sync" with other nodes regarding to disk blocks sharing as you described above ? For a normal EXCLUSIVE inode glock with nocache, it will force a sync (disk blocks). However, this is a read lock. So what is the problem this patch has solved ?

Quoted 2 lines

-- Wendy

This is the easy one to explain.... the page cache relating to the journal inode is only used to read the journal for recovery and otherwise is unused. The problem here comes when a node tries to recover the journal of the same remote node twice (with no umounts etc. between the two events). In that case it was possible for a node to "see" stale data from the first recovery attempt while reading the journal for the second recovery. Using GL_NOCACHE means that we now flush the cache after the first recovery, so when the second recovery occurs, the blocks will be read fresh from disk,

Steve.