Commit 2f43bbd96e43d0b85803f5092be94bbb92d8eac9
Exists in
ti-lsk-linux-4.1.y
and in
10 other branches
Merge branch 'xfs-trans-recover-cleanup' into for-next
Showing 1 changed file Side-by-side Diff
fs/xfs/xfs_log_recover.c
... | ... | @@ -1445,161 +1445,7 @@ |
1445 | 1445 | ****************************************************************************** |
1446 | 1446 | */ |
1447 | 1447 | |
1448 | -STATIC xlog_recover_t * | |
1449 | -xlog_recover_find_tid( | |
1450 | - struct hlist_head *head, | |
1451 | - xlog_tid_t tid) | |
1452 | -{ | |
1453 | - xlog_recover_t *trans; | |
1454 | - | |
1455 | - hlist_for_each_entry(trans, head, r_list) { | |
1456 | - if (trans->r_log_tid == tid) | |
1457 | - return trans; | |
1458 | - } | |
1459 | - return NULL; | |
1460 | -} | |
1461 | - | |
1462 | -STATIC void | |
1463 | -xlog_recover_new_tid( | |
1464 | - struct hlist_head *head, | |
1465 | - xlog_tid_t tid, | |
1466 | - xfs_lsn_t lsn) | |
1467 | -{ | |
1468 | - xlog_recover_t *trans; | |
1469 | - | |
1470 | - trans = kmem_zalloc(sizeof(xlog_recover_t), KM_SLEEP); | |
1471 | - trans->r_log_tid = tid; | |
1472 | - trans->r_lsn = lsn; | |
1473 | - INIT_LIST_HEAD(&trans->r_itemq); | |
1474 | - | |
1475 | - INIT_HLIST_NODE(&trans->r_list); | |
1476 | - hlist_add_head(&trans->r_list, head); | |
1477 | -} | |
1478 | - | |
1479 | -STATIC void | |
1480 | -xlog_recover_add_item( | |
1481 | - struct list_head *head) | |
1482 | -{ | |
1483 | - xlog_recover_item_t *item; | |
1484 | - | |
1485 | - item = kmem_zalloc(sizeof(xlog_recover_item_t), KM_SLEEP); | |
1486 | - INIT_LIST_HEAD(&item->ri_list); | |
1487 | - list_add_tail(&item->ri_list, head); | |
1488 | -} | |
1489 | - | |
1490 | -STATIC int | |
1491 | -xlog_recover_add_to_cont_trans( | |
1492 | - struct xlog *log, | |
1493 | - struct xlog_recover *trans, | |
1494 | - xfs_caddr_t dp, | |
1495 | - int len) | |
1496 | -{ | |
1497 | - xlog_recover_item_t *item; | |
1498 | - xfs_caddr_t ptr, old_ptr; | |
1499 | - int old_len; | |
1500 | - | |
1501 | - if (list_empty(&trans->r_itemq)) { | |
1502 | - /* finish copying rest of trans header */ | |
1503 | - xlog_recover_add_item(&trans->r_itemq); | |
1504 | - ptr = (xfs_caddr_t) &trans->r_theader + | |
1505 | - sizeof(xfs_trans_header_t) - len; | |
1506 | - memcpy(ptr, dp, len); /* d, s, l */ | |
1507 | - return 0; | |
1508 | - } | |
1509 | - /* take the tail entry */ | |
1510 | - item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); | |
1511 | - | |
1512 | - old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; | |
1513 | - old_len = item->ri_buf[item->ri_cnt-1].i_len; | |
1514 | - | |
1515 | - ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP); | |
1516 | - memcpy(&ptr[old_len], dp, len); /* d, s, l */ | |
1517 | - item->ri_buf[item->ri_cnt-1].i_len += len; | |
1518 | - item->ri_buf[item->ri_cnt-1].i_addr = ptr; | |
1519 | - trace_xfs_log_recover_item_add_cont(log, trans, item, 0); | |
1520 | - return 0; | |
1521 | -} | |
1522 | - | |
1523 | 1448 | /* |
1524 | - * The next region to add is the start of a new region. It could be | |
1525 | - * a whole region or it could be the first part of a new region. Because | |
1526 | - * of this, the assumption here is that the type and size fields of all | |
1527 | - * format structures fit into the first 32 bits of the structure. | |
1528 | - * | |
1529 | - * This works because all regions must be 32 bit aligned. Therefore, we | |
1530 | - * either have both fields or we have neither field. In the case we have | |
1531 | - * neither field, the data part of the region is zero length. We only have | |
1532 | - * a log_op_header and can throw away the header since a new one will appear | |
1533 | - * later. If we have at least 4 bytes, then we can determine how many regions | |
1534 | - * will appear in the current log item. | |
1535 | - */ | |
1536 | -STATIC int | |
1537 | -xlog_recover_add_to_trans( | |
1538 | - struct xlog *log, | |
1539 | - struct xlog_recover *trans, | |
1540 | - xfs_caddr_t dp, | |
1541 | - int len) | |
1542 | -{ | |
1543 | - xfs_inode_log_format_t *in_f; /* any will do */ | |
1544 | - xlog_recover_item_t *item; | |
1545 | - xfs_caddr_t ptr; | |
1546 | - | |
1547 | - if (!len) | |
1548 | - return 0; | |
1549 | - if (list_empty(&trans->r_itemq)) { | |
1550 | - /* we need to catch log corruptions here */ | |
1551 | - if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) { | |
1552 | - xfs_warn(log->l_mp, "%s: bad header magic number", | |
1553 | - __func__); | |
1554 | - ASSERT(0); | |
1555 | - return -EIO; | |
1556 | - } | |
1557 | - if (len == sizeof(xfs_trans_header_t)) | |
1558 | - xlog_recover_add_item(&trans->r_itemq); | |
1559 | - memcpy(&trans->r_theader, dp, len); /* d, s, l */ | |
1560 | - return 0; | |
1561 | - } | |
1562 | - | |
1563 | - ptr = kmem_alloc(len, KM_SLEEP); | |
1564 | - memcpy(ptr, dp, len); | |
1565 | - in_f = (xfs_inode_log_format_t *)ptr; | |
1566 | - | |
1567 | - /* take the tail entry */ | |
1568 | - item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); | |
1569 | - if (item->ri_total != 0 && | |
1570 | - item->ri_total == item->ri_cnt) { | |
1571 | - /* tail item is in use, get a new one */ | |
1572 | - xlog_recover_add_item(&trans->r_itemq); | |
1573 | - item = list_entry(trans->r_itemq.prev, | |
1574 | - xlog_recover_item_t, ri_list); | |
1575 | - } | |
1576 | - | |
1577 | - if (item->ri_total == 0) { /* first region to be added */ | |
1578 | - if (in_f->ilf_size == 0 || | |
1579 | - in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) { | |
1580 | - xfs_warn(log->l_mp, | |
1581 | - "bad number of regions (%d) in inode log format", | |
1582 | - in_f->ilf_size); | |
1583 | - ASSERT(0); | |
1584 | - kmem_free(ptr); | |
1585 | - return -EIO; | |
1586 | - } | |
1587 | - | |
1588 | - item->ri_total = in_f->ilf_size; | |
1589 | - item->ri_buf = | |
1590 | - kmem_zalloc(item->ri_total * sizeof(xfs_log_iovec_t), | |
1591 | - KM_SLEEP); | |
1592 | - } | |
1593 | - ASSERT(item->ri_total > item->ri_cnt); | |
1594 | - /* Description region is ri_buf[0] */ | |
1595 | - item->ri_buf[item->ri_cnt].i_addr = ptr; | |
1596 | - item->ri_buf[item->ri_cnt].i_len = len; | |
1597 | - item->ri_cnt++; | |
1598 | - trace_xfs_log_recover_item_add(log, trans, item, 0); | |
1599 | - return 0; | |
1600 | -} | |
1601 | - | |
1602 | -/* | |
1603 | 1449 | * Sort the log items in the transaction. |
1604 | 1450 | * |
1605 | 1451 | * The ordering constraints are defined by the inode allocation and unlink |
1606 | 1452 | |
... | ... | @@ -3254,32 +3100,7 @@ |
3254 | 3100 | return 0; |
3255 | 3101 | } |
3256 | 3102 | |
3257 | -/* | |
3258 | - * Free up any resources allocated by the transaction | |
3259 | - * | |
3260 | - * Remember that EFIs, EFDs, and IUNLINKs are handled later. | |
3261 | - */ | |
3262 | 3103 | STATIC void |
3263 | -xlog_recover_free_trans( | |
3264 | - struct xlog_recover *trans) | |
3265 | -{ | |
3266 | - xlog_recover_item_t *item, *n; | |
3267 | - int i; | |
3268 | - | |
3269 | - list_for_each_entry_safe(item, n, &trans->r_itemq, ri_list) { | |
3270 | - /* Free the regions in the item. */ | |
3271 | - list_del(&item->ri_list); | |
3272 | - for (i = 0; i < item->ri_cnt; i++) | |
3273 | - kmem_free(item->ri_buf[i].i_addr); | |
3274 | - /* Free the item itself */ | |
3275 | - kmem_free(item->ri_buf); | |
3276 | - kmem_free(item); | |
3277 | - } | |
3278 | - /* Free the transaction recover structure */ | |
3279 | - kmem_free(trans); | |
3280 | -} | |
3281 | - | |
3282 | -STATIC void | |
3283 | 3104 | xlog_recover_buffer_ra_pass2( |
3284 | 3105 | struct xlog *log, |
3285 | 3106 | struct xlog_recover_item *item) |
3286 | 3107 | |
3287 | 3108 | |
3288 | 3109 | |
3289 | 3110 | |
... | ... | @@ -3528,22 +3349,309 @@ |
3528 | 3349 | if (!list_empty(&done_list)) |
3529 | 3350 | list_splice_init(&done_list, &trans->r_itemq); |
3530 | 3351 | |
3531 | - xlog_recover_free_trans(trans); | |
3532 | - | |
3533 | 3352 | error2 = xfs_buf_delwri_submit(&buffer_list); |
3534 | 3353 | return error ? error : error2; |
3535 | 3354 | } |
3536 | 3355 | |
3356 | +STATIC void | |
3357 | +xlog_recover_add_item( | |
3358 | + struct list_head *head) | |
3359 | +{ | |
3360 | + xlog_recover_item_t *item; | |
3361 | + | |
3362 | + item = kmem_zalloc(sizeof(xlog_recover_item_t), KM_SLEEP); | |
3363 | + INIT_LIST_HEAD(&item->ri_list); | |
3364 | + list_add_tail(&item->ri_list, head); | |
3365 | +} | |
3366 | + | |
3537 | 3367 | STATIC int |
3538 | -xlog_recover_unmount_trans( | |
3539 | - struct xlog *log) | |
3368 | +xlog_recover_add_to_cont_trans( | |
3369 | + struct xlog *log, | |
3370 | + struct xlog_recover *trans, | |
3371 | + xfs_caddr_t dp, | |
3372 | + int len) | |
3540 | 3373 | { |
3541 | - /* Do nothing now */ | |
3542 | - xfs_warn(log->l_mp, "%s: Unmount LR", __func__); | |
3374 | + xlog_recover_item_t *item; | |
3375 | + xfs_caddr_t ptr, old_ptr; | |
3376 | + int old_len; | |
3377 | + | |
3378 | + if (list_empty(&trans->r_itemq)) { | |
3379 | + /* finish copying rest of trans header */ | |
3380 | + xlog_recover_add_item(&trans->r_itemq); | |
3381 | + ptr = (xfs_caddr_t) &trans->r_theader + | |
3382 | + sizeof(xfs_trans_header_t) - len; | |
3383 | + memcpy(ptr, dp, len); | |
3384 | + return 0; | |
3385 | + } | |
3386 | + /* take the tail entry */ | |
3387 | + item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); | |
3388 | + | |
3389 | + old_ptr = item->ri_buf[item->ri_cnt-1].i_addr; | |
3390 | + old_len = item->ri_buf[item->ri_cnt-1].i_len; | |
3391 | + | |
3392 | + ptr = kmem_realloc(old_ptr, len+old_len, old_len, KM_SLEEP); | |
3393 | + memcpy(&ptr[old_len], dp, len); | |
3394 | + item->ri_buf[item->ri_cnt-1].i_len += len; | |
3395 | + item->ri_buf[item->ri_cnt-1].i_addr = ptr; | |
3396 | + trace_xfs_log_recover_item_add_cont(log, trans, item, 0); | |
3543 | 3397 | return 0; |
3544 | 3398 | } |
3545 | 3399 | |
3546 | 3400 | /* |
3401 | + * The next region to add is the start of a new region. It could be | |
3402 | + * a whole region or it could be the first part of a new region. Because | |
3403 | + * of this, the assumption here is that the type and size fields of all | |
3404 | + * format structures fit into the first 32 bits of the structure. | |
3405 | + * | |
3406 | + * This works because all regions must be 32 bit aligned. Therefore, we | |
3407 | + * either have both fields or we have neither field. In the case we have | |
3408 | + * neither field, the data part of the region is zero length. We only have | |
3409 | + * a log_op_header and can throw away the header since a new one will appear | |
3410 | + * later. If we have at least 4 bytes, then we can determine how many regions | |
3411 | + * will appear in the current log item. | |
3412 | + */ | |
3413 | +STATIC int | |
3414 | +xlog_recover_add_to_trans( | |
3415 | + struct xlog *log, | |
3416 | + struct xlog_recover *trans, | |
3417 | + xfs_caddr_t dp, | |
3418 | + int len) | |
3419 | +{ | |
3420 | + xfs_inode_log_format_t *in_f; /* any will do */ | |
3421 | + xlog_recover_item_t *item; | |
3422 | + xfs_caddr_t ptr; | |
3423 | + | |
3424 | + if (!len) | |
3425 | + return 0; | |
3426 | + if (list_empty(&trans->r_itemq)) { | |
3427 | + /* we need to catch log corruptions here */ | |
3428 | + if (*(uint *)dp != XFS_TRANS_HEADER_MAGIC) { | |
3429 | + xfs_warn(log->l_mp, "%s: bad header magic number", | |
3430 | + __func__); | |
3431 | + ASSERT(0); | |
3432 | + return -EIO; | |
3433 | + } | |
3434 | + if (len == sizeof(xfs_trans_header_t)) | |
3435 | + xlog_recover_add_item(&trans->r_itemq); | |
3436 | + memcpy(&trans->r_theader, dp, len); | |
3437 | + return 0; | |
3438 | + } | |
3439 | + | |
3440 | + ptr = kmem_alloc(len, KM_SLEEP); | |
3441 | + memcpy(ptr, dp, len); | |
3442 | + in_f = (xfs_inode_log_format_t *)ptr; | |
3443 | + | |
3444 | + /* take the tail entry */ | |
3445 | + item = list_entry(trans->r_itemq.prev, xlog_recover_item_t, ri_list); | |
3446 | + if (item->ri_total != 0 && | |
3447 | + item->ri_total == item->ri_cnt) { | |
3448 | + /* tail item is in use, get a new one */ | |
3449 | + xlog_recover_add_item(&trans->r_itemq); | |
3450 | + item = list_entry(trans->r_itemq.prev, | |
3451 | + xlog_recover_item_t, ri_list); | |
3452 | + } | |
3453 | + | |
3454 | + if (item->ri_total == 0) { /* first region to be added */ | |
3455 | + if (in_f->ilf_size == 0 || | |
3456 | + in_f->ilf_size > XLOG_MAX_REGIONS_IN_ITEM) { | |
3457 | + xfs_warn(log->l_mp, | |
3458 | + "bad number of regions (%d) in inode log format", | |
3459 | + in_f->ilf_size); | |
3460 | + ASSERT(0); | |
3461 | + kmem_free(ptr); | |
3462 | + return -EIO; | |
3463 | + } | |
3464 | + | |
3465 | + item->ri_total = in_f->ilf_size; | |
3466 | + item->ri_buf = | |
3467 | + kmem_zalloc(item->ri_total * sizeof(xfs_log_iovec_t), | |
3468 | + KM_SLEEP); | |
3469 | + } | |
3470 | + ASSERT(item->ri_total > item->ri_cnt); | |
3471 | + /* Description region is ri_buf[0] */ | |
3472 | + item->ri_buf[item->ri_cnt].i_addr = ptr; | |
3473 | + item->ri_buf[item->ri_cnt].i_len = len; | |
3474 | + item->ri_cnt++; | |
3475 | + trace_xfs_log_recover_item_add(log, trans, item, 0); | |
3476 | + return 0; | |
3477 | +} | |
3478 | + | |
3479 | +/* | |
3480 | + * Free up any resources allocated by the transaction | |
3481 | + * | |
3482 | + * Remember that EFIs, EFDs, and IUNLINKs are handled later. | |
3483 | + */ | |
3484 | +STATIC void | |
3485 | +xlog_recover_free_trans( | |
3486 | + struct xlog_recover *trans) | |
3487 | +{ | |
3488 | + xlog_recover_item_t *item, *n; | |
3489 | + int i; | |
3490 | + | |
3491 | + list_for_each_entry_safe(item, n, &trans->r_itemq, ri_list) { | |
3492 | + /* Free the regions in the item. */ | |
3493 | + list_del(&item->ri_list); | |
3494 | + for (i = 0; i < item->ri_cnt; i++) | |
3495 | + kmem_free(item->ri_buf[i].i_addr); | |
3496 | + /* Free the item itself */ | |
3497 | + kmem_free(item->ri_buf); | |
3498 | + kmem_free(item); | |
3499 | + } | |
3500 | + /* Free the transaction recover structure */ | |
3501 | + kmem_free(trans); | |
3502 | +} | |
3503 | + | |
3504 | +/* | |
3505 | + * On error or completion, trans is freed. | |
3506 | + */ | |
3507 | +STATIC int | |
3508 | +xlog_recovery_process_trans( | |
3509 | + struct xlog *log, | |
3510 | + struct xlog_recover *trans, | |
3511 | + xfs_caddr_t dp, | |
3512 | + unsigned int len, | |
3513 | + unsigned int flags, | |
3514 | + int pass) | |
3515 | +{ | |
3516 | + int error = 0; | |
3517 | + bool freeit = false; | |
3518 | + | |
3519 | + /* mask off ophdr transaction container flags */ | |
3520 | + flags &= ~XLOG_END_TRANS; | |
3521 | + if (flags & XLOG_WAS_CONT_TRANS) | |
3522 | + flags &= ~XLOG_CONTINUE_TRANS; | |
3523 | + | |
3524 | + /* | |
3525 | + * Callees must not free the trans structure. We'll decide if we need to | |
3526 | + * free it or not based on the operation being done and it's result. | |
3527 | + */ | |
3528 | + switch (flags) { | |
3529 | + /* expected flag values */ | |
3530 | + case 0: | |
3531 | + case XLOG_CONTINUE_TRANS: | |
3532 | + error = xlog_recover_add_to_trans(log, trans, dp, len); | |
3533 | + break; | |
3534 | + case XLOG_WAS_CONT_TRANS: | |
3535 | + error = xlog_recover_add_to_cont_trans(log, trans, dp, len); | |
3536 | + break; | |
3537 | + case XLOG_COMMIT_TRANS: | |
3538 | + error = xlog_recover_commit_trans(log, trans, pass); | |
3539 | + /* success or fail, we are now done with this transaction. */ | |
3540 | + freeit = true; | |
3541 | + break; | |
3542 | + | |
3543 | + /* unexpected flag values */ | |
3544 | + case XLOG_UNMOUNT_TRANS: | |
3545 | + /* just skip trans */ | |
3546 | + xfs_warn(log->l_mp, "%s: Unmount LR", __func__); | |
3547 | + freeit = true; | |
3548 | + break; | |
3549 | + case XLOG_START_TRANS: | |
3550 | + default: | |
3551 | + xfs_warn(log->l_mp, "%s: bad flag 0x%x", __func__, flags); | |
3552 | + ASSERT(0); | |
3553 | + error = -EIO; | |
3554 | + break; | |
3555 | + } | |
3556 | + if (error || freeit) | |
3557 | + xlog_recover_free_trans(trans); | |
3558 | + return error; | |
3559 | +} | |
3560 | + | |
3561 | +/* | |
3562 | + * Lookup the transaction recovery structure associated with the ID in the | |
3563 | + * current ophdr. If the transaction doesn't exist and the start flag is set in | |
3564 | + * the ophdr, then allocate a new transaction for future ID matches to find. | |
3565 | + * Either way, return what we found during the lookup - an existing transaction | |
3566 | + * or nothing. | |
3567 | + */ | |
3568 | +STATIC struct xlog_recover * | |
3569 | +xlog_recover_ophdr_to_trans( | |
3570 | + struct hlist_head rhash[], | |
3571 | + struct xlog_rec_header *rhead, | |
3572 | + struct xlog_op_header *ohead) | |
3573 | +{ | |
3574 | + struct xlog_recover *trans; | |
3575 | + xlog_tid_t tid; | |
3576 | + struct hlist_head *rhp; | |
3577 | + | |
3578 | + tid = be32_to_cpu(ohead->oh_tid); | |
3579 | + rhp = &rhash[XLOG_RHASH(tid)]; | |
3580 | + hlist_for_each_entry(trans, rhp, r_list) { | |
3581 | + if (trans->r_log_tid == tid) | |
3582 | + return trans; | |
3583 | + } | |
3584 | + | |
3585 | + /* | |
3586 | + * skip over non-start transaction headers - we could be | |
3587 | + * processing slack space before the next transaction starts | |
3588 | + */ | |
3589 | + if (!(ohead->oh_flags & XLOG_START_TRANS)) | |
3590 | + return NULL; | |
3591 | + | |
3592 | + ASSERT(be32_to_cpu(ohead->oh_len) == 0); | |
3593 | + | |
3594 | + /* | |
3595 | + * This is a new transaction so allocate a new recovery container to | |
3596 | + * hold the recovery ops that will follow. | |
3597 | + */ | |
3598 | + trans = kmem_zalloc(sizeof(struct xlog_recover), KM_SLEEP); | |
3599 | + trans->r_log_tid = tid; | |
3600 | + trans->r_lsn = be64_to_cpu(rhead->h_lsn); | |
3601 | + INIT_LIST_HEAD(&trans->r_itemq); | |
3602 | + INIT_HLIST_NODE(&trans->r_list); | |
3603 | + hlist_add_head(&trans->r_list, rhp); | |
3604 | + | |
3605 | + /* | |
3606 | + * Nothing more to do for this ophdr. Items to be added to this new | |
3607 | + * transaction will be in subsequent ophdr containers. | |
3608 | + */ | |
3609 | + return NULL; | |
3610 | +} | |
3611 | + | |
3612 | +STATIC int | |
3613 | +xlog_recover_process_ophdr( | |
3614 | + struct xlog *log, | |
3615 | + struct hlist_head rhash[], | |
3616 | + struct xlog_rec_header *rhead, | |
3617 | + struct xlog_op_header *ohead, | |
3618 | + xfs_caddr_t dp, | |
3619 | + xfs_caddr_t end, | |
3620 | + int pass) | |
3621 | +{ | |
3622 | + struct xlog_recover *trans; | |
3623 | + unsigned int len; | |
3624 | + | |
3625 | + /* Do we understand who wrote this op? */ | |
3626 | + if (ohead->oh_clientid != XFS_TRANSACTION && | |
3627 | + ohead->oh_clientid != XFS_LOG) { | |
3628 | + xfs_warn(log->l_mp, "%s: bad clientid 0x%x", | |
3629 | + __func__, ohead->oh_clientid); | |
3630 | + ASSERT(0); | |
3631 | + return -EIO; | |
3632 | + } | |
3633 | + | |
3634 | + /* | |
3635 | + * Check the ophdr contains all the data it is supposed to contain. | |
3636 | + */ | |
3637 | + len = be32_to_cpu(ohead->oh_len); | |
3638 | + if (dp + len > end) { | |
3639 | + xfs_warn(log->l_mp, "%s: bad length 0x%x", __func__, len); | |
3640 | + WARN_ON(1); | |
3641 | + return -EIO; | |
3642 | + } | |
3643 | + | |
3644 | + trans = xlog_recover_ophdr_to_trans(rhash, rhead, ohead); | |
3645 | + if (!trans) { | |
3646 | + /* nothing to do, so skip over this ophdr */ | |
3647 | + return 0; | |
3648 | + } | |
3649 | + | |
3650 | + return xlog_recovery_process_trans(log, trans, dp, len, | |
3651 | + ohead->oh_flags, pass); | |
3652 | +} | |
3653 | + | |
3654 | +/* | |
3547 | 3655 | * There are two valid states of the r_state field. 0 indicates that the |
3548 | 3656 | * transaction structure is in a normal state. We have either seen the |
3549 | 3657 | * start of the transaction or the last operation we added was not a partial |
3550 | 3658 | |
3551 | 3659 | |
3552 | 3660 | |
3553 | 3661 | |
... | ... | @@ -3560,86 +3668,30 @@ |
3560 | 3668 | xfs_caddr_t dp, |
3561 | 3669 | int pass) |
3562 | 3670 | { |
3563 | - xfs_caddr_t lp; | |
3671 | + struct xlog_op_header *ohead; | |
3672 | + xfs_caddr_t end; | |
3564 | 3673 | int num_logops; |
3565 | - xlog_op_header_t *ohead; | |
3566 | - xlog_recover_t *trans; | |
3567 | - xlog_tid_t tid; | |
3568 | 3674 | int error; |
3569 | - unsigned long hash; | |
3570 | - uint flags; | |
3571 | 3675 | |
3572 | - lp = dp + be32_to_cpu(rhead->h_len); | |
3676 | + end = dp + be32_to_cpu(rhead->h_len); | |
3573 | 3677 | num_logops = be32_to_cpu(rhead->h_num_logops); |
3574 | 3678 | |
3575 | 3679 | /* check the log format matches our own - else we can't recover */ |
3576 | 3680 | if (xlog_header_check_recover(log->l_mp, rhead)) |
3577 | 3681 | return -EIO; |
3578 | 3682 | |
3579 | - while ((dp < lp) && num_logops) { | |
3580 | - ASSERT(dp + sizeof(xlog_op_header_t) <= lp); | |
3581 | - ohead = (xlog_op_header_t *)dp; | |
3582 | - dp += sizeof(xlog_op_header_t); | |
3583 | - if (ohead->oh_clientid != XFS_TRANSACTION && | |
3584 | - ohead->oh_clientid != XFS_LOG) { | |
3585 | - xfs_warn(log->l_mp, "%s: bad clientid 0x%x", | |
3586 | - __func__, ohead->oh_clientid); | |
3587 | - ASSERT(0); | |
3588 | - return -EIO; | |
3589 | - } | |
3590 | - tid = be32_to_cpu(ohead->oh_tid); | |
3591 | - hash = XLOG_RHASH(tid); | |
3592 | - trans = xlog_recover_find_tid(&rhash[hash], tid); | |
3593 | - if (trans == NULL) { /* not found; add new tid */ | |
3594 | - if (ohead->oh_flags & XLOG_START_TRANS) | |
3595 | - xlog_recover_new_tid(&rhash[hash], tid, | |
3596 | - be64_to_cpu(rhead->h_lsn)); | |
3597 | - } else { | |
3598 | - if (dp + be32_to_cpu(ohead->oh_len) > lp) { | |
3599 | - xfs_warn(log->l_mp, "%s: bad length 0x%x", | |
3600 | - __func__, be32_to_cpu(ohead->oh_len)); | |
3601 | - WARN_ON(1); | |
3602 | - return -EIO; | |
3603 | - } | |
3604 | - flags = ohead->oh_flags & ~XLOG_END_TRANS; | |
3605 | - if (flags & XLOG_WAS_CONT_TRANS) | |
3606 | - flags &= ~XLOG_CONTINUE_TRANS; | |
3607 | - switch (flags) { | |
3608 | - case XLOG_COMMIT_TRANS: | |
3609 | - error = xlog_recover_commit_trans(log, | |
3610 | - trans, pass); | |
3611 | - break; | |
3612 | - case XLOG_UNMOUNT_TRANS: | |
3613 | - error = xlog_recover_unmount_trans(log); | |
3614 | - break; | |
3615 | - case XLOG_WAS_CONT_TRANS: | |
3616 | - error = xlog_recover_add_to_cont_trans(log, | |
3617 | - trans, dp, | |
3618 | - be32_to_cpu(ohead->oh_len)); | |
3619 | - break; | |
3620 | - case XLOG_START_TRANS: | |
3621 | - xfs_warn(log->l_mp, "%s: bad transaction", | |
3622 | - __func__); | |
3623 | - ASSERT(0); | |
3624 | - error = -EIO; | |
3625 | - break; | |
3626 | - case 0: | |
3627 | - case XLOG_CONTINUE_TRANS: | |
3628 | - error = xlog_recover_add_to_trans(log, trans, | |
3629 | - dp, be32_to_cpu(ohead->oh_len)); | |
3630 | - break; | |
3631 | - default: | |
3632 | - xfs_warn(log->l_mp, "%s: bad flag 0x%x", | |
3633 | - __func__, flags); | |
3634 | - ASSERT(0); | |
3635 | - error = -EIO; | |
3636 | - break; | |
3637 | - } | |
3638 | - if (error) { | |
3639 | - xlog_recover_free_trans(trans); | |
3640 | - return error; | |
3641 | - } | |
3642 | - } | |
3683 | + while ((dp < end) && num_logops) { | |
3684 | + | |
3685 | + ohead = (struct xlog_op_header *)dp; | |
3686 | + dp += sizeof(*ohead); | |
3687 | + ASSERT(dp <= end); | |
3688 | + | |
3689 | + /* errors will abort recovery */ | |
3690 | + error = xlog_recover_process_ophdr(log, rhash, rhead, ohead, | |
3691 | + dp, end, pass); | |
3692 | + if (error) | |
3693 | + return error; | |
3694 | + | |
3643 | 3695 | dp += be32_to_cpu(ohead->oh_len); |
3644 | 3696 | num_logops--; |
3645 | 3697 | } |