diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 81 |
1 files changed, 48 insertions, 33 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 503b842f3ba2..171a744f8e45 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -854,7 +854,8 @@ static void gfs2_rgrp_send_discards(struct gfs2_sbd *sdp, u64 offset, | |||
854 | if ((start + nr_sects) != blk) { | 854 | if ((start + nr_sects) != blk) { |
855 | rv = blkdev_issue_discard(bdev, start, | 855 | rv = blkdev_issue_discard(bdev, start, |
856 | nr_sects, GFP_NOFS, | 856 | nr_sects, GFP_NOFS, |
857 | DISCARD_FL_BARRIER); | 857 | BLKDEV_IFL_WAIT | |
858 | BLKDEV_IFL_BARRIER); | ||
858 | if (rv) | 859 | if (rv) |
859 | goto fail; | 860 | goto fail; |
860 | nr_sects = 0; | 861 | nr_sects = 0; |
@@ -869,7 +870,7 @@ start_new_extent: | |||
869 | } | 870 | } |
870 | if (nr_sects) { | 871 | if (nr_sects) { |
871 | rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, | 872 | rv = blkdev_issue_discard(bdev, start, nr_sects, GFP_NOFS, |
872 | DISCARD_FL_BARRIER); | 873 | BLKDEV_IFL_WAIT | BLKDEV_IFL_BARRIER); |
873 | if (rv) | 874 | if (rv) |
874 | goto fail; | 875 | goto fail; |
875 | } | 876 | } |
@@ -948,13 +949,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 | 949 | * try_rgrp_unlink - Look for any unlinked, allocated, but unused inodes |
949 | * @rgd: The rgrp | 950 | * @rgd: The rgrp |
950 | * | 951 | * |
951 | * Returns: The inode, if one has been found | 952 | * Returns: 0 if no error |
953 | * The inode, if one has been found, in inode. | ||
952 | */ | 954 | */ |
953 | 955 | ||
954 | static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, | 956 | static u64 try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, |
955 | u64 skip) | 957 | u64 skip) |
956 | { | 958 | { |
957 | struct inode *inode; | ||
958 | u32 goal = 0, block; | 959 | u32 goal = 0, block; |
959 | u64 no_addr; | 960 | u64 no_addr; |
960 | struct gfs2_sbd *sdp = rgd->rd_sbd; | 961 | struct gfs2_sbd *sdp = rgd->rd_sbd; |
@@ -979,14 +980,11 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, | |||
979 | if (no_addr == skip) | 980 | if (no_addr == skip) |
980 | continue; | 981 | continue; |
981 | *last_unlinked = no_addr; | 982 | *last_unlinked = no_addr; |
982 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, | 983 | return no_addr; |
983 | no_addr, -1, 1); | ||
984 | if (!IS_ERR(inode)) | ||
985 | return inode; | ||
986 | } | 984 | } |
987 | 985 | ||
988 | rgd->rd_flags &= ~GFS2_RDF_CHECK; | 986 | rgd->rd_flags &= ~GFS2_RDF_CHECK; |
989 | return NULL; | 987 | return 0; |
990 | } | 988 | } |
991 | 989 | ||
992 | /** | 990 | /** |
@@ -1067,11 +1065,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. | 1065 | * Try to acquire rgrp in way which avoids contending with others. |
1068 | * | 1066 | * |
1069 | * Returns: errno | 1067 | * Returns: errno |
1068 | * unlinked: the block address of an unlinked block to be reclaimed | ||
1070 | */ | 1069 | */ |
1071 | 1070 | ||
1072 | static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | 1071 | static int get_local_rgrp(struct gfs2_inode *ip, u64 *unlinked, |
1072 | u64 *last_unlinked) | ||
1073 | { | 1073 | { |
1074 | struct inode *inode = NULL; | ||
1075 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1074 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1076 | struct gfs2_rgrpd *rgd, *begin = NULL; | 1075 | struct gfs2_rgrpd *rgd, *begin = NULL; |
1077 | struct gfs2_alloc *al = ip->i_alloc; | 1076 | struct gfs2_alloc *al = ip->i_alloc; |
@@ -1080,6 +1079,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1080 | int loops = 0; | 1079 | int loops = 0; |
1081 | int error, rg_locked; | 1080 | int error, rg_locked; |
1082 | 1081 | ||
1082 | *unlinked = 0; | ||
1083 | rgd = gfs2_blk2rgrpd(sdp, ip->i_goal); | 1083 | rgd = gfs2_blk2rgrpd(sdp, ip->i_goal); |
1084 | 1084 | ||
1085 | while (rgd) { | 1085 | while (rgd) { |
@@ -1096,19 +1096,24 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1096 | case 0: | 1096 | case 0: |
1097 | if (try_rgrp_fit(rgd, al)) | 1097 | if (try_rgrp_fit(rgd, al)) |
1098 | goto out; | 1098 | goto out; |
1099 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1099 | /* If the rg came in already locked, there's no |
1100 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); | 1100 | way we can recover from a failed try_rgrp_unlink |
1101 | because that would require an iput which can only | ||
1102 | happen after the rgrp is unlocked. */ | ||
1103 | if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) | ||
1104 | *unlinked = try_rgrp_unlink(rgd, last_unlinked, | ||
1105 | ip->i_no_addr); | ||
1101 | if (!rg_locked) | 1106 | if (!rg_locked) |
1102 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1107 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1103 | if (inode) | 1108 | if (*unlinked) |
1104 | return inode; | 1109 | return -EAGAIN; |
1105 | /* fall through */ | 1110 | /* fall through */ |
1106 | case GLR_TRYFAILED: | 1111 | case GLR_TRYFAILED: |
1107 | rgd = recent_rgrp_next(rgd); | 1112 | rgd = recent_rgrp_next(rgd); |
1108 | break; | 1113 | break; |
1109 | 1114 | ||
1110 | default: | 1115 | default: |
1111 | return ERR_PTR(error); | 1116 | return error; |
1112 | } | 1117 | } |
1113 | } | 1118 | } |
1114 | 1119 | ||
@@ -1130,12 +1135,13 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1130 | case 0: | 1135 | case 0: |
1131 | if (try_rgrp_fit(rgd, al)) | 1136 | if (try_rgrp_fit(rgd, al)) |
1132 | goto out; | 1137 | goto out; |
1133 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1138 | if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) |
1134 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); | 1139 | *unlinked = try_rgrp_unlink(rgd, last_unlinked, |
1140 | ip->i_no_addr); | ||
1135 | if (!rg_locked) | 1141 | if (!rg_locked) |
1136 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1142 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1137 | if (inode) | 1143 | if (*unlinked) |
1138 | return inode; | 1144 | return -EAGAIN; |
1139 | break; | 1145 | break; |
1140 | 1146 | ||
1141 | case GLR_TRYFAILED: | 1147 | case GLR_TRYFAILED: |
@@ -1143,7 +1149,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1143 | break; | 1149 | break; |
1144 | 1150 | ||
1145 | default: | 1151 | default: |
1146 | return ERR_PTR(error); | 1152 | return error; |
1147 | } | 1153 | } |
1148 | 1154 | ||
1149 | rgd = gfs2_rgrpd_get_next(rgd); | 1155 | rgd = gfs2_rgrpd_get_next(rgd); |
@@ -1152,7 +1158,7 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1152 | 1158 | ||
1153 | if (rgd == begin) { | 1159 | if (rgd == begin) { |
1154 | if (++loops >= 3) | 1160 | if (++loops >= 3) |
1155 | return ERR_PTR(-ENOSPC); | 1161 | return -ENOSPC; |
1156 | if (!skipped) | 1162 | if (!skipped) |
1157 | loops++; | 1163 | loops++; |
1158 | flags = 0; | 1164 | flags = 0; |
@@ -1172,7 +1178,7 @@ out: | |||
1172 | forward_rgrp_set(sdp, rgd); | 1178 | forward_rgrp_set(sdp, rgd); |
1173 | } | 1179 | } |
1174 | 1180 | ||
1175 | return NULL; | 1181 | return 0; |
1176 | } | 1182 | } |
1177 | 1183 | ||
1178 | /** | 1184 | /** |
@@ -1186,9 +1192,8 @@ int gfs2_inplace_reserve_i(struct gfs2_inode *ip, char *file, unsigned int line) | |||
1186 | { | 1192 | { |
1187 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); | 1193 | struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode); |
1188 | struct gfs2_alloc *al = ip->i_alloc; | 1194 | struct gfs2_alloc *al = ip->i_alloc; |
1189 | 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,17 +1209,27 @@ 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 | /* Find an rgrp suitable for allocation. If it encounters any unlinked |
1208 | if (inode) { | 1213 | dinodes along the way, error will equal -EAGAIN and unlinked will |
1214 | contains it block address. We then need to look up that inode and | ||
1215 | try to free it, and try the allocation again. */ | ||
1216 | error = get_local_rgrp(ip, &unlinked, &last_unlinked); | ||
1217 | if (error) { | ||
1209 | if (ip != GFS2_I(sdp->sd_rindex)) | 1218 | if (ip != GFS2_I(sdp->sd_rindex)) |
1210 | gfs2_glock_dq_uninit(&al->al_ri_gh); | 1219 | gfs2_glock_dq_uninit(&al->al_ri_gh); |
1211 | if (IS_ERR(inode)) | 1220 | if (error != -EAGAIN) |
1212 | return PTR_ERR(inode); | 1221 | return error; |
1213 | iput(inode); | 1222 | |
1223 | gfs2_process_unlinked_inode(ip->i_inode.i_sb, unlinked); | ||
1224 | /* regardless of whether or not gfs2_process_unlinked_inode | ||
1225 | was successful, we don't want to repeat it again. */ | ||
1226 | last_unlinked = unlinked; | ||
1214 | gfs2_log_flush(sdp, NULL); | 1227 | gfs2_log_flush(sdp, NULL); |
1228 | error = 0; | ||
1229 | |||
1215 | goto try_again; | 1230 | goto try_again; |
1216 | } | 1231 | } |
1217 | 1232 | /* no error, so we have the rgrp set in the inode's allocation. */ | |
1218 | al->al_file = file; | 1233 | al->al_file = file; |
1219 | al->al_line = line; | 1234 | al->al_line = line; |
1220 | 1235 | ||