diff options
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 159 |
1 files changed, 152 insertions, 7 deletions
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 82f99b8ce07b..64e530e67053 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -3119,6 +3119,106 @@ xlog_recover_free_trans( | |||
3119 | kmem_free(trans); | 3119 | kmem_free(trans); |
3120 | } | 3120 | } |
3121 | 3121 | ||
3122 | STATIC void | ||
3123 | xlog_recover_buffer_ra_pass2( | ||
3124 | struct xlog *log, | ||
3125 | struct xlog_recover_item *item) | ||
3126 | { | ||
3127 | struct xfs_buf_log_format *buf_f = item->ri_buf[0].i_addr; | ||
3128 | struct xfs_mount *mp = log->l_mp; | ||
3129 | |||
3130 | if (xlog_check_buffer_cancelled(log, buf_f->blf_blkno, | ||
3131 | buf_f->blf_len, buf_f->blf_flags)) { | ||
3132 | return; | ||
3133 | } | ||
3134 | |||
3135 | xfs_buf_readahead(mp->m_ddev_targp, buf_f->blf_blkno, | ||
3136 | buf_f->blf_len, NULL); | ||
3137 | } | ||
3138 | |||
3139 | STATIC void | ||
3140 | xlog_recover_inode_ra_pass2( | ||
3141 | struct xlog *log, | ||
3142 | struct xlog_recover_item *item) | ||
3143 | { | ||
3144 | struct xfs_inode_log_format ilf_buf; | ||
3145 | struct xfs_inode_log_format *ilfp; | ||
3146 | struct xfs_mount *mp = log->l_mp; | ||
3147 | int error; | ||
3148 | |||
3149 | if (item->ri_buf[0].i_len == sizeof(struct xfs_inode_log_format)) { | ||
3150 | ilfp = item->ri_buf[0].i_addr; | ||
3151 | } else { | ||
3152 | ilfp = &ilf_buf; | ||
3153 | memset(ilfp, 0, sizeof(*ilfp)); | ||
3154 | error = xfs_inode_item_format_convert(&item->ri_buf[0], ilfp); | ||
3155 | if (error) | ||
3156 | return; | ||
3157 | } | ||
3158 | |||
3159 | if (xlog_check_buffer_cancelled(log, ilfp->ilf_blkno, ilfp->ilf_len, 0)) | ||
3160 | return; | ||
3161 | |||
3162 | xfs_buf_readahead(mp->m_ddev_targp, ilfp->ilf_blkno, | ||
3163 | ilfp->ilf_len, &xfs_inode_buf_ops); | ||
3164 | } | ||
3165 | |||
3166 | STATIC void | ||
3167 | xlog_recover_dquot_ra_pass2( | ||
3168 | struct xlog *log, | ||
3169 | struct xlog_recover_item *item) | ||
3170 | { | ||
3171 | struct xfs_mount *mp = log->l_mp; | ||
3172 | struct xfs_disk_dquot *recddq; | ||
3173 | struct xfs_dq_logformat *dq_f; | ||
3174 | uint type; | ||
3175 | |||
3176 | |||
3177 | if (mp->m_qflags == 0) | ||
3178 | return; | ||
3179 | |||
3180 | recddq = item->ri_buf[1].i_addr; | ||
3181 | if (recddq == NULL) | ||
3182 | return; | ||
3183 | if (item->ri_buf[1].i_len < sizeof(struct xfs_disk_dquot)) | ||
3184 | return; | ||
3185 | |||
3186 | type = recddq->d_flags & (XFS_DQ_USER | XFS_DQ_PROJ | XFS_DQ_GROUP); | ||
3187 | ASSERT(type); | ||
3188 | if (log->l_quotaoffs_flag & type) | ||
3189 | return; | ||
3190 | |||
3191 | dq_f = item->ri_buf[0].i_addr; | ||
3192 | ASSERT(dq_f); | ||
3193 | ASSERT(dq_f->qlf_len == 1); | ||
3194 | |||
3195 | xfs_buf_readahead(mp->m_ddev_targp, dq_f->qlf_blkno, | ||
3196 | dq_f->qlf_len, NULL); | ||
3197 | } | ||
3198 | |||
3199 | STATIC void | ||
3200 | xlog_recover_ra_pass2( | ||
3201 | struct xlog *log, | ||
3202 | struct xlog_recover_item *item) | ||
3203 | { | ||
3204 | switch (ITEM_TYPE(item)) { | ||
3205 | case XFS_LI_BUF: | ||
3206 | xlog_recover_buffer_ra_pass2(log, item); | ||
3207 | break; | ||
3208 | case XFS_LI_INODE: | ||
3209 | xlog_recover_inode_ra_pass2(log, item); | ||
3210 | break; | ||
3211 | case XFS_LI_DQUOT: | ||
3212 | xlog_recover_dquot_ra_pass2(log, item); | ||
3213 | break; | ||
3214 | case XFS_LI_EFI: | ||
3215 | case XFS_LI_EFD: | ||
3216 | case XFS_LI_QUOTAOFF: | ||
3217 | default: | ||
3218 | break; | ||
3219 | } | ||
3220 | } | ||
3221 | |||
3122 | STATIC int | 3222 | STATIC int |
3123 | xlog_recover_commit_pass1( | 3223 | xlog_recover_commit_pass1( |
3124 | struct xlog *log, | 3224 | struct xlog *log, |
@@ -3180,6 +3280,26 @@ xlog_recover_commit_pass2( | |||
3180 | } | 3280 | } |
3181 | } | 3281 | } |
3182 | 3282 | ||
3283 | STATIC int | ||
3284 | xlog_recover_items_pass2( | ||
3285 | struct xlog *log, | ||
3286 | struct xlog_recover *trans, | ||
3287 | struct list_head *buffer_list, | ||
3288 | struct list_head *item_list) | ||
3289 | { | ||
3290 | struct xlog_recover_item *item; | ||
3291 | int error = 0; | ||
3292 | |||
3293 | list_for_each_entry(item, item_list, ri_list) { | ||
3294 | error = xlog_recover_commit_pass2(log, trans, | ||
3295 | buffer_list, item); | ||
3296 | if (error) | ||
3297 | return error; | ||
3298 | } | ||
3299 | |||
3300 | return error; | ||
3301 | } | ||
3302 | |||
3183 | /* | 3303 | /* |
3184 | * Perform the transaction. | 3304 | * Perform the transaction. |
3185 | * | 3305 | * |
@@ -3192,9 +3312,16 @@ xlog_recover_commit_trans( | |||
3192 | struct xlog_recover *trans, | 3312 | struct xlog_recover *trans, |
3193 | int pass) | 3313 | int pass) |
3194 | { | 3314 | { |
3195 | int error = 0, error2; | 3315 | int error = 0; |
3196 | xlog_recover_item_t *item; | 3316 | int error2; |
3197 | LIST_HEAD (buffer_list); | 3317 | int items_queued = 0; |
3318 | struct xlog_recover_item *item; | ||
3319 | struct xlog_recover_item *next; | ||
3320 | LIST_HEAD (buffer_list); | ||
3321 | LIST_HEAD (ra_list); | ||
3322 | LIST_HEAD (done_list); | ||
3323 | |||
3324 | #define XLOG_RECOVER_COMMIT_QUEUE_MAX 100 | ||
3198 | 3325 | ||
3199 | hlist_del(&trans->r_list); | 3326 | hlist_del(&trans->r_list); |
3200 | 3327 | ||
@@ -3202,14 +3329,22 @@ xlog_recover_commit_trans( | |||
3202 | if (error) | 3329 | if (error) |
3203 | return error; | 3330 | return error; |
3204 | 3331 | ||
3205 | list_for_each_entry(item, &trans->r_itemq, ri_list) { | 3332 | list_for_each_entry_safe(item, next, &trans->r_itemq, ri_list) { |
3206 | switch (pass) { | 3333 | switch (pass) { |
3207 | case XLOG_RECOVER_PASS1: | 3334 | case XLOG_RECOVER_PASS1: |
3208 | error = xlog_recover_commit_pass1(log, trans, item); | 3335 | error = xlog_recover_commit_pass1(log, trans, item); |
3209 | break; | 3336 | break; |
3210 | case XLOG_RECOVER_PASS2: | 3337 | case XLOG_RECOVER_PASS2: |
3211 | error = xlog_recover_commit_pass2(log, trans, | 3338 | xlog_recover_ra_pass2(log, item); |
3212 | &buffer_list, item); | 3339 | list_move_tail(&item->ri_list, &ra_list); |
3340 | items_queued++; | ||
3341 | if (items_queued >= XLOG_RECOVER_COMMIT_QUEUE_MAX) { | ||
3342 | error = xlog_recover_items_pass2(log, trans, | ||
3343 | &buffer_list, &ra_list); | ||
3344 | list_splice_tail_init(&ra_list, &done_list); | ||
3345 | items_queued = 0; | ||
3346 | } | ||
3347 | |||
3213 | break; | 3348 | break; |
3214 | default: | 3349 | default: |
3215 | ASSERT(0); | 3350 | ASSERT(0); |
@@ -3219,9 +3354,19 @@ xlog_recover_commit_trans( | |||
3219 | goto out; | 3354 | goto out; |
3220 | } | 3355 | } |
3221 | 3356 | ||
3357 | out: | ||
3358 | if (!list_empty(&ra_list)) { | ||
3359 | if (!error) | ||
3360 | error = xlog_recover_items_pass2(log, trans, | ||
3361 | &buffer_list, &ra_list); | ||
3362 | list_splice_tail_init(&ra_list, &done_list); | ||
3363 | } | ||
3364 | |||
3365 | if (!list_empty(&done_list)) | ||
3366 | list_splice_init(&done_list, &trans->r_itemq); | ||
3367 | |||
3222 | xlog_recover_free_trans(trans); | 3368 | xlog_recover_free_trans(trans); |
3223 | 3369 | ||
3224 | out: | ||
3225 | error2 = xfs_buf_delwri_submit(&buffer_list); | 3370 | error2 = xfs_buf_delwri_submit(&buffer_list); |
3226 | return error ? error : error2; | 3371 | return error ? error : error2; |
3227 | } | 3372 | } |