diff options
author | Bob Peterson <rpeterso@redhat.com> | 2010-09-30 10:34:00 -0400 |
---|---|---|
committer | Steven Whitehouse <swhiteho@redhat.com> | 2010-09-30 12:23:03 -0400 |
commit | 46290341cd649c2bfb69e5067c1804c0395c83a1 (patch) | |
tree | 1ef4a9c1d158ec182645d4be4cb3357a52a4404d /fs/gfs2/rgrp.c | |
parent | feb47ca9314666d920855b8a235032dea2b2caa4 (diff) |
GFS2 fatal: filesystem consistency error on rename
This patch fixes a GFS2 problem whereby the first rename after a
mount can result in a file system consistency error being flagged
improperly and cause the file system to withdraw. The problem is
that the rename code tries to run the rgrp list with function
gfs2_blk2rgrpd before the rgrp list is guaranteed to be read in
from disk. The patch makes the rename function hold the rindex
glock (as the gfs2_unlink code does today) which reads in the rgrp
list if need be. There were a total of three places in the rename
code that improperly referenced the rgrp list without the rindex
glock and this patch fixes all three.
Signed-off-by: Bob Peterson <rpeterso@redhat.com>
Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 22 |
1 files changed, 13 insertions, 9 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index f9ddcf401753..fb67f593f408 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -1200,7 +1200,8 @@ out: | |||
1200 | * Returns: errno | 1200 | * Returns: errno |
1201 | */ | 1201 | */ |
1202 | 1202 | ||
1203 | int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | 1203 | int gfs2_inplace_reserve_i(struct gfs2_inode *ip, int hold_rindex, |
1204 | char *file, unsigned int line) | ||
1204 | { | 1205 | { |
1205 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1206 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1206 | struct gfs2_alloc *al = ip->i_alloc; | 1207 | struct gfs2_alloc *al = ip->i_alloc; |
@@ -1211,12 +1212,15 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
1211 | return -EINVAL; | 1212 | return -EINVAL; |
1212 | 1213 | ||
1213 | try_again: | 1214 | try_again: |
1214 | /* We need to hold the rindex unless the inode we're using is | 1215 | if (hold_rindex) { |
1215 | the rindex itself, in which case it's already held. */ | 1216 | /* We need to hold the rindex unless the inode we're using is |
1216 | if (ip != GFS2_I(sdp->sd_rindex)) | 1217 | the rindex itself, in which case it's already held. */ |
1217 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); | 1218 | if (ip != GFS2_I(sdp->sd_rindex)) |
1218 | else if (!sdp->sd_rgrps) /* We may not have the rindex read in, so: */ | 1219 | error = gfs2_rindex_hold(sdp, &al->al_ri_gh); |
1219 | error = gfs2_ri_update_special(ip); | 1220 | else if (!sdp->sd_rgrps) /* We may not have the rindex read |
1221 | in, so: */ | ||
1222 | error = gfs2_ri_update_special(ip); | ||
1223 | } | ||
1220 | 1224 | ||
1221 | if (error) | 1225 | if (error) |
1222 | return error; | 1226 | return error; |
@@ -1227,7 +1231,7 @@ try_again: | |||
1227 | try to free it, and try the allocation again. */ | 1231 | try to free it, and try the allocation again. */ |
1228 | error = get_local_rgrp(ip, &unlinked, &last_unlinked); | 1232 | error = get_local_rgrp(ip, &unlinked, &last_unlinked); |
1229 | if (error) { | 1233 | if (error) { |
1230 | if (ip != GFS2_I(sdp->sd_rindex)) | 1234 | if (hold_rindex && ip != GFS2_I(sdp->sd_rindex)) |
1231 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1235 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1232 | if (error != -EAGAIN) | 1236 | if (error != -EAGAIN) |
1233 | return error; | 1237 | return error; |
@@ -1269,7 +1273,7 @@ void gfs2_inplace_release(struct gfs2_inode *ip) | |||
1269 | al->al_rgd = NULL; | 1273 | al->al_rgd = NULL; |
1270 | if (al->al_rgd_gh.gh_gl) | 1274 | if (al->al_rgd_gh.gh_gl) |
1271 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1275 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1272 | if (ip != GFS2_I(sdp->sd_rindex)) | 1276 | if (ip != GFS2_I(sdp->sd_rindex) && al->al_ri_gh.gh_gl) |
1273 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1277 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1274 | } | 1278 | } |
1275 | 1279 | ||