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.c58
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
954static struct inode *try_rgrp_unlink(struct gfs2_rgrpd *rgd, u64 *last_unlinked, 955static 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: