diff options
author | Christoph Hellwig <hch@infradead.org> | 2010-12-01 17:06:22 -0500 |
---|---|---|
committer | Alex Elder <aelder@sgi.com> | 2010-12-16 17:05:22 -0500 |
commit | d5689eaa0ac5588cf459ee32f86d5700dd7d6403 (patch) | |
tree | 2d637bc35de7f95d10c5c1fc17f57bc7adfb1e41 /fs/xfs | |
parent | e2714bf8d5c8e131a6df6b0ea2269433e9a03a9b (diff) |
xfs: use struct list_head for the buf cancel table
Signed-off-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Alex Elder <aelder@sgi.com>
Diffstat (limited to 'fs/xfs')
-rw-r--r-- | fs/xfs/xfs_buf_item.h | 11 | ||||
-rw-r--r-- | fs/xfs/xfs_log_priv.h | 6 | ||||
-rw-r--r-- | fs/xfs/xfs_log_recover.c | 159 |
3 files changed, 65 insertions, 111 deletions
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h index 0e2ed43f16c7..b6ecd2061e7c 100644 --- a/fs/xfs/xfs_buf_item.h +++ b/fs/xfs/xfs_buf_item.h | |||
@@ -105,17 +105,6 @@ typedef struct xfs_buf_log_item { | |||
105 | xfs_buf_log_format_t bli_format; /* in-log header */ | 105 | xfs_buf_log_format_t bli_format; /* in-log header */ |
106 | } xfs_buf_log_item_t; | 106 | } xfs_buf_log_item_t; |
107 | 107 | ||
108 | /* | ||
109 | * This structure is used during recovery to record the buf log | ||
110 | * items which have been canceled and should not be replayed. | ||
111 | */ | ||
112 | typedef struct xfs_buf_cancel { | ||
113 | xfs_daddr_t bc_blkno; | ||
114 | uint bc_len; | ||
115 | int bc_refcount; | ||
116 | struct xfs_buf_cancel *bc_next; | ||
117 | } xfs_buf_cancel_t; | ||
118 | |||
119 | void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); | 108 | void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); |
120 | void xfs_buf_item_relse(struct xfs_buf *); | 109 | void xfs_buf_item_relse(struct xfs_buf *); |
121 | void xfs_buf_item_log(xfs_buf_log_item_t *, uint, uint); | 110 | void xfs_buf_item_log(xfs_buf_log_item_t *, uint, uint); |
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index edcdfe01617f..c1ce505313e9 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
@@ -21,7 +21,6 @@ | |||
21 | struct xfs_buf; | 21 | struct xfs_buf; |
22 | struct log; | 22 | struct log; |
23 | struct xlog_ticket; | 23 | struct xlog_ticket; |
24 | struct xfs_buf_cancel; | ||
25 | struct xfs_mount; | 24 | struct xfs_mount; |
26 | 25 | ||
27 | /* | 26 | /* |
@@ -491,7 +490,7 @@ typedef struct log { | |||
491 | struct xfs_buftarg *l_targ; /* buftarg of log */ | 490 | struct xfs_buftarg *l_targ; /* buftarg of log */ |
492 | uint l_flags; | 491 | uint l_flags; |
493 | uint l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */ | 492 | uint l_quotaoffs_flag; /* XFS_DQ_*, for QUOTAOFFs */ |
494 | struct xfs_buf_cancel **l_buf_cancel_table; | 493 | struct list_head *l_buf_cancel_table; |
495 | int l_iclog_hsize; /* size of iclog header */ | 494 | int l_iclog_hsize; /* size of iclog header */ |
496 | int l_iclog_heads; /* # of iclog header sectors */ | 495 | int l_iclog_heads; /* # of iclog header sectors */ |
497 | uint l_sectBBsize; /* sector size in BBs (2^n) */ | 496 | uint l_sectBBsize; /* sector size in BBs (2^n) */ |
@@ -534,6 +533,9 @@ typedef struct log { | |||
534 | 533 | ||
535 | } xlog_t; | 534 | } xlog_t; |
536 | 535 | ||
536 | #define XLOG_BUF_CANCEL_BUCKET(log, blkno) \ | ||
537 | ((log)->l_buf_cancel_table + ((__uint64_t)blkno % XLOG_BC_TABLE_SIZE)) | ||
538 | |||
537 | #define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR) | 539 | #define XLOG_FORCED_SHUTDOWN(log) ((log)->l_flags & XLOG_IO_ERROR) |
538 | 540 | ||
539 | /* common routines */ | 541 | /* common routines */ |
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index e51d93db1b0b..960afd41315e 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -53,6 +53,17 @@ STATIC void xlog_recover_check_summary(xlog_t *); | |||
53 | #endif | 53 | #endif |
54 | 54 | ||
55 | /* | 55 | /* |
56 | * This structure is used during recovery to record the buf log items which | ||
57 | * have been canceled and should not be replayed. | ||
58 | */ | ||
59 | struct xfs_buf_cancel { | ||
60 | xfs_daddr_t bc_blkno; | ||
61 | uint bc_len; | ||
62 | int bc_refcount; | ||
63 | struct list_head bc_list; | ||
64 | }; | ||
65 | |||
66 | /* | ||
56 | * Sector aligned buffer routines for buffer create/read/write/access | 67 | * Sector aligned buffer routines for buffer create/read/write/access |
57 | */ | 68 | */ |
58 | 69 | ||
@@ -1607,15 +1618,11 @@ xlog_recover_reorder_trans( | |||
1607 | */ | 1618 | */ |
1608 | STATIC void | 1619 | STATIC void |
1609 | xlog_recover_do_buffer_pass1( | 1620 | xlog_recover_do_buffer_pass1( |
1610 | xlog_t *log, | 1621 | struct log *log, |
1611 | xfs_buf_log_format_t *buf_f) | 1622 | xfs_buf_log_format_t *buf_f) |
1612 | { | 1623 | { |
1613 | xfs_buf_cancel_t *bcp; | 1624 | struct list_head *bucket; |
1614 | xfs_buf_cancel_t *nextp; | 1625 | struct xfs_buf_cancel *bcp; |
1615 | xfs_buf_cancel_t *prevp; | ||
1616 | xfs_buf_cancel_t **bucket; | ||
1617 | xfs_daddr_t blkno = buf_f->blf_blkno; | ||
1618 | uint len = buf_f->blf_len; | ||
1619 | 1626 | ||
1620 | /* | 1627 | /* |
1621 | * If this isn't a cancel buffer item, then just return. | 1628 | * If this isn't a cancel buffer item, then just return. |
@@ -1626,51 +1633,25 @@ xlog_recover_do_buffer_pass1( | |||
1626 | } | 1633 | } |
1627 | 1634 | ||
1628 | /* | 1635 | /* |
1629 | * Insert an xfs_buf_cancel record into the hash table of | 1636 | * Insert an xfs_buf_cancel record into the hash table of them. |
1630 | * them. If there is already an identical record, bump | 1637 | * If there is already an identical record, bump its reference count. |
1631 | * its reference count. | ||
1632 | */ | ||
1633 | bucket = &log->l_buf_cancel_table[(__uint64_t)blkno % | ||
1634 | XLOG_BC_TABLE_SIZE]; | ||
1635 | /* | ||
1636 | * If the hash bucket is empty then just insert a new record into | ||
1637 | * the bucket. | ||
1638 | */ | ||
1639 | if (*bucket == NULL) { | ||
1640 | bcp = (xfs_buf_cancel_t *)kmem_alloc(sizeof(xfs_buf_cancel_t), | ||
1641 | KM_SLEEP); | ||
1642 | bcp->bc_blkno = blkno; | ||
1643 | bcp->bc_len = len; | ||
1644 | bcp->bc_refcount = 1; | ||
1645 | bcp->bc_next = NULL; | ||
1646 | *bucket = bcp; | ||
1647 | return; | ||
1648 | } | ||
1649 | |||
1650 | /* | ||
1651 | * The hash bucket is not empty, so search for duplicates of our | ||
1652 | * record. If we find one them just bump its refcount. If not | ||
1653 | * then add us at the end of the list. | ||
1654 | */ | 1638 | */ |
1655 | prevp = NULL; | 1639 | bucket = XLOG_BUF_CANCEL_BUCKET(log, buf_f->blf_blkno); |
1656 | nextp = *bucket; | 1640 | list_for_each_entry(bcp, bucket, bc_list) { |
1657 | while (nextp != NULL) { | 1641 | if (bcp->bc_blkno == buf_f->blf_blkno && |
1658 | if (nextp->bc_blkno == blkno && nextp->bc_len == len) { | 1642 | bcp->bc_len == buf_f->blf_len) { |
1659 | nextp->bc_refcount++; | 1643 | bcp->bc_refcount++; |
1660 | trace_xfs_log_recover_buf_cancel_ref_inc(log, buf_f); | 1644 | trace_xfs_log_recover_buf_cancel_ref_inc(log, buf_f); |
1661 | return; | 1645 | return; |
1662 | } | 1646 | } |
1663 | prevp = nextp; | 1647 | } |
1664 | nextp = nextp->bc_next; | 1648 | |
1665 | } | 1649 | bcp = kmem_alloc(sizeof(struct xfs_buf_cancel), KM_SLEEP); |
1666 | ASSERT(prevp != NULL); | 1650 | bcp->bc_blkno = buf_f->blf_blkno; |
1667 | bcp = (xfs_buf_cancel_t *)kmem_alloc(sizeof(xfs_buf_cancel_t), | 1651 | bcp->bc_len = buf_f->blf_len; |
1668 | KM_SLEEP); | ||
1669 | bcp->bc_blkno = blkno; | ||
1670 | bcp->bc_len = len; | ||
1671 | bcp->bc_refcount = 1; | 1652 | bcp->bc_refcount = 1; |
1672 | bcp->bc_next = NULL; | 1653 | list_add_tail(&bcp->bc_list, bucket); |
1673 | prevp->bc_next = bcp; | 1654 | |
1674 | trace_xfs_log_recover_buf_cancel_add(log, buf_f); | 1655 | trace_xfs_log_recover_buf_cancel_add(log, buf_f); |
1675 | } | 1656 | } |
1676 | 1657 | ||
@@ -1689,14 +1670,13 @@ xlog_recover_do_buffer_pass1( | |||
1689 | */ | 1670 | */ |
1690 | STATIC int | 1671 | STATIC int |
1691 | xlog_check_buffer_cancelled( | 1672 | xlog_check_buffer_cancelled( |
1692 | xlog_t *log, | 1673 | struct log *log, |
1693 | xfs_daddr_t blkno, | 1674 | xfs_daddr_t blkno, |
1694 | uint len, | 1675 | uint len, |
1695 | ushort flags) | 1676 | ushort flags) |
1696 | { | 1677 | { |
1697 | xfs_buf_cancel_t *bcp; | 1678 | struct list_head *bucket; |
1698 | xfs_buf_cancel_t *prevp; | 1679 | struct xfs_buf_cancel *bcp; |
1699 | xfs_buf_cancel_t **bucket; | ||
1700 | 1680 | ||
1701 | if (log->l_buf_cancel_table == NULL) { | 1681 | if (log->l_buf_cancel_table == NULL) { |
1702 | /* | 1682 | /* |
@@ -1707,55 +1687,36 @@ xlog_check_buffer_cancelled( | |||
1707 | return 0; | 1687 | return 0; |
1708 | } | 1688 | } |
1709 | 1689 | ||
1710 | bucket = &log->l_buf_cancel_table[(__uint64_t)blkno % | ||
1711 | XLOG_BC_TABLE_SIZE]; | ||
1712 | bcp = *bucket; | ||
1713 | if (bcp == NULL) { | ||
1714 | /* | ||
1715 | * There is no corresponding entry in the table built | ||
1716 | * in pass one, so this buffer has not been cancelled. | ||
1717 | */ | ||
1718 | ASSERT(!(flags & XFS_BLF_CANCEL)); | ||
1719 | return 0; | ||
1720 | } | ||
1721 | |||
1722 | /* | 1690 | /* |
1723 | * Search for an entry in the buffer cancel table that | 1691 | * Search for an entry in the cancel table that matches our buffer. |
1724 | * matches our buffer. | ||
1725 | */ | 1692 | */ |
1726 | prevp = NULL; | 1693 | bucket = XLOG_BUF_CANCEL_BUCKET(log, blkno); |
1727 | while (bcp != NULL) { | 1694 | list_for_each_entry(bcp, bucket, bc_list) { |
1728 | if (bcp->bc_blkno == blkno && bcp->bc_len == len) { | 1695 | if (bcp->bc_blkno == blkno && bcp->bc_len == len) |
1729 | /* | 1696 | goto found; |
1730 | * We've go a match, so return 1 so that the | ||
1731 | * recovery of this buffer is cancelled. | ||
1732 | * If this buffer is actually a buffer cancel | ||
1733 | * log item, then decrement the refcount on the | ||
1734 | * one in the table and remove it if this is the | ||
1735 | * last reference. | ||
1736 | */ | ||
1737 | if (flags & XFS_BLF_CANCEL) { | ||
1738 | bcp->bc_refcount--; | ||
1739 | if (bcp->bc_refcount == 0) { | ||
1740 | if (prevp == NULL) { | ||
1741 | *bucket = bcp->bc_next; | ||
1742 | } else { | ||
1743 | prevp->bc_next = bcp->bc_next; | ||
1744 | } | ||
1745 | kmem_free(bcp); | ||
1746 | } | ||
1747 | } | ||
1748 | return 1; | ||
1749 | } | ||
1750 | prevp = bcp; | ||
1751 | bcp = bcp->bc_next; | ||
1752 | } | 1697 | } |
1698 | |||
1753 | /* | 1699 | /* |
1754 | * We didn't find a corresponding entry in the table, so | 1700 | * We didn't find a corresponding entry in the table, so return 0 so |
1755 | * return 0 so that the buffer is NOT cancelled. | 1701 | * that the buffer is NOT cancelled. |
1756 | */ | 1702 | */ |
1757 | ASSERT(!(flags & XFS_BLF_CANCEL)); | 1703 | ASSERT(!(flags & XFS_BLF_CANCEL)); |
1758 | return 0; | 1704 | return 0; |
1705 | |||
1706 | found: | ||
1707 | /* | ||
1708 | * We've go a match, so return 1 so that the recovery of this buffer | ||
1709 | * is cancelled. If this buffer is actually a buffer cancel log | ||
1710 | * item, then decrement the refcount on the one in the table and | ||
1711 | * remove it if this is the last reference. | ||
1712 | */ | ||
1713 | if (flags & XFS_BLF_CANCEL) { | ||
1714 | if (--bcp->bc_refcount == 0) { | ||
1715 | list_del(&bcp->bc_list); | ||
1716 | kmem_free(bcp); | ||
1717 | } | ||
1718 | } | ||
1719 | return 1; | ||
1759 | } | 1720 | } |
1760 | 1721 | ||
1761 | /* | 1722 | /* |
@@ -3649,7 +3610,7 @@ xlog_do_log_recovery( | |||
3649 | xfs_daddr_t head_blk, | 3610 | xfs_daddr_t head_blk, |
3650 | xfs_daddr_t tail_blk) | 3611 | xfs_daddr_t tail_blk) |
3651 | { | 3612 | { |
3652 | int error; | 3613 | int error, i; |
3653 | 3614 | ||
3654 | ASSERT(head_blk != tail_blk); | 3615 | ASSERT(head_blk != tail_blk); |
3655 | 3616 | ||
@@ -3657,10 +3618,12 @@ xlog_do_log_recovery( | |||
3657 | * First do a pass to find all of the cancelled buf log items. | 3618 | * First do a pass to find all of the cancelled buf log items. |
3658 | * Store them in the buf_cancel_table for use in the second pass. | 3619 | * Store them in the buf_cancel_table for use in the second pass. |
3659 | */ | 3620 | */ |
3660 | log->l_buf_cancel_table = | 3621 | log->l_buf_cancel_table = kmem_zalloc(XLOG_BC_TABLE_SIZE * |
3661 | (xfs_buf_cancel_t **)kmem_zalloc(XLOG_BC_TABLE_SIZE * | 3622 | sizeof(struct list_head), |
3662 | sizeof(xfs_buf_cancel_t*), | ||
3663 | KM_SLEEP); | 3623 | KM_SLEEP); |
3624 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) | ||
3625 | INIT_LIST_HEAD(&log->l_buf_cancel_table[i]); | ||
3626 | |||
3664 | error = xlog_do_recovery_pass(log, head_blk, tail_blk, | 3627 | error = xlog_do_recovery_pass(log, head_blk, tail_blk, |
3665 | XLOG_RECOVER_PASS1); | 3628 | XLOG_RECOVER_PASS1); |
3666 | if (error != 0) { | 3629 | if (error != 0) { |
@@ -3679,7 +3642,7 @@ xlog_do_log_recovery( | |||
3679 | int i; | 3642 | int i; |
3680 | 3643 | ||
3681 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) | 3644 | for (i = 0; i < XLOG_BC_TABLE_SIZE; i++) |
3682 | ASSERT(log->l_buf_cancel_table[i] == NULL); | 3645 | ASSERT(list_empty(&log->l_buf_cancel_table[i])); |
3683 | } | 3646 | } |
3684 | #endif /* DEBUG */ | 3647 | #endif /* DEBUG */ |
3685 | 3648 | ||