diff options
Diffstat (limited to 'fs/xfs/xfs_log.c')
-rw-r--r-- | fs/xfs/xfs_log.c | 702 |
1 files changed, 445 insertions, 257 deletions
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index 2be019136287..3038dd52c72a 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -44,13 +44,8 @@ | |||
44 | 44 | ||
45 | kmem_zone_t *xfs_log_ticket_zone; | 45 | kmem_zone_t *xfs_log_ticket_zone; |
46 | 46 | ||
47 | #define xlog_write_adv_cnt(ptr, len, off, bytes) \ | ||
48 | { (ptr) += (bytes); \ | ||
49 | (len) -= (bytes); \ | ||
50 | (off) += (bytes);} | ||
51 | |||
52 | /* Local miscellaneous function prototypes */ | 47 | /* Local miscellaneous function prototypes */ |
53 | STATIC int xlog_commit_record(xfs_mount_t *mp, xlog_ticket_t *ticket, | 48 | STATIC int xlog_commit_record(struct log *log, struct xlog_ticket *ticket, |
54 | xlog_in_core_t **, xfs_lsn_t *); | 49 | xlog_in_core_t **, xfs_lsn_t *); |
55 | STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, | 50 | STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, |
56 | xfs_buftarg_t *log_target, | 51 | xfs_buftarg_t *log_target, |
@@ -59,11 +54,9 @@ STATIC xlog_t * xlog_alloc_log(xfs_mount_t *mp, | |||
59 | STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); | 54 | STATIC int xlog_space_left(xlog_t *log, int cycle, int bytes); |
60 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); | 55 | STATIC int xlog_sync(xlog_t *log, xlog_in_core_t *iclog); |
61 | STATIC void xlog_dealloc_log(xlog_t *log); | 56 | STATIC void xlog_dealloc_log(xlog_t *log); |
62 | STATIC int xlog_write(xfs_mount_t *mp, xfs_log_iovec_t region[], | 57 | STATIC int xlog_write(struct log *log, struct xfs_log_vec *log_vector, |
63 | int nentries, struct xlog_ticket *tic, | 58 | struct xlog_ticket *tic, xfs_lsn_t *start_lsn, |
64 | xfs_lsn_t *start_lsn, | 59 | xlog_in_core_t **commit_iclog, uint flags); |
65 | xlog_in_core_t **commit_iclog, | ||
66 | uint flags); | ||
67 | 60 | ||
68 | /* local state machine functions */ | 61 | /* local state machine functions */ |
69 | STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int); | 62 | STATIC void xlog_state_done_syncing(xlog_in_core_t *iclog, int); |
@@ -102,7 +95,7 @@ STATIC xlog_ticket_t *xlog_ticket_alloc(xlog_t *log, | |||
102 | uint flags); | 95 | uint flags); |
103 | 96 | ||
104 | #if defined(DEBUG) | 97 | #if defined(DEBUG) |
105 | STATIC void xlog_verify_dest_ptr(xlog_t *log, __psint_t ptr); | 98 | STATIC void xlog_verify_dest_ptr(xlog_t *log, char *ptr); |
106 | STATIC void xlog_verify_grant_head(xlog_t *log, int equals); | 99 | STATIC void xlog_verify_grant_head(xlog_t *log, int equals); |
107 | STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, | 100 | STATIC void xlog_verify_iclog(xlog_t *log, xlog_in_core_t *iclog, |
108 | int count, boolean_t syncing); | 101 | int count, boolean_t syncing); |
@@ -258,7 +251,7 @@ xfs_log_done( | |||
258 | * If we get an error, just continue and give back the log ticket. | 251 | * If we get an error, just continue and give back the log ticket. |
259 | */ | 252 | */ |
260 | (((ticket->t_flags & XLOG_TIC_INITED) == 0) && | 253 | (((ticket->t_flags & XLOG_TIC_INITED) == 0) && |
261 | (xlog_commit_record(mp, ticket, iclog, &lsn)))) { | 254 | (xlog_commit_record(log, ticket, iclog, &lsn)))) { |
262 | lsn = (xfs_lsn_t) -1; | 255 | lsn = (xfs_lsn_t) -1; |
263 | if (ticket->t_flags & XLOG_TIC_PERM_RESERV) { | 256 | if (ticket->t_flags & XLOG_TIC_PERM_RESERV) { |
264 | flags |= XFS_LOG_REL_PERM_RESERV; | 257 | flags |= XFS_LOG_REL_PERM_RESERV; |
@@ -516,18 +509,10 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
516 | #ifdef DEBUG | 509 | #ifdef DEBUG |
517 | xlog_in_core_t *first_iclog; | 510 | xlog_in_core_t *first_iclog; |
518 | #endif | 511 | #endif |
519 | xfs_log_iovec_t reg[1]; | ||
520 | xlog_ticket_t *tic = NULL; | 512 | xlog_ticket_t *tic = NULL; |
521 | xfs_lsn_t lsn; | 513 | xfs_lsn_t lsn; |
522 | int error; | 514 | int error; |
523 | 515 | ||
524 | /* the data section must be 32 bit size aligned */ | ||
525 | struct { | ||
526 | __uint16_t magic; | ||
527 | __uint16_t pad1; | ||
528 | __uint32_t pad2; /* may as well make it 64 bits */ | ||
529 | } magic = { XLOG_UNMOUNT_TYPE, 0, 0 }; | ||
530 | |||
531 | /* | 516 | /* |
532 | * Don't write out unmount record on read-only mounts. | 517 | * Don't write out unmount record on read-only mounts. |
533 | * Or, if we are doing a forced umount (typically because of IO errors). | 518 | * Or, if we are doing a forced umount (typically because of IO errors). |
@@ -549,16 +534,30 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
549 | } while (iclog != first_iclog); | 534 | } while (iclog != first_iclog); |
550 | #endif | 535 | #endif |
551 | if (! (XLOG_FORCED_SHUTDOWN(log))) { | 536 | if (! (XLOG_FORCED_SHUTDOWN(log))) { |
552 | reg[0].i_addr = (void*)&magic; | ||
553 | reg[0].i_len = sizeof(magic); | ||
554 | reg[0].i_type = XLOG_REG_TYPE_UNMOUNT; | ||
555 | |||
556 | error = xfs_log_reserve(mp, 600, 1, &tic, | 537 | error = xfs_log_reserve(mp, 600, 1, &tic, |
557 | XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE); | 538 | XFS_LOG, 0, XLOG_UNMOUNT_REC_TYPE); |
558 | if (!error) { | 539 | if (!error) { |
540 | /* the data section must be 32 bit size aligned */ | ||
541 | struct { | ||
542 | __uint16_t magic; | ||
543 | __uint16_t pad1; | ||
544 | __uint32_t pad2; /* may as well make it 64 bits */ | ||
545 | } magic = { | ||
546 | .magic = XLOG_UNMOUNT_TYPE, | ||
547 | }; | ||
548 | struct xfs_log_iovec reg = { | ||
549 | .i_addr = (void *)&magic, | ||
550 | .i_len = sizeof(magic), | ||
551 | .i_type = XLOG_REG_TYPE_UNMOUNT, | ||
552 | }; | ||
553 | struct xfs_log_vec vec = { | ||
554 | .lv_niovecs = 1, | ||
555 | .lv_iovecp = ®, | ||
556 | }; | ||
557 | |||
559 | /* remove inited flag */ | 558 | /* remove inited flag */ |
560 | ((xlog_ticket_t *)tic)->t_flags = 0; | 559 | tic->t_flags = 0; |
561 | error = xlog_write(mp, reg, 1, tic, &lsn, | 560 | error = xlog_write(log, &vec, tic, &lsn, |
562 | NULL, XLOG_UNMOUNT_TRANS); | 561 | NULL, XLOG_UNMOUNT_TRANS); |
563 | /* | 562 | /* |
564 | * At this point, we're umounting anyway, | 563 | * At this point, we're umounting anyway, |
@@ -648,10 +647,26 @@ xfs_log_unmount(xfs_mount_t *mp) | |||
648 | xlog_dealloc_log(mp->m_log); | 647 | xlog_dealloc_log(mp->m_log); |
649 | } | 648 | } |
650 | 649 | ||
650 | void | ||
651 | xfs_log_item_init( | ||
652 | struct xfs_mount *mp, | ||
653 | struct xfs_log_item *item, | ||
654 | int type, | ||
655 | struct xfs_item_ops *ops) | ||
656 | { | ||
657 | item->li_mountp = mp; | ||
658 | item->li_ailp = mp->m_ail; | ||
659 | item->li_type = type; | ||
660 | item->li_ops = ops; | ||
661 | } | ||
662 | |||
651 | /* | 663 | /* |
652 | * Write region vectors to log. The write happens using the space reservation | 664 | * Write region vectors to log. The write happens using the space reservation |
653 | * of the ticket (tic). It is not a requirement that all writes for a given | 665 | * of the ticket (tic). It is not a requirement that all writes for a given |
654 | * transaction occur with one call to xfs_log_write(). | 666 | * transaction occur with one call to xfs_log_write(). However, it is important |
667 | * to note that the transaction reservation code makes an assumption about the | ||
668 | * number of log headers a transaction requires that may be violated if you | ||
669 | * don't pass all the transaction vectors in one call.... | ||
655 | */ | 670 | */ |
656 | int | 671 | int |
657 | xfs_log_write( | 672 | xfs_log_write( |
@@ -663,11 +678,15 @@ xfs_log_write( | |||
663 | { | 678 | { |
664 | struct log *log = mp->m_log; | 679 | struct log *log = mp->m_log; |
665 | int error; | 680 | int error; |
681 | struct xfs_log_vec vec = { | ||
682 | .lv_niovecs = nentries, | ||
683 | .lv_iovecp = reg, | ||
684 | }; | ||
666 | 685 | ||
667 | if (XLOG_FORCED_SHUTDOWN(log)) | 686 | if (XLOG_FORCED_SHUTDOWN(log)) |
668 | return XFS_ERROR(EIO); | 687 | return XFS_ERROR(EIO); |
669 | 688 | ||
670 | error = xlog_write(mp, reg, nentries, tic, start_lsn, NULL, 0); | 689 | error = xlog_write(log, &vec, tic, start_lsn, NULL, 0); |
671 | if (error) | 690 | if (error) |
672 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); | 691 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
673 | return error; | 692 | return error; |
@@ -1020,6 +1039,7 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1020 | int i; | 1039 | int i; |
1021 | int iclogsize; | 1040 | int iclogsize; |
1022 | int error = ENOMEM; | 1041 | int error = ENOMEM; |
1042 | uint log2_size = 0; | ||
1023 | 1043 | ||
1024 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); | 1044 | log = kmem_zalloc(sizeof(xlog_t), KM_MAYFAIL); |
1025 | if (!log) { | 1045 | if (!log) { |
@@ -1045,29 +1065,30 @@ xlog_alloc_log(xfs_mount_t *mp, | |||
1045 | 1065 | ||
1046 | error = EFSCORRUPTED; | 1066 | error = EFSCORRUPTED; |
1047 | if (xfs_sb_version_hassector(&mp->m_sb)) { | 1067 | if (xfs_sb_version_hassector(&mp->m_sb)) { |
1048 | log->l_sectbb_log = mp->m_sb.sb_logsectlog - BBSHIFT; | 1068 | log2_size = mp->m_sb.sb_logsectlog; |
1049 | if (log->l_sectbb_log < 0 || | 1069 | if (log2_size < BBSHIFT) { |
1050 | log->l_sectbb_log > mp->m_sectbb_log) { | 1070 | xlog_warn("XFS: Log sector size too small " |
1051 | xlog_warn("XFS: Log sector size (0x%x) out of range.", | 1071 | "(0x%x < 0x%x)", log2_size, BBSHIFT); |
1052 | log->l_sectbb_log); | ||
1053 | goto out_free_log; | 1072 | goto out_free_log; |
1054 | } | 1073 | } |
1055 | 1074 | ||
1056 | /* for larger sector sizes, must have v2 or external log */ | 1075 | log2_size -= BBSHIFT; |
1057 | if (log->l_sectbb_log != 0 && | 1076 | if (log2_size > mp->m_sectbb_log) { |
1058 | (log->l_logBBstart != 0 && | 1077 | xlog_warn("XFS: Log sector size too large " |
1059 | !xfs_sb_version_haslogv2(&mp->m_sb))) { | 1078 | "(0x%x > 0x%x)", log2_size, mp->m_sectbb_log); |
1060 | xlog_warn("XFS: log sector size (0x%x) invalid " | ||
1061 | "for configuration.", log->l_sectbb_log); | ||
1062 | goto out_free_log; | 1079 | goto out_free_log; |
1063 | } | 1080 | } |
1064 | if (mp->m_sb.sb_logsectlog < BBSHIFT) { | 1081 | |
1065 | xlog_warn("XFS: Log sector log (0x%x) too small.", | 1082 | /* for larger sector sizes, must have v2 or external log */ |
1066 | mp->m_sb.sb_logsectlog); | 1083 | if (log2_size && log->l_logBBstart > 0 && |
1084 | !xfs_sb_version_haslogv2(&mp->m_sb)) { | ||
1085 | |||
1086 | xlog_warn("XFS: log sector size (0x%x) invalid " | ||
1087 | "for configuration.", log2_size); | ||
1067 | goto out_free_log; | 1088 | goto out_free_log; |
1068 | } | 1089 | } |
1069 | } | 1090 | } |
1070 | log->l_sectbb_mask = (1 << log->l_sectbb_log) - 1; | 1091 | log->l_sectBBsize = 1 << log2_size; |
1071 | 1092 | ||
1072 | xlog_get_iclog_buffer_size(mp, log); | 1093 | xlog_get_iclog_buffer_size(mp, log); |
1073 | 1094 | ||
@@ -1174,26 +1195,31 @@ out: | |||
1174 | * ticket. Return the lsn of the commit record. | 1195 | * ticket. Return the lsn of the commit record. |
1175 | */ | 1196 | */ |
1176 | STATIC int | 1197 | STATIC int |
1177 | xlog_commit_record(xfs_mount_t *mp, | 1198 | xlog_commit_record( |
1178 | xlog_ticket_t *ticket, | 1199 | struct log *log, |
1179 | xlog_in_core_t **iclog, | 1200 | struct xlog_ticket *ticket, |
1180 | xfs_lsn_t *commitlsnp) | 1201 | struct xlog_in_core **iclog, |
1202 | xfs_lsn_t *commitlsnp) | ||
1181 | { | 1203 | { |
1182 | int error; | 1204 | struct xfs_mount *mp = log->l_mp; |
1183 | xfs_log_iovec_t reg[1]; | 1205 | int error; |
1184 | 1206 | struct xfs_log_iovec reg = { | |
1185 | reg[0].i_addr = NULL; | 1207 | .i_addr = NULL, |
1186 | reg[0].i_len = 0; | 1208 | .i_len = 0, |
1187 | reg[0].i_type = XLOG_REG_TYPE_COMMIT; | 1209 | .i_type = XLOG_REG_TYPE_COMMIT, |
1210 | }; | ||
1211 | struct xfs_log_vec vec = { | ||
1212 | .lv_niovecs = 1, | ||
1213 | .lv_iovecp = ®, | ||
1214 | }; | ||
1188 | 1215 | ||
1189 | ASSERT_ALWAYS(iclog); | 1216 | ASSERT_ALWAYS(iclog); |
1190 | if ((error = xlog_write(mp, reg, 1, ticket, commitlsnp, | 1217 | error = xlog_write(log, &vec, ticket, commitlsnp, iclog, |
1191 | iclog, XLOG_COMMIT_TRANS))) { | 1218 | XLOG_COMMIT_TRANS); |
1219 | if (error) | ||
1192 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); | 1220 | xfs_force_shutdown(mp, SHUTDOWN_LOG_IO_ERROR); |
1193 | } | ||
1194 | return error; | 1221 | return error; |
1195 | } /* xlog_commit_record */ | 1222 | } |
1196 | |||
1197 | 1223 | ||
1198 | /* | 1224 | /* |
1199 | * Push on the buffer cache code if we ever use more than 75% of the on-disk | 1225 | * Push on the buffer cache code if we ever use more than 75% of the on-disk |
@@ -1614,6 +1640,192 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket) | |||
1614 | } | 1640 | } |
1615 | 1641 | ||
1616 | /* | 1642 | /* |
1643 | * Calculate the potential space needed by the log vector. Each region gets | ||
1644 | * its own xlog_op_header_t and may need to be double word aligned. | ||
1645 | */ | ||
1646 | static int | ||
1647 | xlog_write_calc_vec_length( | ||
1648 | struct xlog_ticket *ticket, | ||
1649 | struct xfs_log_vec *log_vector) | ||
1650 | { | ||
1651 | struct xfs_log_vec *lv; | ||
1652 | int headers = 0; | ||
1653 | int len = 0; | ||
1654 | int i; | ||
1655 | |||
1656 | /* acct for start rec of xact */ | ||
1657 | if (ticket->t_flags & XLOG_TIC_INITED) | ||
1658 | headers++; | ||
1659 | |||
1660 | for (lv = log_vector; lv; lv = lv->lv_next) { | ||
1661 | headers += lv->lv_niovecs; | ||
1662 | |||
1663 | for (i = 0; i < lv->lv_niovecs; i++) { | ||
1664 | struct xfs_log_iovec *vecp = &lv->lv_iovecp[i]; | ||
1665 | |||
1666 | len += vecp->i_len; | ||
1667 | xlog_tic_add_region(ticket, vecp->i_len, vecp->i_type); | ||
1668 | } | ||
1669 | } | ||
1670 | |||
1671 | ticket->t_res_num_ophdrs += headers; | ||
1672 | len += headers * sizeof(struct xlog_op_header); | ||
1673 | |||
1674 | return len; | ||
1675 | } | ||
1676 | |||
1677 | /* | ||
1678 | * If first write for transaction, insert start record We can't be trying to | ||
1679 | * commit if we are inited. We can't have any "partial_copy" if we are inited. | ||
1680 | */ | ||
1681 | static int | ||
1682 | xlog_write_start_rec( | ||
1683 | struct xlog_op_header *ophdr, | ||
1684 | struct xlog_ticket *ticket) | ||
1685 | { | ||
1686 | if (!(ticket->t_flags & XLOG_TIC_INITED)) | ||
1687 | return 0; | ||
1688 | |||
1689 | ophdr->oh_tid = cpu_to_be32(ticket->t_tid); | ||
1690 | ophdr->oh_clientid = ticket->t_clientid; | ||
1691 | ophdr->oh_len = 0; | ||
1692 | ophdr->oh_flags = XLOG_START_TRANS; | ||
1693 | ophdr->oh_res2 = 0; | ||
1694 | |||
1695 | ticket->t_flags &= ~XLOG_TIC_INITED; | ||
1696 | |||
1697 | return sizeof(struct xlog_op_header); | ||
1698 | } | ||
1699 | |||
1700 | static xlog_op_header_t * | ||
1701 | xlog_write_setup_ophdr( | ||
1702 | struct log *log, | ||
1703 | struct xlog_op_header *ophdr, | ||
1704 | struct xlog_ticket *ticket, | ||
1705 | uint flags) | ||
1706 | { | ||
1707 | ophdr->oh_tid = cpu_to_be32(ticket->t_tid); | ||
1708 | ophdr->oh_clientid = ticket->t_clientid; | ||
1709 | ophdr->oh_res2 = 0; | ||
1710 | |||
1711 | /* are we copying a commit or unmount record? */ | ||
1712 | ophdr->oh_flags = flags; | ||
1713 | |||
1714 | /* | ||
1715 | * We've seen logs corrupted with bad transaction client ids. This | ||
1716 | * makes sure that XFS doesn't generate them on. Turn this into an EIO | ||
1717 | * and shut down the filesystem. | ||
1718 | */ | ||
1719 | switch (ophdr->oh_clientid) { | ||
1720 | case XFS_TRANSACTION: | ||
1721 | case XFS_VOLUME: | ||
1722 | case XFS_LOG: | ||
1723 | break; | ||
1724 | default: | ||
1725 | xfs_fs_cmn_err(CE_WARN, log->l_mp, | ||
1726 | "Bad XFS transaction clientid 0x%x in ticket 0x%p", | ||
1727 | ophdr->oh_clientid, ticket); | ||
1728 | return NULL; | ||
1729 | } | ||
1730 | |||
1731 | return ophdr; | ||
1732 | } | ||
1733 | |||
1734 | /* | ||
1735 | * Set up the parameters of the region copy into the log. This has | ||
1736 | * to handle region write split across multiple log buffers - this | ||
1737 | * state is kept external to this function so that this code can | ||
1738 | * can be written in an obvious, self documenting manner. | ||
1739 | */ | ||
1740 | static int | ||
1741 | xlog_write_setup_copy( | ||
1742 | struct xlog_ticket *ticket, | ||
1743 | struct xlog_op_header *ophdr, | ||
1744 | int space_available, | ||
1745 | int space_required, | ||
1746 | int *copy_off, | ||
1747 | int *copy_len, | ||
1748 | int *last_was_partial_copy, | ||
1749 | int *bytes_consumed) | ||
1750 | { | ||
1751 | int still_to_copy; | ||
1752 | |||
1753 | still_to_copy = space_required - *bytes_consumed; | ||
1754 | *copy_off = *bytes_consumed; | ||
1755 | |||
1756 | if (still_to_copy <= space_available) { | ||
1757 | /* write of region completes here */ | ||
1758 | *copy_len = still_to_copy; | ||
1759 | ophdr->oh_len = cpu_to_be32(*copy_len); | ||
1760 | if (*last_was_partial_copy) | ||
1761 | ophdr->oh_flags |= (XLOG_END_TRANS|XLOG_WAS_CONT_TRANS); | ||
1762 | *last_was_partial_copy = 0; | ||
1763 | *bytes_consumed = 0; | ||
1764 | return 0; | ||
1765 | } | ||
1766 | |||
1767 | /* partial write of region, needs extra log op header reservation */ | ||
1768 | *copy_len = space_available; | ||
1769 | ophdr->oh_len = cpu_to_be32(*copy_len); | ||
1770 | ophdr->oh_flags |= XLOG_CONTINUE_TRANS; | ||
1771 | if (*last_was_partial_copy) | ||
1772 | ophdr->oh_flags |= XLOG_WAS_CONT_TRANS; | ||
1773 | *bytes_consumed += *copy_len; | ||
1774 | (*last_was_partial_copy)++; | ||
1775 | |||
1776 | /* account for new log op header */ | ||
1777 | ticket->t_curr_res -= sizeof(struct xlog_op_header); | ||
1778 | ticket->t_res_num_ophdrs++; | ||
1779 | |||
1780 | return sizeof(struct xlog_op_header); | ||
1781 | } | ||
1782 | |||
1783 | static int | ||
1784 | xlog_write_copy_finish( | ||
1785 | struct log *log, | ||
1786 | struct xlog_in_core *iclog, | ||
1787 | uint flags, | ||
1788 | int *record_cnt, | ||
1789 | int *data_cnt, | ||
1790 | int *partial_copy, | ||
1791 | int *partial_copy_len, | ||
1792 | int log_offset, | ||
1793 | struct xlog_in_core **commit_iclog) | ||
1794 | { | ||
1795 | if (*partial_copy) { | ||
1796 | /* | ||
1797 | * This iclog has already been marked WANT_SYNC by | ||
1798 | * xlog_state_get_iclog_space. | ||
1799 | */ | ||
1800 | xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt); | ||
1801 | *record_cnt = 0; | ||
1802 | *data_cnt = 0; | ||
1803 | return xlog_state_release_iclog(log, iclog); | ||
1804 | } | ||
1805 | |||
1806 | *partial_copy = 0; | ||
1807 | *partial_copy_len = 0; | ||
1808 | |||
1809 | if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) { | ||
1810 | /* no more space in this iclog - push it. */ | ||
1811 | xlog_state_finish_copy(log, iclog, *record_cnt, *data_cnt); | ||
1812 | *record_cnt = 0; | ||
1813 | *data_cnt = 0; | ||
1814 | |||
1815 | spin_lock(&log->l_icloglock); | ||
1816 | xlog_state_want_sync(log, iclog); | ||
1817 | spin_unlock(&log->l_icloglock); | ||
1818 | |||
1819 | if (!commit_iclog) | ||
1820 | return xlog_state_release_iclog(log, iclog); | ||
1821 | ASSERT(flags & XLOG_COMMIT_TRANS); | ||
1822 | *commit_iclog = iclog; | ||
1823 | } | ||
1824 | |||
1825 | return 0; | ||
1826 | } | ||
1827 | |||
1828 | /* | ||
1617 | * Write some region out to in-core log | 1829 | * Write some region out to in-core log |
1618 | * | 1830 | * |
1619 | * This will be called when writing externally provided regions or when | 1831 | * This will be called when writing externally provided regions or when |
@@ -1655,209 +1867,157 @@ xlog_print_tic_res(xfs_mount_t *mp, xlog_ticket_t *ticket) | |||
1655 | */ | 1867 | */ |
1656 | STATIC int | 1868 | STATIC int |
1657 | xlog_write( | 1869 | xlog_write( |
1658 | struct xfs_mount *mp, | 1870 | struct log *log, |
1659 | struct xfs_log_iovec reg[], | 1871 | struct xfs_log_vec *log_vector, |
1660 | int nentries, | ||
1661 | struct xlog_ticket *ticket, | 1872 | struct xlog_ticket *ticket, |
1662 | xfs_lsn_t *start_lsn, | 1873 | xfs_lsn_t *start_lsn, |
1663 | struct xlog_in_core **commit_iclog, | 1874 | struct xlog_in_core **commit_iclog, |
1664 | uint flags) | 1875 | uint flags) |
1665 | { | 1876 | { |
1666 | xlog_t *log = mp->m_log; | 1877 | struct xlog_in_core *iclog = NULL; |
1667 | xlog_in_core_t *iclog = NULL; /* ptr to current in-core log */ | 1878 | struct xfs_log_iovec *vecp; |
1668 | xlog_op_header_t *logop_head; /* ptr to log operation header */ | 1879 | struct xfs_log_vec *lv; |
1669 | __psint_t ptr; /* copy address into data region */ | 1880 | int len; |
1670 | int len; /* # xlog_write() bytes 2 still copy */ | 1881 | int index; |
1671 | int index; /* region index currently copying */ | 1882 | int partial_copy = 0; |
1672 | int log_offset; /* offset (from 0) into data region */ | 1883 | int partial_copy_len = 0; |
1673 | int start_rec_copy; /* # bytes to copy for start record */ | 1884 | int contwr = 0; |
1674 | int partial_copy; /* did we split a region? */ | 1885 | int record_cnt = 0; |
1675 | int partial_copy_len;/* # bytes copied if split region */ | 1886 | int data_cnt = 0; |
1676 | int need_copy; /* # bytes need to memcpy this region */ | 1887 | int error; |
1677 | int copy_len; /* # bytes actually memcpy'ing */ | ||
1678 | int copy_off; /* # bytes from entry start */ | ||
1679 | int contwr; /* continued write of in-core log? */ | ||
1680 | int error; | ||
1681 | int record_cnt = 0, data_cnt = 0; | ||
1682 | |||
1683 | partial_copy_len = partial_copy = 0; | ||
1684 | |||
1685 | /* Calculate potential maximum space. Each region gets its own | ||
1686 | * xlog_op_header_t and may need to be double word aligned. | ||
1687 | */ | ||
1688 | len = 0; | ||
1689 | if (ticket->t_flags & XLOG_TIC_INITED) { /* acct for start rec of xact */ | ||
1690 | len += sizeof(xlog_op_header_t); | ||
1691 | ticket->t_res_num_ophdrs++; | ||
1692 | } | ||
1693 | 1888 | ||
1694 | for (index = 0; index < nentries; index++) { | 1889 | *start_lsn = 0; |
1695 | len += sizeof(xlog_op_header_t); /* each region gets >= 1 */ | ||
1696 | ticket->t_res_num_ophdrs++; | ||
1697 | len += reg[index].i_len; | ||
1698 | xlog_tic_add_region(ticket, reg[index].i_len, reg[index].i_type); | ||
1699 | } | ||
1700 | contwr = *start_lsn = 0; | ||
1701 | 1890 | ||
1702 | if (ticket->t_curr_res < len) { | 1891 | len = xlog_write_calc_vec_length(ticket, log_vector); |
1703 | xlog_print_tic_res(mp, ticket); | 1892 | if (ticket->t_curr_res < len) { |
1893 | xlog_print_tic_res(log->l_mp, ticket); | ||
1704 | #ifdef DEBUG | 1894 | #ifdef DEBUG |
1705 | xlog_panic( | 1895 | xlog_panic( |
1706 | "xfs_log_write: reservation ran out. Need to up reservation"); | 1896 | "xfs_log_write: reservation ran out. Need to up reservation"); |
1707 | #else | 1897 | #else |
1708 | /* Customer configurable panic */ | 1898 | /* Customer configurable panic */ |
1709 | xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, mp, | 1899 | xfs_cmn_err(XFS_PTAG_LOGRES, CE_ALERT, log->l_mp, |
1710 | "xfs_log_write: reservation ran out. Need to up reservation"); | 1900 | "xfs_log_write: reservation ran out. Need to up reservation"); |
1711 | /* If we did not panic, shutdown the filesystem */ | 1901 | |
1712 | xfs_force_shutdown(mp, SHUTDOWN_CORRUPT_INCORE); | 1902 | /* If we did not panic, shutdown the filesystem */ |
1903 | xfs_force_shutdown(log->l_mp, SHUTDOWN_CORRUPT_INCORE); | ||
1713 | #endif | 1904 | #endif |
1714 | } else | 1905 | } |
1906 | |||
1715 | ticket->t_curr_res -= len; | 1907 | ticket->t_curr_res -= len; |
1716 | 1908 | ||
1717 | for (index = 0; index < nentries; ) { | 1909 | index = 0; |
1718 | if ((error = xlog_state_get_iclog_space(log, len, &iclog, ticket, | 1910 | lv = log_vector; |
1719 | &contwr, &log_offset))) | 1911 | vecp = lv->lv_iovecp; |
1720 | return error; | 1912 | while (lv && index < lv->lv_niovecs) { |
1913 | void *ptr; | ||
1914 | int log_offset; | ||
1721 | 1915 | ||
1722 | ASSERT(log_offset <= iclog->ic_size - 1); | 1916 | error = xlog_state_get_iclog_space(log, len, &iclog, ticket, |
1723 | ptr = (__psint_t) ((char *)iclog->ic_datap+log_offset); | 1917 | &contwr, &log_offset); |
1918 | if (error) | ||
1919 | return error; | ||
1724 | 1920 | ||
1725 | /* start_lsn is the first lsn written to. That's all we need. */ | 1921 | ASSERT(log_offset <= iclog->ic_size - 1); |
1726 | if (! *start_lsn) | 1922 | ptr = iclog->ic_datap + log_offset; |
1727 | *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn); | ||
1728 | 1923 | ||
1729 | /* This loop writes out as many regions as can fit in the amount | 1924 | /* start_lsn is the first lsn written to. That's all we need. */ |
1730 | * of space which was allocated by xlog_state_get_iclog_space(). | 1925 | if (!*start_lsn) |
1731 | */ | 1926 | *start_lsn = be64_to_cpu(iclog->ic_header.h_lsn); |
1732 | while (index < nentries) { | ||
1733 | ASSERT(reg[index].i_len % sizeof(__int32_t) == 0); | ||
1734 | ASSERT((__psint_t)ptr % sizeof(__int32_t) == 0); | ||
1735 | start_rec_copy = 0; | ||
1736 | |||
1737 | /* If first write for transaction, insert start record. | ||
1738 | * We can't be trying to commit if we are inited. We can't | ||
1739 | * have any "partial_copy" if we are inited. | ||
1740 | */ | ||
1741 | if (ticket->t_flags & XLOG_TIC_INITED) { | ||
1742 | logop_head = (xlog_op_header_t *)ptr; | ||
1743 | logop_head->oh_tid = cpu_to_be32(ticket->t_tid); | ||
1744 | logop_head->oh_clientid = ticket->t_clientid; | ||
1745 | logop_head->oh_len = 0; | ||
1746 | logop_head->oh_flags = XLOG_START_TRANS; | ||
1747 | logop_head->oh_res2 = 0; | ||
1748 | ticket->t_flags &= ~XLOG_TIC_INITED; /* clear bit */ | ||
1749 | record_cnt++; | ||
1750 | |||
1751 | start_rec_copy = sizeof(xlog_op_header_t); | ||
1752 | xlog_write_adv_cnt(ptr, len, log_offset, start_rec_copy); | ||
1753 | } | ||
1754 | 1927 | ||
1755 | /* Copy log operation header directly into data section */ | 1928 | /* |
1756 | logop_head = (xlog_op_header_t *)ptr; | 1929 | * This loop writes out as many regions as can fit in the amount |
1757 | logop_head->oh_tid = cpu_to_be32(ticket->t_tid); | 1930 | * of space which was allocated by xlog_state_get_iclog_space(). |
1758 | logop_head->oh_clientid = ticket->t_clientid; | 1931 | */ |
1759 | logop_head->oh_res2 = 0; | 1932 | while (lv && index < lv->lv_niovecs) { |
1933 | struct xfs_log_iovec *reg = &vecp[index]; | ||
1934 | struct xlog_op_header *ophdr; | ||
1935 | int start_rec_copy; | ||
1936 | int copy_len; | ||
1937 | int copy_off; | ||
1938 | |||
1939 | ASSERT(reg->i_len % sizeof(__int32_t) == 0); | ||
1940 | ASSERT((unsigned long)ptr % sizeof(__int32_t) == 0); | ||
1941 | |||
1942 | start_rec_copy = xlog_write_start_rec(ptr, ticket); | ||
1943 | if (start_rec_copy) { | ||
1944 | record_cnt++; | ||
1945 | xlog_write_adv_cnt(&ptr, &len, &log_offset, | ||
1946 | start_rec_copy); | ||
1947 | } | ||
1760 | 1948 | ||
1761 | /* header copied directly */ | 1949 | ophdr = xlog_write_setup_ophdr(log, ptr, ticket, flags); |
1762 | xlog_write_adv_cnt(ptr, len, log_offset, sizeof(xlog_op_header_t)); | 1950 | if (!ophdr) |
1951 | return XFS_ERROR(EIO); | ||
1763 | 1952 | ||
1764 | /* are we copying a commit or unmount record? */ | 1953 | xlog_write_adv_cnt(&ptr, &len, &log_offset, |
1765 | logop_head->oh_flags = flags; | 1954 | sizeof(struct xlog_op_header)); |
1955 | |||
1956 | len += xlog_write_setup_copy(ticket, ophdr, | ||
1957 | iclog->ic_size-log_offset, | ||
1958 | reg->i_len, | ||
1959 | ©_off, ©_len, | ||
1960 | &partial_copy, | ||
1961 | &partial_copy_len); | ||
1962 | xlog_verify_dest_ptr(log, ptr); | ||
1963 | |||
1964 | /* copy region */ | ||
1965 | ASSERT(copy_len >= 0); | ||
1966 | memcpy(ptr, reg->i_addr + copy_off, copy_len); | ||
1967 | xlog_write_adv_cnt(&ptr, &len, &log_offset, copy_len); | ||
1968 | |||
1969 | copy_len += start_rec_copy + sizeof(xlog_op_header_t); | ||
1970 | record_cnt++; | ||
1971 | data_cnt += contwr ? copy_len : 0; | ||
1972 | |||
1973 | error = xlog_write_copy_finish(log, iclog, flags, | ||
1974 | &record_cnt, &data_cnt, | ||
1975 | &partial_copy, | ||
1976 | &partial_copy_len, | ||
1977 | log_offset, | ||
1978 | commit_iclog); | ||
1979 | if (error) | ||
1980 | return error; | ||
1766 | 1981 | ||
1767 | /* | 1982 | /* |
1768 | * We've seen logs corrupted with bad transaction client | 1983 | * if we had a partial copy, we need to get more iclog |
1769 | * ids. This makes sure that XFS doesn't generate them on. | 1984 | * space but we don't want to increment the region |
1770 | * Turn this into an EIO and shut down the filesystem. | 1985 | * index because there is still more is this region to |
1771 | */ | 1986 | * write. |
1772 | switch (logop_head->oh_clientid) { | 1987 | * |
1773 | case XFS_TRANSACTION: | 1988 | * If we completed writing this region, and we flushed |
1774 | case XFS_VOLUME: | 1989 | * the iclog (indicated by resetting of the record |
1775 | case XFS_LOG: | 1990 | * count), then we also need to get more log space. If |
1776 | break; | 1991 | * this was the last record, though, we are done and |
1777 | default: | 1992 | * can just return. |
1778 | xfs_fs_cmn_err(CE_WARN, mp, | 1993 | */ |
1779 | "Bad XFS transaction clientid 0x%x in ticket 0x%p", | 1994 | if (partial_copy) |
1780 | logop_head->oh_clientid, ticket); | 1995 | break; |
1781 | return XFS_ERROR(EIO); | ||
1782 | } | ||
1783 | 1996 | ||
1784 | /* Partial write last time? => (partial_copy != 0) | 1997 | if (++index == lv->lv_niovecs) { |
1785 | * need_copy is the amount we'd like to copy if everything could | 1998 | lv = lv->lv_next; |
1786 | * fit in the current memcpy. | 1999 | index = 0; |
1787 | */ | 2000 | if (lv) |
1788 | need_copy = reg[index].i_len - partial_copy_len; | 2001 | vecp = lv->lv_iovecp; |
1789 | 2002 | } | |
1790 | copy_off = partial_copy_len; | 2003 | if (record_cnt == 0) { |
1791 | if (need_copy <= iclog->ic_size - log_offset) { /*complete write */ | 2004 | if (!lv) |
1792 | copy_len = need_copy; | 2005 | return 0; |
1793 | logop_head->oh_len = cpu_to_be32(copy_len); | 2006 | break; |
1794 | if (partial_copy) | 2007 | } |
1795 | logop_head->oh_flags|= (XLOG_END_TRANS|XLOG_WAS_CONT_TRANS); | ||
1796 | partial_copy_len = partial_copy = 0; | ||
1797 | } else { /* partial write */ | ||
1798 | copy_len = iclog->ic_size - log_offset; | ||
1799 | logop_head->oh_len = cpu_to_be32(copy_len); | ||
1800 | logop_head->oh_flags |= XLOG_CONTINUE_TRANS; | ||
1801 | if (partial_copy) | ||
1802 | logop_head->oh_flags |= XLOG_WAS_CONT_TRANS; | ||
1803 | partial_copy_len += copy_len; | ||
1804 | partial_copy++; | ||
1805 | len += sizeof(xlog_op_header_t); /* from splitting of region */ | ||
1806 | /* account for new log op header */ | ||
1807 | ticket->t_curr_res -= sizeof(xlog_op_header_t); | ||
1808 | ticket->t_res_num_ophdrs++; | ||
1809 | } | ||
1810 | xlog_verify_dest_ptr(log, ptr); | ||
1811 | |||
1812 | /* copy region */ | ||
1813 | ASSERT(copy_len >= 0); | ||
1814 | memcpy((xfs_caddr_t)ptr, reg[index].i_addr + copy_off, copy_len); | ||
1815 | xlog_write_adv_cnt(ptr, len, log_offset, copy_len); | ||
1816 | |||
1817 | /* make copy_len total bytes copied, including headers */ | ||
1818 | copy_len += start_rec_copy + sizeof(xlog_op_header_t); | ||
1819 | record_cnt++; | ||
1820 | data_cnt += contwr ? copy_len : 0; | ||
1821 | if (partial_copy) { /* copied partial region */ | ||
1822 | /* already marked WANT_SYNC by xlog_state_get_iclog_space */ | ||
1823 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
1824 | record_cnt = data_cnt = 0; | ||
1825 | if ((error = xlog_state_release_iclog(log, iclog))) | ||
1826 | return error; | ||
1827 | break; /* don't increment index */ | ||
1828 | } else { /* copied entire region */ | ||
1829 | index++; | ||
1830 | partial_copy_len = partial_copy = 0; | ||
1831 | |||
1832 | if (iclog->ic_size - log_offset <= sizeof(xlog_op_header_t)) { | ||
1833 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
1834 | record_cnt = data_cnt = 0; | ||
1835 | spin_lock(&log->l_icloglock); | ||
1836 | xlog_state_want_sync(log, iclog); | ||
1837 | spin_unlock(&log->l_icloglock); | ||
1838 | if (commit_iclog) { | ||
1839 | ASSERT(flags & XLOG_COMMIT_TRANS); | ||
1840 | *commit_iclog = iclog; | ||
1841 | } else if ((error = xlog_state_release_iclog(log, iclog))) | ||
1842 | return error; | ||
1843 | if (index == nentries) | ||
1844 | return 0; /* we are done */ | ||
1845 | else | ||
1846 | break; | ||
1847 | } | 2008 | } |
1848 | } /* if (partial_copy) */ | 2009 | } |
1849 | } /* while (index < nentries) */ | 2010 | |
1850 | } /* for (index = 0; index < nentries; ) */ | 2011 | ASSERT(len == 0); |
1851 | ASSERT(len == 0); | 2012 | |
2013 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
2014 | if (!commit_iclog) | ||
2015 | return xlog_state_release_iclog(log, iclog); | ||
1852 | 2016 | ||
1853 | xlog_state_finish_copy(log, iclog, record_cnt, data_cnt); | ||
1854 | if (commit_iclog) { | ||
1855 | ASSERT(flags & XLOG_COMMIT_TRANS); | 2017 | ASSERT(flags & XLOG_COMMIT_TRANS); |
1856 | *commit_iclog = iclog; | 2018 | *commit_iclog = iclog; |
1857 | return 0; | 2019 | return 0; |
1858 | } | 2020 | } |
1859 | return xlog_state_release_iclog(log, iclog); | ||
1860 | } /* xlog_write */ | ||
1861 | 2021 | ||
1862 | 2022 | ||
1863 | /***************************************************************************** | 2023 | /***************************************************************************** |
@@ -3157,14 +3317,16 @@ xfs_log_ticket_get( | |||
3157 | * Allocate and initialise a new log ticket. | 3317 | * Allocate and initialise a new log ticket. |
3158 | */ | 3318 | */ |
3159 | STATIC xlog_ticket_t * | 3319 | STATIC xlog_ticket_t * |
3160 | xlog_ticket_alloc(xlog_t *log, | 3320 | xlog_ticket_alloc( |
3161 | int unit_bytes, | 3321 | struct log *log, |
3162 | int cnt, | 3322 | int unit_bytes, |
3163 | char client, | 3323 | int cnt, |
3164 | uint xflags) | 3324 | char client, |
3325 | uint xflags) | ||
3165 | { | 3326 | { |
3166 | xlog_ticket_t *tic; | 3327 | struct xlog_ticket *tic; |
3167 | uint num_headers; | 3328 | uint num_headers; |
3329 | int iclog_space; | ||
3168 | 3330 | ||
3169 | tic = kmem_zone_zalloc(xfs_log_ticket_zone, KM_SLEEP|KM_MAYFAIL); | 3331 | tic = kmem_zone_zalloc(xfs_log_ticket_zone, KM_SLEEP|KM_MAYFAIL); |
3170 | if (!tic) | 3332 | if (!tic) |
@@ -3208,16 +3370,40 @@ xlog_ticket_alloc(xlog_t *log, | |||
3208 | /* for start-rec */ | 3370 | /* for start-rec */ |
3209 | unit_bytes += sizeof(xlog_op_header_t); | 3371 | unit_bytes += sizeof(xlog_op_header_t); |
3210 | 3372 | ||
3211 | /* for LR headers */ | 3373 | /* |
3212 | num_headers = ((unit_bytes + log->l_iclog_size-1) >> log->l_iclog_size_log); | 3374 | * for LR headers - the space for data in an iclog is the size minus |
3375 | * the space used for the headers. If we use the iclog size, then we | ||
3376 | * undercalculate the number of headers required. | ||
3377 | * | ||
3378 | * Furthermore - the addition of op headers for split-recs might | ||
3379 | * increase the space required enough to require more log and op | ||
3380 | * headers, so take that into account too. | ||
3381 | * | ||
3382 | * IMPORTANT: This reservation makes the assumption that if this | ||
3383 | * transaction is the first in an iclog and hence has the LR headers | ||
3384 | * accounted to it, then the remaining space in the iclog is | ||
3385 | * exclusively for this transaction. i.e. if the transaction is larger | ||
3386 | * than the iclog, it will be the only thing in that iclog. | ||
3387 | * Fundamentally, this means we must pass the entire log vector to | ||
3388 | * xlog_write to guarantee this. | ||
3389 | */ | ||
3390 | iclog_space = log->l_iclog_size - log->l_iclog_hsize; | ||
3391 | num_headers = howmany(unit_bytes, iclog_space); | ||
3392 | |||
3393 | /* for split-recs - ophdrs added when data split over LRs */ | ||
3394 | unit_bytes += sizeof(xlog_op_header_t) * num_headers; | ||
3395 | |||
3396 | /* add extra header reservations if we overrun */ | ||
3397 | while (!num_headers || | ||
3398 | howmany(unit_bytes, iclog_space) > num_headers) { | ||
3399 | unit_bytes += sizeof(xlog_op_header_t); | ||
3400 | num_headers++; | ||
3401 | } | ||
3213 | unit_bytes += log->l_iclog_hsize * num_headers; | 3402 | unit_bytes += log->l_iclog_hsize * num_headers; |
3214 | 3403 | ||
3215 | /* for commit-rec LR header - note: padding will subsume the ophdr */ | 3404 | /* for commit-rec LR header - note: padding will subsume the ophdr */ |
3216 | unit_bytes += log->l_iclog_hsize; | 3405 | unit_bytes += log->l_iclog_hsize; |
3217 | 3406 | ||
3218 | /* for split-recs - ophdrs added when data split over LRs */ | ||
3219 | unit_bytes += sizeof(xlog_op_header_t) * num_headers; | ||
3220 | |||
3221 | /* for roundoff padding for transaction data and one for commit record */ | 3407 | /* for roundoff padding for transaction data and one for commit record */ |
3222 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb) && | 3408 | if (xfs_sb_version_haslogv2(&log->l_mp->m_sb) && |
3223 | log->l_mp->m_sb.sb_logsunit > 1) { | 3409 | log->l_mp->m_sb.sb_logsunit > 1) { |
@@ -3233,13 +3419,13 @@ xlog_ticket_alloc(xlog_t *log, | |||
3233 | tic->t_curr_res = unit_bytes; | 3419 | tic->t_curr_res = unit_bytes; |
3234 | tic->t_cnt = cnt; | 3420 | tic->t_cnt = cnt; |
3235 | tic->t_ocnt = cnt; | 3421 | tic->t_ocnt = cnt; |
3236 | tic->t_tid = (xlog_tid_t)((__psint_t)tic & 0xffffffff); | 3422 | tic->t_tid = random32(); |
3237 | tic->t_clientid = client; | 3423 | tic->t_clientid = client; |
3238 | tic->t_flags = XLOG_TIC_INITED; | 3424 | tic->t_flags = XLOG_TIC_INITED; |
3239 | tic->t_trans_type = 0; | 3425 | tic->t_trans_type = 0; |
3240 | if (xflags & XFS_LOG_PERM_RESERV) | 3426 | if (xflags & XFS_LOG_PERM_RESERV) |
3241 | tic->t_flags |= XLOG_TIC_PERM_RESERV; | 3427 | tic->t_flags |= XLOG_TIC_PERM_RESERV; |
3242 | sv_init(&(tic->t_wait), SV_DEFAULT, "logtick"); | 3428 | sv_init(&tic->t_wait, SV_DEFAULT, "logtick"); |
3243 | 3429 | ||
3244 | xlog_tic_reset_res(tic); | 3430 | xlog_tic_reset_res(tic); |
3245 | 3431 | ||
@@ -3260,20 +3446,22 @@ xlog_ticket_alloc(xlog_t *log, | |||
3260 | * part of the log in case we trash the log structure. | 3446 | * part of the log in case we trash the log structure. |
3261 | */ | 3447 | */ |
3262 | void | 3448 | void |
3263 | xlog_verify_dest_ptr(xlog_t *log, | 3449 | xlog_verify_dest_ptr( |
3264 | __psint_t ptr) | 3450 | struct log *log, |
3451 | char *ptr) | ||
3265 | { | 3452 | { |
3266 | int i; | 3453 | int i; |
3267 | int good_ptr = 0; | 3454 | int good_ptr = 0; |
3268 | 3455 | ||
3269 | for (i=0; i < log->l_iclog_bufs; i++) { | 3456 | for (i = 0; i < log->l_iclog_bufs; i++) { |
3270 | if (ptr >= (__psint_t)log->l_iclog_bak[i] && | 3457 | if (ptr >= log->l_iclog_bak[i] && |
3271 | ptr <= (__psint_t)log->l_iclog_bak[i]+log->l_iclog_size) | 3458 | ptr <= log->l_iclog_bak[i] + log->l_iclog_size) |
3272 | good_ptr++; | 3459 | good_ptr++; |
3273 | } | 3460 | } |
3274 | if (! good_ptr) | 3461 | |
3462 | if (!good_ptr) | ||
3275 | xlog_panic("xlog_verify_dest_ptr: invalid ptr"); | 3463 | xlog_panic("xlog_verify_dest_ptr: invalid ptr"); |
3276 | } /* xlog_verify_dest_ptr */ | 3464 | } |
3277 | 3465 | ||
3278 | STATIC void | 3466 | STATIC void |
3279 | xlog_verify_grant_head(xlog_t *log, int equals) | 3467 | xlog_verify_grant_head(xlog_t *log, int equals) |