aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2010-12-01 17:06:22 -0500
committerAlex Elder <aelder@sgi.com>2010-12-16 17:05:22 -0500
commitd5689eaa0ac5588cf459ee32f86d5700dd7d6403 (patch)
tree2d637bc35de7f95d10c5c1fc17f57bc7adfb1e41 /fs/xfs
parente2714bf8d5c8e131a6df6b0ea2269433e9a03a9b (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.h11
-rw-r--r--fs/xfs/xfs_log_priv.h6
-rw-r--r--fs/xfs/xfs_log_recover.c159
3 files changed, 65 insertions, 111 deletions
diff --git a/fs/xfs/xfs_buf_item.h b/fs/xfs/xfs_buf_item.h
index 0e2ed43f16c..b6ecd2061e7 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 */
112typedef 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
119void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *); 108void xfs_buf_item_init(struct xfs_buf *, struct xfs_mount *);
120void xfs_buf_item_relse(struct xfs_buf *); 109void xfs_buf_item_relse(struct xfs_buf *);
121void xfs_buf_item_log(xfs_buf_log_item_t *, uint, uint); 110void 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 edcdfe01617..c1ce505313e 100644
--- a/fs/xfs/xfs_log_priv.h
+++ b/fs/xfs/xfs_log_priv.h
@@ -21,7 +21,6 @@
21struct xfs_buf; 21struct xfs_buf;
22struct log; 22struct log;
23struct xlog_ticket; 23struct xlog_ticket;
24struct xfs_buf_cancel;
25struct xfs_mount; 24struct 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 e51d93db1b0..960afd41315 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 */
59struct 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 */
1608STATIC void 1619STATIC void
1609xlog_recover_do_buffer_pass1( 1620xlog_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 */
1690STATIC int 1671STATIC int
1691xlog_check_buffer_cancelled( 1672xlog_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
1706found:
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