aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBob Peterson <rpeterso@redhat.com>2010-05-11 17:58:11 -0400
committerSteven Whitehouse <swhiteho@redhat.com>2010-05-12 04:55:39 -0400
commitcc0581bd6132984641e47809552fc9d5dfcadbcf (patch)
tree21a75ca6f00e99661d679a09c5c8e01e8e61c40e
parenteaefbf968a83a160324225fb2ac9c49e56c86515 (diff)
GFS2: stuck in inode wait, no glocks stuck
This patch changes the lock ordering when gfs2 reclaims unlinked dinodes, thereby avoiding a livelock. Signed-off-by: Bob Peterson <rpeterso@redhat.com> Signed-off-by: Steven Whitehouse <swhiteho@redhat.com>
-rw-r--r--fs/gfs2/rgrp.c78
1 files changed, 30 insertions, 48 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c
index 37391550284f..8bce73ed4d8e 100644
--- a/fs/gfs2/rgrp.c
+++ b/fs/gfs2/rgrp.c
@@ -952,16 +952,14 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al)
952 * The inode, if one has been found, in inode. 952 * The inode, if one has been found, in inode.
953 */ 953 */
954 954
955static int try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, 955static u64 try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked,
956 u64 skip, struct inode **inode) 956 u64 skip)
957{ 957{
958 u32 goal = 0, block; 958 u32 goal = 0, block;
959 u64 no_addr; 959 u64 no_addr;
960 struct gfs2_sbd *sdp = rgd->rd_sbd; 960 struct gfs2_sbd *sdp = rgd->rd_sbd;
961 unsigned int n; 961 unsigned int n;
962 int error = 0;
963 962
964 *inode = NULL;
965 for(;;) { 963 for(;;) {
966 if (goal >= rgd->rd_data) 964 if (goal >= rgd->rd_data)
967 break; 965 break;
@@ -981,10 +979,7 @@ static int try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked,
981 if (no_addr == skip) 979 if (no_addr == skip)
982 continue; 980 continue;
983 *last_unlinked = no_addr; 981 *last_unlinked = no_addr;
984 error = gfs2_unlinked_inode_lookup(rgd->rd_sbd->sd_vfs, 982 return no_addr;
985 no_addr, inode);
986 if (*inode || error)
987 return error;
988 } 983 }
989 984
990 rgd->rd_flags &= ~GFS2_RDF_CHECK; 985 rgd->rd_flags &= ~GFS2_RDF_CHECK;
@@ -1069,11 +1064,12 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd)
1069 * Try to acquire rgrp in way which avoids contending with others. 1064 * Try to acquire rgrp in way which avoids contending with others.
1070 * 1065 *
1071 * Returns: errno 1066 * Returns: errno
1067 * unlinked: the block address of an unlinked block to be reclaimed
1072 */ 1068 */
1073 1069
1074static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) 1070static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked,
1071 u64 *last_unlinked)
1075{ 1072{
1076 struct inode *inode = NULL;
1077 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); 1073 struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
1078 struct gfs2_rgrpd *rgd, *begin = NULL; 1074 struct gfs2_rgrpd *rgd, *begin = NULL;
1079 struct gfs2_alloc *al = ip->i_alloc; 1075 struct gfs2_alloc *al = ip->i_alloc;
@@ -1082,6 +1078,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1082 int loops = 0; 1078 int loops = 0;
1083 int error, rg_locked; 1079 int error, rg_locked;
1084 1080
1081 *unlinked = 0;
1085 rgd = gfs2_blk2rgrpd(sdp, ip->i_goal); 1082 rgd = gfs2_blk2rgrpd(sdp, ip->i_goal);
1086 1083
1087 while (rgd) { 1084 while (rgd) {
@@ -1103,29 +1100,19 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1103 because that would require an iput which can only 1100 because that would require an iput which can only
1104 happen after the rgrp is unlocked. */ 1101 happen after the rgrp is unlocked. */
1105 if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) 1102 if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK)
1106 error = try_rgrp_unlink(rgd, last_unlinked, 1103 *unlinked = try_rgrp_unlink(rgd, last_unlinked,
1107 ip->i_no_addr, &inode); 1104 ip->i_no_addr);
1108 if (!rg_locked) 1105 if (!rg_locked)
1109 gfs2_glock_dq_uninit(&al->al_rgd_gh); 1106 gfs2_glock_dq_uninit(&al->al_rgd_gh);
1110 if (inode) { 1107 if (*unlinked)
1111 if (error) { 1108 return -EAGAIN;
1112 if (inode->i_state & I_NEW)
1113 iget_failed(inode);
1114 else
1115 iput(inode);
1116 return ERR_PTR(error);
1117 }
1118 return inode;
1119 }
1120 if (error)
1121 return ERR_PTR(error);
1122 /* fall through */ 1109 /* fall through */
1123 case GLR_TRYFAILED: 1110 case GLR_TRYFAILED:
1124 rgd = recent_rgrp_next(rgd); 1111 rgd = recent_rgrp_next(rgd);
1125 break; 1112 break;
1126 1113
1127 default: 1114 default:
1128 return ERR_PTR(error); 1115 return error;
1129 } 1116 }
1130 } 1117 }
1131 1118
@@ -1148,22 +1135,12 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1148 if (try_rgrp_fit(rgd, al)) 1135 if (try_rgrp_fit(rgd, al))
1149 goto out; 1136 goto out;
1150 if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) 1137 if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK)
1151 error = try_rgrp_unlink(rgd, last_unlinked, 1138 *unlinked = try_rgrp_unlink(rgd, last_unlinked,
1152 ip->i_no_addr, &inode); 1139 ip->i_no_addr);
1153 if (!rg_locked) 1140 if (!rg_locked)
1154 gfs2_glock_dq_uninit(&al->al_rgd_gh); 1141 gfs2_glock_dq_uninit(&al->al_rgd_gh);
1155 if (inode) { 1142 if (*unlinked)
1156 if (error) { 1143 return -EAGAIN;
1157 if (inode->i_state & I_NEW)
1158 iget_failed(inode);
1159 else
1160 iput(inode);
1161 return ERR_PTR(error);
1162 }
1163 return inode;
1164 }
1165 if (error)
1166 return ERR_PTR(error);
1167 break; 1144 break;
1168 1145
1169 case GLR_TRYFAILED: 1146 case GLR_TRYFAILED:
@@ -1171,7 +1148,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1171 break; 1148 break;
1172 1149
1173 default: 1150 default:
1174 return ERR_PTR(error); 1151 return error;
1175 } 1152 }
1176 1153
1177 rgd = gfs2_rgrpd_get_next(rgd); 1154 rgd = gfs2_rgrpd_get_next(rgd);
@@ -1180,7 +1157,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked)
1180 1157
1181 if (rgd == begin) { 1158 if (rgd == begin) {
1182 if (++loops >= 3) 1159 if (++loops >= 3)
1183 return ERR_PTR(-ENOSPC); 1160 return -ENOSPC;
1184 if (!skipped) 1161 if (!skipped)
1185 loops++; 1162 loops++;
1186 flags = 0; 1163 flags = 0;
@@ -1200,7 +1177,7 @@ out:
1200 forward_rgrp_set(sdp, rgd); 1177 forward_rgrp_set(sdp, rgd);
1201 } 1178 }
1202 1179
1203 return NULL; 1180 return 0;
1204} 1181}
1205 1182
1206/** 1183/**
@@ -1216,7 +1193,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line)
1216 struct gfs2_alloc *al = ip->i_alloc; 1193 struct gfs2_alloc *al = ip->i_alloc;
1217 struct inode *inode; 1194 struct inode *inode;
1218 int error = 0; 1195 int error = 0;
1219 u64 last_unlinked = NO_BLOCK; 1196 u64 last_unlinked = NO_BLOCK, unlinked;
1220 1197
1221 if (gfs2_assert_warn(sdp, al->al_requested)) 1198 if (gfs2_assert_warn(sdp, al->al_requested))
1222 return -EINVAL; 1199 return -EINVAL;
@@ -1232,14 +1209,19 @@ try_again:
1232 if (error) 1209 if (error)
1233 return error; 1210 return error;
1234 1211
1235 inode = get_local_rgrp(ip, &last_unlinked); 1212 error = get_local_rgrp(ip, &unlinked, &last_unlinked);
1236 if (inode) { 1213 if (error) {
1237 if (ip != GFS2_I(sdp->sd_rindex)) 1214 if (ip != GFS2_I(sdp->sd_rindex))
1238 gfs2_glock_dq_uninit(&al->al_ri_gh); 1215 gfs2_glock_dq_uninit(&al->al_ri_gh);
1239 if (IS_ERR(inode)) 1216 if (error != -EAGAIN)
1240 return PTR_ERR(inode); 1217 return error;
1241 iput(inode); 1218 error = gfs2_unlinked_inode_lookup(ip->i_inode.i_sb,
1219 unlinked, &inode);
1220 if (inode)
1221 iput(inode);
1242 gfs2_log_flush(sdp, NULL); 1222 gfs2_log_flush(sdp, NULL);
1223 if (error == GLR_TRYFAILED)
1224 error = 0;
1243 goto try_again; 1225 goto try_again;
1244 } 1226 }
1245 1227