aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristoph Hellwig <hch@infradead.org>2008-10-30 01:53:59 -0400
committerLachlan McIlroy <lachlan@sgi.com>2008-10-30 01:53:59 -0400
commit561f7d17390d00444e6cd0b02b7516c91528082e (patch)
tree59359b995320bf79a55c2f23305960b5ffe74d8f
parentf2277f06e626d694e61bb356524ff536ced24acf (diff)
[XFS] split up xfs_btree_init_cursor
xfs_btree_init_cursor contains close to little shared code for the different btrees and will get even more non-common code in the future. Split it up into one routine per btree type. Because xfs_btree_dup_cursor needs to call the init routine for a generic btree cursor add a new btree operation vector that contains a dup_cursor method that initializes a new cursor based on an existing one. The btree operations vector is based on an idea and code from Dave Chinner and will grow more entries later during this series. SGI-PV: 985583 SGI-Modid: xfs-linux-melb:xfs-kern:32176a 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>
-rw-r--r--fs/xfs/xfs_alloc.c34
-rw-r--r--fs/xfs/xfs_alloc_btree.c45
-rw-r--r--fs/xfs/xfs_alloc_btree.h5
-rw-r--r--fs/xfs/xfs_bmap.c17
-rw-r--r--fs/xfs/xfs_bmap_btree.c59
-rw-r--r--fs/xfs/xfs_bmap_btree.h4
-rw-r--r--fs/xfs/xfs_btree.c107
-rw-r--r--fs/xfs/xfs_btree.h20
-rw-r--r--fs/xfs/xfs_ialloc.c12
-rw-r--r--fs/xfs/xfs_ialloc_btree.c41
-rw-r--r--fs/xfs/xfs_ialloc_btree.h4
-rw-r--r--fs/xfs/xfs_itable.c6
12 files changed, 196 insertions, 158 deletions
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c
index 1956f83489f1..69833eb1de4f 100644
--- a/fs/xfs/xfs_alloc.c
+++ b/fs/xfs/xfs_alloc.c
@@ -640,8 +640,8 @@ xfs_alloc_ag_vextent_exact(
640 /* 640 /*
641 * Allocate/initialize a cursor for the by-number freespace btree. 641 * Allocate/initialize a cursor for the by-number freespace btree.
642 */ 642 */
643 bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, 643 bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
644 args->agno, XFS_BTNUM_BNO, NULL, 0); 644 args->agno, XFS_BTNUM_BNO);
645 /* 645 /*
646 * Lookup bno and minlen in the btree (minlen is irrelevant, really). 646 * Lookup bno and minlen in the btree (minlen is irrelevant, really).
647 * Look for the closest free block <= bno, it must contain bno 647 * Look for the closest free block <= bno, it must contain bno
@@ -696,8 +696,8 @@ xfs_alloc_ag_vextent_exact(
696 * We are allocating agbno for rlen [agbno .. end] 696 * We are allocating agbno for rlen [agbno .. end]
697 * Allocate/initialize a cursor for the by-size btree. 697 * Allocate/initialize a cursor for the by-size btree.
698 */ 698 */
699 cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, 699 cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
700 args->agno, XFS_BTNUM_CNT, NULL, 0); 700 args->agno, XFS_BTNUM_CNT);
701 ASSERT(args->agbno + args->len <= 701 ASSERT(args->agbno + args->len <=
702 be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length)); 702 be32_to_cpu(XFS_BUF_TO_AGF(args->agbp)->agf_length));
703 if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, 703 if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
@@ -759,8 +759,8 @@ xfs_alloc_ag_vextent_near(
759 /* 759 /*
760 * Get a cursor for the by-size btree. 760 * Get a cursor for the by-size btree.
761 */ 761 */
762 cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, 762 cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
763 args->agno, XFS_BTNUM_CNT, NULL, 0); 763 args->agno, XFS_BTNUM_CNT);
764 ltlen = 0; 764 ltlen = 0;
765 bno_cur_lt = bno_cur_gt = NULL; 765 bno_cur_lt = bno_cur_gt = NULL;
766 /* 766 /*
@@ -886,8 +886,8 @@ xfs_alloc_ag_vextent_near(
886 /* 886 /*
887 * Set up a cursor for the by-bno tree. 887 * Set up a cursor for the by-bno tree.
888 */ 888 */
889 bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, 889 bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp,
890 args->agbp, args->agno, XFS_BTNUM_BNO, NULL, 0); 890 args->agbp, args->agno, XFS_BTNUM_BNO);
891 /* 891 /*
892 * Fix up the btree entries. 892 * Fix up the btree entries.
893 */ 893 */
@@ -914,8 +914,8 @@ xfs_alloc_ag_vextent_near(
914 /* 914 /*
915 * Allocate and initialize the cursor for the leftward search. 915 * Allocate and initialize the cursor for the leftward search.
916 */ 916 */
917 bno_cur_lt = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, 917 bno_cur_lt = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
918 args->agno, XFS_BTNUM_BNO, NULL, 0); 918 args->agno, XFS_BTNUM_BNO);
919 /* 919 /*
920 * Lookup <= bno to find the leftward search's starting point. 920 * Lookup <= bno to find the leftward search's starting point.
921 */ 921 */
@@ -1267,8 +1267,8 @@ xfs_alloc_ag_vextent_size(
1267 /* 1267 /*
1268 * Allocate and initialize a cursor for the by-size btree. 1268 * Allocate and initialize a cursor for the by-size btree.
1269 */ 1269 */
1270 cnt_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, 1270 cnt_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
1271 args->agno, XFS_BTNUM_CNT, NULL, 0); 1271 args->agno, XFS_BTNUM_CNT);
1272 bno_cur = NULL; 1272 bno_cur = NULL;
1273 /* 1273 /*
1274 * Look for an entry >= maxlen+alignment-1 blocks. 1274 * Look for an entry >= maxlen+alignment-1 blocks.
@@ -1372,8 +1372,8 @@ xfs_alloc_ag_vextent_size(
1372 /* 1372 /*
1373 * Allocate and initialize a cursor for the by-block tree. 1373 * Allocate and initialize a cursor for the by-block tree.
1374 */ 1374 */
1375 bno_cur = xfs_btree_init_cursor(args->mp, args->tp, args->agbp, 1375 bno_cur = xfs_allocbt_init_cursor(args->mp, args->tp, args->agbp,
1376 args->agno, XFS_BTNUM_BNO, NULL, 0); 1376 args->agno, XFS_BTNUM_BNO);
1377 if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen, 1377 if ((error = xfs_alloc_fixup_trees(cnt_cur, bno_cur, fbno, flen,
1378 rbno, rlen, XFSA_FIXUP_CNT_OK))) 1378 rbno, rlen, XFSA_FIXUP_CNT_OK)))
1379 goto error0; 1379 goto error0;
@@ -1515,8 +1515,7 @@ xfs_free_ag_extent(
1515 /* 1515 /*
1516 * Allocate and initialize a cursor for the by-block btree. 1516 * Allocate and initialize a cursor for the by-block btree.
1517 */ 1517 */
1518 bno_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO, NULL, 1518 bno_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_BNO);
1519 0);
1520 cnt_cur = NULL; 1519 cnt_cur = NULL;
1521 /* 1520 /*
1522 * Look for a neighboring block on the left (lower block numbers) 1521 * Look for a neighboring block on the left (lower block numbers)
@@ -1575,8 +1574,7 @@ xfs_free_ag_extent(
1575 /* 1574 /*
1576 * Now allocate and initialize a cursor for the by-size tree. 1575 * Now allocate and initialize a cursor for the by-size tree.
1577 */ 1576 */
1578 cnt_cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT, NULL, 1577 cnt_cur = xfs_allocbt_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_CNT);
1579 0);
1580 /* 1578 /*
1581 * Have both left and right contiguous neighbors. 1579 * Have both left and right contiguous neighbors.
1582 * Merge all three into a single free block. 1580 * Merge all three into a single free block.
diff --git a/fs/xfs/xfs_alloc_btree.c b/fs/xfs/xfs_alloc_btree.c
index 3ce2645508ae..60c121f1e81b 100644
--- a/fs/xfs/xfs_alloc_btree.c
+++ b/fs/xfs/xfs_alloc_btree.c
@@ -2209,3 +2209,48 @@ xfs_alloc_update(
2209 } 2209 }
2210 return 0; 2210 return 0;
2211} 2211}
2212
2213STATIC struct xfs_btree_cur *
2214xfs_allocbt_dup_cursor(
2215 struct xfs_btree_cur *cur)
2216{
2217 return xfs_allocbt_init_cursor(cur->bc_mp, cur->bc_tp,
2218 cur->bc_private.a.agbp, cur->bc_private.a.agno,
2219 cur->bc_btnum);
2220}
2221
2222static const struct xfs_btree_ops xfs_allocbt_ops = {
2223 .dup_cursor = xfs_allocbt_dup_cursor,
2224};
2225
2226/*
2227 * Allocate a new allocation btree cursor.
2228 */
2229struct xfs_btree_cur * /* new alloc btree cursor */
2230xfs_allocbt_init_cursor(
2231 struct xfs_mount *mp, /* file system mount point */
2232 struct xfs_trans *tp, /* transaction pointer */
2233 struct xfs_buf *agbp, /* buffer for agf structure */
2234 xfs_agnumber_t agno, /* allocation group number */
2235 xfs_btnum_t btnum) /* btree identifier */
2236{
2237 struct xfs_agf *agf = XFS_BUF_TO_AGF(agbp);
2238 struct xfs_btree_cur *cur;
2239
2240 ASSERT(btnum == XFS_BTNUM_BNO || btnum == XFS_BTNUM_CNT);
2241
2242 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
2243
2244 cur->bc_tp = tp;
2245 cur->bc_mp = mp;
2246 cur->bc_nlevels = be32_to_cpu(agf->agf_levels[btnum]);
2247 cur->bc_btnum = btnum;
2248 cur->bc_blocklog = mp->m_sb.sb_blocklog;
2249
2250 cur->bc_ops = &xfs_allocbt_ops;
2251
2252 cur->bc_private.a.agbp = agbp;
2253 cur->bc_private.a.agno = agno;
2254
2255 return cur;
2256}
diff --git a/fs/xfs/xfs_alloc_btree.h b/fs/xfs/xfs_alloc_btree.h
index 5bd1a2c8bd07..60735384a4ce 100644
--- a/fs/xfs/xfs_alloc_btree.h
+++ b/fs/xfs/xfs_alloc_btree.h
@@ -152,4 +152,9 @@ extern int xfs_alloc_lookup_le(struct xfs_btree_cur *cur, xfs_agblock_t bno,
152extern int xfs_alloc_update(struct xfs_btree_cur *cur, xfs_agblock_t bno, 152extern int xfs_alloc_update(struct xfs_btree_cur *cur, xfs_agblock_t bno,
153 xfs_extlen_t len); 153 xfs_extlen_t len);
154 154
155
156extern struct xfs_btree_cur *xfs_allocbt_init_cursor(struct xfs_mount *,
157 struct xfs_trans *, struct xfs_buf *,
158 xfs_agnumber_t, xfs_btnum_t);
159
155#endif /* __XFS_ALLOC_BTREE_H__ */ 160#endif /* __XFS_ALLOC_BTREE_H__ */
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c
index a1aab9275d5a..a84d0c30b485 100644
--- a/fs/xfs/xfs_bmap.c
+++ b/fs/xfs/xfs_bmap.c
@@ -422,8 +422,7 @@ xfs_bmap_add_attrfork_btree(
422 if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip)) 422 if (ip->i_df.if_broot_bytes <= XFS_IFORK_DSIZE(ip))
423 *flags |= XFS_ILOG_DBROOT; 423 *flags |= XFS_ILOG_DBROOT;
424 else { 424 else {
425 cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip, 425 cur = xfs_bmbt_init_cursor(mp, tp, ip, XFS_DATA_FORK);
426 XFS_DATA_FORK);
427 cur->bc_private.b.flist = flist; 426 cur->bc_private.b.flist = flist;
428 cur->bc_private.b.firstblock = *firstblock; 427 cur->bc_private.b.firstblock = *firstblock;
429 if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat))) 428 if ((error = xfs_bmbt_lookup_ge(cur, 0, 0, 0, &stat)))
@@ -3441,8 +3440,7 @@ xfs_bmap_extents_to_btree(
3441 * Need a cursor. Can't allocate until bb_level is filled in. 3440 * Need a cursor. Can't allocate until bb_level is filled in.
3442 */ 3441 */
3443 mp = ip->i_mount; 3442 mp = ip->i_mount;
3444 cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip, 3443 cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
3445 whichfork);
3446 cur->bc_private.b.firstblock = *firstblock; 3444 cur->bc_private.b.firstblock = *firstblock;
3447 cur->bc_private.b.flist = flist; 3445 cur->bc_private.b.flist = flist;
3448 cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0; 3446 cur->bc_private.b.flags = wasdel ? XFS_BTCUR_BPRV_WASDEL : 0;
@@ -5029,8 +5027,7 @@ xfs_bmapi(
5029 if (abno == NULLFSBLOCK) 5027 if (abno == NULLFSBLOCK)
5030 break; 5028 break;
5031 if ((ifp->if_flags & XFS_IFBROOT) && !cur) { 5029 if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
5032 cur = xfs_btree_init_cursor(mp, 5030 cur = xfs_bmbt_init_cursor(mp, tp,
5033 tp, NULL, 0, XFS_BTNUM_BMAP,
5034 ip, whichfork); 5031 ip, whichfork);
5035 cur->bc_private.b.firstblock = 5032 cur->bc_private.b.firstblock =
5036 *firstblock; 5033 *firstblock;
@@ -5147,9 +5144,8 @@ xfs_bmapi(
5147 */ 5144 */
5148 ASSERT(mval->br_blockcount <= len); 5145 ASSERT(mval->br_blockcount <= len);
5149 if ((ifp->if_flags & XFS_IFBROOT) && !cur) { 5146 if ((ifp->if_flags & XFS_IFBROOT) && !cur) {
5150 cur = xfs_btree_init_cursor(mp, 5147 cur = xfs_bmbt_init_cursor(mp,
5151 tp, NULL, 0, XFS_BTNUM_BMAP, 5148 tp, ip, whichfork);
5152 ip, whichfork);
5153 cur->bc_private.b.firstblock = 5149 cur->bc_private.b.firstblock =
5154 *firstblock; 5150 *firstblock;
5155 cur->bc_private.b.flist = flist; 5151 cur->bc_private.b.flist = flist;
@@ -5440,8 +5436,7 @@ xfs_bunmapi(
5440 logflags = 0; 5436 logflags = 0;
5441 if (ifp->if_flags & XFS_IFBROOT) { 5437 if (ifp->if_flags & XFS_IFBROOT) {
5442 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE); 5438 ASSERT(XFS_IFORK_FORMAT(ip, whichfork) == XFS_DINODE_FMT_BTREE);
5443 cur = xfs_btree_init_cursor(mp, tp, NULL, 0, XFS_BTNUM_BMAP, ip, 5439 cur = xfs_bmbt_init_cursor(mp, tp, ip, whichfork);
5444 whichfork);
5445 cur->bc_private.b.firstblock = *firstblock; 5440 cur->bc_private.b.firstblock = *firstblock;
5446 cur->bc_private.b.flist = flist; 5441 cur->bc_private.b.flist = flist;
5447 cur->bc_private.b.flags = 0; 5442 cur->bc_private.b.flags = 0;
diff --git a/fs/xfs/xfs_bmap_btree.c b/fs/xfs/xfs_bmap_btree.c
index 23efad29a5cd..cfbdd00045cf 100644
--- a/fs/xfs/xfs_bmap_btree.c
+++ b/fs/xfs/xfs_bmap_btree.c
@@ -2608,3 +2608,62 @@ xfs_check_nostate_extents(
2608 } 2608 }
2609 return 0; 2609 return 0;
2610} 2610}
2611
2612
2613STATIC struct xfs_btree_cur *
2614xfs_bmbt_dup_cursor(
2615 struct xfs_btree_cur *cur)
2616{
2617 struct xfs_btree_cur *new;
2618
2619 new = xfs_bmbt_init_cursor(cur->bc_mp, cur->bc_tp,
2620 cur->bc_private.b.ip, cur->bc_private.b.whichfork);
2621
2622 /*
2623 * Copy the firstblock, flist, and flags values,
2624 * since init cursor doesn't get them.
2625 */
2626 new->bc_private.b.firstblock = cur->bc_private.b.firstblock;
2627 new->bc_private.b.flist = cur->bc_private.b.flist;
2628 new->bc_private.b.flags = cur->bc_private.b.flags;
2629
2630 return new;
2631}
2632
2633static const struct xfs_btree_ops xfs_bmbt_ops = {
2634 .dup_cursor = xfs_bmbt_dup_cursor,
2635};
2636
2637/*
2638 * Allocate a new bmap btree cursor.
2639 */
2640struct xfs_btree_cur * /* new bmap btree cursor */
2641xfs_bmbt_init_cursor(
2642 struct xfs_mount *mp, /* file system mount point */
2643 struct xfs_trans *tp, /* transaction pointer */
2644 struct xfs_inode *ip, /* inode owning the btree */
2645 int whichfork) /* data or attr fork */
2646{
2647 struct xfs_ifork *ifp = XFS_IFORK_PTR(ip, whichfork);
2648 struct xfs_btree_cur *cur;
2649
2650 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
2651
2652 cur->bc_tp = tp;
2653 cur->bc_mp = mp;
2654 cur->bc_nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
2655 cur->bc_btnum = XFS_BTNUM_BMAP;
2656 cur->bc_blocklog = mp->m_sb.sb_blocklog;
2657
2658 cur->bc_ops = &xfs_bmbt_ops;
2659
2660 cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
2661 cur->bc_private.b.ip = ip;
2662 cur->bc_private.b.firstblock = NULLFSBLOCK;
2663 cur->bc_private.b.flist = NULL;
2664 cur->bc_private.b.allocated = 0;
2665 cur->bc_private.b.flags = 0;
2666 cur->bc_private.b.whichfork = whichfork;
2667
2668 return cur;
2669}
diff --git a/fs/xfs/xfs_bmap_btree.h b/fs/xfs/xfs_bmap_btree.h
index cd0d4b4bb816..4f12fff54975 100644
--- a/fs/xfs/xfs_bmap_btree.h
+++ b/fs/xfs/xfs_bmap_btree.h
@@ -24,6 +24,7 @@ struct xfs_btree_cur;
24struct xfs_btree_lblock; 24struct xfs_btree_lblock;
25struct xfs_mount; 25struct xfs_mount;
26struct xfs_inode; 26struct xfs_inode;
27struct xfs_trans;
27 28
28/* 29/*
29 * Bmap root header, on-disk form only. 30 * Bmap root header, on-disk form only.
@@ -300,6 +301,9 @@ extern void xfs_bmbt_to_bmdr(xfs_bmbt_block_t *, int, xfs_bmdr_block_t *, int);
300extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t, 301extern int xfs_bmbt_update(struct xfs_btree_cur *, xfs_fileoff_t,
301 xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t); 302 xfs_fsblock_t, xfs_filblks_t, xfs_exntst_t);
302 303
304extern struct xfs_btree_cur *xfs_bmbt_init_cursor(struct xfs_mount *,
305 struct xfs_trans *, struct xfs_inode *, int);
306
303#endif /* __KERNEL__ */ 307#endif /* __KERNEL__ */
304 308
305#endif /* __XFS_BMAP_BTREE_H__ */ 309#endif /* __XFS_BMAP_BTREE_H__ */
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c
index 31002093bfb7..074f7f6aa27c 100644
--- a/fs/xfs/xfs_btree.c
+++ b/fs/xfs/xfs_btree.c
@@ -387,16 +387,17 @@ xfs_btree_dup_cursor(
387 387
388 tp = cur->bc_tp; 388 tp = cur->bc_tp;
389 mp = cur->bc_mp; 389 mp = cur->bc_mp;
390
390 /* 391 /*
391 * Allocate a new cursor like the old one. 392 * Allocate a new cursor like the old one.
392 */ 393 */
393 new = xfs_btree_init_cursor(mp, tp, cur->bc_private.a.agbp, 394 new = cur->bc_ops->dup_cursor(cur);
394 cur->bc_private.a.agno, cur->bc_btnum, cur->bc_private.b.ip, 395
395 cur->bc_private.b.whichfork);
396 /* 396 /*
397 * Copy the record currently in the cursor. 397 * Copy the record currently in the cursor.
398 */ 398 */
399 new->bc_rec = cur->bc_rec; 399 new->bc_rec = cur->bc_rec;
400
400 /* 401 /*
401 * For each level current, re-get the buffer and copy the ptr value. 402 * For each level current, re-get the buffer and copy the ptr value.
402 */ 403 */
@@ -416,15 +417,6 @@ xfs_btree_dup_cursor(
416 } else 417 } else
417 new->bc_bufs[i] = NULL; 418 new->bc_bufs[i] = NULL;
418 } 419 }
419 /*
420 * For bmap btrees, copy the firstblock, flist, and flags values,
421 * since init cursor doesn't get them.
422 */
423 if (new->bc_btnum == XFS_BTNUM_BMAP) {
424 new->bc_private.b.firstblock = cur->bc_private.b.firstblock;
425 new->bc_private.b.flist = cur->bc_private.b.flist;
426 new->bc_private.b.flags = cur->bc_private.b.flags;
427 }
428 *ncur = new; 420 *ncur = new;
429 return 0; 421 return 0;
430} 422}
@@ -505,97 +497,6 @@ xfs_btree_get_bufs(
505} 497}
506 498
507/* 499/*
508 * Allocate a new btree cursor.
509 * The cursor is either for allocation (A) or bmap (B) or inodes (I).
510 */
511xfs_btree_cur_t * /* new btree cursor */
512xfs_btree_init_cursor(
513 xfs_mount_t *mp, /* file system mount point */
514 xfs_trans_t *tp, /* transaction pointer */
515 xfs_buf_t *agbp, /* (A only) buffer for agf structure */
516 /* (I only) buffer for agi structure */
517 xfs_agnumber_t agno, /* (AI only) allocation group number */
518 xfs_btnum_t btnum, /* btree identifier */
519 xfs_inode_t *ip, /* (B only) inode owning the btree */
520 int whichfork) /* (B only) data or attr fork */
521{
522 xfs_agf_t *agf; /* (A) allocation group freespace */
523 xfs_agi_t *agi; /* (I) allocation group inodespace */
524 xfs_btree_cur_t *cur; /* return value */
525 xfs_ifork_t *ifp; /* (I) inode fork pointer */
526 int nlevels=0; /* number of levels in the btree */
527
528 ASSERT(xfs_btree_cur_zone != NULL);
529 /*
530 * Allocate a new cursor.
531 */
532 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
533 /*
534 * Deduce the number of btree levels from the arguments.
535 */
536 switch (btnum) {
537 case XFS_BTNUM_BNO:
538 case XFS_BTNUM_CNT:
539 agf = XFS_BUF_TO_AGF(agbp);
540 nlevels = be32_to_cpu(agf->agf_levels[btnum]);
541 break;
542 case XFS_BTNUM_BMAP:
543 ifp = XFS_IFORK_PTR(ip, whichfork);
544 nlevels = be16_to_cpu(ifp->if_broot->bb_level) + 1;
545 break;
546 case XFS_BTNUM_INO:
547 agi = XFS_BUF_TO_AGI(agbp);
548 nlevels = be32_to_cpu(agi->agi_level);
549 break;
550 default:
551 ASSERT(0);
552 }
553 /*
554 * Fill in the common fields.
555 */
556 cur->bc_tp = tp;
557 cur->bc_mp = mp;
558 cur->bc_nlevels = nlevels;
559 cur->bc_btnum = btnum;
560 cur->bc_blocklog = mp->m_sb.sb_blocklog;
561 /*
562 * Fill in private fields.
563 */
564 switch (btnum) {
565 case XFS_BTNUM_BNO:
566 case XFS_BTNUM_CNT:
567 /*
568 * Allocation btree fields.
569 */
570 cur->bc_private.a.agbp = agbp;
571 cur->bc_private.a.agno = agno;
572 break;
573 case XFS_BTNUM_INO:
574 /*
575 * Inode allocation btree fields.
576 */
577 cur->bc_private.a.agbp = agbp;
578 cur->bc_private.a.agno = agno;
579 break;
580 case XFS_BTNUM_BMAP:
581 /*
582 * Bmap btree fields.
583 */
584 cur->bc_private.b.forksize = XFS_IFORK_SIZE(ip, whichfork);
585 cur->bc_private.b.ip = ip;
586 cur->bc_private.b.firstblock = NULLFSBLOCK;
587 cur->bc_private.b.flist = NULL;
588 cur->bc_private.b.allocated = 0;
589 cur->bc_private.b.flags = 0;
590 cur->bc_private.b.whichfork = whichfork;
591 break;
592 default:
593 ASSERT(0);
594 }
595 return cur;
596}
597
598/*
599 * Check for the cursor referring to the last block at the given level. 500 * Check for the cursor referring to the last block at the given level.
600 */ 501 */
601int /* 1=is last block, 0=not last block */ 502int /* 1=is last block, 0=not last block */
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h
index 332b9f1da203..d30ee7498606 100644
--- a/fs/xfs/xfs_btree.h
+++ b/fs/xfs/xfs_btree.h
@@ -131,6 +131,11 @@ extern const __uint32_t xfs_magics[];
131 131
132#define XFS_BTREE_MAXLEVELS 8 /* max of all btrees */ 132#define XFS_BTREE_MAXLEVELS 8 /* max of all btrees */
133 133
134struct xfs_btree_ops {
135 /* cursor operations */
136 struct xfs_btree_cur *(*dup_cursor)(struct xfs_btree_cur *);
137};
138
134/* 139/*
135 * Btree cursor structure. 140 * Btree cursor structure.
136 * This collects all information needed by the btree code in one place. 141 * This collects all information needed by the btree code in one place.
@@ -139,6 +144,7 @@ typedef struct xfs_btree_cur
139{ 144{
140 struct xfs_trans *bc_tp; /* transaction we're in, if any */ 145 struct xfs_trans *bc_tp; /* transaction we're in, if any */
141 struct xfs_mount *bc_mp; /* file system mount struct */ 146 struct xfs_mount *bc_mp; /* file system mount struct */
147 const struct xfs_btree_ops *bc_ops;
142 union { 148 union {
143 xfs_alloc_rec_incore_t a; 149 xfs_alloc_rec_incore_t a;
144 xfs_bmbt_irec_t b; 150 xfs_bmbt_irec_t b;
@@ -308,20 +314,6 @@ xfs_btree_get_bufs(
308 uint lock); /* lock flags for get_buf */ 314 uint lock); /* lock flags for get_buf */
309 315
310/* 316/*
311 * Allocate a new btree cursor.
312 * The cursor is either for allocation (A) or bmap (B).
313 */
314xfs_btree_cur_t * /* new btree cursor */
315xfs_btree_init_cursor(
316 struct xfs_mount *mp, /* file system mount point */
317 struct xfs_trans *tp, /* transaction pointer */
318 struct xfs_buf *agbp, /* (A only) buffer for agf structure */
319 xfs_agnumber_t agno, /* (A only) allocation group number */
320 xfs_btnum_t btnum, /* btree identifier */
321 struct xfs_inode *ip, /* (B only) inode owning the btree */
322 int whichfork); /* (B only) data/attr fork */
323
324/*
325 * Check for the cursor referring to the last block at the given level. 317 * Check for the cursor referring to the last block at the given level.
326 */ 318 */
327int /* 1=is last block, 0=not last block */ 319int /* 1=is last block, 0=not last block */
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c
index aad8c5da38af..11bb169561ce 100644
--- a/fs/xfs/xfs_ialloc.c
+++ b/fs/xfs/xfs_ialloc.c
@@ -335,8 +335,7 @@ xfs_ialloc_ag_alloc(
335 /* 335 /*
336 * Insert records describing the new inode chunk into the btree. 336 * Insert records describing the new inode chunk into the btree.
337 */ 337 */
338 cur = xfs_btree_init_cursor(args.mp, tp, agbp, agno, 338 cur = xfs_inobt_init_cursor(args.mp, tp, agbp, agno);
339 XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
340 for (thisino = newino; 339 for (thisino = newino;
341 thisino < newino + newlen; 340 thisino < newino + newlen;
342 thisino += XFS_INODES_PER_CHUNK) { 341 thisino += XFS_INODES_PER_CHUNK) {
@@ -676,8 +675,7 @@ nextag:
676 */ 675 */
677 agno = tagno; 676 agno = tagno;
678 *IO_agbp = NULL; 677 *IO_agbp = NULL;
679 cur = xfs_btree_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno), 678 cur = xfs_inobt_init_cursor(mp, tp, agbp, be32_to_cpu(agi->agi_seqno));
680 XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
681 /* 679 /*
682 * If pagino is 0 (this is the root inode allocation) use newino. 680 * If pagino is 0 (this is the root inode allocation) use newino.
683 * This must work because we've just allocated some. 681 * This must work because we've just allocated some.
@@ -1022,8 +1020,7 @@ xfs_difree(
1022 /* 1020 /*
1023 * Initialize the cursor. 1021 * Initialize the cursor.
1024 */ 1022 */
1025 cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO, 1023 cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
1026 (xfs_inode_t *)0, 0);
1027#ifdef DEBUG 1024#ifdef DEBUG
1028 if (cur->bc_nlevels == 1) { 1025 if (cur->bc_nlevels == 1) {
1029 int freecount = 0; 1026 int freecount = 0;
@@ -1259,8 +1256,7 @@ xfs_dilocate(
1259#endif /* DEBUG */ 1256#endif /* DEBUG */
1260 return error; 1257 return error;
1261 } 1258 }
1262 cur = xfs_btree_init_cursor(mp, tp, agbp, agno, XFS_BTNUM_INO, 1259 cur = xfs_inobt_init_cursor(mp, tp, agbp, agno);
1263 (xfs_inode_t *)0, 0);
1264 if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) { 1260 if ((error = xfs_inobt_lookup_le(cur, agino, 0, 0, &i))) {
1265#ifdef DEBUG 1261#ifdef DEBUG
1266 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: " 1262 xfs_fs_cmn_err(CE_ALERT, mp, "xfs_dilocate: "
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c
index 83502f3edef0..8c0c4748a8df 100644
--- a/fs/xfs/xfs_ialloc_btree.c
+++ b/fs/xfs/xfs_ialloc_btree.c
@@ -2076,3 +2076,44 @@ xfs_inobt_update(
2076 } 2076 }
2077 return 0; 2077 return 0;
2078} 2078}
2079
2080STATIC struct xfs_btree_cur *
2081xfs_inobt_dup_cursor(
2082 struct xfs_btree_cur *cur)
2083{
2084 return xfs_inobt_init_cursor(cur->bc_mp, cur->bc_tp,
2085 cur->bc_private.a.agbp, cur->bc_private.a.agno);
2086}
2087
2088static const struct xfs_btree_ops xfs_inobt_ops = {
2089 .dup_cursor = xfs_inobt_dup_cursor,
2090};
2091
2092/*
2093 * Allocate a new inode btree cursor.
2094 */
2095struct xfs_btree_cur * /* new inode btree cursor */
2096xfs_inobt_init_cursor(
2097 struct xfs_mount *mp, /* file system mount point */
2098 struct xfs_trans *tp, /* transaction pointer */
2099 struct xfs_buf *agbp, /* buffer for agi structure */
2100 xfs_agnumber_t agno) /* allocation group number */
2101{
2102 struct xfs_agi *agi = XFS_BUF_TO_AGI(agbp);
2103 struct xfs_btree_cur *cur;
2104
2105 cur = kmem_zone_zalloc(xfs_btree_cur_zone, KM_SLEEP);
2106
2107 cur->bc_tp = tp;
2108 cur->bc_mp = mp;
2109 cur->bc_nlevels = be32_to_cpu(agi->agi_level);
2110 cur->bc_btnum = XFS_BTNUM_INO;
2111 cur->bc_blocklog = mp->m_sb.sb_blocklog;
2112
2113 cur->bc_ops = &xfs_inobt_ops;
2114
2115 cur->bc_private.a.agbp = agbp;
2116 cur->bc_private.a.agno = agno;
2117
2118 return cur;
2119}
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h
index 8efc4a5b8b92..eea409349eba 100644
--- a/fs/xfs/xfs_ialloc_btree.h
+++ b/fs/xfs/xfs_ialloc_btree.h
@@ -175,4 +175,8 @@ extern int xfs_inobt_lookup_le(struct xfs_btree_cur *cur, xfs_agino_t ino,
175extern int xfs_inobt_update(struct xfs_btree_cur *cur, xfs_agino_t ino, 175extern int xfs_inobt_update(struct xfs_btree_cur *cur, xfs_agino_t ino,
176 __int32_t fcnt, xfs_inofree_t free); 176 __int32_t fcnt, xfs_inofree_t free);
177 177
178
179extern struct xfs_btree_cur *xfs_inobt_init_cursor(struct xfs_mount *,
180 struct xfs_trans *, struct xfs_buf *, xfs_agnumber_t);
181
178#endif /* __XFS_IALLOC_BTREE_H__ */ 182#endif /* __XFS_IALLOC_BTREE_H__ */
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c
index 4f4c93941067..a5f02f0e4c2a 100644
--- a/fs/xfs/xfs_itable.c
+++ b/fs/xfs/xfs_itable.c
@@ -416,8 +416,7 @@ xfs_bulkstat(
416 /* 416 /*
417 * Allocate and initialize a btree cursor for ialloc btree. 417 * Allocate and initialize a btree cursor for ialloc btree.
418 */ 418 */
419 cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, XFS_BTNUM_INO, 419 cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno);
420 (xfs_inode_t *)0, 0);
421 irbp = irbuf; 420 irbp = irbuf;
422 irbufend = irbuf + nirbuf; 421 irbufend = irbuf + nirbuf;
423 end_of_ag = 0; 422 end_of_ag = 0;
@@ -842,8 +841,7 @@ xfs_inumbers(
842 agino = 0; 841 agino = 0;
843 continue; 842 continue;
844 } 843 }
845 cur = xfs_btree_init_cursor(mp, NULL, agbp, agno, 844 cur = xfs_inobt_init_cursor(mp, NULL, agbp, agno);
846 XFS_BTNUM_INO, (xfs_inode_t *)0, 0);
847 error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp); 845 error = xfs_inobt_lookup_ge(cur, agino, 0, 0, &tmp);
848 if (error) { 846 if (error) {
849 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR); 847 xfs_btree_del_cursor(cur, XFS_BTREE_ERROR);