aboutsummaryrefslogtreecommitdiffstats
path: root/fs
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
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')
-rw-r--r--fs/xfs/xfs_alloc.c17
-rw-r--r--fs/xfs/xfs_alloc_btree.c106
-rw-r--r--fs/xfs/xfs_alloc_btree.h7
-rw-r--r--fs/xfs/xfs_bmap.c18
-rw-r--r--fs/xfs/xfs_bmap_btree.c45
-rw-r--r--fs/xfs/xfs_bmap_btree.h2
-rw-r--r--fs/xfs/xfs_btree.c121
-rw-r--r--fs/xfs/xfs_btree.h14
-rw-r--r--fs/xfs/xfs_ialloc.c20
-rw-r--r--fs/xfs/xfs_ialloc_btree.c52
-rw-r--r--fs/xfs/xfs_ialloc_btree.h8
11 files changed, 228 insertions, 182 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 6bda0ae26c2a..875e1bae1941 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -136,6 +136,23 @@ xfs_alloc_lookup_le(
136 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat); 136 return xfs_btree_lookup(cur, XFS_LOOKUP_LE, stat);
137} 137}
138 138
139/*
140 * Update the record referred to by cur to the value given
141 * by [bno, len].
142 * This either works (return 0) or gets an EFSCORRUPTED error.
143 */
144STATIC int /* error */
145xfs_alloc_update(
146 struct xfs_btree_cur *cur, /* btree cursor */
147 xfs_agblock_t bno, /* starting block of extent */
148 xfs_extlen_t len) /* length of extent */
149{
150 union xfs_btree_rec rec;
151
152 rec.alloc.ar_startblock = cpu_to_be32(bno);
153 rec.alloc.ar_blockcount = cpu_to_be32(len);
154 return xfs_btree_update(cur, &rec);
155}
139 156
140/* 157/*
141 * Compute aligned version of the found extent. 158 * Compute aligned version of the found extent.
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
1664STATIC struct xfs_btree_cur *
1665xfs_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 */
1668int /* error */ 1676STATIC void
1669xfs_alloc_update( 1677xfs_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
1734STATIC struct xfs_btree_cur * 1705 agf->agf_longest = len;
1735xfs_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
1743STATIC int 1710STATIC 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;
diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h
index aa110ff4feb1..81e2f3607819 100644
--- a/fs/xfs/xfs_alloc_btree.h
+++ b/fs/xfs/xfs_alloc_btree.h
@@ -113,13 +113,6 @@ extern int xfs_alloc_get_rec(struct xfs_btree_cur *cur, xfs_agblock_t *bno,
113 */ 113 */
114extern int xfs_alloc_insert(struct xfs_btree_cur *cur, int *stat); 114extern int xfs_alloc_insert(struct xfs_btree_cur *cur, int *stat);
115 115
116/*
117 * Update the record referred to by cur, to the value given by [bno, len].
118 * This either works (return 0) or gets an EFSCORRUPTED error.
119 */
120extern int xfs_alloc_update(struct xfs_btree_cur *cur, xfs_agblock_t bno,
121 xfs_extlen_t len);
122
123 116
124extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *, 117extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
125 struct xfs_trans *, struct xfs_buf *, 118 struct xfs_trans *, struct xfs_buf *,
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index 1296b4102e97..7d6c4ace8052 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -430,6 +430,24 @@ xfs_bmbt_lookup_ge(
430 return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat); 430 return xfs_btree_lookup(cur, XFS_LOOKUP_GE, stat);
431} 431}
432 432
433/*
434* Update the record referred to by cur to the value given
435 * by [off, bno, len, state].
436 * This either works (return 0) or gets an EFSCORRUPTED error.
437 */
438STATIC int
439xfs_bmbt_update(
440 struct xfs_btree_cur *cur,
441 xfs_fileoff_t off,
442 xfs_fsblock_t bno,
443 xfs_filblks_t len,
444 xfs_exntst_t state)
445{
446 union xfs_btree_rec rec;
447
448 xfs_bmbt_disk_set_allf(&rec.bmbt, off, bno, len, state);
449 return xfs_btree_update(cur, &rec);
450}
433 451
434/* 452/*
435 * Called from xfs_bmap_add_attrfork to handle btree format files. 453 * Called from xfs_bmap_add_attrfork to handle btree format files.
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 0a56257b7fd5..99200a9898f7 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -1964,51 +1964,6 @@ xfs_bmbt_to_bmdr(
1964} 1964}
1965 1965
1966/* 1966/*
1967 * Update the record to the passed values.
1968 */
1969int
1970xfs_bmbt_update(
1971 xfs_btree_cur_t *cur,
1972 xfs_fileoff_t off,
1973 xfs_fsblock_t bno,
1974 xfs_filblks_t len,
1975 xfs_exntst_t state)
1976{
1977 xfs_bmbt_block_t *block;
1978 xfs_buf_t *bp;
1979 int error;
1980 xfs_bmbt_key_t key;
1981 int ptr;
1982 xfs_bmbt_rec_t *rp;
1983
1984 XFS_BMBT_TRACE_CURSOR(cur, ENTRY);
1985 XFS_BMBT_TRACE_ARGFFFI(cur, (xfs_dfiloff_t)off, (xfs_dfsbno_t)bno,
1986 (xfs_dfilblks_t)len, (int)state);
1987 block = xfs_bmbt_get_block(cur, 0, &bp);
1988#ifdef DEBUG
1989 if ((error = xfs_btree_check_lblock(cur, block, 0, bp))) {
1990 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
1991 return error;
1992 }
1993#endif
1994 ptr = cur->bc_ptrs[0];
1995 rp = XFS_BMAP_REC_IADDR(block, ptr, cur);
1996 xfs_bmbt_disk_set_allf(rp, off, bno, len, state);
1997 xfs_bmbt_log_recs(cur, bp, ptr, ptr);
1998 if (ptr > 1) {
1999 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2000 return 0;
2001 }
2002 key.br_startoff = cpu_to_be64(off);
2003 if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, 1))) {
2004 XFS_BMBT_TRACE_CURSOR(cur, ERROR);
2005 return error;
2006 }
2007 XFS_BMBT_TRACE_CURSOR(cur, EXIT);
2008 return 0;
2009}
2010
2011/*
2012 * Check extent records, which have just been read, for 1967 * Check extent records, which have just been read, for
2013 * any bit in the extent flag field. ASSERT on debug 1968 * any bit in the extent flag field. ASSERT on debug
2014 * kernels, as this condition should not occur. 1969 * kernels, as this condition should not occur.
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index d04198cdc4b3..6bfd62ec54fb 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -274,8 +274,6 @@ extern void xfs_bmbt_disk_set_allf(xfs_bmbt_rec_t *r, xfs_fileoff_t o,
274 xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v); 274 xfs_fsblock_t b, xfs_filblks_t c, xfs_exntst_t v);
275 275
276extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int); 276extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int);
277extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,
278 xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t);
279 277
280extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *, 278extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
281 struct xfs_trans *, struct xfs_inode *, int); 279 struct xfs_trans *, struct xfs_inode *, int);
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
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index ac3f527b0ac4..c3bfa5556c19 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -187,6 +187,12 @@ struct xfs_btree_ops {
187 /* cursor operations */ 187 /* cursor operations */
188 struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *); 188 struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *);
189 189
190 /* update last record information */
191 void (*update_lastrec)(struct xfs_btree_cur *cur,
192 struct xfs_btree_block *block,
193 union xfs_btree_rec *rec,
194 int ptr, int reason);
195
190 /* records in block/level */ 196 /* records in block/level */
191 int (*get_maxrecs)(struct xfs_btree_cur *cur, int level); 197 int (*get_maxrecs)(struct xfs_btree_cur *cur, int level);
192 198
@@ -221,6 +227,12 @@ struct xfs_btree_ops {
221}; 227};
222 228
223/* 229/*
230 * Reasons for the update_lastrec method to be called.
231 */
232#define LASTREC_UPDATE 0
233
234
235/*
224 * Btree cursor structure. 236 * Btree cursor structure.
225 * This collects all information needed by the btree code in one place. 237 * This collects all information needed by the btree code in one place.
226 */ 238 */
@@ -264,6 +276,7 @@ typedef struct xfs_btree_cur
264/* cursor flags */ 276/* cursor flags */
265#define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */ 277#define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */
266#define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */ 278#define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */
279#define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */
267 280
268 281
269#define XFS_BTREE_NOERROR 0 282#define XFS_BTREE_NOERROR 0
@@ -519,6 +532,7 @@ int xfs_btree_increment(struct xfs_btree_cur *, int, int *);
519int xfs_btree_decrement(struct xfs_btree_cur *, int, int *); 532int xfs_btree_decrement(struct xfs_btree_cur *, int, int *);
520int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *); 533int xfs_btree_lookup(struct xfs_btree_cur *, xfs_lookup_t, int *);
521int xfs_btree_updkey(struct xfs_btree_cur *, union xfs_btree_key *, int); 534int xfs_btree_updkey(struct xfs_btree_cur *, union xfs_btree_key *, int);
535int xfs_btree_update(struct xfs_btree_cur *, union xfs_btree_rec *);
522 536
523/* 537/*
524 * Helpers. 538 * Helpers.
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index bbf537f64c41..138651afd44f 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -172,6 +172,26 @@ xfs_inobt_lookup_le(
172} 172}
173 173
174/* 174/*
175 * Update the record referred to by cur to the value given
176 * by [ino, fcnt, free].
177 * This either works (return 0) or gets an EFSCORRUPTED error.
178 */
179STATIC int /* error */
180xfs_inobt_update(
181 struct xfs_btree_cur *cur, /* btree cursor */
182 xfs_agino_t ino, /* starting inode of chunk */
183 __int32_t fcnt, /* free inode count */
184 xfs_inofree_t free) /* free inode mask */
185{
186 union xfs_btree_rec rec;
187
188 rec.inobt.ir_startino = cpu_to_be32(ino);
189 rec.inobt.ir_freecount = cpu_to_be32(fcnt);
190 rec.inobt.ir_free = cpu_to_be64(free);
191 return xfs_btree_update(cur, &rec);
192}
193
194/*
175 * Allocate new inodes in the allocation group specified by agbp. 195 * Allocate new inodes in the allocation group specified by agbp.
176 * Return 0 for success, else error code. 196 * Return 0 for success, else error code.
177 */ 197 */
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index cd8bb519cb5f..d080a6833a8d 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -1551,58 +1551,6 @@ xfs_inobt_insert(
1551 return 0; 1551 return 0;
1552} 1552}
1553 1553
1554/*
1555 * Update the record referred to by cur, to the value given
1556 * by [ino, fcnt, free].
1557 * This either works (return 0) or gets an EFSCORRUPTED error.
1558 */
1559int /* error */
1560xfs_inobt_update(
1561 xfs_btree_cur_t *cur, /* btree cursor */
1562 xfs_agino_t ino, /* starting inode of chunk */
1563 __int32_t fcnt, /* free inode count */
1564 xfs_inofree_t free) /* free inode mask */
1565{
1566 xfs_inobt_block_t *block; /* btree block to update */
1567 xfs_buf_t *bp; /* buffer containing btree block */
1568 int error; /* error return value */
1569 int ptr; /* current record number (updating) */
1570 xfs_inobt_rec_t *rp; /* pointer to updated record */
1571
1572 /*
1573 * Pick up the current block.
1574 */
1575 bp = cur->bc_bufs[0];
1576 block = XFS_BUF_TO_INOBT_BLOCK(bp);
1577#ifdef DEBUG
1578 if ((error = xfs_btree_check_sblock(cur, block, 0, bp)))
1579 return error;
1580#endif
1581 /*
1582 * Get the address of the rec to be updated.
1583 */
1584 ptr = cur->bc_ptrs[0];
1585 rp = XFS_INOBT_REC_ADDR(block, ptr, cur);
1586 /*
1587 * Fill in the new contents and log them.
1588 */
1589 rp->ir_startino = cpu_to_be32(ino);
1590 rp->ir_freecount = cpu_to_be32(fcnt);
1591 rp->ir_free = cpu_to_be64(free);
1592 xfs_inobt_log_recs(cur, bp, ptr, ptr);
1593 /*
1594 * Updating first record in leaf. Pass new key value up to our parent.
1595 */
1596 if (ptr == 1) {
1597 xfs_inobt_key_t key; /* key containing [ino] */
1598
1599 key.ir_startino = cpu_to_be32(ino);
1600 if ((error = xfs_btree_updkey(cur, (union xfs_btree_key *)&key, 1)))
1601 return error;
1602 }
1603 return 0;
1604}
1605
1606STATIC struct xfs_btree_cur * 1554STATIC struct xfs_btree_cur *
1607xfs_inobt_dup_cursor( 1555xfs_inobt_dup_cursor(
1608 struct xfs_btree_cur *cur) 1556 struct xfs_btree_cur *cur)
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index 674b459521f5..7f77549e82a6 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -135,14 +135,6 @@ extern int xfs_inobt_get_rec(struct xfs_btree_cur *cur, xfs_agino_t *ino,
135 */ 135 */
136extern int xfs_inobt_insert(struct xfs_btree_cur *cur, int *stat); 136extern int xfs_inobt_insert(struct xfs_btree_cur *cur, int *stat);
137 137
138/*
139 * Update the record referred to by cur, to the value given
140 * by [ino, fcnt, free].
141 * This either works (return 0) or gets an EFSCORRUPTED error.
142 */
143extern int xfs_inobt_update(struct xfs_btree_cur *cur, xfs_agino_t ino,
144 __int32_t fcnt, xfs_inofree_t free);
145
146 138
147extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *, 139extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
148 struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t); 140 struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t);