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/ops_inode.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/ops_inode.c')
-rw-r--r-- | fs/gfs2/ops_inode.c | 8 |
1 files changed, 6 insertions, 2 deletions
diff --git a/fs/gfs2/ops_inode.c b/fs/gfs2/ops_inode.c index fba00171d915..0534510200d5 100644 --- a/fs/gfs2/ops_inode.c +++ b/fs/gfs2/ops_inode.c | |||
@@ -736,7 +736,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
736 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); | 736 | struct gfs2_inode *ip = GFS2_I(odentry->d_inode); |
737 | struct gfs2_inode *nip = NULL; | 737 | struct gfs2_inode *nip = NULL; |
738 | struct gfs2_sbd *sdp = GFS2_SB(odir); | 738 | struct gfs2_sbd *sdp = GFS2_SB(odir); |
739 | struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }; | 739 | struct gfs2_holder ghs[5], r_gh = { .gh_gl = NULL, }, ri_gh; |
740 | struct gfs2_rgrpd *nrgd; | 740 | struct gfs2_rgrpd *nrgd; |
741 | unsigned int num_gh; | 741 | unsigned int num_gh; |
742 | int dir_rename = 0; | 742 | int dir_rename = 0; |
@@ -750,6 +750,9 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
750 | return 0; | 750 | return 0; |
751 | } | 751 | } |
752 | 752 | ||
753 | error = gfs2_rindex_hold(sdp, &ri_gh); | ||
754 | if (error) | ||
755 | return error; | ||
753 | 756 | ||
754 | if (odip != ndip) { | 757 | if (odip != ndip) { |
755 | error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, | 758 | error = gfs2_glock_nq_init(sdp->sd_rename_gl, LM_ST_EXCLUSIVE, |
@@ -879,7 +882,7 @@ static int gfs2_rename(struct inode *odir, struct dentry *odentry, | |||
879 | 882 | ||
880 | al->al_requested = sdp->sd_max_dirres; | 883 | al->al_requested = sdp->sd_max_dirres; |
881 | 884 | ||
882 | error = gfs2_inplace_reserve(ndip); | 885 | error = gfs2_inplace_reserve_ri(ndip); |
883 | if (error) | 886 | if (error) |
884 | goto out_gunlock_q; | 887 | goto out_gunlock_q; |
885 | 888 | ||
@@ -961,6 +964,7 @@ out_gunlock_r: | |||
961 | if (r_gh.gh_gl) | 964 | if (r_gh.gh_gl) |
962 | gfs2_glock_dq_uninit(&r_gh); | 965 | gfs2_glock_dq_uninit(&r_gh); |
963 | out: | 966 | out: |
967 | gfs2_glock_dq_uninit(&ri_gh); | ||
964 | return error; | 968 | return error; |
965 | } | 969 | } |
966 | 970 | ||