diff options
author | Christoph Hellwig <hch@infradead.org> | 2008-10-30 01:56:32 -0400 |
---|---|---|
committer | Lachlan McIlroy <lachlan@sgi.com> | 2008-10-30 01:56:32 -0400 |
commit | 278d0ca14e889c3932a05d1a68675252a12b3466 (patch) | |
tree | a228d171d4aded60b27639e30eca1bf58ed7daa6 /fs/xfs/xfs_alloc_btree.c | |
parent | 38bb74237d2d94c1aced2ec626d7d0f317e360da (diff) |
[XFS] implement generic xfs_btree_update
From: Dave Chinner <dgc@sgi.com>
The most complicated part here is the lastrec tracking for the alloc
btree. Most logic is in the update_lastrec method which has to do some
hopefully good enough dirty magic to maintain it.
[hch: split out from bigger patch and a rework of the lastrec
logic]
SGI-PV: 985583
SGI-Modid: xfs-linux-melb:xfs-kern:32194a
Signed-off-by: Christoph Hellwig <hch@infradead.org>
Signed-off-by: Lachlan McIlroy <lachlan@sgi.com>
Signed-off-by: Bill O'Donnell <billodo@sgi.com>
Signed-off-by: David Chinner <david@fromorbit.com>
Diffstat (limited to 'fs/xfs/xfs_alloc_btree.c')
-rw-r--r-- | fs/xfs/xfs_alloc_btree.c | 106 |
1 files changed, 38 insertions, 68 deletions
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c index 28c6a698f562..c5c32999b810 100644 --- a/fs/xfs/xfs_alloc_btree.c +++ b/fs/xfs/xfs_alloc_btree.c | |||
@@ -1661,83 +1661,50 @@ xfs_alloc_insert( | |||
1661 | return 0; | 1661 | return 0; |
1662 | } | 1662 | } |
1663 | 1663 | ||
1664 | STATIC struct xfs_btree_cur * | ||
1665 | xfs_allocbt_dup_cursor( | ||
1666 | struct xfs_btree_cur *cur) | ||
1667 | { | ||
1668 | return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, | ||
1669 | cur->bc_private.a.agbp, cur->bc_private.a.agno, | ||
1670 | cur->bc_btnum); | ||
1671 | } | ||
1672 | |||
1664 | /* | 1673 | /* |
1665 | * Update the record referred to by cur, to the value given by [bno, len]. | 1674 | * Update the longest extent in the AGF |
1666 | * This either works (return 0) or gets an EFSCORRUPTED error. | ||
1667 | */ | 1675 | */ |
1668 | int /* error */ | 1676 | STATIC void |
1669 | xfs_alloc_update( | 1677 | xfs_allocbt_update_lastrec( |
1670 | xfs_btree_cur_t *cur, /* btree cursor */ | 1678 | struct xfs_btree_cur *cur, |
1671 | xfs_agblock_t bno, /* starting block of extent */ | 1679 | struct xfs_btree_block *block, |
1672 | xfs_extlen_t len) /* length of extent */ | 1680 | union xfs_btree_rec *rec, |
1681 | int ptr, | ||
1682 | int reason) | ||
1673 | { | 1683 | { |
1674 | xfs_alloc_block_t *block; /* btree block to update */ | 1684 | struct xfs_agf *agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); |
1675 | int error; /* error return value */ | 1685 | xfs_agnumber_t seqno = be32_to_cpu(agf->agf_seqno); |
1676 | int ptr; /* current record number (updating) */ | 1686 | __be32 len; |
1677 | 1687 | ||
1678 | ASSERT(len > 0); | 1688 | ASSERT(cur->bc_btnum == XFS_BTNUM_CNT); |
1679 | /* | ||
1680 | * Pick up the a.g. freelist struct and the current block. | ||
1681 | */ | ||
1682 | block = XFS_BUF_TO_ALLOC_BLOCK(cur->bc_bufs[0]); | ||
1683 | #ifdef DEBUG | ||
1684 | if ((error = xfs_btree_check_sblock(cur, block, 0, cur->bc_bufs[0]))) | ||
1685 | return error; | ||
1686 | #endif | ||
1687 | /* | ||
1688 | * Get the address of the rec to be updated. | ||
1689 | */ | ||
1690 | ptr = cur->bc_ptrs[0]; | ||
1691 | { | ||
1692 | xfs_alloc_rec_t *rp; /* pointer to updated record */ | ||
1693 | 1689 | ||
1694 | rp = XFS_ALLOC_REC_ADDR(block, ptr, cur); | 1690 | switch (reason) { |
1691 | case LASTREC_UPDATE: | ||
1695 | /* | 1692 | /* |
1696 | * Fill in the new contents and log them. | 1693 | * If this is the last leaf block and it's the last record, |
1694 | * then update the size of the longest extent in the AG. | ||
1697 | */ | 1695 | */ |
1698 | rp->ar_startblock = cpu_to_be32(bno); | 1696 | if (ptr != xfs_btree_get_numrecs(block)) |
1699 | rp->ar_blockcount = cpu_to_be32(len); | 1697 | return; |
1700 | xfs_alloc_log_recs(cur, cur->bc_bufs[0], ptr, ptr); | 1698 | len = rec->alloc.ar_blockcount; |
1701 | } | 1699 | break; |
1702 | /* | 1700 | default: |
1703 | * If it's the by-size btree and it's the last leaf block and | 1701 | ASSERT(0); |
1704 | * it's the last record... then update the size of the longest | 1702 | return; |
1705 | * extent in the a.g., which we cache in the a.g. freelist header. | ||
1706 | */ | ||
1707 | if (cur->bc_btnum == XFS_BTNUM_CNT && | ||
1708 | be32_to_cpu(block->bb_rightsib) == NULLAGBLOCK && | ||
1709 | ptr == be16_to_cpu(block->bb_numrecs)) { | ||
1710 | xfs_agf_t *agf; /* a.g. freespace header */ | ||
1711 | xfs_agnumber_t seqno; | ||
1712 | |||
1713 | agf = XFS_BUF_TO_AGF(cur->bc_private.a.agbp); | ||
1714 | seqno = be32_to_cpu(agf->agf_seqno); | ||
1715 | cur->bc_mp->m_perag[seqno].pagf_longest = len; | ||
1716 | agf->agf_longest = cpu_to_be32(len); | ||
1717 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, | ||
1718 | XFS_AGF_LONGEST); | ||
1719 | } | ||
1720 | /* | ||
1721 | * Updating first record in leaf. Pass new key value up to our parent. | ||
1722 | */ | ||
1723 | if (ptr == 1) { | ||
1724 | xfs_alloc_key_t key; /* key containing [bno, len] */ | ||
1725 | |||
1726 | key.ar_startblock = cpu_to_be32(bno); | ||
1727 | key.ar_blockcount = cpu_to_be32(len); | ||
1728 | if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, 1))) | ||
1729 | return error; | ||
1730 | } | 1703 | } |
1731 | return 0; | ||
1732 | } | ||
1733 | 1704 | ||
1734 | STATIC struct xfs_btree_cur * | 1705 | agf->agf_longest = len; |
1735 | xfs_allocbt_dup_cursor( | 1706 | cur->bc_mp->m_perag[seqno].pagf_longest = be32_to_cpu(len); |
1736 | struct xfs_btree_cur *cur) | 1707 | xfs_alloc_log_agf(cur->bc_tp, cur->bc_private.a.agbp, XFS_AGF_LONGEST); |
1737 | { | ||
1738 | return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp, | ||
1739 | cur->bc_private.a.agbp, cur->bc_private.a.agno, | ||
1740 | cur->bc_btnum); | ||
1741 | } | 1708 | } |
1742 | 1709 | ||
1743 | STATIC int | 1710 | STATIC int |
@@ -1864,6 +1831,7 @@ static const struct xfs_btree_ops xfs_allocbt_ops = { | |||
1864 | .key_len = sizeof(xfs_alloc_key_t), | 1831 | .key_len = sizeof(xfs_alloc_key_t), |
1865 | 1832 | ||
1866 | .dup_cursor = xfs_allocbt_dup_cursor, | 1833 | .dup_cursor = xfs_allocbt_dup_cursor, |
1834 | .update_lastrec = xfs_allocbt_update_lastrec, | ||
1867 | .get_maxrecs = xfs_allocbt_get_maxrecs, | 1835 | .get_maxrecs = xfs_allocbt_get_maxrecs, |
1868 | .init_key_from_rec = xfs_allocbt_init_key_from_rec, | 1836 | .init_key_from_rec = xfs_allocbt_init_key_from_rec, |
1869 | .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, | 1837 | .init_ptr_from_cur = xfs_allocbt_init_ptr_from_cur, |
@@ -1902,6 +1870,8 @@ xfs_allocbt_init_cursor( | |||
1902 | cur->bc_blocklog = mp->m_sb.sb_blocklog; | 1870 | cur->bc_blocklog = mp->m_sb.sb_blocklog; |
1903 | 1871 | ||
1904 | cur->bc_ops = &xfs_allocbt_ops; | 1872 | cur->bc_ops = &xfs_allocbt_ops; |
1873 | if (btnum == XFS_BTNUM_CNT) | ||
1874 | cur->bc_flags = XFS_BTREE_LASTREC_UPDATE; | ||
1905 | 1875 | ||
1906 | cur->bc_private.a.agbp = agbp; | 1876 | cur->bc_private.a.agbp = agbp; |
1907 | cur->bc_private.a.agno = agno; | 1877 | cur->bc_private.a.agno = agno; |