diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 68 |
1 files changed, 39 insertions, 29 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 503b842f3ba2..8bce73ed4d8e 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -948,13 +948,13 @@ static int try_rgrp_fit(struct gfs2_rgrpd *rgd, struct gfs2_alloc *al) | |||
948 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes | 948 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes |
949 | * @rgd: The rgrp | 949 | * @rgd: The rgrp |
950 | * | 950 | * |
951 | * Returns: The inode, if one has been found | 951 | * Returns: 0 if no error |
952 | * The inode, if one has been found, in inode. | ||
952 | */ | 953 | */ |
953 | 954 | ||
954 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, | 955 | static u64 try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, |
955 | u64 skip) | 956 | u64 skip) |
956 | { | 957 | { |
957 | struct inode *inode; | ||
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; |
@@ -979,14 +979,11 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, | |||
979 | if (no_addr == skip) | 979 | if (no_addr == skip) |
980 | continue; | 980 | continue; |
981 | *last_unlinked = no_addr; | 981 | *last_unlinked = no_addr; |
982 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, | 982 | return no_addr; |
983 | no_addr, -1, 1); | ||
984 | if (!IS_ERR(inode)) | ||
985 | return inode; | ||
986 | } | 983 | } |
987 | 984 | ||
988 | rgd->rd_flags &= ~GFS2_RDF_CHECK; | 985 | rgd->rd_flags &= ~GFS2_RDF_CHECK; |
989 | return NULL; | 986 | return 0; |
990 | } | 987 | } |
991 | 988 | ||
992 | /** | 989 | /** |
@@ -1067,11 +1064,12 @@ static void forward_rgrp_set(struct gfs2_sbd *sdp, struct gfs2_rgrpd *rgd) | |||
1067 | * Try to acquire rgrp in way which avoids contending with others. | 1064 | * Try to acquire rgrp in way which avoids contending with others. |
1068 | * | 1065 | * |
1069 | * Returns: errno | 1066 | * Returns: errno |
1067 | * unlinked: the block address of an unlinked block to be reclaimed | ||
1070 | */ | 1068 | */ |
1071 | 1069 | ||
1072 | static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | 1070 | static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked, |
1071 | u64 *last_unlinked) | ||
1073 | { | 1072 | { |
1074 | struct inode *inode = NULL; | ||
1075 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1073 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1076 | struct gfs2_rgrpd *rgd, *begin = NULL; | 1074 | struct gfs2_rgrpd *rgd, *begin = NULL; |
1077 | struct gfs2_alloc *al = ip->i_alloc; | 1075 | struct gfs2_alloc *al = ip->i_alloc; |
@@ -1080,6 +1078,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1080 | int loops = 0; | 1078 | int loops = 0; |
1081 | int error, rg_locked; | 1079 | int error, rg_locked; |
1082 | 1080 | ||
1081 | *unlinked = 0; | ||
1083 | rgd = gfs2_blk2rgrpd(sdp, ip->i_goal); | 1082 | rgd = gfs2_blk2rgrpd(sdp, ip->i_goal); |
1084 | 1083 | ||
1085 | while (rgd) { | 1084 | while (rgd) { |
@@ -1096,19 +1095,24 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1096 | case 0: | 1095 | case 0: |
1097 | if (try_rgrp_fit(rgd, al)) | 1096 | if (try_rgrp_fit(rgd, al)) |
1098 | goto out; | 1097 | goto out; |
1099 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1098 | /* If the rg came in already locked, there's no |
1100 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); | 1099 | way we can recover from a failed try_rgrp_unlink |
1100 | because that would require an iput which can only | ||
1101 | happen after the rgrp is unlocked. */ | ||
1102 | if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) | ||
1103 | *unlinked = try_rgrp_unlink(rgd, last_unlinked, | ||
1104 | ip->i_no_addr); | ||
1101 | if (!rg_locked) | 1105 | if (!rg_locked) |
1102 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1106 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1103 | if (inode) | 1107 | if (*unlinked) |
1104 | return inode; | 1108 | return -EAGAIN; |
1105 | /* fall through */ | 1109 | /* fall through */ |
1106 | case GLR_TRYFAILED: | 1110 | case GLR_TRYFAILED: |
1107 | rgd = recent_rgrp_next(rgd); | 1111 | rgd = recent_rgrp_next(rgd); |
1108 | break; | 1112 | break; |
1109 | 1113 | ||
1110 | default: | 1114 | default: |
1111 | return ERR_PTR(error); | 1115 | return error; |
1112 | } | 1116 | } |
1113 | } | 1117 | } |
1114 | 1118 | ||
@@ -1130,12 +1134,13 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1130 | case 0: | 1134 | case 0: |
1131 | if (try_rgrp_fit(rgd, al)) | 1135 | if (try_rgrp_fit(rgd, al)) |
1132 | goto out; | 1136 | goto out; |
1133 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1137 | if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) |
1134 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); | 1138 | *unlinked = try_rgrp_unlink(rgd, last_unlinked, |
1139 | ip->i_no_addr); | ||
1135 | if (!rg_locked) | 1140 | if (!rg_locked) |
1136 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1141 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1137 | if (inode) | 1142 | if (*unlinked) |
1138 | return inode; | 1143 | return -EAGAIN; |
1139 | break; | 1144 | break; |
1140 | 1145 | ||
1141 | case GLR_TRYFAILED: | 1146 | case GLR_TRYFAILED: |
@@ -1143,7 +1148,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1143 | break; | 1148 | break; |
1144 | 1149 | ||
1145 | default: | 1150 | default: |
1146 | return ERR_PTR(error); | 1151 | return error; |
1147 | } | 1152 | } |
1148 | 1153 | ||
1149 | rgd = gfs2_rgrpd_get_next(rgd); | 1154 | rgd = gfs2_rgrpd_get_next(rgd); |
@@ -1152,7 +1157,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1152 | 1157 | ||
1153 | if (rgd == begin) { | 1158 | if (rgd == begin) { |
1154 | if (++loops >= 3) | 1159 | if (++loops >= 3) |
1155 | return ERR_PTR(-ENOSPC); | 1160 | return -ENOSPC; |
1156 | if (!skipped) | 1161 | if (!skipped) |
1157 | loops++; | 1162 | loops++; |
1158 | flags = 0; | 1163 | flags = 0; |
@@ -1172,7 +1177,7 @@ out: | |||
1172 | forward_rgrp_set(sdp, rgd); | 1177 | forward_rgrp_set(sdp, rgd); |
1173 | } | 1178 | } |
1174 | 1179 | ||
1175 | return NULL; | 1180 | return 0; |
1176 | } | 1181 | } |
1177 | 1182 | ||
1178 | /** | 1183 | /** |
@@ -1188,7 +1193,7 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
1188 | struct gfs2_alloc *al = ip->i_alloc; | 1193 | struct gfs2_alloc *al = ip->i_alloc; |
1189 | struct inode *inode; | 1194 | struct inode *inode; |
1190 | int error = 0; | 1195 | int error = 0; |
1191 | u64 last_unlinked = NO_BLOCK; | 1196 | u64 last_unlinked = NO_BLOCK, unlinked; |
1192 | 1197 | ||
1193 | if (gfs2_assert_warn(sdp, al->al_requested)) | 1198 | if (gfs2_assert_warn(sdp, al->al_requested)) |
1194 | return -EINVAL; | 1199 | return -EINVAL; |
@@ -1204,14 +1209,19 @@ try_again: | |||
1204 | if (error) | 1209 | if (error) |
1205 | return error; | 1210 | return error; |
1206 | 1211 | ||
1207 | inode = get_local_rgrp(ip, &last_unlinked); | 1212 | error = get_local_rgrp(ip, &unlinked, &last_unlinked); |
1208 | if (inode) { | 1213 | if (error) { |
1209 | if (ip != GFS2_I(sdp->sd_rindex)) | 1214 | if (ip != GFS2_I(sdp->sd_rindex)) |
1210 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1215 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1211 | if (IS_ERR(inode)) | 1216 | if (error != -EAGAIN) |
1212 | return PTR_ERR(inode); | 1217 | return error; |
1213 | iput(inode); | 1218 | error = gfs2_unlinked_inode_lookup(ip->i_inode.i_sb, |
1219 | unlinked, &inode); | ||
1220 | if (inode) | ||
1221 | iput(inode); | ||
1214 | gfs2_log_flush(sdp, NULL); | 1222 | gfs2_log_flush(sdp, NULL); |
1223 | if (error == GLR_TRYFAILED) | ||
1224 | error = 0; | ||
1215 | goto try_again; | 1225 | goto try_again; |
1216 | } | 1226 | } |
1217 | 1227 | ||