aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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);