diff options
Diffstat (limited to 'fs/gfs2/rgrp.c')
-rw-r--r-- | fs/gfs2/rgrp.c | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/fs/gfs2/rgrp.c b/fs/gfs2/rgrp.c index 503b842f3ba2..37391550284f 100644 --- a/fs/gfs2/rgrp.c +++ b/fs/gfs2/rgrp.c | |||
@@ -948,18 +948,20 @@ 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 int try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, |
955 | u64 skip) | 956 | u64 skip, struct inode **inode) |
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; |
961 | unsigned int n; | 961 | unsigned int n; |
962 | int error = 0; | ||
962 | 963 | ||
964 | *inode = NULL; | ||
963 | for(;;) { | 965 | for(;;) { |
964 | if (goal >= rgd->rd_data) | 966 | if (goal >= rgd->rd_data) |
965 | break; | 967 | break; |
@@ -979,14 +981,14 @@ static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, | |||
979 | if (no_addr == skip) | 981 | if (no_addr == skip) |
980 | continue; | 982 | continue; |
981 | *last_unlinked = no_addr; | 983 | *last_unlinked = no_addr; |
982 | inode = gfs2_inode_lookup(rgd->rd_sbd->sd_vfs, DT_UNKNOWN, | 984 | error = gfs2_unlinked_inode_lookup(rgd->rd_sbd->sd_vfs, |
983 | no_addr, -1, 1); | 985 | no_addr, inode); |
984 | if (!IS_ERR(inode)) | 986 | if (*inode || error) |
985 | return inode; | 987 | return error; |
986 | } | 988 | } |
987 | 989 | ||
988 | rgd->rd_flags &= ~GFS2_RDF_CHECK; | 990 | rgd->rd_flags &= ~GFS2_RDF_CHECK; |
989 | return NULL; | 991 | return 0; |
990 | } | 992 | } |
991 | 993 | ||
992 | /** | 994 | /** |
@@ -1096,12 +1098,27 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1096 | case 0: | 1098 | case 0: |
1097 | if (try_rgrp_fit(rgd, al)) | 1099 | if (try_rgrp_fit(rgd, al)) |
1098 | goto out; | 1100 | goto out; |
1099 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1101 | /* If the rg came in already locked, there's no |
1100 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); | 1102 | way we can recover from a failed try_rgrp_unlink |
1103 | because that would require an iput which can only | ||
1104 | happen after the rgrp is unlocked. */ | ||
1105 | if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) | ||
1106 | error = try_rgrp_unlink(rgd, last_unlinked, | ||
1107 | ip->i_no_addr, &inode); | ||
1101 | if (!rg_locked) | 1108 | if (!rg_locked) |
1102 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1109 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1103 | if (inode) | 1110 | if (inode) { |
1111 | if (error) { | ||
1112 | if (inode->i_state & I_NEW) | ||
1113 | iget_failed(inode); | ||
1114 | else | ||
1115 | iput(inode); | ||
1116 | return ERR_PTR(error); | ||
1117 | } | ||
1104 | return inode; | 1118 | return inode; |
1119 | } | ||
1120 | if (error) | ||
1121 | return ERR_PTR(error); | ||
1105 | /* fall through */ | 1122 | /* fall through */ |
1106 | case GLR_TRYFAILED: | 1123 | case GLR_TRYFAILED: |
1107 | rgd = recent_rgrp_next(rgd); | 1124 | rgd = recent_rgrp_next(rgd); |
@@ -1130,12 +1147,23 @@ static struct inode *get_local_rgrp(struct gfs2_inode *ip, u64 *last_unlinked) | |||
1130 | case 0: | 1147 | case 0: |
1131 | if (try_rgrp_fit(rgd, al)) | 1148 | if (try_rgrp_fit(rgd, al)) |
1132 | goto out; | 1149 | goto out; |
1133 | if (rgd->rd_flags & GFS2_RDF_CHECK) | 1150 | if (!rg_locked && rgd->rd_flags & GFS2_RDF_CHECK) |
1134 | inode = try_rgrp_unlink(rgd, last_unlinked, ip->i_no_addr); | 1151 | error = try_rgrp_unlink(rgd, last_unlinked, |
1152 | ip->i_no_addr, &inode); | ||
1135 | if (!rg_locked) | 1153 | if (!rg_locked) |
1136 | gfs2_glock_dq_uninit(&al->al_rgd_gh); | 1154 | gfs2_glock_dq_uninit(&al->al_rgd_gh); |
1137 | if (inode) | 1155 | if (inode) { |
1156 | if (error) { | ||
1157 | if (inode->i_state & I_NEW) | ||
1158 | iget_failed(inode); | ||
1159 | else | ||
1160 | iput(inode); | ||
1161 | return ERR_PTR(error); | ||
1162 | } | ||
1138 | return inode; | 1163 | return inode; |
1164 | } | ||
1165 | if (error) | ||
1166 | return ERR_PTR(error); | ||
1139 | break; | 1167 | break; |
1140 | 1168 | ||
1141 | case GLR_TRYFAILED: | 1169 | case GLR_TRYFAILED: |