aboutsummaryrefslogtreecommitdiffstats
path: root/fs/gfs2/rgrp.c
diff options
context:
space:
mode:
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r--fs/gfs2/rgrp.c68
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
954static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, 955static 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
1072static 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)
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