2020-05-13 02:54:17 +03:00
/* SPDX-License-Identifier: GPL-2.0 */
2005-04-17 02:20:36 +04:00
/*
2005-11-02 06:58:39 +03:00
* Copyright ( c ) 2000 - 2001 , 2005 Silicon Graphics , Inc .
* All Rights Reserved .
2005-04-17 02:20:36 +04:00
*/
# ifndef __XFS_BTREE_H__
# define __XFS_BTREE_H__
struct xfs_buf ;
struct xfs_inode ;
struct xfs_mount ;
struct xfs_trans ;
2020-03-11 20:42:34 +03:00
struct xfs_ifork ;
2021-06-02 03:48:24 +03:00
struct xfs_perag ;
2005-04-17 02:20:36 +04:00
2008-10-30 08:54:12 +03:00
/*
* Generic key , ptr and record wrapper structures .
*
* These are disk format structures , and are converted where necessary
* by the btree specific code that needs to interpret them .
*/
union xfs_btree_ptr {
__be32 s ; /* short form ptr */
__be64 l ; /* long form ptr */
} ;
xfs: support btrees with overlapping intervals for keys
On a filesystem with both reflink and reverse mapping enabled, it's
possible to have multiple rmap records referring to the same blocks on
disk. When overlapping intervals are possible, querying a classic
btree to find all records intersecting a given interval is inefficient
because we cannot use the left side of the search interval to filter
out non-matching records the same way that we can use the existing
btree key to filter out records coming after the right side of the
search interval. This will become important once we want to use the
rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl.
(For the non-overlapping case, we can perform such queries trivially
by starting at the left side of the interval and walking the tree
until we pass the right side.)
Therefore, extend the btree code to come closer to supporting
intervals as a first-class record attribute. This involves widening
the btree node's key space to store both the lowest key reachable via
the node pointer (as the btree does now) and the highest key reachable
via the same pointer and teaching the btree modifying functions to
keep the highest-key records up to date.
This behavior can be turned on via a new btree ops flag so that btrees
that cannot store overlapping intervals don't pay the overhead costs
in terms of extra code and disk format changes.
When we're deleting a record in a btree that supports overlapped
interval records and the deletion results in two btree blocks being
joined, we defer updating the high/low keys until after all possible
joining (at higher levels in the tree) have finished. At this point,
the btree pointers at all levels have been updated to remove the empty
blocks and we can update the low and high keys.
When we're doing this, we must be careful to update the keys of all
node pointers up to the root instead of stopping at the first set of
keys that don't need updating. This is because it's possible for a
single deletion to cause joining of multiple levels of tree, and so
we need to update everything going back to the root.
The diff_two_keys functions return < 0, 0, or > 0 if key1 is less than,
equal to, or greater than key2, respectively. This is consistent
with the rest of the kernel and the C library.
In btree_updkeys(), we need to evaluate the force_all parameter before
running the key diff to avoid reading uninitialized memory when we're
forcing a key update. This happens when we've allocated an empty slot
at level N + 1 to point to a new block at level N and we're in the
process of filling out the new keys.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2016-08-03 04:08:36 +03:00
/*
2016-09-19 03:24:36 +03:00
* The in - core btree key . Overlapping btrees actually store two keys
* per pointer , so we reserve enough memory to hold both . The __ * bigkey
* items should never be accessed directly .
xfs: support btrees with overlapping intervals for keys
On a filesystem with both reflink and reverse mapping enabled, it's
possible to have multiple rmap records referring to the same blocks on
disk. When overlapping intervals are possible, querying a classic
btree to find all records intersecting a given interval is inefficient
because we cannot use the left side of the search interval to filter
out non-matching records the same way that we can use the existing
btree key to filter out records coming after the right side of the
search interval. This will become important once we want to use the
rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl.
(For the non-overlapping case, we can perform such queries trivially
by starting at the left side of the interval and walking the tree
until we pass the right side.)
Therefore, extend the btree code to come closer to supporting
intervals as a first-class record attribute. This involves widening
the btree node's key space to store both the lowest key reachable via
the node pointer (as the btree does now) and the highest key reachable
via the same pointer and teaching the btree modifying functions to
keep the highest-key records up to date.
This behavior can be turned on via a new btree ops flag so that btrees
that cannot store overlapping intervals don't pay the overhead costs
in terms of extra code and disk format changes.
When we're deleting a record in a btree that supports overlapped
interval records and the deletion results in two btree blocks being
joined, we defer updating the high/low keys until after all possible
joining (at higher levels in the tree) have finished. At this point,
the btree pointers at all levels have been updated to remove the empty
blocks and we can update the low and high keys.
When we're doing this, we must be careful to update the keys of all
node pointers up to the root instead of stopping at the first set of
keys that don't need updating. This is because it's possible for a
single deletion to cause joining of multiple levels of tree, and so
we need to update everything going back to the root.
The diff_two_keys functions return < 0, 0, or > 0 if key1 is less than,
equal to, or greater than key2, respectively. This is consistent
with the rest of the kernel and the C library.
In btree_updkeys(), we need to evaluate the force_all parameter before
running the key diff to avoid reading uninitialized memory when we're
forcing a key update. This happens when we've allocated an empty slot
at level N + 1 to point to a new block at level N and we're in the
process of filling out the new keys.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2016-08-03 04:08:36 +03:00
*/
2016-09-19 03:24:36 +03:00
union xfs_btree_key {
xfs: support btrees with overlapping intervals for keys
On a filesystem with both reflink and reverse mapping enabled, it's
possible to have multiple rmap records referring to the same blocks on
disk. When overlapping intervals are possible, querying a classic
btree to find all records intersecting a given interval is inefficient
because we cannot use the left side of the search interval to filter
out non-matching records the same way that we can use the existing
btree key to filter out records coming after the right side of the
search interval. This will become important once we want to use the
rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl.
(For the non-overlapping case, we can perform such queries trivially
by starting at the left side of the interval and walking the tree
until we pass the right side.)
Therefore, extend the btree code to come closer to supporting
intervals as a first-class record attribute. This involves widening
the btree node's key space to store both the lowest key reachable via
the node pointer (as the btree does now) and the highest key reachable
via the same pointer and teaching the btree modifying functions to
keep the highest-key records up to date.
This behavior can be turned on via a new btree ops flag so that btrees
that cannot store overlapping intervals don't pay the overhead costs
in terms of extra code and disk format changes.
When we're deleting a record in a btree that supports overlapped
interval records and the deletion results in two btree blocks being
joined, we defer updating the high/low keys until after all possible
joining (at higher levels in the tree) have finished. At this point,
the btree pointers at all levels have been updated to remove the empty
blocks and we can update the low and high keys.
When we're doing this, we must be careful to update the keys of all
node pointers up to the root instead of stopping at the first set of
keys that don't need updating. This is because it's possible for a
single deletion to cause joining of multiple levels of tree, and so
we need to update everything going back to the root.
The diff_two_keys functions return < 0, 0, or > 0 if key1 is less than,
equal to, or greater than key2, respectively. This is consistent
with the rest of the kernel and the C library.
In btree_updkeys(), we need to evaluate the force_all parameter before
running the key diff to avoid reading uninitialized memory when we're
forcing a key update. This happens when we've allocated an empty slot
at level N + 1 to point to a new block at level N and we're in the
process of filling out the new keys.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2016-08-03 04:08:36 +03:00
struct xfs_bmbt_key bmbt ;
xfs_bmdr_key_t bmbr ; /* bmbt root block */
xfs_alloc_key_t alloc ;
struct xfs_inobt_key inobt ;
2016-09-19 03:24:36 +03:00
struct xfs_rmap_key rmap ;
struct xfs_rmap_key __rmap_bigkey [ 2 ] ;
2016-10-03 19:11:18 +03:00
struct xfs_refcount_key refc ;
xfs: support btrees with overlapping intervals for keys
On a filesystem with both reflink and reverse mapping enabled, it's
possible to have multiple rmap records referring to the same blocks on
disk. When overlapping intervals are possible, querying a classic
btree to find all records intersecting a given interval is inefficient
because we cannot use the left side of the search interval to filter
out non-matching records the same way that we can use the existing
btree key to filter out records coming after the right side of the
search interval. This will become important once we want to use the
rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl.
(For the non-overlapping case, we can perform such queries trivially
by starting at the left side of the interval and walking the tree
until we pass the right side.)
Therefore, extend the btree code to come closer to supporting
intervals as a first-class record attribute. This involves widening
the btree node's key space to store both the lowest key reachable via
the node pointer (as the btree does now) and the highest key reachable
via the same pointer and teaching the btree modifying functions to
keep the highest-key records up to date.
This behavior can be turned on via a new btree ops flag so that btrees
that cannot store overlapping intervals don't pay the overhead costs
in terms of extra code and disk format changes.
When we're deleting a record in a btree that supports overlapped
interval records and the deletion results in two btree blocks being
joined, we defer updating the high/low keys until after all possible
joining (at higher levels in the tree) have finished. At this point,
the btree pointers at all levels have been updated to remove the empty
blocks and we can update the low and high keys.
When we're doing this, we must be careful to update the keys of all
node pointers up to the root instead of stopping at the first set of
keys that don't need updating. This is because it's possible for a
single deletion to cause joining of multiple levels of tree, and so
we need to update everything going back to the root.
The diff_two_keys functions return < 0, 0, or > 0 if key1 is less than,
equal to, or greater than key2, respectively. This is consistent
with the rest of the kernel and the C library.
In btree_updkeys(), we need to evaluate the force_all parameter before
running the key diff to avoid reading uninitialized memory when we're
forcing a key update. This happens when we've allocated an empty slot
at level N + 1 to point to a new block at level N and we're in the
process of filling out the new keys.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2016-08-03 04:08:36 +03:00
} ;
2008-10-30 08:54:12 +03:00
union xfs_btree_rec {
2016-08-03 04:36:07 +03:00
struct xfs_bmbt_rec bmbt ;
xfs_bmdr_rec_t bmbr ; /* bmbt root block */
struct xfs_alloc_rec alloc ;
struct xfs_inobt_rec inobt ;
struct xfs_rmap_rec rmap ;
2016-10-03 19:11:18 +03:00
struct xfs_refcount_rec refc ;
2008-10-30 08:54:12 +03:00
} ;
2013-10-23 03:51:50 +04:00
/*
* This nonsense is to make - wlint happy .
*/
# define XFS_LOOKUP_EQ ((xfs_lookup_t)XFS_LOOKUP_EQi)
# define XFS_LOOKUP_LE ((xfs_lookup_t)XFS_LOOKUP_LEi)
# define XFS_LOOKUP_GE ((xfs_lookup_t)XFS_LOOKUP_GEi)
# define XFS_BTNUM_BNO ((xfs_btnum_t)XFS_BTNUM_BNOi)
# define XFS_BTNUM_CNT ((xfs_btnum_t)XFS_BTNUM_CNTi)
# define XFS_BTNUM_BMAP ((xfs_btnum_t)XFS_BTNUM_BMAPi)
# define XFS_BTNUM_INO ((xfs_btnum_t)XFS_BTNUM_INOi)
2014-04-24 10:00:52 +04:00
# define XFS_BTNUM_FINO ((xfs_btnum_t)XFS_BTNUM_FINOi)
2016-08-03 04:30:32 +03:00
# define XFS_BTNUM_RMAP ((xfs_btnum_t)XFS_BTNUM_RMAPi)
2016-10-03 19:11:16 +03:00
# define XFS_BTNUM_REFC ((xfs_btnum_t)XFS_BTNUM_REFCi)
2013-10-23 03:51:50 +04:00
2017-06-16 21:00:05 +03:00
uint32_t xfs_btree_magic ( int crc , xfs_btnum_t btnum ) ;
2017-01-28 10:16:38 +03:00
2005-04-17 02:20:36 +04:00
/*
* For logging record fields .
*/
2022-04-21 03:46:33 +03:00
# define XFS_BB_MAGIC (1u << 0)
# define XFS_BB_LEVEL (1u << 1)
# define XFS_BB_NUMRECS (1u << 2)
# define XFS_BB_LEFTSIB (1u << 3)
# define XFS_BB_RIGHTSIB (1u << 4)
# define XFS_BB_BLKNO (1u << 5)
# define XFS_BB_LSN (1u << 6)
# define XFS_BB_UUID (1u << 7)
# define XFS_BB_OWNER (1u << 8)
2005-04-17 02:20:36 +04:00
# define XFS_BB_NUM_BITS 5
2022-04-21 03:46:33 +03:00
# define XFS_BB_ALL_BITS ((1u << XFS_BB_NUM_BITS) - 1)
2013-08-30 04:23:44 +04:00
# define XFS_BB_NUM_BITS_CRC 9
2022-04-21 03:46:33 +03:00
# define XFS_BB_ALL_BITS_CRC ((1u << XFS_BB_NUM_BITS_CRC) - 1)
2005-04-17 02:20:36 +04:00
2008-10-30 08:55:03 +03:00
/*
* Generic stats interface
*/
2015-10-12 10:21:22 +03:00
# define XFS_BTREE_STATS_INC(cur, stat) \
2016-12-05 06:38:58 +03:00
XFS_STATS_INC_OFF ( ( cur ) - > bc_mp , ( cur ) - > bc_statoff + __XBTS_ # # stat )
# define XFS_BTREE_STATS_ADD(cur, stat, val) \
XFS_STATS_ADD_OFF ( ( cur ) - > bc_mp , ( cur ) - > bc_statoff + __XBTS_ # # stat , val )
2005-04-17 02:20:36 +04:00
2008-10-30 08:53:59 +03:00
struct xfs_btree_ops {
2008-10-30 08:55:34 +03:00
/* size of the key and record structures */
size_t key_len ;
size_t rec_len ;
2008-10-30 08:53:59 +03:00
/* cursor operations */
struct xfs_btree_cur * ( * dup_cursor ) ( struct xfs_btree_cur * ) ;
2008-10-30 08:57:40 +03:00
void ( * update_cursor ) ( struct xfs_btree_cur * src ,
struct xfs_btree_cur * dst ) ;
2008-10-30 08:55:13 +03:00
2008-10-30 08:57:16 +03:00
/* update btree root pointer */
void ( * set_root ) ( struct xfs_btree_cur * cur ,
2021-08-12 19:49:03 +03:00
const union xfs_btree_ptr * nptr , int level_change ) ;
2008-10-30 08:57:16 +03:00
2008-10-30 08:57:03 +03:00
/* block allocation / freeing */
int ( * alloc_block ) ( struct xfs_btree_cur * cur ,
2021-08-12 19:53:27 +03:00
const union xfs_btree_ptr * start_bno ,
2008-10-30 08:57:03 +03:00
union xfs_btree_ptr * new_bno ,
2014-04-14 13:03:53 +04:00
int * stat ) ;
2008-10-30 08:57:51 +03:00
int ( * free_block ) ( struct xfs_btree_cur * cur , struct xfs_buf * bp ) ;
2008-10-30 08:57:03 +03:00
2008-10-30 08:56:32 +03:00
/* update last record information */
void ( * update_lastrec ) ( struct xfs_btree_cur * cur ,
2021-08-12 19:56:49 +03:00
const struct xfs_btree_block * block ,
const union xfs_btree_rec * rec ,
2008-10-30 08:56:32 +03:00
int ptr , int reason ) ;
2008-10-30 08:55:23 +03:00
/* records in block/level */
2008-10-30 08:58:01 +03:00
int ( * get_minrecs ) ( struct xfs_btree_cur * cur , int level ) ;
2008-10-30 08:55:23 +03:00
int ( * get_maxrecs ) ( struct xfs_btree_cur * cur , int level ) ;
2008-10-30 08:57:40 +03:00
/* records on disk. Matter for the root in inode case. */
int ( * get_dmaxrecs ) ( struct xfs_btree_cur * cur , int level ) ;
2008-10-30 08:56:09 +03:00
/* init values of btree structures */
void ( * init_key_from_rec ) ( union xfs_btree_key * key ,
2021-08-11 03:02:16 +03:00
const union xfs_btree_rec * rec ) ;
2008-10-30 08:57:40 +03:00
void ( * init_rec_from_cur ) ( struct xfs_btree_cur * cur ,
union xfs_btree_rec * rec ) ;
2008-10-30 08:56:09 +03:00
void ( * init_ptr_from_cur ) ( struct xfs_btree_cur * cur ,
union xfs_btree_ptr * ptr ) ;
xfs: support btrees with overlapping intervals for keys
On a filesystem with both reflink and reverse mapping enabled, it's
possible to have multiple rmap records referring to the same blocks on
disk. When overlapping intervals are possible, querying a classic
btree to find all records intersecting a given interval is inefficient
because we cannot use the left side of the search interval to filter
out non-matching records the same way that we can use the existing
btree key to filter out records coming after the right side of the
search interval. This will become important once we want to use the
rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl.
(For the non-overlapping case, we can perform such queries trivially
by starting at the left side of the interval and walking the tree
until we pass the right side.)
Therefore, extend the btree code to come closer to supporting
intervals as a first-class record attribute. This involves widening
the btree node's key space to store both the lowest key reachable via
the node pointer (as the btree does now) and the highest key reachable
via the same pointer and teaching the btree modifying functions to
keep the highest-key records up to date.
This behavior can be turned on via a new btree ops flag so that btrees
that cannot store overlapping intervals don't pay the overhead costs
in terms of extra code and disk format changes.
When we're deleting a record in a btree that supports overlapped
interval records and the deletion results in two btree blocks being
joined, we defer updating the high/low keys until after all possible
joining (at higher levels in the tree) have finished. At this point,
the btree pointers at all levels have been updated to remove the empty
blocks and we can update the low and high keys.
When we're doing this, we must be careful to update the keys of all
node pointers up to the root instead of stopping at the first set of
keys that don't need updating. This is because it's possible for a
single deletion to cause joining of multiple levels of tree, and so
we need to update everything going back to the root.
The diff_two_keys functions return < 0, 0, or > 0 if key1 is less than,
equal to, or greater than key2, respectively. This is consistent
with the rest of the kernel and the C library.
In btree_updkeys(), we need to evaluate the force_all parameter before
running the key diff to avoid reading uninitialized memory when we're
forcing a key update. This happens when we've allocated an empty slot
at level N + 1 to point to a new block at level N and we're in the
process of filling out the new keys.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2016-08-03 04:08:36 +03:00
void ( * init_high_key_from_rec ) ( union xfs_btree_key * key ,
2021-08-11 03:02:16 +03:00
const union xfs_btree_rec * rec ) ;
2008-10-30 08:56:09 +03:00
/* difference between key value and cursor value */
2017-06-16 21:00:05 +03:00
int64_t ( * key_diff ) ( struct xfs_btree_cur * cur ,
2021-08-11 03:02:15 +03:00
const union xfs_btree_key * key ) ;
2008-10-30 08:56:09 +03:00
xfs: support btrees with overlapping intervals for keys
On a filesystem with both reflink and reverse mapping enabled, it's
possible to have multiple rmap records referring to the same blocks on
disk. When overlapping intervals are possible, querying a classic
btree to find all records intersecting a given interval is inefficient
because we cannot use the left side of the search interval to filter
out non-matching records the same way that we can use the existing
btree key to filter out records coming after the right side of the
search interval. This will become important once we want to use the
rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl.
(For the non-overlapping case, we can perform such queries trivially
by starting at the left side of the interval and walking the tree
until we pass the right side.)
Therefore, extend the btree code to come closer to supporting
intervals as a first-class record attribute. This involves widening
the btree node's key space to store both the lowest key reachable via
the node pointer (as the btree does now) and the highest key reachable
via the same pointer and teaching the btree modifying functions to
keep the highest-key records up to date.
This behavior can be turned on via a new btree ops flag so that btrees
that cannot store overlapping intervals don't pay the overhead costs
in terms of extra code and disk format changes.
When we're deleting a record in a btree that supports overlapped
interval records and the deletion results in two btree blocks being
joined, we defer updating the high/low keys until after all possible
joining (at higher levels in the tree) have finished. At this point,
the btree pointers at all levels have been updated to remove the empty
blocks and we can update the low and high keys.
When we're doing this, we must be careful to update the keys of all
node pointers up to the root instead of stopping at the first set of
keys that don't need updating. This is because it's possible for a
single deletion to cause joining of multiple levels of tree, and so
we need to update everything going back to the root.
The diff_two_keys functions return < 0, 0, or > 0 if key1 is less than,
equal to, or greater than key2, respectively. This is consistent
with the rest of the kernel and the C library.
In btree_updkeys(), we need to evaluate the force_all parameter before
running the key diff to avoid reading uninitialized memory when we're
forcing a key update. This happens when we've allocated an empty slot
at level N + 1 to point to a new block at level N and we're in the
process of filling out the new keys.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2016-08-03 04:08:36 +03:00
/*
* Difference between key2 and key1 - - positive if key1 > key2 ,
* negative if key1 < key2 , and zero if equal .
*/
2017-06-16 21:00:05 +03:00
int64_t ( * diff_two_keys ) ( struct xfs_btree_cur * cur ,
2021-08-11 03:02:15 +03:00
const union xfs_btree_key * key1 ,
const union xfs_btree_key * key2 ) ;
xfs: support btrees with overlapping intervals for keys
On a filesystem with both reflink and reverse mapping enabled, it's
possible to have multiple rmap records referring to the same blocks on
disk. When overlapping intervals are possible, querying a classic
btree to find all records intersecting a given interval is inefficient
because we cannot use the left side of the search interval to filter
out non-matching records the same way that we can use the existing
btree key to filter out records coming after the right side of the
search interval. This will become important once we want to use the
rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl.
(For the non-overlapping case, we can perform such queries trivially
by starting at the left side of the interval and walking the tree
until we pass the right side.)
Therefore, extend the btree code to come closer to supporting
intervals as a first-class record attribute. This involves widening
the btree node's key space to store both the lowest key reachable via
the node pointer (as the btree does now) and the highest key reachable
via the same pointer and teaching the btree modifying functions to
keep the highest-key records up to date.
This behavior can be turned on via a new btree ops flag so that btrees
that cannot store overlapping intervals don't pay the overhead costs
in terms of extra code and disk format changes.
When we're deleting a record in a btree that supports overlapped
interval records and the deletion results in two btree blocks being
joined, we defer updating the high/low keys until after all possible
joining (at higher levels in the tree) have finished. At this point,
the btree pointers at all levels have been updated to remove the empty
blocks and we can update the low and high keys.
When we're doing this, we must be careful to update the keys of all
node pointers up to the root instead of stopping at the first set of
keys that don't need updating. This is because it's possible for a
single deletion to cause joining of multiple levels of tree, and so
we need to update everything going back to the root.
The diff_two_keys functions return < 0, 0, or > 0 if key1 is less than,
equal to, or greater than key2, respectively. This is consistent
with the rest of the kernel and the C library.
In btree_updkeys(), we need to evaluate the force_all parameter before
running the key diff to avoid reading uninitialized memory when we're
forcing a key update. This happens when we've allocated an empty slot
at level N + 1 to point to a new block at level N and we're in the
process of filling out the new keys.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2016-08-03 04:08:36 +03:00
2012-11-14 10:54:40 +04:00
const struct xfs_buf_ops * buf_ops ;
2012-11-14 10:53:49 +04:00
2008-10-30 08:58:32 +03:00
/* check that k1 is lower than k2 */
int ( * keys_inorder ) ( struct xfs_btree_cur * cur ,
2021-08-11 03:02:17 +03:00
const union xfs_btree_key * k1 ,
const union xfs_btree_key * k2 ) ;
2008-10-30 08:58:32 +03:00
/* check that r1 is lower than r2 */
int ( * recs_inorder ) ( struct xfs_btree_cur * cur ,
2021-08-11 03:02:17 +03:00
const union xfs_btree_rec * r1 ,
const union xfs_btree_rec * r2 ) ;
2008-10-30 08:53:59 +03:00
} ;
2008-10-30 08:56:32 +03:00
/*
* Reasons for the update_lastrec method to be called .
*/
# define LASTREC_UPDATE 0
2008-10-30 08:57:40 +03:00
# define LASTREC_INSREC 1
2008-10-30 08:58:01 +03:00
# define LASTREC_DELREC 2
2008-10-30 08:56:32 +03:00
2016-08-03 04:10:21 +03:00
union xfs_btree_irec {
struct xfs_alloc_rec_incore a ;
struct xfs_bmbt_irec b ;
struct xfs_inobt_rec_incore i ;
2016-08-03 04:39:05 +03:00
struct xfs_rmap_irec r ;
2016-10-03 19:11:18 +03:00
struct xfs_refcount_irec rc ;
} ;
2020-03-11 03:57:07 +03:00
/* Per-AG btree information. */
struct xfs_btree_cur_ag {
2021-09-23 19:41:13 +03:00
struct xfs_perag * pag ;
2020-03-11 20:40:26 +03:00
union {
struct xfs_buf * agbp ;
struct xbtree_afakeroot * afake ; /* for staging cursor */
} ;
2020-03-11 03:57:51 +03:00
union {
struct {
2021-09-23 19:41:13 +03:00
unsigned int nr_ops ; /* # record updates */
unsigned int shape_changes ; /* # of extent splits */
2020-03-11 03:57:51 +03:00
} refc ;
struct {
2021-09-23 19:41:13 +03:00
bool active ; /* allocation cursor state */
2020-03-11 03:57:51 +03:00
} abt ;
} ;
2020-03-11 03:57:07 +03:00
} ;
/* Btree-in-inode cursor information */
struct xfs_btree_cur_ino {
struct xfs_inode * ip ;
2020-03-11 20:42:34 +03:00
struct xbtree_ifakeroot * ifake ; /* for staging cursor */
2020-03-11 03:57:07 +03:00
int allocated ;
short forksize ;
char whichfork ;
char flags ;
/* We are converting a delalloc reservation */
# define XFS_BTCUR_BMBT_WASDEL (1 << 0)
/* For extent swap, ignore owner check in verifier */
# define XFS_BTCUR_BMBT_INVALID_OWNER (1 << 1)
} ;
2021-09-16 22:24:04 +03:00
struct xfs_btree_level {
/* buffer pointer */
struct xfs_buf * bp ;
/* key/record number */
uint16_t ptr ;
/* readahead info */
# define XFS_BTCUR_LEFTRA (1 << 0) /* left sibling has been read-ahead */
# define XFS_BTCUR_RIGHTRA (1 << 1) /* right sibling has been read-ahead */
uint16_t ra ;
} ;
2005-04-17 02:20:36 +04:00
/*
* Btree cursor structure .
* This collects all information needed by the btree code in one place .
*/
2021-09-16 22:18:47 +03:00
struct xfs_btree_cur
2005-04-17 02:20:36 +04:00
{
struct xfs_trans * bc_tp ; /* transaction we're in, if any */
struct xfs_mount * bc_mp ; /* file system mount struct */
2008-10-30 08:53:59 +03:00
const struct xfs_btree_ops * bc_ops ;
2021-09-28 00:26:19 +03:00
struct kmem_cache * bc_cache ; /* cursor cache */
2021-10-12 19:41:47 +03:00
unsigned int bc_flags ; /* btree features - below */
xfs_btnum_t bc_btnum ; /* identifies which btree type */
2016-08-03 04:10:21 +03:00
union xfs_btree_irec bc_rec ; /* current insert/search record value */
2021-10-12 19:41:47 +03:00
uint8_t bc_nlevels ; /* number of levels in the tree */
2021-09-16 22:26:56 +03:00
uint8_t bc_maxlevels ; /* maximum levels for this btree type */
2021-10-12 19:41:47 +03:00
int bc_statoff ; /* offset of btree stats array */
2021-06-02 03:48:24 +03:00
/*
* Short btree pointers need an agno to be able to turn the pointers
* into physical addresses for IO , so the btree cursor switches between
* bc_ino and bc_ag based on whether XFS_BTREE_LONG_PTRS is set for the
* cursor .
*/
2005-04-17 02:20:36 +04:00
union {
2020-03-11 03:57:07 +03:00
struct xfs_btree_cur_ag bc_ag ;
struct xfs_btree_cur_ino bc_ino ;
} ;
2021-09-16 22:24:04 +03:00
/* Must be at the end of the struct! */
struct xfs_btree_level bc_levels [ ] ;
2021-09-16 22:18:47 +03:00
} ;
2005-04-17 02:20:36 +04:00
2021-09-16 22:24:04 +03:00
/*
* Compute the size of a btree cursor that can handle a btree of a given
* height . The bc_levels array handles node and leaf blocks , so its size
* is exactly nlevels .
*/
static inline size_t
xfs_btree_cur_sizeof ( unsigned int nlevels )
{
return struct_size ( ( struct xfs_btree_cur * ) NULL , bc_levels , nlevels ) ;
}
2008-10-30 08:54:22 +03:00
/* cursor flags */
2008-10-30 08:54:33 +03:00
# define XFS_BTREE_LONG_PTRS (1<<0) /* pointers are 64bits long */
2008-10-30 08:54:22 +03:00
# define XFS_BTREE_ROOT_IN_INODE (1<<1) /* root may be variable size */
2008-10-30 08:56:32 +03:00
# define XFS_BTREE_LASTREC_UPDATE (1<<2) /* track last rec externally */
2013-04-21 23:53:46 +04:00
# define XFS_BTREE_CRC_BLOCKS (1<<3) /* uses extended btree blocks */
xfs: support btrees with overlapping intervals for keys
On a filesystem with both reflink and reverse mapping enabled, it's
possible to have multiple rmap records referring to the same blocks on
disk. When overlapping intervals are possible, querying a classic
btree to find all records intersecting a given interval is inefficient
because we cannot use the left side of the search interval to filter
out non-matching records the same way that we can use the existing
btree key to filter out records coming after the right side of the
search interval. This will become important once we want to use the
rmap btree to rebuild BMBTs, or implement the (future) fsmap ioctl.
(For the non-overlapping case, we can perform such queries trivially
by starting at the left side of the interval and walking the tree
until we pass the right side.)
Therefore, extend the btree code to come closer to supporting
intervals as a first-class record attribute. This involves widening
the btree node's key space to store both the lowest key reachable via
the node pointer (as the btree does now) and the highest key reachable
via the same pointer and teaching the btree modifying functions to
keep the highest-key records up to date.
This behavior can be turned on via a new btree ops flag so that btrees
that cannot store overlapping intervals don't pay the overhead costs
in terms of extra code and disk format changes.
When we're deleting a record in a btree that supports overlapped
interval records and the deletion results in two btree blocks being
joined, we defer updating the high/low keys until after all possible
joining (at higher levels in the tree) have finished. At this point,
the btree pointers at all levels have been updated to remove the empty
blocks and we can update the low and high keys.
When we're doing this, we must be careful to update the keys of all
node pointers up to the root instead of stopping at the first set of
keys that don't need updating. This is because it's possible for a
single deletion to cause joining of multiple levels of tree, and so
we need to update everything going back to the root.
The diff_two_keys functions return < 0, 0, or > 0 if key1 is less than,
equal to, or greater than key2, respectively. This is consistent
with the rest of the kernel and the C library.
In btree_updkeys(), we need to evaluate the force_all parameter before
running the key diff to avoid reading uninitialized memory when we're
forcing a key update. This happens when we've allocated an empty slot
at level N + 1 to point to a new block at level N and we're in the
process of filling out the new keys.
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
Reviewed-by: Dave Chinner <dchinner@redhat.com>
Signed-off-by: Dave Chinner <david@fromorbit.com>
2016-08-03 04:08:36 +03:00
# define XFS_BTREE_OVERLAPPING (1<<4) /* overlapping intervals */
2020-03-11 20:40:26 +03:00
/*
* The root of this btree is a fakeroot structure so that we can stage a btree
* rebuild without leaving it accessible via primary metadata . The ops struct
* is dynamically allocated and must be freed when the cursor is deleted .
*/
# define XFS_BTREE_STAGING (1<<5)
2008-10-30 08:54:22 +03:00
2005-04-17 02:20:36 +04:00
# define XFS_BTREE_NOERROR 0
# define XFS_BTREE_ERROR 1
/*
* Convert from buffer to btree block header .
*/
2011-07-23 03:40:15 +04:00
# define XFS_BUF_TO_BLOCK(bp) ((struct xfs_btree_block *)((bp)->b_addr))
2005-04-17 02:20:36 +04:00
2017-10-18 07:37:33 +03:00
/*
* Internal long and short btree block checks . They return NULL if the
* block is ok or the address of the failed check otherwise .
*/
xfs_failaddr_t __xfs_btree_check_lblock ( struct xfs_btree_cur * cur ,
struct xfs_btree_block * block , int level , struct xfs_buf * bp ) ;
xfs_failaddr_t __xfs_btree_check_sblock ( struct xfs_btree_cur * cur ,
struct xfs_btree_block * block , int level , struct xfs_buf * bp ) ;
2005-04-17 02:20:36 +04:00
/*
2008-10-30 08:54:53 +03:00
* Check that block header is ok .
2005-04-17 02:20:36 +04:00
*/
2008-10-30 08:54:53 +03:00
int
xfs_btree_check_block (
struct xfs_btree_cur * cur , /* btree cursor */
struct xfs_btree_block * block , /* generic btree block pointer */
2005-04-17 02:20:36 +04:00
int level , /* level of the btree block */
struct xfs_buf * bp ) ; /* buffer containing block, if any */
/*
2008-10-30 08:54:53 +03:00
* Check that ( long ) pointer is ok .
2005-04-17 02:20:36 +04:00
*/
2017-10-18 07:37:33 +03:00
bool /* error (0 or EFSCORRUPTED) */
2005-04-17 02:20:36 +04:00
xfs_btree_check_lptr (
2008-10-30 08:54:53 +03:00
struct xfs_btree_cur * cur , /* btree cursor */
2017-10-18 07:37:33 +03:00
xfs_fsblock_t fsbno , /* btree block disk address */
int level ) ; /* btree block level */
/*
* Check that ( short ) pointer is ok .
*/
bool /* error (0 or EFSCORRUPTED) */
xfs_btree_check_sptr (
struct xfs_btree_cur * cur , /* btree cursor */
xfs_agblock_t agbno , /* btree block disk address */
2005-04-17 02:20:36 +04:00
int level ) ; /* btree block level */
/*
* Delete the btree cursor .
*/
void
xfs_btree_del_cursor (
2021-09-16 22:18:47 +03:00
struct xfs_btree_cur * cur , /* btree cursor */
2005-04-17 02:20:36 +04:00
int error ) ; /* del because of error */
/*
* Duplicate the btree cursor .
* Allocate a new one , copy the record , re - get the buffers .
*/
int /* error */
xfs_btree_dup_cursor (
2021-09-16 22:18:47 +03:00
struct xfs_btree_cur * cur , /* input cursor */
struct xfs_btree_cur * * ncur ) ; /* output cursor */
2005-04-17 02:20:36 +04:00
/*
* Compute first and last byte offsets for the fields given .
* Interprets the offsets table , which contains struct field offsets .
*/
void
xfs_btree_offsets (
2022-04-21 03:46:33 +03:00
uint32_t fields , /* bitmask of fields */
2005-04-17 02:20:36 +04:00
const short * offsets , /* table of field offsets */
int nbits , /* number of bits to inspect */
int * first , /* output: first byte offset */
int * last ) ; /* output: last byte offset */
/*
* Get a buffer for the block , return it read in .
* Long - form addressing .
*/
int /* error */
xfs_btree_read_bufl (
struct xfs_mount * mp , /* file system mount point */
struct xfs_trans * tp , /* transaction pointer */
xfs_fsblock_t fsbno , /* file system block number */
struct xfs_buf * * bpp , /* buffer for fsbno */
2012-11-12 15:54:08 +04:00
int refval , /* ref count value for buffer */
2012-11-14 10:54:40 +04:00
const struct xfs_buf_ops * ops ) ;
2005-04-17 02:20:36 +04:00
/*
* Read - ahead the block , don ' t wait for it , don ' t return a buffer .
* Long - form addressing .
*/
void /* error */
xfs_btree_reada_bufl (
struct xfs_mount * mp , /* file system mount point */
xfs_fsblock_t fsbno , /* file system block number */
2012-11-12 15:54:08 +04:00
xfs_extlen_t count , /* count of filesystem blocks */
2012-11-14 10:54:40 +04:00
const struct xfs_buf_ops * ops ) ;
2005-04-17 02:20:36 +04:00
/*
* Read - ahead the block , don ' t wait for it , don ' t return a buffer .
* Short - form addressing .
*/
void /* error */
xfs_btree_reada_bufs (
struct xfs_mount * mp , /* file system mount point */
xfs_agnumber_t agno , /* allocation group number */
xfs_agblock_t agbno , /* allocation group block number */
2012-11-12 15:54:08 +04:00
xfs_extlen_t count , /* count of filesystem blocks */
2012-11-14 10:54:40 +04:00
const struct xfs_buf_ops * ops ) ;
2005-04-17 02:20:36 +04:00
2012-11-14 02:40:27 +04:00
/*
* Initialise a new btree block header
*/
void
xfs_btree_init_block (
struct xfs_mount * mp ,
struct xfs_buf * bp ,
2017-01-28 10:16:39 +03:00
xfs_btnum_t btnum ,
2012-11-14 02:40:27 +04:00
__u16 level ,
__u16 numrecs ,
2019-06-12 19:00:00 +03:00
__u64 owner ) ;
2008-10-30 08:55:34 +03:00
2013-04-21 23:53:46 +04:00
void
xfs_btree_init_block_int (
struct xfs_mount * mp ,
struct xfs_btree_block * buf ,
xfs_daddr_t blkno ,
2017-01-28 10:16:39 +03:00
xfs_btnum_t btnum ,
2013-04-21 23:53:46 +04:00
__u16 level ,
__u16 numrecs ,
__u64 owner ,
unsigned int flags ) ;
2008-10-30 08:55:45 +03:00
/*
* Common btree core entry points .
*/
int xfs_btree_increment ( struct xfs_btree_cur * , int , int * ) ;
2008-10-30 08:55:58 +03:00
int xfs_btree_decrement ( struct xfs_btree_cur * , int , int * ) ;
2008-10-30 08:56:09 +03:00
int xfs_btree_lookup ( struct xfs_btree_cur * , xfs_lookup_t , int * ) ;
2008-10-30 08:56:32 +03:00
int xfs_btree_update ( struct xfs_btree_cur * , union xfs_btree_rec * ) ;
2008-10-30 08:57:28 +03:00
int xfs_btree_new_iroot ( struct xfs_btree_cur * , int * , int * ) ;
2008-10-30 08:57:40 +03:00
int xfs_btree_insert ( struct xfs_btree_cur * , int * ) ;
2008-10-30 08:58:01 +03:00
int xfs_btree_delete ( struct xfs_btree_cur * , int * ) ;
2008-10-30 08:58:11 +03:00
int xfs_btree_get_rec ( struct xfs_btree_cur * , union xfs_btree_rec * * , int * ) ;
2017-06-16 21:00:05 +03:00
int xfs_btree_change_owner ( struct xfs_btree_cur * cur , uint64_t new_owner ,
xfs: recovery of swap extents operations for CRC filesystems
This is the recovery side of the btree block owner change operation
performed by swapext on CRC enabled filesystems. We detect that an
owner change is needed by the flag that has been placed on the inode
log format flag field. Because the inode recovery is being replayed
after the buffers that make up the BMBT in the given checkpoint, we
can walk all the buffers and directly modify them when we see the
flag set on an inode.
Because the inode can be relogged and hence present in multiple
chekpoints with the "change owner" flag set, we could do multiple
passes across the inode to do this change. While this isn't optimal,
we can't directly ignore the flag as there may be multiple
independent swap extent operations being replayed on the same inode
in different checkpoints so we can't ignore them.
Further, because the owner change operation uses ordered buffers, we
might have buffers that are newer on disk than the current
checkpoint and so already have the owner changed in them. Hence we
cannot just peek at a buffer in the tree and check that it has the
correct owner and assume that the change was completed.
So, for the moment just brute force the owner change every time we
see an inode with the flag set. Note that we have to be careful here
because the owner of the buffers may point to either the old owner
or the new owner. Currently the verifier can't verify the owner
directly, so there is no failure case here right now. If we verify
the owner exactly in future, then we'll have to take this into
account.
This was tested in terms of normal operation via xfstests - all of
the fsr tests now pass without failure. however, we really need to
modify xfs/227 to stress v3 inodes correctly to ensure we fully
cover this case for v5 filesystems.
In terms of recovery testing, I used a hacked version of xfs_fsr
that held the temp inode open for a few seconds before exiting so
that the filesystem could be shut down with an open owner change
recovery flags set on at least the temp inode. fsr leaves the temp
inode unlinked and in btree format, so this was necessary for the
owner change to be reliably replayed.
logprint confirmed the tmp inode in the log had the correct flag set:
INO: cnt:3 total:3 a:0x69e9e0 len:56 a:0x69ea20 len:176 a:0x69eae0 len:88
INODE: #regs:3 ino:0x44 flags:0x209 dsize:88
^^^^^
0x200 is set, indicating a data fork owner change needed to be
replayed on inode 0x44. A printk in the revoery code confirmed that
the inode change was recovered:
XFS (vdc): Mounting Filesystem
XFS (vdc): Starting recovery (logdev: internal)
recovering owner change ino 0x44
XFS (vdc): Version 5 superblock detected. This kernel L support enabled!
Use of these features in this kernel is at your own risk!
XFS (vdc): Ending recovery (logdev: internal)
The script used to test this was:
$ cat ./recovery-fsr.sh
#!/bin/bash
dev=/dev/vdc
mntpt=/mnt/scratch
testfile=$mntpt/testfile
umount $mntpt
mkfs.xfs -f -m crc=1 $dev
mount $dev $mntpt
chmod 777 $mntpt
for i in `seq 10000 -1 0`; do
xfs_io -f -d -c "pwrite $(($i * 4096)) 4096" $testfile > /dev/null 2>&1
done
xfs_bmap -vp $testfile |head -20
xfs_fsr -d -v $testfile &
sleep 10
/home/dave/src/xfstests-dev/src/godown -f $mntpt
wait
umount $mntpt
xfs_logprint -t $dev |tail -20
time mount $dev $mntpt
xfs_bmap -vp $testfile
umount $mntpt
$
Signed-off-by: Dave Chinner <dchinner@redhat.com>
Reviewed-by: Mark Tinguely <tinguely@sgi.com>
Signed-off-by: Ben Myers <bpm@sgi.com>
2013-08-30 04:23:45 +04:00
struct list_head * buffer_list ) ;
2008-10-30 08:55:45 +03:00
2013-04-21 23:53:46 +04:00
/*
* btree block CRC helpers
*/
void xfs_btree_lblock_calc_crc ( struct xfs_buf * ) ;
bool xfs_btree_lblock_verify_crc ( struct xfs_buf * ) ;
void xfs_btree_sblock_calc_crc ( struct xfs_buf * ) ;
bool xfs_btree_sblock_verify_crc ( struct xfs_buf * ) ;
2008-10-30 08:58:21 +03:00
/*
* Internal btree helpers also used by xfs_bmap . c .
*/
2022-04-21 03:46:33 +03:00
void xfs_btree_log_block ( struct xfs_btree_cur * , struct xfs_buf * , uint32_t ) ;
2008-10-30 08:58:21 +03:00
void xfs_btree_log_recs ( struct xfs_btree_cur * , struct xfs_buf * , int , int ) ;
2008-10-30 08:55:34 +03:00
/*
* Helpers .
*/
2021-08-12 19:56:49 +03:00
static inline int xfs_btree_get_numrecs ( const struct xfs_btree_block * block )
2008-10-30 08:55:45 +03:00
{
return be16_to_cpu ( block - > bb_numrecs ) ;
}
2008-10-30 08:56:43 +03:00
static inline void xfs_btree_set_numrecs ( struct xfs_btree_block * block ,
2017-06-16 21:00:05 +03:00
uint16_t numrecs )
2008-10-30 08:56:43 +03:00
{
block - > bb_numrecs = cpu_to_be16 ( numrecs ) ;
}
2021-08-12 19:56:49 +03:00
static inline int xfs_btree_get_level ( const struct xfs_btree_block * block )
2008-10-30 08:55:34 +03:00
{
return be16_to_cpu ( block - > bb_level ) ;
}
2005-04-17 02:20:36 +04:00
/*
* Min and max functions for extlen , agblock , fileoff , and filblks types .
*/
2007-06-28 10:43:39 +04:00
# define XFS_EXTLEN_MIN(a,b) min_t(xfs_extlen_t, (a), (b))
# define XFS_EXTLEN_MAX(a,b) max_t(xfs_extlen_t, (a), (b))
# define XFS_AGBLOCK_MIN(a,b) min_t(xfs_agblock_t, (a), (b))
# define XFS_AGBLOCK_MAX(a,b) max_t(xfs_agblock_t, (a), (b))
# define XFS_FILEOFF_MIN(a,b) min_t(xfs_fileoff_t, (a), (b))
# define XFS_FILEOFF_MAX(a,b) max_t(xfs_fileoff_t, (a), (b))
# define XFS_FILBLKS_MIN(a,b) min_t(xfs_filblks_t, (a), (b))
# define XFS_FILBLKS_MAX(a,b) max_t(xfs_filblks_t, (a), (b))
2005-11-02 06:38:42 +03:00
2018-01-08 21:51:03 +03:00
xfs_failaddr_t xfs_btree_sblock_v5hdr_verify ( struct xfs_buf * bp ) ;
xfs_failaddr_t xfs_btree_sblock_verify ( struct xfs_buf * bp ,
unsigned int max_recs ) ;
xfs_failaddr_t xfs_btree_lblock_v5hdr_verify ( struct xfs_buf * bp ,
uint64_t owner ) ;
xfs_failaddr_t xfs_btree_lblock_verify ( struct xfs_buf * bp ,
unsigned int max_recs ) ;
2018-01-08 21:51:00 +03:00
2021-10-13 21:10:45 +03:00
unsigned int xfs_btree_compute_maxlevels ( const unsigned int * limits ,
unsigned long long records ) ;
unsigned long long xfs_btree_calc_size ( const unsigned int * limits ,
unsigned long long records ) ;
2021-09-16 22:27:43 +03:00
unsigned int xfs_btree_space_to_height ( const unsigned int * limits ,
unsigned long long blocks ) ;
2016-01-04 08:13:21 +03:00
2019-08-29 00:37:57 +03:00
/*
* Return codes for the query range iterator function are 0 to continue
* iterating , and non - zero to stop iterating . Any non - zero value will be
* passed up to the _query_range caller . The special value - ECANCELED can be
* used to stop iteration , because _query_range never generates that error
* code on its own .
*/
2016-08-03 04:10:21 +03:00
typedef int ( * xfs_btree_query_range_fn ) ( struct xfs_btree_cur * cur ,
2021-08-11 03:02:16 +03:00
const union xfs_btree_rec * rec , void * priv ) ;
2016-08-03 04:10:21 +03:00
int xfs_btree_query_range ( struct xfs_btree_cur * cur ,
2021-08-11 03:02:15 +03:00
const union xfs_btree_irec * low_rec ,
const union xfs_btree_irec * high_rec ,
2016-08-03 04:10:21 +03:00
xfs_btree_query_range_fn fn , void * priv ) ;
2017-03-29 00:56:35 +03:00
int xfs_btree_query_all ( struct xfs_btree_cur * cur , xfs_btree_query_range_fn fn ,
void * priv ) ;
2016-08-03 04:10:21 +03:00
2016-08-03 04:10:55 +03:00
typedef int ( * xfs_btree_visit_blocks_fn ) ( struct xfs_btree_cur * cur , int level ,
void * data ) ;
2019-10-29 02:12:35 +03:00
/* Visit record blocks. */
# define XFS_BTREE_VISIT_RECORDS (1 << 0)
/* Visit leaf blocks. */
# define XFS_BTREE_VISIT_LEAVES (1 << 1)
/* Visit all blocks. */
# define XFS_BTREE_VISIT_ALL (XFS_BTREE_VISIT_RECORDS | \
XFS_BTREE_VISIT_LEAVES )
2016-08-03 04:10:55 +03:00
int xfs_btree_visit_blocks ( struct xfs_btree_cur * cur ,
2019-10-29 02:12:35 +03:00
xfs_btree_visit_blocks_fn fn , unsigned int flags , void * data ) ;
2016-08-03 04:10:55 +03:00
2016-09-19 03:25:20 +03:00
int xfs_btree_count_blocks ( struct xfs_btree_cur * cur , xfs_extlen_t * blocks ) ;
2017-06-16 21:00:07 +03:00
union xfs_btree_rec * xfs_btree_rec_addr ( struct xfs_btree_cur * cur , int n ,
struct xfs_btree_block * block ) ;
union xfs_btree_key * xfs_btree_key_addr ( struct xfs_btree_cur * cur , int n ,
struct xfs_btree_block * block ) ;
union xfs_btree_key * xfs_btree_high_key_addr ( struct xfs_btree_cur * cur , int n ,
struct xfs_btree_block * block ) ;
union xfs_btree_ptr * xfs_btree_ptr_addr ( struct xfs_btree_cur * cur , int n ,
struct xfs_btree_block * block ) ;
int xfs_btree_lookup_get_block ( struct xfs_btree_cur * cur , int level ,
2021-08-12 20:10:44 +03:00
const union xfs_btree_ptr * pp , struct xfs_btree_block * * blkp ) ;
2017-06-16 21:00:07 +03:00
struct xfs_btree_block * xfs_btree_get_block ( struct xfs_btree_cur * cur ,
int level , struct xfs_buf * * bpp ) ;
2021-08-12 20:10:44 +03:00
bool xfs_btree_ptr_is_null ( struct xfs_btree_cur * cur ,
const union xfs_btree_ptr * ptr ) ;
2017-10-18 07:37:37 +03:00
int64_t xfs_btree_diff_two_ptrs ( struct xfs_btree_cur * cur ,
const union xfs_btree_ptr * a ,
const union xfs_btree_ptr * b ) ;
void xfs_btree_get_sibling ( struct xfs_btree_cur * cur ,
struct xfs_btree_block * block ,
union xfs_btree_ptr * ptr , int lr ) ;
2017-10-26 01:03:46 +03:00
void xfs_btree_get_keys ( struct xfs_btree_cur * cur ,
struct xfs_btree_block * block , union xfs_btree_key * key ) ;
union xfs_btree_key * xfs_btree_high_key_from_key ( struct xfs_btree_cur * cur ,
union xfs_btree_key * key ) ;
2021-08-12 20:10:44 +03:00
int xfs_btree_has_record ( struct xfs_btree_cur * cur ,
const union xfs_btree_irec * low ,
const union xfs_btree_irec * high , bool * exists ) ;
2018-05-09 20:02:03 +03:00
bool xfs_btree_has_more_records ( struct xfs_btree_cur * cur ) ;
2020-03-11 20:42:34 +03:00
struct xfs_ifork * xfs_btree_ifork_ptr ( struct xfs_btree_cur * cur ) ;
2017-06-16 21:00:07 +03:00
2019-11-06 19:47:09 +03:00
/* Does this cursor point to the last block in the given level? */
static inline bool
xfs_btree_islastblock (
2021-09-16 22:18:47 +03:00
struct xfs_btree_cur * cur ,
2019-11-06 19:47:09 +03:00
int level )
{
struct xfs_btree_block * block ;
struct xfs_buf * bp ;
block = xfs_btree_get_block ( cur , level , & bp ) ;
ASSERT ( block & & xfs_btree_check_block ( cur , block , level , bp ) = = 0 ) ;
if ( cur - > bc_flags & XFS_BTREE_LONG_PTRS )
return block - > bb_u . l . bb_rightsib = = cpu_to_be64 ( NULLFSBLOCK ) ;
return block - > bb_u . s . bb_rightsib = = cpu_to_be32 ( NULLAGBLOCK ) ;
}
2020-03-11 20:51:50 +03:00
void xfs_btree_set_ptr_null ( struct xfs_btree_cur * cur ,
union xfs_btree_ptr * ptr ) ;
2021-08-12 20:10:44 +03:00
int xfs_btree_get_buf_block ( struct xfs_btree_cur * cur ,
const union xfs_btree_ptr * ptr , struct xfs_btree_block * * block ,
struct xfs_buf * * bpp ) ;
2020-03-11 20:51:50 +03:00
void xfs_btree_set_sibling ( struct xfs_btree_cur * cur ,
2021-08-12 20:10:44 +03:00
struct xfs_btree_block * block , const union xfs_btree_ptr * ptr ,
2020-03-11 20:51:50 +03:00
int lr ) ;
void xfs_btree_init_block_cur ( struct xfs_btree_cur * cur ,
struct xfs_buf * bp , int level , int numrecs ) ;
void xfs_btree_copy_ptrs ( struct xfs_btree_cur * cur ,
union xfs_btree_ptr * dst_ptr ,
const union xfs_btree_ptr * src_ptr , int numptrs ) ;
void xfs_btree_copy_keys ( struct xfs_btree_cur * cur ,
2021-08-12 20:10:44 +03:00
union xfs_btree_key * dst_key ,
const union xfs_btree_key * src_key , int numkeys ) ;
2020-03-11 20:51:50 +03:00
2021-09-16 22:25:32 +03:00
static inline struct xfs_btree_cur *
xfs_btree_alloc_cursor (
struct xfs_mount * mp ,
struct xfs_trans * tp ,
2021-09-16 22:27:24 +03:00
xfs_btnum_t btnum ,
2021-09-23 22:21:37 +03:00
uint8_t maxlevels ,
2021-09-28 00:26:19 +03:00
struct kmem_cache * cache )
2021-09-16 22:25:32 +03:00
{
struct xfs_btree_cur * cur ;
2021-09-23 22:21:37 +03:00
cur = kmem_cache_zalloc ( cache , GFP_NOFS | __GFP_NOFAIL ) ;
2021-09-16 22:25:32 +03:00
cur - > bc_tp = tp ;
cur - > bc_mp = mp ;
cur - > bc_btnum = btnum ;
2021-09-16 22:27:24 +03:00
cur - > bc_maxlevels = maxlevels ;
2021-09-23 22:21:37 +03:00
cur - > bc_cache = cache ;
2021-09-16 22:25:32 +03:00
return cur ;
}
2021-09-23 22:21:37 +03:00
int __init xfs_btree_init_cur_caches ( void ) ;
void xfs_btree_destroy_cur_caches ( void ) ;
2005-04-17 02:20:36 +04:00
# endif /* __XFS_BTREE_H__ */