2 * Copyright (c) 2000 Silicon Graphics, Inc. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms of version 2 of the GNU General Public License as
6 * published by the Free Software Foundation.
8 * This program is distributed in the hope that it would be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
12 * Further, this software is distributed without any warranty that it is
13 * free of the rightful claim of any third person regarding infringement
14 * or the like. Any license provided herein, whether implied or
15 * otherwise, applies only to this software file. Patent licenses, if
16 * any, provided herein do not apply to combinations of this program with
17 * other software, or any other product whatsoever.
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write the Free Software Foundation, Inc., 59
21 * Temple Place - Suite 330, Boston MA 02111-1307, USA.
23 * Contact information: Silicon Graphics, Inc., 1600 Amphitheatre Pkwy,
24 * Mountain View, CA 94043, or:
28 * For further information regarding this notice, see:
30 * http://oss.sgi.com/projects/GenInfo/SGIGPLNoticeExplan/
34 * This file contains common code for the space manager's btree implementations.
40 * Cursor allocation zone.
42 xfs_zone_t
*xfs_btree_cur_zone
;
45 * Btree magic numbers.
47 const __uint32_t xfs_magics
[XFS_BTNUM_MAX
] =
49 XFS_ABTB_MAGIC
, XFS_ABTC_MAGIC
, XFS_BMAP_MAGIC
, XFS_IBT_MAGIC
53 * Prototypes for internal routines.
57 * Checking routine: return maxrecs for the block.
59 STATIC
int /* number of records fitting in block */
61 xfs_btree_cur_t
*cur
, /* btree cursor */
62 xfs_btree_block_t
*block
);/* generic btree block pointer */
69 * Checking routine: return maxrecs for the block.
71 STATIC
int /* number of records fitting in block */
73 xfs_btree_cur_t
*cur
, /* btree cursor */
74 xfs_btree_block_t
*block
) /* generic btree block pointer */
76 switch (cur
->bc_btnum
) {
79 return (int)XFS_ALLOC_BLOCK_MAXRECS(INT_GET(block
->bb_h
.bb_level
, ARCH_CONVERT
), cur
);
81 return (int)XFS_BMAP_BLOCK_IMAXRECS(INT_GET(block
->bb_h
.bb_level
, ARCH_CONVERT
), cur
);
83 return (int)XFS_INOBT_BLOCK_MAXRECS(INT_GET(block
->bb_h
.bb_level
, ARCH_CONVERT
), cur
);
96 * Debug routine: check that block header is ok.
99 xfs_btree_check_block(
100 xfs_btree_cur_t
*cur
, /* btree cursor */
101 xfs_btree_block_t
*block
, /* generic btree block pointer */
102 int level
, /* level of the btree block */
103 xfs_buf_t
*bp
) /* buffer containing block, if any */
105 if (XFS_BTREE_LONG_PTRS(cur
->bc_btnum
))
106 xfs_btree_check_lblock(cur
, (xfs_btree_lblock_t
*)block
, level
,
109 xfs_btree_check_sblock(cur
, (xfs_btree_sblock_t
*)block
, level
,
114 * Debug routine: check that keys are in the right order.
118 xfs_btnum_t btnum
, /* btree identifier */
119 void *ak1
, /* pointer to left (lower) key */
120 void *ak2
) /* pointer to right (higher) key */
123 case XFS_BTNUM_BNO
: {
129 ASSERT(INT_GET(k1
->ar_startblock
, ARCH_CONVERT
) < INT_GET(k2
->ar_startblock
, ARCH_CONVERT
));
132 case XFS_BTNUM_CNT
: {
138 ASSERT(INT_GET(k1
->ar_blockcount
, ARCH_CONVERT
) < INT_GET(k2
->ar_blockcount
, ARCH_CONVERT
) ||
139 (INT_GET(k1
->ar_blockcount
, ARCH_CONVERT
) == INT_GET(k2
->ar_blockcount
, ARCH_CONVERT
) &&
140 INT_GET(k1
->ar_startblock
, ARCH_CONVERT
) < INT_GET(k2
->ar_startblock
, ARCH_CONVERT
)));
143 case XFS_BTNUM_BMAP
: {
149 ASSERT(INT_GET(k1
->br_startoff
, ARCH_CONVERT
) < INT_GET(k2
->br_startoff
, ARCH_CONVERT
));
152 case XFS_BTNUM_INO
: {
158 ASSERT(INT_GET(k1
->ir_startino
, ARCH_CONVERT
) < INT_GET(k2
->ir_startino
, ARCH_CONVERT
));
168 * Checking routine: check that long form block header is ok.
171 int /* error (0 or EFSCORRUPTED) */
172 xfs_btree_check_lblock(
173 xfs_btree_cur_t
*cur
, /* btree cursor */
174 xfs_btree_lblock_t
*block
, /* btree long form block pointer */
175 int level
, /* level of the btree block */
176 xfs_buf_t
*bp
) /* buffer for block, if any */
178 int lblock_ok
; /* block passes checks */
179 xfs_mount_t
*mp
; /* file system mount point */
183 INT_GET(block
->bb_magic
, ARCH_CONVERT
) == xfs_magics
[cur
->bc_btnum
] &&
184 INT_GET(block
->bb_level
, ARCH_CONVERT
) == level
&&
185 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) <=
186 xfs_btree_maxrecs(cur
, (xfs_btree_block_t
*)block
) &&
187 !INT_ISZERO(block
->bb_leftsib
, ARCH_CONVERT
) &&
188 (INT_GET(block
->bb_leftsib
, ARCH_CONVERT
) == NULLDFSBNO
||
189 XFS_FSB_SANITY_CHECK(mp
, INT_GET(block
->bb_leftsib
, ARCH_CONVERT
))) &&
190 !INT_ISZERO(block
->bb_rightsib
, ARCH_CONVERT
) &&
191 (INT_GET(block
->bb_rightsib
, ARCH_CONVERT
) == NULLDFSBNO
||
192 XFS_FSB_SANITY_CHECK(mp
, INT_GET(block
->bb_rightsib
, ARCH_CONVERT
)));
193 if (XFS_TEST_ERROR(!lblock_ok
, mp
, XFS_ERRTAG_BTREE_CHECK_LBLOCK
,
194 XFS_RANDOM_BTREE_CHECK_LBLOCK
)) {
196 xfs_buftrace("LBTREE ERROR", bp
);
197 #ifdef __KERNEL__ /* additional, temporary, debugging code */
199 "EFSCORRUPTED returned from file %s line %d",
202 return XFS_ERROR(EFSCORRUPTED
);
208 * Checking routine: check that (long) pointer is ok.
210 int /* error (0 or EFSCORRUPTED) */
211 xfs_btree_check_lptr(
212 xfs_btree_cur_t
*cur
, /* btree cursor */
213 xfs_dfsbno_t ptr
, /* btree block disk address */
214 int level
) /* btree block level */
216 xfs_mount_t
*mp
; /* file system mount point */
219 XFS_WANT_CORRUPTED_RETURN(
222 XFS_FSB_SANITY_CHECK(mp
, ptr
));
228 * Debug routine: check that records are in the right order.
232 xfs_btnum_t btnum
, /* btree identifier */
233 void *ar1
, /* pointer to left (lower) record */
234 void *ar2
) /* pointer to right (higher) record */
237 case XFS_BTNUM_BNO
: {
243 ASSERT(INT_GET(r1
->ar_startblock
, ARCH_CONVERT
) + INT_GET(r1
->ar_blockcount
, ARCH_CONVERT
) <=
244 INT_GET(r2
->ar_startblock
, ARCH_CONVERT
));
247 case XFS_BTNUM_CNT
: {
253 ASSERT(INT_GET(r1
->ar_blockcount
, ARCH_CONVERT
) < INT_GET(r2
->ar_blockcount
, ARCH_CONVERT
) ||
254 (INT_GET(r1
->ar_blockcount
, ARCH_CONVERT
) == INT_GET(r2
->ar_blockcount
, ARCH_CONVERT
) &&
255 INT_GET(r1
->ar_startblock
, ARCH_CONVERT
) < INT_GET(r2
->ar_startblock
, ARCH_CONVERT
)));
258 case XFS_BTNUM_BMAP
: {
264 ASSERT(xfs_bmbt_get_startoff(r1
) +
265 xfs_bmbt_get_blockcount(r1
) <=
266 xfs_bmbt_get_startoff(r2
));
269 case XFS_BTNUM_INO
: {
275 ASSERT(INT_GET(r1
->ir_startino
, ARCH_CONVERT
) + XFS_INODES_PER_CHUNK
<=
276 INT_GET(r2
->ir_startino
, ARCH_CONVERT
));
286 * Checking routine: check that block header is ok.
289 int /* error (0 or EFSCORRUPTED) */
290 xfs_btree_check_sblock(
291 xfs_btree_cur_t
*cur
, /* btree cursor */
292 xfs_btree_sblock_t
*block
, /* btree short form block pointer */
293 int level
, /* level of the btree block */
294 xfs_buf_t
*bp
) /* buffer containing block */
296 xfs_buf_t
*agbp
; /* buffer for ag. freespace struct */
297 xfs_agf_t
*agf
; /* ag. freespace structure */
298 xfs_agblock_t agflen
; /* native ag. freespace length */
299 int sblock_ok
; /* block passes checks */
301 agbp
= cur
->bc_private
.a
.agbp
;
302 agf
= XFS_BUF_TO_AGF(agbp
);
303 agflen
= INT_GET(agf
->agf_length
, ARCH_CONVERT
);
305 INT_GET(block
->bb_magic
, ARCH_CONVERT
) == xfs_magics
[cur
->bc_btnum
] &&
306 INT_GET(block
->bb_level
, ARCH_CONVERT
) == level
&&
307 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
) <=
308 xfs_btree_maxrecs(cur
, (xfs_btree_block_t
*)block
) &&
309 (INT_GET(block
->bb_leftsib
, ARCH_CONVERT
) == NULLAGBLOCK
||
310 INT_GET(block
->bb_leftsib
, ARCH_CONVERT
) < agflen
) &&
311 !INT_ISZERO(block
->bb_leftsib
, ARCH_CONVERT
) &&
312 (INT_GET(block
->bb_rightsib
, ARCH_CONVERT
) == NULLAGBLOCK
||
313 INT_GET(block
->bb_rightsib
, ARCH_CONVERT
) < agflen
) &&
314 !INT_ISZERO(block
->bb_rightsib
, ARCH_CONVERT
);
315 if (XFS_TEST_ERROR(!sblock_ok
, cur
->bc_mp
,
316 XFS_ERRTAG_BTREE_CHECK_SBLOCK
,
317 XFS_RANDOM_BTREE_CHECK_SBLOCK
)) {
319 xfs_buftrace("SBTREE ERROR", bp
);
320 #ifdef __KERNEL__ /* additional, temporary, debugging code */
322 "xfs_btree_check_sblock: Not OK:");
324 "magic 0x%x level %d numrecs %d leftsib %d rightsib %d",
325 INT_GET(block
->bb_magic
, ARCH_CONVERT
),
326 INT_GET(block
->bb_level
, ARCH_CONVERT
),
327 INT_GET(block
->bb_numrecs
, ARCH_CONVERT
),
328 INT_GET(block
->bb_leftsib
, ARCH_CONVERT
),
329 INT_GET(block
->bb_rightsib
, ARCH_CONVERT
));
331 return XFS_ERROR(EFSCORRUPTED
);
337 * Checking routine: check that (short) pointer is ok.
339 int /* error (0 or EFSCORRUPTED) */
340 xfs_btree_check_sptr(
341 xfs_btree_cur_t
*cur
, /* btree cursor */
342 xfs_agblock_t ptr
, /* btree block disk address */
343 int level
) /* btree block level */
345 xfs_buf_t
*agbp
; /* buffer for ag. freespace struct */
346 xfs_agf_t
*agf
; /* ag. freespace structure */
348 agbp
= cur
->bc_private
.a
.agbp
;
349 agf
= XFS_BUF_TO_AGF(agbp
);
350 XFS_WANT_CORRUPTED_RETURN(
352 ptr
!= NULLAGBLOCK
&& ptr
!= 0 &&
353 ptr
< INT_GET(agf
->agf_length
, ARCH_CONVERT
));
358 * Delete the btree cursor.
361 xfs_btree_del_cursor(
362 xfs_btree_cur_t
*cur
, /* btree cursor */
363 int error
) /* del because of error */
365 int i
; /* btree level */
368 * Clear the buffer pointers, and release the buffers.
369 * If we're doing this in the face of an error, we
370 * need to make sure to inspect all of the entries
371 * in the bc_bufs array for buffers to be unlocked.
372 * This is because some of the btree code works from
373 * level n down to 0, and if we get an error along
374 * the way we won't have initialized all the entries
377 for (i
= 0; i
< cur
->bc_nlevels
; i
++) {
379 xfs_btree_setbuf(cur
, i
, NULL
);
384 * Can't free a bmap cursor without having dealt with the
385 * allocated indirect blocks' accounting.
387 ASSERT(cur
->bc_btnum
!= XFS_BTNUM_BMAP
||
388 cur
->bc_private
.b
.allocated
== 0);
392 kmem_zone_free(xfs_btree_cur_zone
, cur
);
396 * Duplicate the btree cursor.
397 * Allocate a new one, copy the record, re-get the buffers.
400 xfs_btree_dup_cursor(
401 xfs_btree_cur_t
*cur
, /* input cursor */
402 xfs_btree_cur_t
**ncur
) /* output cursor */
404 xfs_buf_t
*bp
; /* btree block's buffer pointer */
405 int error
; /* error return value */
406 int i
; /* level number of btree block */
407 xfs_mount_t
*mp
; /* mount structure for filesystem */
408 xfs_btree_cur_t
*new; /* new cursor value */
409 xfs_trans_t
*tp
; /* transaction pointer, can be NULL */
414 * Allocate a new cursor like the old one.
416 new = xfs_btree_init_cursor(mp
, tp
, cur
->bc_private
.a
.agbp
,
417 cur
->bc_private
.a
.agno
, cur
->bc_btnum
, cur
->bc_private
.b
.ip
,
418 cur
->bc_private
.b
.whichfork
);
420 * Copy the record currently in the cursor.
422 new->bc_rec
= cur
->bc_rec
;
424 * For each level current, re-get the buffer and copy the ptr value.
426 for (i
= 0; i
< new->bc_nlevels
; i
++) {
427 new->bc_ptrs
[i
] = cur
->bc_ptrs
[i
];
428 new->bc_ra
[i
] = cur
->bc_ra
[i
];
429 if ((bp
= cur
->bc_bufs
[i
])) {
430 if ((error
= xfs_trans_read_buf(mp
, tp
, mp
->m_ddev_targp
,
431 XFS_BUF_ADDR(bp
), mp
->m_bsize
, 0, &bp
))) {
432 xfs_btree_del_cursor(new, error
);
436 new->bc_bufs
[i
] = bp
;
438 ASSERT(!XFS_BUF_GETERROR(bp
));
440 new->bc_bufs
[i
] = NULL
;
443 * For bmap btrees, copy the firstblock, flist, and flags values,
444 * since init cursor doesn't get them.
446 if (new->bc_btnum
== XFS_BTNUM_BMAP
) {
447 new->bc_private
.b
.firstblock
= cur
->bc_private
.b
.firstblock
;
448 new->bc_private
.b
.flist
= cur
->bc_private
.b
.flist
;
449 new->bc_private
.b
.flags
= cur
->bc_private
.b
.flags
;
456 * Change the cursor to point to the first record at the given level.
457 * Other levels are unaffected.
459 int /* success=1, failure=0 */
461 xfs_btree_cur_t
*cur
, /* btree cursor */
462 int level
) /* level to change */
464 xfs_btree_block_t
*block
; /* generic btree block pointer */
465 xfs_buf_t
*bp
; /* buffer containing block */
468 * Get the block pointer for this level.
470 block
= xfs_btree_get_block(cur
, level
, &bp
);
471 xfs_btree_check_block(cur
, block
, level
, bp
);
473 * It's empty, there is no such record.
475 if (INT_ISZERO(block
->bb_h
.bb_numrecs
, ARCH_CONVERT
))
478 * Set the ptr value to 1, that's the first record/key.
480 cur
->bc_ptrs
[level
] = 1;
485 * Retrieve the block pointer from the cursor at the given level.
486 * This may be a bmap btree root or from a buffer.
488 xfs_btree_block_t
* /* generic btree block pointer */
490 xfs_btree_cur_t
*cur
, /* btree cursor */
491 int level
, /* level in btree */
492 xfs_buf_t
**bpp
) /* buffer containing the block */
494 xfs_btree_block_t
*block
; /* return value */
495 xfs_buf_t
*bp
; /* return buffer */
496 xfs_ifork_t
*ifp
; /* inode fork pointer */
497 int whichfork
; /* data or attr fork */
499 if (cur
->bc_btnum
== XFS_BTNUM_BMAP
&& level
== cur
->bc_nlevels
- 1) {
500 whichfork
= cur
->bc_private
.b
.whichfork
;
501 ifp
= XFS_IFORK_PTR(cur
->bc_private
.b
.ip
, whichfork
);
502 block
= (xfs_btree_block_t
*)ifp
->if_broot
;
505 bp
= cur
->bc_bufs
[level
];
506 block
= XFS_BUF_TO_BLOCK(bp
);
508 ASSERT(block
!= NULL
);
514 * Get a buffer for the block, return it with no data read.
515 * Long-form addressing.
517 xfs_buf_t
* /* buffer for fsbno */
519 xfs_mount_t
*mp
, /* file system mount point */
520 xfs_trans_t
*tp
, /* transaction pointer */
521 xfs_fsblock_t fsbno
, /* file system block number */
522 uint lock
) /* lock flags for get_buf */
524 xfs_buf_t
*bp
; /* buffer pointer (return value) */
525 xfs_daddr_t d
; /* real disk block address */
527 ASSERT(fsbno
!= NULLFSBLOCK
);
528 d
= XFS_FSB_TO_DADDR(mp
, fsbno
);
529 bp
= xfs_trans_get_buf(tp
, mp
->m_ddev_targp
, d
, mp
->m_bsize
, lock
);
531 ASSERT(!XFS_BUF_GETERROR(bp
));
536 * Get a buffer for the block, return it with no data read.
537 * Short-form addressing.
539 xfs_buf_t
* /* buffer for agno/agbno */
541 xfs_mount_t
*mp
, /* file system mount point */
542 xfs_trans_t
*tp
, /* transaction pointer */
543 xfs_agnumber_t agno
, /* allocation group number */
544 xfs_agblock_t agbno
, /* allocation group block number */
545 uint lock
) /* lock flags for get_buf */
547 xfs_buf_t
*bp
; /* buffer pointer (return value) */
548 xfs_daddr_t d
; /* real disk block address */
550 ASSERT(agno
!= NULLAGNUMBER
);
551 ASSERT(agbno
!= NULLAGBLOCK
);
552 d
= XFS_AGB_TO_DADDR(mp
, agno
, agbno
);
553 bp
= xfs_trans_get_buf(tp
, mp
->m_ddev_targp
, d
, mp
->m_bsize
, lock
);
555 ASSERT(!XFS_BUF_GETERROR(bp
));
560 * Allocate a new btree cursor.
561 * The cursor is either for allocation (A) or bmap (B) or inodes (I).
563 xfs_btree_cur_t
* /* new btree cursor */
564 xfs_btree_init_cursor(
565 xfs_mount_t
*mp
, /* file system mount point */
566 xfs_trans_t
*tp
, /* transaction pointer */
567 xfs_buf_t
*agbp
, /* (A only) buffer for agf structure */
568 /* (I only) buffer for agi structure */
569 xfs_agnumber_t agno
, /* (AI only) allocation group number */
570 xfs_btnum_t btnum
, /* btree identifier */
571 xfs_inode_t
*ip
, /* (B only) inode owning the btree */
572 int whichfork
) /* (B only) data or attr fork */
574 xfs_agf_t
*agf
; /* (A) allocation group freespace */
575 xfs_agi_t
*agi
; /* (I) allocation group inodespace */
576 xfs_btree_cur_t
*cur
; /* return value */
577 xfs_ifork_t
*ifp
; /* (I) inode fork pointer */
578 int nlevels
=0; /* number of levels in the btree */
580 ASSERT(xfs_btree_cur_zone
!= NULL
);
582 * Allocate a new cursor.
584 cur
= kmem_zone_zalloc(xfs_btree_cur_zone
, KM_SLEEP
);
586 * Deduce the number of btree levels from the arguments.
591 agf
= XFS_BUF_TO_AGF(agbp
);
592 nlevels
= INT_GET(agf
->agf_levels
[btnum
], ARCH_CONVERT
);
595 ifp
= XFS_IFORK_PTR(ip
, whichfork
);
596 nlevels
= INT_GET(ifp
->if_broot
->bb_level
, ARCH_CONVERT
) + 1;
599 agi
= XFS_BUF_TO_AGI(agbp
);
600 nlevels
= INT_GET(agi
->agi_level
, ARCH_CONVERT
);
606 * Fill in the common fields.
610 cur
->bc_nlevels
= nlevels
;
611 cur
->bc_btnum
= btnum
;
612 cur
->bc_blocklog
= mp
->m_sb
.sb_blocklog
;
614 * Fill in private fields.
620 * Allocation btree fields.
622 cur
->bc_private
.a
.agbp
= agbp
;
623 cur
->bc_private
.a
.agno
= agno
;
629 cur
->bc_private
.b
.forksize
= XFS_IFORK_SIZE(ip
, whichfork
);
630 cur
->bc_private
.b
.ip
= ip
;
631 cur
->bc_private
.b
.firstblock
= NULLFSBLOCK
;
632 cur
->bc_private
.b
.flist
= NULL
;
633 cur
->bc_private
.b
.allocated
= 0;
634 cur
->bc_private
.b
.flags
= 0;
635 cur
->bc_private
.b
.whichfork
= whichfork
;
639 * Inode allocation btree fields.
641 cur
->bc_private
.i
.agbp
= agbp
;
642 cur
->bc_private
.i
.agno
= agno
;
651 * Check for the cursor referring to the last block at the given level.
653 int /* 1=is last block, 0=not last block */
654 xfs_btree_islastblock(
655 xfs_btree_cur_t
*cur
, /* btree cursor */
656 int level
) /* level to check */
658 xfs_btree_block_t
*block
; /* generic btree block pointer */
659 xfs_buf_t
*bp
; /* buffer containing block */
661 block
= xfs_btree_get_block(cur
, level
, &bp
);
662 xfs_btree_check_block(cur
, block
, level
, bp
);
663 if (XFS_BTREE_LONG_PTRS(cur
->bc_btnum
))
664 return INT_GET(block
->bb_u
.l
.bb_rightsib
, ARCH_CONVERT
) == NULLDFSBNO
;
666 return INT_GET(block
->bb_u
.s
.bb_rightsib
, ARCH_CONVERT
) == NULLAGBLOCK
;
670 * Change the cursor to point to the last record in the current block
671 * at the given level. Other levels are unaffected.
673 int /* success=1, failure=0 */
675 xfs_btree_cur_t
*cur
, /* btree cursor */
676 int level
) /* level to change */
678 xfs_btree_block_t
*block
; /* generic btree block pointer */
679 xfs_buf_t
*bp
; /* buffer containing block */
682 * Get the block pointer for this level.
684 block
= xfs_btree_get_block(cur
, level
, &bp
);
685 xfs_btree_check_block(cur
, block
, level
, bp
);
687 * It's empty, there is no such record.
689 if (INT_ISZERO(block
->bb_h
.bb_numrecs
, ARCH_CONVERT
))
692 * Set the ptr value to numrecs, that's the last record/key.
694 cur
->bc_ptrs
[level
] = INT_GET(block
->bb_h
.bb_numrecs
, ARCH_CONVERT
);
699 * Compute first and last byte offsets for the fields given.
700 * Interprets the offsets table, which contains struct field offsets.
704 __int64_t fields
, /* bitmask of fields */
705 const short *offsets
, /* table of field offsets */
706 int nbits
, /* number of bits to inspect */
707 int *first
, /* output: first byte offset */
708 int *last
) /* output: last byte offset */
710 int i
; /* current bit number */
711 __int64_t imask
; /* mask for current bit number */
715 * Find the lowest bit, so the first byte offset.
717 for (i
= 0, imask
= 1LL; ; i
++, imask
<<= 1) {
718 if (imask
& fields
) {
724 * Find the highest bit, so the last byte offset.
726 for (i
= nbits
- 1, imask
= 1LL << i
; ; i
--, imask
>>= 1) {
727 if (imask
& fields
) {
728 *last
= offsets
[i
+ 1] - 1;
735 * Get a buffer for the block, return it read in.
736 * Long-form addressing.
740 xfs_mount_t
*mp
, /* file system mount point */
741 xfs_trans_t
*tp
, /* transaction pointer */
742 xfs_fsblock_t fsbno
, /* file system block number */
743 uint lock
, /* lock flags for read_buf */
744 xfs_buf_t
**bpp
, /* buffer for fsbno */
745 int refval
) /* ref count value for buffer */
747 xfs_buf_t
*bp
; /* return value */
748 xfs_daddr_t d
; /* real disk block address */
751 ASSERT(fsbno
!= NULLFSBLOCK
);
752 d
= XFS_FSB_TO_DADDR(mp
, fsbno
);
753 if ((error
= xfs_trans_read_buf(mp
, tp
, mp
->m_ddev_targp
, d
,
754 mp
->m_bsize
, lock
, &bp
))) {
757 ASSERT(!bp
|| !XFS_BUF_GETERROR(bp
));
759 XFS_BUF_SET_VTYPE_REF(bp
, B_FS_MAP
, refval
);
766 * Get a buffer for the block, return it read in.
767 * Short-form addressing.
771 xfs_mount_t
*mp
, /* file system mount point */
772 xfs_trans_t
*tp
, /* transaction pointer */
773 xfs_agnumber_t agno
, /* allocation group number */
774 xfs_agblock_t agbno
, /* allocation group block number */
775 uint lock
, /* lock flags for read_buf */
776 xfs_buf_t
**bpp
, /* buffer for agno/agbno */
777 int refval
) /* ref count value for buffer */
779 xfs_buf_t
*bp
; /* return value */
780 xfs_daddr_t d
; /* real disk block address */
783 ASSERT(agno
!= NULLAGNUMBER
);
784 ASSERT(agbno
!= NULLAGBLOCK
);
785 d
= XFS_AGB_TO_DADDR(mp
, agno
, agbno
);
786 if ((error
= xfs_trans_read_buf(mp
, tp
, mp
->m_ddev_targp
, d
,
787 mp
->m_bsize
, lock
, &bp
))) {
790 ASSERT(!bp
|| !XFS_BUF_GETERROR(bp
));
793 case XFS_ALLOC_BTREE_REF
:
794 XFS_BUF_SET_VTYPE_REF(bp
, B_FS_MAP
, refval
);
796 case XFS_INO_BTREE_REF
:
797 XFS_BUF_SET_VTYPE_REF(bp
, B_FS_INOMAP
, refval
);
806 * Read-ahead btree blocks, at the given level.
807 * Bits in lr are set from XFS_BTCUR_{LEFT,RIGHT}RA.
810 xfs_btree_readahead_core(
811 xfs_btree_cur_t
*cur
, /* btree cursor */
812 int lev
, /* level in btree */
813 int lr
) /* left/right bits */
815 xfs_alloc_block_t
*a
;
817 xfs_inobt_block_t
*i
;
820 ASSERT(cur
->bc_bufs
[lev
] != NULL
);
821 cur
->bc_ra
[lev
] |= lr
;
822 switch (cur
->bc_btnum
) {
825 a
= XFS_BUF_TO_ALLOC_BLOCK(cur
->bc_bufs
[lev
]);
826 if ((lr
& XFS_BTCUR_LEFTRA
) && INT_GET(a
->bb_leftsib
, ARCH_CONVERT
) != NULLAGBLOCK
) {
827 xfs_btree_reada_bufs(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
828 INT_GET(a
->bb_leftsib
, ARCH_CONVERT
), 1);
831 if ((lr
& XFS_BTCUR_RIGHTRA
) && INT_GET(a
->bb_rightsib
, ARCH_CONVERT
) != NULLAGBLOCK
) {
832 xfs_btree_reada_bufs(cur
->bc_mp
, cur
->bc_private
.a
.agno
,
833 INT_GET(a
->bb_rightsib
, ARCH_CONVERT
), 1);
838 b
= XFS_BUF_TO_BMBT_BLOCK(cur
->bc_bufs
[lev
]);
839 if ((lr
& XFS_BTCUR_LEFTRA
) && INT_GET(b
->bb_leftsib
, ARCH_CONVERT
) != NULLDFSBNO
) {
840 xfs_btree_reada_bufl(cur
->bc_mp
, INT_GET(b
->bb_leftsib
, ARCH_CONVERT
), 1);
843 if ((lr
& XFS_BTCUR_RIGHTRA
) && INT_GET(b
->bb_rightsib
, ARCH_CONVERT
) != NULLDFSBNO
) {
844 xfs_btree_reada_bufl(cur
->bc_mp
, INT_GET(b
->bb_rightsib
, ARCH_CONVERT
), 1);
849 i
= XFS_BUF_TO_INOBT_BLOCK(cur
->bc_bufs
[lev
]);
850 if ((lr
& XFS_BTCUR_LEFTRA
) && INT_GET(i
->bb_leftsib
, ARCH_CONVERT
) != NULLAGBLOCK
) {
851 xfs_btree_reada_bufs(cur
->bc_mp
, cur
->bc_private
.i
.agno
,
852 INT_GET(i
->bb_leftsib
, ARCH_CONVERT
), 1);
855 if ((lr
& XFS_BTCUR_RIGHTRA
) && INT_GET(i
->bb_rightsib
, ARCH_CONVERT
) != NULLAGBLOCK
) {
856 xfs_btree_reada_bufs(cur
->bc_mp
, cur
->bc_private
.i
.agno
,
857 INT_GET(i
->bb_rightsib
, ARCH_CONVERT
), 1);
868 * Set the buffer for level "lev" in the cursor to bp, releasing
869 * any previous buffer.
873 xfs_btree_cur_t
*cur
, /* btree cursor */
874 int lev
, /* level in btree */
875 xfs_buf_t
*bp
) /* new buffer to set */
877 xfs_btree_block_t
*b
; /* btree block */
878 xfs_buf_t
*obp
; /* old buffer pointer */
880 obp
= cur
->bc_bufs
[lev
];
882 xfs_trans_brelse(cur
->bc_tp
, obp
);
883 cur
->bc_bufs
[lev
] = bp
;
887 b
= XFS_BUF_TO_BLOCK(bp
);
888 if (XFS_BTREE_LONG_PTRS(cur
->bc_btnum
)) {
889 if (INT_GET(b
->bb_u
.l
.bb_leftsib
, ARCH_CONVERT
) == NULLDFSBNO
)
890 cur
->bc_ra
[lev
] |= XFS_BTCUR_LEFTRA
;
891 if (INT_GET(b
->bb_u
.l
.bb_rightsib
, ARCH_CONVERT
) == NULLDFSBNO
)
892 cur
->bc_ra
[lev
] |= XFS_BTCUR_RIGHTRA
;
894 if (INT_GET(b
->bb_u
.s
.bb_leftsib
, ARCH_CONVERT
) == NULLAGBLOCK
)
895 cur
->bc_ra
[lev
] |= XFS_BTCUR_LEFTRA
;
896 if (INT_GET(b
->bb_u
.s
.bb_rightsib
, ARCH_CONVERT
) == NULLAGBLOCK
)
897 cur
->bc_ra
[lev
] |= XFS_BTCUR_RIGHTRA
;