aboutsummaryrefslogtreecommitdiffstats
path: root/fs/xfs/xfs_btree.c
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2008-10-30 01:56:32 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 01:56:32 -0400
commit278d0ca14e889c3932a05d1a68675252a12b3466 (patch)
treea228d171d4aded60b27639e30eca1bf58ed7daa6 /fs/xfs/xfs_btree.c
parent38bb74237d2d94c1aced2ec626d7d0f317e360da (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_btree.c')
-rw-r--r--fs/xfs/xfs_btree.c121
1 files changed, 121 insertions, 0 deletions
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 1459a2b9a729..205272f282d9 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -988,6 +988,30 @@ xfs_btree_get_sibling(
988 } 988 }
989} 989}
990 990
991/*
992 * Return true if ptr is the last record in the btree and
993 * we need to track updateѕ to this record. The decision
994 * will be further refined in the update_lastrec method.
995 */
996STATIC int
997xfs_btree_is_lastrec(
998 struct xfs_btree_cur *cur,
999 struct xfs_btree_block *block,
1000 int level)
1001{
1002 union xfs_btree_ptr ptr;
1003
1004 if (level > 0)
1005 return 0;
1006 if (!(cur->bc_flags & XFS_BTREE_LASTREC_UPDATE))
1007 return 0;
1008
1009 xfs_btree_get_sibling(cur, block, &ptr, XFS_BB_RIGHTSIB);
1010 if (!xfs_btree_ptr_is_null(cur, &ptr))
1011 return 0;
1012 return 1;
1013}
1014
991STATIC xfs_daddr_t 1015STATIC xfs_daddr_t
992xfs_btree_ptr_to_daddr( 1016xfs_btree_ptr_to_daddr(
993 struct xfs_btree_cur *cur, 1017 struct xfs_btree_cur *cur,
@@ -1080,6 +1104,20 @@ xfs_btree_copy_keys(
1080} 1104}
1081 1105
1082/* 1106/*
1107 * Copy records from one btree block to another.
1108 */
1109STATIC void
1110xfs_btree_copy_recs(
1111 struct xfs_btree_cur *cur,
1112 union xfs_btree_rec *dst_rec,
1113 union xfs_btree_rec *src_rec,
1114 int numrecs)
1115{
1116 ASSERT(numrecs >= 0);
1117 memcpy(dst_rec, src_rec, numrecs * cur->bc_ops->rec_len);
1118}
1119
1120/*
1083 * Log key values from the btree block. 1121 * Log key values from the btree block.
1084 */ 1122 */
1085STATIC void 1123STATIC void
@@ -1105,6 +1143,26 @@ xfs_btree_log_keys(
1105} 1143}
1106 1144
1107/* 1145/*
1146 * Log record values from the btree block.
1147 */
1148STATIC void
1149xfs_btree_log_recs(
1150 struct xfs_btree_cur *cur,
1151 struct xfs_buf *bp,
1152 int first,
1153 int last)
1154{
1155 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1156 XFS_BTREE_TRACE_ARGBII(cur, bp, first, last);
1157
1158 xfs_trans_log_buf(cur->bc_tp, bp,
1159 xfs_btree_rec_offset(cur, first),
1160 xfs_btree_rec_offset(cur, last + 1) - 1);
1161
1162 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1163}
1164
1165/*
1108 * Increment cursor by one record at the level. 1166 * Increment cursor by one record at the level.
1109 * For nonzero levels the leaf-ward information is untouched. 1167 * For nonzero levels the leaf-ward information is untouched.
1110 */ 1168 */
@@ -1576,3 +1634,66 @@ xfs_btree_updkey(
1576 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT); 1634 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1577 return 0; 1635 return 0;
1578} 1636}
1637
1638/*
1639 * Update the record referred to by cur to the value in the
1640 * given record. This either works (return 0) or gets an
1641 * EFSCORRUPTED error.
1642 */
1643int
1644xfs_btree_update(
1645 struct xfs_btree_cur *cur,
1646 union xfs_btree_rec *rec)
1647{
1648 struct xfs_btree_block *block;
1649 struct xfs_buf *bp;
1650 int error;
1651 int ptr;
1652 union xfs_btree_rec *rp;
1653
1654 XFS_BTREE_TRACE_CURSOR(cur, XBT_ENTRY);
1655 XFS_BTREE_TRACE_ARGR(cur, rec);
1656
1657 /* Pick up the current block. */
1658 block = xfs_btree_get_block(cur, 0, &bp);
1659
1660#ifdef DEBUG
1661 error = xfs_btree_check_block(cur, block, 0, bp);
1662 if (error)
1663 goto error0;
1664#endif
1665 /* Get the address of the rec to be updated. */
1666 ptr = cur->bc_ptrs[0];
1667 rp = xfs_btree_rec_addr(cur, ptr, block);
1668
1669 /* Fill in the new contents and log them. */
1670 xfs_btree_copy_recs(cur, rp, rec, 1);
1671 xfs_btree_log_recs(cur, bp, ptr, ptr);
1672
1673 /*
1674 * If we are tracking the last record in the tree and
1675 * we are at the far right edge of the tree, update it.
1676 */
1677 if (xfs_btree_is_lastrec(cur, block, 0)) {
1678 cur->bc_ops->update_lastrec(cur, block, rec,
1679 ptr, LASTREC_UPDATE);
1680 }
1681
1682 /* Updating first rec in leaf. Pass new key value up to our parent. */
1683 if (ptr == 1) {
1684 union xfs_btree_key key;
1685
1686 cur->bc_ops->init_key_from_rec(&key, rec);
1687 error = xfs_btree_updkey(cur, &key, 1);
1688 if (error)
1689 goto error0;
1690 }
1691
1692 XFS_BTREE_TRACE_CURSOR(cur, XBT_EXIT);
1693 return 0;
1694
1695error0:
1696 XFS_BTREE_TRACE_CURSOR(cur, XBT_ERROR);
1697 return error;
1698}
1699