aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--fs/xfs/xfs_log_recover.c134
1 files changed, 66 insertions, 68 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c
index 4099618f5fa0..841398d24211 100644
--- a/fs/xfs/xfs_log_recover.c
+++ b/fs/xfs/xfs_log_recover.c
@@ -3147,6 +3147,70 @@ out_error:
3147 return; 3147 return;
3148} 3148}
3149 3149
3150STATIC xfs_agino_t
3151xlog_recover_process_one_iunlink(
3152 struct xfs_mount *mp,
3153 xfs_agnumber_t agno,
3154 xfs_agino_t agino,
3155 int bucket)
3156{
3157 struct xfs_buf *ibp;
3158 struct xfs_dinode *dip;
3159 struct xfs_inode *ip;
3160 xfs_ino_t ino;
3161 int error;
3162
3163 ino = XFS_AGINO_TO_INO(mp, agno, agino);
3164 error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0);
3165 if (error)
3166 goto fail;
3167
3168 /*
3169 * Get the on disk inode to find the next inode in the bucket.
3170 */
3171 ASSERT(ip != NULL);
3172 error = xfs_itobp(mp, NULL, ip, &dip, &ibp, 0, 0, XFS_BUF_LOCK);
3173 if (error)
3174 goto fail;
3175
3176 ASSERT(dip != NULL);
3177 ASSERT(ip->i_d.di_nlink == 0);
3178
3179 /* setup for the next pass */
3180 agino = be32_to_cpu(dip->di_next_unlinked);
3181 xfs_buf_relse(ibp);
3182
3183 /*
3184 * Prevent any DMAPI event from being sent when the reference on
3185 * the inode is dropped.
3186 */
3187 ip->i_d.di_dmevmask = 0;
3188
3189 /*
3190 * If this is a new inode, handle it specially. Otherwise, just
3191 * drop our reference to the inode. If there are no other
3192 * references, this will send the inode to xfs_inactive() which
3193 * will truncate the file and free the inode.
3194 */
3195 if (ip->i_d.di_mode == 0)
3196 xfs_iput_new(ip, 0);
3197 else
3198 IRELE(ip);
3199 return agino;
3200
3201 fail:
3202 /*
3203 * We can't read in the inode this bucket points to, or this inode
3204 * is messed up. Just ditch this bucket of inodes. We will lose
3205 * some inodes and space, but at least we won't hang.
3206 *
3207 * Call xlog_recover_clear_agi_bucket() to perform a transaction to
3208 * clear the inode pointer in the bucket.
3209 */
3210 xlog_recover_clear_agi_bucket(mp, agno, bucket);
3211 return NULLAGINO;
3212}
3213
3150/* 3214/*
3151 * xlog_iunlink_recover 3215 * xlog_iunlink_recover
3152 * 3216 *
@@ -3167,11 +3231,7 @@ xlog_recover_process_iunlinks(
3167 xfs_agnumber_t agno; 3231 xfs_agnumber_t agno;
3168 xfs_agi_t *agi; 3232 xfs_agi_t *agi;
3169 xfs_buf_t *agibp; 3233 xfs_buf_t *agibp;
3170 xfs_buf_t *ibp;
3171 xfs_dinode_t *dip;
3172 xfs_inode_t *ip;
3173 xfs_agino_t agino; 3234 xfs_agino_t agino;
3174 xfs_ino_t ino;
3175 int bucket; 3235 int bucket;
3176 int error; 3236 int error;
3177 uint mp_dmevmask; 3237 uint mp_dmevmask;
@@ -3201,10 +3261,8 @@ xlog_recover_process_iunlinks(
3201 agi = XFS_BUF_TO_AGI(agibp); 3261 agi = XFS_BUF_TO_AGI(agibp);
3202 3262
3203 for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) { 3263 for (bucket = 0; bucket < XFS_AGI_UNLINKED_BUCKETS; bucket++) {
3204
3205 agino = be32_to_cpu(agi->agi_unlinked[bucket]); 3264 agino = be32_to_cpu(agi->agi_unlinked[bucket]);
3206 while (agino != NULLAGINO) { 3265 while (agino != NULLAGINO) {
3207
3208 /* 3266 /*
3209 * Release the agi buffer so that it can 3267 * Release the agi buffer so that it can
3210 * be acquired in the normal course of the 3268 * be acquired in the normal course of the
@@ -3212,68 +3270,8 @@ xlog_recover_process_iunlinks(
3212 */ 3270 */
3213 xfs_buf_relse(agibp); 3271 xfs_buf_relse(agibp);
3214 3272
3215 ino = XFS_AGINO_TO_INO(mp, agno, agino); 3273 agino = xlog_recover_process_one_iunlink(mp,
3216 error = xfs_iget(mp, NULL, ino, 0, 0, &ip, 0); 3274 agno, agino, bucket);
3217 ASSERT(error || (ip != NULL));
3218
3219 if (!error) {
3220 /*
3221 * Get the on disk inode to find the
3222 * next inode in the bucket.
3223 */
3224 error = xfs_itobp(mp, NULL, ip, &dip,
3225 &ibp, 0, 0,
3226 XFS_BUF_LOCK);
3227 ASSERT(error || (dip != NULL));
3228 }
3229
3230 if (!error) {
3231 ASSERT(ip->i_d.di_nlink == 0);
3232
3233 /* setup for the next pass */
3234 agino = be32_to_cpu(
3235 dip->di_next_unlinked);
3236 xfs_buf_relse(ibp);
3237 /*
3238 * Prevent any DMAPI event from
3239 * being sent when the
3240 * reference on the inode is
3241 * dropped.
3242 */
3243 ip->i_d.di_dmevmask = 0;
3244
3245 /*
3246 * If this is a new inode, handle
3247 * it specially. Otherwise,
3248 * just drop our reference to the
3249 * inode. If there are no
3250 * other references, this will
3251 * send the inode to
3252 * xfs_inactive() which will
3253 * truncate the file and free
3254 * the inode.
3255 */
3256 if (ip->i_d.di_mode == 0)
3257 xfs_iput_new(ip, 0);
3258 else
3259 IRELE(ip);
3260 } else {
3261 /*
3262 * We can't read in the inode
3263 * this bucket points to, or
3264 * this inode is messed up. Just
3265 * ditch this bucket of inodes. We
3266 * will lose some inodes and space,
3267 * but at least we won't hang. Call
3268 * xlog_recover_clear_agi_bucket()
3269 * to perform a transaction to clear
3270 * the inode pointer in the bucket.
3271 */
3272 xlog_recover_clear_agi_bucket(mp, agno,
3273 bucket);
3274
3275 agino = NULLAGINO;
3276 }
3277 3275
3278 /* 3276 /*
3279 * Reacquire the agibuffer and continue around 3277 * Reacquire the agibuffer and continue around