diff options
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 134 |
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 | ||
3150 | STATIC xfs_agino_t | ||
3151 | xlog_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 |