aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorZhi Yong Wu <wuzhy@linux.vnet.ibm.com>2013-08-14 03:16:03 -0400
committerBen Myers <bpm@sgi.com>2013-08-23 15:32:50 -0400
commit00574da199291751bfaaee15ad0f42a7144276ad (patch)
treec1d4bb20d559b5e5d2a137347886c45dde7b3c46 /fs/xfs
parent8d1d40832b1c53ae73931f1b536ce1ab7375b3c8 (diff)
xfs: introduce object readahead to log recovery
It can take a long time to run log recovery operation because it is single threaded and is bound by read latency. We can find that it took most of the time to wait for the read IO to occur, so if one object readahead is introduced to log recovery, it will obviously reduce the log recovery time. Log recovery time stat: w/o this patch w/ this patch real: 0m15.023s 0m7.802s user: 0m0.001s 0m0.001s sys: 0m0.246s 0m0.107s Signed-off-by: Zhi Yong Wu <wuzhy@linux.vnet.ibm.com> Reviewed-by: Ben Myers <bpm@sgi.com> Signed-off-by: Ben Myers <bpm@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r--fs/xfs/xfs_log_recover.c159
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
3122STATIC void
3123xlog_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
3139STATIC void
3140xlog_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
3166STATIC void
3167xlog_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
3199STATIC void
3200xlog_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
3122STATIC int 3222STATIC int
3123xlog_recover_commit_pass1( 3223xlog_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
3283STATIC int
3284xlog_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
3357out:
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
3224out:
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}