mirror of
https://github.com/torvalds/linux.git
synced 2024-11-10 22:21:40 +00:00
xfs: create separate structures and code for u32 bitmaps
Create a version of the xbitmap that handles 32-bit integer intervals and adapt the xfs_agblock_t bitmap to use it. This reduces the size of the interval tree nodes from 48 to 36 bytes and enables us to use a more efficient slab (:0000040 instead of :0000048) which allows us to pack more nodes into a single slab page (102 vs 85). As a side effect, the users of these bitmaps no longer have to convert between u32 and u64 quantities just to use the bitmap; and the hairy overflow checking code in xagb_bitmap_test goes away. Later in this patchset we're going to add bitmaps for xfs_agino_t, xfs_rgblock_t, and xfs_dablk_t, so the increase in code size (5622 vs. 9959 bytes) seems worth it. Signed-off-by: Darrick J. Wong <djwong@kernel.org> Reviewed-by: Christoph Hellwig <hch@lst.de>
This commit is contained in:
parent
e069d54970
commit
6ece924b95
@ -494,12 +494,11 @@ xrep_agfl_walk_rmap(
|
||||
/* Strike out the blocks that are cross-linked according to the rmapbt. */
|
||||
STATIC int
|
||||
xrep_agfl_check_extent(
|
||||
uint64_t start,
|
||||
uint64_t len,
|
||||
uint32_t agbno,
|
||||
uint32_t len,
|
||||
void *priv)
|
||||
{
|
||||
struct xrep_agfl *ra = priv;
|
||||
xfs_agblock_t agbno = start;
|
||||
xfs_agblock_t last_agbno = agbno + len - 1;
|
||||
int error;
|
||||
|
||||
@ -647,8 +646,8 @@ struct xrep_agfl_fill {
|
||||
/* Fill the AGFL with whatever blocks are in this extent. */
|
||||
static int
|
||||
xrep_agfl_fill(
|
||||
uint64_t start,
|
||||
uint64_t len,
|
||||
uint32_t start,
|
||||
uint32_t len,
|
||||
void *priv)
|
||||
{
|
||||
struct xrep_agfl_fill *af = priv;
|
||||
|
@ -16,7 +16,9 @@
|
||||
|
||||
#include <linux/interval_tree_generic.h>
|
||||
|
||||
struct xbitmap_node {
|
||||
/* u64 bitmap */
|
||||
|
||||
struct xbitmap64_node {
|
||||
struct rb_node bn_rbnode;
|
||||
|
||||
/* First set bit of this interval and subtree. */
|
||||
@ -39,72 +41,72 @@ struct xbitmap_node {
|
||||
* forward-declare them anyway for clarity.
|
||||
*/
|
||||
static inline void
|
||||
xbitmap_tree_insert(struct xbitmap_node *node, struct rb_root_cached *root);
|
||||
xbitmap64_tree_insert(struct xbitmap64_node *node, struct rb_root_cached *root);
|
||||
|
||||
static inline void
|
||||
xbitmap_tree_remove(struct xbitmap_node *node, struct rb_root_cached *root);
|
||||
xbitmap64_tree_remove(struct xbitmap64_node *node, struct rb_root_cached *root);
|
||||
|
||||
static inline struct xbitmap_node *
|
||||
xbitmap_tree_iter_first(struct rb_root_cached *root, uint64_t start,
|
||||
static inline struct xbitmap64_node *
|
||||
xbitmap64_tree_iter_first(struct rb_root_cached *root, uint64_t start,
|
||||
uint64_t last);
|
||||
|
||||
static inline struct xbitmap_node *
|
||||
xbitmap_tree_iter_next(struct xbitmap_node *node, uint64_t start,
|
||||
static inline struct xbitmap64_node *
|
||||
xbitmap64_tree_iter_next(struct xbitmap64_node *node, uint64_t start,
|
||||
uint64_t last);
|
||||
|
||||
INTERVAL_TREE_DEFINE(struct xbitmap_node, bn_rbnode, uint64_t,
|
||||
__bn_subtree_last, START, LAST, static inline, xbitmap_tree)
|
||||
INTERVAL_TREE_DEFINE(struct xbitmap64_node, bn_rbnode, uint64_t,
|
||||
__bn_subtree_last, START, LAST, static inline, xbitmap64_tree)
|
||||
|
||||
/* Iterate each interval of a bitmap. Do not change the bitmap. */
|
||||
#define for_each_xbitmap_extent(bn, bitmap) \
|
||||
#define for_each_xbitmap64_extent(bn, bitmap) \
|
||||
for ((bn) = rb_entry_safe(rb_first(&(bitmap)->xb_root.rb_root), \
|
||||
struct xbitmap_node, bn_rbnode); \
|
||||
struct xbitmap64_node, bn_rbnode); \
|
||||
(bn) != NULL; \
|
||||
(bn) = rb_entry_safe(rb_next(&(bn)->bn_rbnode), \
|
||||
struct xbitmap_node, bn_rbnode))
|
||||
struct xbitmap64_node, bn_rbnode))
|
||||
|
||||
/* Clear a range of this bitmap. */
|
||||
int
|
||||
xbitmap_clear(
|
||||
struct xbitmap *bitmap,
|
||||
xbitmap64_clear(
|
||||
struct xbitmap64 *bitmap,
|
||||
uint64_t start,
|
||||
uint64_t len)
|
||||
{
|
||||
struct xbitmap_node *bn;
|
||||
struct xbitmap_node *new_bn;
|
||||
struct xbitmap64_node *bn;
|
||||
struct xbitmap64_node *new_bn;
|
||||
uint64_t last = start + len - 1;
|
||||
|
||||
while ((bn = xbitmap_tree_iter_first(&bitmap->xb_root, start, last))) {
|
||||
while ((bn = xbitmap64_tree_iter_first(&bitmap->xb_root, start, last))) {
|
||||
if (bn->bn_start < start && bn->bn_last > last) {
|
||||
uint64_t old_last = bn->bn_last;
|
||||
|
||||
/* overlaps with the entire clearing range */
|
||||
xbitmap_tree_remove(bn, &bitmap->xb_root);
|
||||
xbitmap64_tree_remove(bn, &bitmap->xb_root);
|
||||
bn->bn_last = start - 1;
|
||||
xbitmap_tree_insert(bn, &bitmap->xb_root);
|
||||
xbitmap64_tree_insert(bn, &bitmap->xb_root);
|
||||
|
||||
/* add an extent */
|
||||
new_bn = kmalloc(sizeof(struct xbitmap_node),
|
||||
new_bn = kmalloc(sizeof(struct xbitmap64_node),
|
||||
XCHK_GFP_FLAGS);
|
||||
if (!new_bn)
|
||||
return -ENOMEM;
|
||||
new_bn->bn_start = last + 1;
|
||||
new_bn->bn_last = old_last;
|
||||
xbitmap_tree_insert(new_bn, &bitmap->xb_root);
|
||||
xbitmap64_tree_insert(new_bn, &bitmap->xb_root);
|
||||
} else if (bn->bn_start < start) {
|
||||
/* overlaps with the left side of the clearing range */
|
||||
xbitmap_tree_remove(bn, &bitmap->xb_root);
|
||||
xbitmap64_tree_remove(bn, &bitmap->xb_root);
|
||||
bn->bn_last = start - 1;
|
||||
xbitmap_tree_insert(bn, &bitmap->xb_root);
|
||||
xbitmap64_tree_insert(bn, &bitmap->xb_root);
|
||||
} else if (bn->bn_last > last) {
|
||||
/* overlaps with the right side of the clearing range */
|
||||
xbitmap_tree_remove(bn, &bitmap->xb_root);
|
||||
xbitmap64_tree_remove(bn, &bitmap->xb_root);
|
||||
bn->bn_start = last + 1;
|
||||
xbitmap_tree_insert(bn, &bitmap->xb_root);
|
||||
xbitmap64_tree_insert(bn, &bitmap->xb_root);
|
||||
break;
|
||||
} else {
|
||||
/* in the middle of the clearing range */
|
||||
xbitmap_tree_remove(bn, &bitmap->xb_root);
|
||||
xbitmap64_tree_remove(bn, &bitmap->xb_root);
|
||||
kfree(bn);
|
||||
}
|
||||
}
|
||||
@ -114,59 +116,59 @@ xbitmap_clear(
|
||||
|
||||
/* Set a range of this bitmap. */
|
||||
int
|
||||
xbitmap_set(
|
||||
struct xbitmap *bitmap,
|
||||
xbitmap64_set(
|
||||
struct xbitmap64 *bitmap,
|
||||
uint64_t start,
|
||||
uint64_t len)
|
||||
{
|
||||
struct xbitmap_node *left;
|
||||
struct xbitmap_node *right;
|
||||
struct xbitmap64_node *left;
|
||||
struct xbitmap64_node *right;
|
||||
uint64_t last = start + len - 1;
|
||||
int error;
|
||||
|
||||
/* Is this whole range already set? */
|
||||
left = xbitmap_tree_iter_first(&bitmap->xb_root, start, last);
|
||||
left = xbitmap64_tree_iter_first(&bitmap->xb_root, start, last);
|
||||
if (left && left->bn_start <= start && left->bn_last >= last)
|
||||
return 0;
|
||||
|
||||
/* Clear out everything in the range we want to set. */
|
||||
error = xbitmap_clear(bitmap, start, len);
|
||||
error = xbitmap64_clear(bitmap, start, len);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Do we have a left-adjacent extent? */
|
||||
left = xbitmap_tree_iter_first(&bitmap->xb_root, start - 1, start - 1);
|
||||
left = xbitmap64_tree_iter_first(&bitmap->xb_root, start - 1, start - 1);
|
||||
ASSERT(!left || left->bn_last + 1 == start);
|
||||
|
||||
/* Do we have a right-adjacent extent? */
|
||||
right = xbitmap_tree_iter_first(&bitmap->xb_root, last + 1, last + 1);
|
||||
right = xbitmap64_tree_iter_first(&bitmap->xb_root, last + 1, last + 1);
|
||||
ASSERT(!right || right->bn_start == last + 1);
|
||||
|
||||
if (left && right) {
|
||||
/* combine left and right adjacent extent */
|
||||
xbitmap_tree_remove(left, &bitmap->xb_root);
|
||||
xbitmap_tree_remove(right, &bitmap->xb_root);
|
||||
xbitmap64_tree_remove(left, &bitmap->xb_root);
|
||||
xbitmap64_tree_remove(right, &bitmap->xb_root);
|
||||
left->bn_last = right->bn_last;
|
||||
xbitmap_tree_insert(left, &bitmap->xb_root);
|
||||
xbitmap64_tree_insert(left, &bitmap->xb_root);
|
||||
kfree(right);
|
||||
} else if (left) {
|
||||
/* combine with left extent */
|
||||
xbitmap_tree_remove(left, &bitmap->xb_root);
|
||||
xbitmap64_tree_remove(left, &bitmap->xb_root);
|
||||
left->bn_last = last;
|
||||
xbitmap_tree_insert(left, &bitmap->xb_root);
|
||||
xbitmap64_tree_insert(left, &bitmap->xb_root);
|
||||
} else if (right) {
|
||||
/* combine with right extent */
|
||||
xbitmap_tree_remove(right, &bitmap->xb_root);
|
||||
xbitmap64_tree_remove(right, &bitmap->xb_root);
|
||||
right->bn_start = start;
|
||||
xbitmap_tree_insert(right, &bitmap->xb_root);
|
||||
xbitmap64_tree_insert(right, &bitmap->xb_root);
|
||||
} else {
|
||||
/* add an extent */
|
||||
left = kmalloc(sizeof(struct xbitmap_node), XCHK_GFP_FLAGS);
|
||||
left = kmalloc(sizeof(struct xbitmap64_node), XCHK_GFP_FLAGS);
|
||||
if (!left)
|
||||
return -ENOMEM;
|
||||
left->bn_start = start;
|
||||
left->bn_last = last;
|
||||
xbitmap_tree_insert(left, &bitmap->xb_root);
|
||||
xbitmap64_tree_insert(left, &bitmap->xb_root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -174,21 +176,21 @@ xbitmap_set(
|
||||
|
||||
/* Free everything related to this bitmap. */
|
||||
void
|
||||
xbitmap_destroy(
|
||||
struct xbitmap *bitmap)
|
||||
xbitmap64_destroy(
|
||||
struct xbitmap64 *bitmap)
|
||||
{
|
||||
struct xbitmap_node *bn;
|
||||
struct xbitmap64_node *bn;
|
||||
|
||||
while ((bn = xbitmap_tree_iter_first(&bitmap->xb_root, 0, -1ULL))) {
|
||||
xbitmap_tree_remove(bn, &bitmap->xb_root);
|
||||
while ((bn = xbitmap64_tree_iter_first(&bitmap->xb_root, 0, -1ULL))) {
|
||||
xbitmap64_tree_remove(bn, &bitmap->xb_root);
|
||||
kfree(bn);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up a per-AG block bitmap. */
|
||||
void
|
||||
xbitmap_init(
|
||||
struct xbitmap *bitmap)
|
||||
xbitmap64_init(
|
||||
struct xbitmap64 *bitmap)
|
||||
{
|
||||
bitmap->xb_root = RB_ROOT_CACHED;
|
||||
}
|
||||
@ -208,18 +210,18 @@ xbitmap_init(
|
||||
* This is the logical equivalent of bitmap &= ~sub.
|
||||
*/
|
||||
int
|
||||
xbitmap_disunion(
|
||||
struct xbitmap *bitmap,
|
||||
struct xbitmap *sub)
|
||||
xbitmap64_disunion(
|
||||
struct xbitmap64 *bitmap,
|
||||
struct xbitmap64 *sub)
|
||||
{
|
||||
struct xbitmap_node *bn;
|
||||
struct xbitmap64_node *bn;
|
||||
int error;
|
||||
|
||||
if (xbitmap_empty(bitmap) || xbitmap_empty(sub))
|
||||
if (xbitmap64_empty(bitmap) || xbitmap64_empty(sub))
|
||||
return 0;
|
||||
|
||||
for_each_xbitmap_extent(bn, sub) {
|
||||
error = xbitmap_clear(bitmap, bn->bn_start,
|
||||
for_each_xbitmap64_extent(bn, sub) {
|
||||
error = xbitmap64_clear(bitmap, bn->bn_start,
|
||||
bn->bn_last - bn->bn_start + 1);
|
||||
if (error)
|
||||
return error;
|
||||
@ -228,6 +230,345 @@ xbitmap_disunion(
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* How many bits are set in this bitmap? */
|
||||
uint64_t
|
||||
xbitmap64_hweight(
|
||||
struct xbitmap64 *bitmap)
|
||||
{
|
||||
struct xbitmap64_node *bn;
|
||||
uint64_t ret = 0;
|
||||
|
||||
for_each_xbitmap64_extent(bn, bitmap)
|
||||
ret += bn->bn_last - bn->bn_start + 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call a function for every run of set bits in this bitmap. */
|
||||
int
|
||||
xbitmap64_walk(
|
||||
struct xbitmap64 *bitmap,
|
||||
xbitmap64_walk_fn fn,
|
||||
void *priv)
|
||||
{
|
||||
struct xbitmap64_node *bn;
|
||||
int error = 0;
|
||||
|
||||
for_each_xbitmap64_extent(bn, bitmap) {
|
||||
error = fn(bn->bn_start, bn->bn_last - bn->bn_start + 1, priv);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Does this bitmap have no bits set at all? */
|
||||
bool
|
||||
xbitmap64_empty(
|
||||
struct xbitmap64 *bitmap)
|
||||
{
|
||||
return bitmap->xb_root.rb_root.rb_node == NULL;
|
||||
}
|
||||
|
||||
/* Is the start of the range set or clear? And for how long? */
|
||||
bool
|
||||
xbitmap64_test(
|
||||
struct xbitmap64 *bitmap,
|
||||
uint64_t start,
|
||||
uint64_t *len)
|
||||
{
|
||||
struct xbitmap64_node *bn;
|
||||
uint64_t last = start + *len - 1;
|
||||
|
||||
bn = xbitmap64_tree_iter_first(&bitmap->xb_root, start, last);
|
||||
if (!bn)
|
||||
return false;
|
||||
if (bn->bn_start <= start) {
|
||||
if (bn->bn_last < last)
|
||||
*len = bn->bn_last - start + 1;
|
||||
return true;
|
||||
}
|
||||
*len = bn->bn_start - start;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* u32 bitmap */
|
||||
|
||||
struct xbitmap32_node {
|
||||
struct rb_node bn_rbnode;
|
||||
|
||||
/* First set bit of this interval and subtree. */
|
||||
uint32_t bn_start;
|
||||
|
||||
/* Last set bit of this interval. */
|
||||
uint32_t bn_last;
|
||||
|
||||
/* Last set bit of this subtree. Do not touch this. */
|
||||
uint32_t __bn_subtree_last;
|
||||
};
|
||||
|
||||
/* Define our own interval tree type with uint32_t parameters. */
|
||||
|
||||
/*
|
||||
* These functions are defined by the INTERVAL_TREE_DEFINE macro, but we'll
|
||||
* forward-declare them anyway for clarity.
|
||||
*/
|
||||
static inline void
|
||||
xbitmap32_tree_insert(struct xbitmap32_node *node, struct rb_root_cached *root);
|
||||
|
||||
static inline void
|
||||
xbitmap32_tree_remove(struct xbitmap32_node *node, struct rb_root_cached *root);
|
||||
|
||||
static inline struct xbitmap32_node *
|
||||
xbitmap32_tree_iter_first(struct rb_root_cached *root, uint32_t start,
|
||||
uint32_t last);
|
||||
|
||||
static inline struct xbitmap32_node *
|
||||
xbitmap32_tree_iter_next(struct xbitmap32_node *node, uint32_t start,
|
||||
uint32_t last);
|
||||
|
||||
INTERVAL_TREE_DEFINE(struct xbitmap32_node, bn_rbnode, uint32_t,
|
||||
__bn_subtree_last, START, LAST, static inline, xbitmap32_tree)
|
||||
|
||||
/* Iterate each interval of a bitmap. Do not change the bitmap. */
|
||||
#define for_each_xbitmap32_extent(bn, bitmap) \
|
||||
for ((bn) = rb_entry_safe(rb_first(&(bitmap)->xb_root.rb_root), \
|
||||
struct xbitmap32_node, bn_rbnode); \
|
||||
(bn) != NULL; \
|
||||
(bn) = rb_entry_safe(rb_next(&(bn)->bn_rbnode), \
|
||||
struct xbitmap32_node, bn_rbnode))
|
||||
|
||||
/* Clear a range of this bitmap. */
|
||||
int
|
||||
xbitmap32_clear(
|
||||
struct xbitmap32 *bitmap,
|
||||
uint32_t start,
|
||||
uint32_t len)
|
||||
{
|
||||
struct xbitmap32_node *bn;
|
||||
struct xbitmap32_node *new_bn;
|
||||
uint32_t last = start + len - 1;
|
||||
|
||||
while ((bn = xbitmap32_tree_iter_first(&bitmap->xb_root, start, last))) {
|
||||
if (bn->bn_start < start && bn->bn_last > last) {
|
||||
uint32_t old_last = bn->bn_last;
|
||||
|
||||
/* overlaps with the entire clearing range */
|
||||
xbitmap32_tree_remove(bn, &bitmap->xb_root);
|
||||
bn->bn_last = start - 1;
|
||||
xbitmap32_tree_insert(bn, &bitmap->xb_root);
|
||||
|
||||
/* add an extent */
|
||||
new_bn = kmalloc(sizeof(struct xbitmap32_node),
|
||||
XCHK_GFP_FLAGS);
|
||||
if (!new_bn)
|
||||
return -ENOMEM;
|
||||
new_bn->bn_start = last + 1;
|
||||
new_bn->bn_last = old_last;
|
||||
xbitmap32_tree_insert(new_bn, &bitmap->xb_root);
|
||||
} else if (bn->bn_start < start) {
|
||||
/* overlaps with the left side of the clearing range */
|
||||
xbitmap32_tree_remove(bn, &bitmap->xb_root);
|
||||
bn->bn_last = start - 1;
|
||||
xbitmap32_tree_insert(bn, &bitmap->xb_root);
|
||||
} else if (bn->bn_last > last) {
|
||||
/* overlaps with the right side of the clearing range */
|
||||
xbitmap32_tree_remove(bn, &bitmap->xb_root);
|
||||
bn->bn_start = last + 1;
|
||||
xbitmap32_tree_insert(bn, &bitmap->xb_root);
|
||||
break;
|
||||
} else {
|
||||
/* in the middle of the clearing range */
|
||||
xbitmap32_tree_remove(bn, &bitmap->xb_root);
|
||||
kfree(bn);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Set a range of this bitmap. */
|
||||
int
|
||||
xbitmap32_set(
|
||||
struct xbitmap32 *bitmap,
|
||||
uint32_t start,
|
||||
uint32_t len)
|
||||
{
|
||||
struct xbitmap32_node *left;
|
||||
struct xbitmap32_node *right;
|
||||
uint32_t last = start + len - 1;
|
||||
int error;
|
||||
|
||||
/* Is this whole range already set? */
|
||||
left = xbitmap32_tree_iter_first(&bitmap->xb_root, start, last);
|
||||
if (left && left->bn_start <= start && left->bn_last >= last)
|
||||
return 0;
|
||||
|
||||
/* Clear out everything in the range we want to set. */
|
||||
error = xbitmap32_clear(bitmap, start, len);
|
||||
if (error)
|
||||
return error;
|
||||
|
||||
/* Do we have a left-adjacent extent? */
|
||||
left = xbitmap32_tree_iter_first(&bitmap->xb_root, start - 1, start - 1);
|
||||
ASSERT(!left || left->bn_last + 1 == start);
|
||||
|
||||
/* Do we have a right-adjacent extent? */
|
||||
right = xbitmap32_tree_iter_first(&bitmap->xb_root, last + 1, last + 1);
|
||||
ASSERT(!right || right->bn_start == last + 1);
|
||||
|
||||
if (left && right) {
|
||||
/* combine left and right adjacent extent */
|
||||
xbitmap32_tree_remove(left, &bitmap->xb_root);
|
||||
xbitmap32_tree_remove(right, &bitmap->xb_root);
|
||||
left->bn_last = right->bn_last;
|
||||
xbitmap32_tree_insert(left, &bitmap->xb_root);
|
||||
kfree(right);
|
||||
} else if (left) {
|
||||
/* combine with left extent */
|
||||
xbitmap32_tree_remove(left, &bitmap->xb_root);
|
||||
left->bn_last = last;
|
||||
xbitmap32_tree_insert(left, &bitmap->xb_root);
|
||||
} else if (right) {
|
||||
/* combine with right extent */
|
||||
xbitmap32_tree_remove(right, &bitmap->xb_root);
|
||||
right->bn_start = start;
|
||||
xbitmap32_tree_insert(right, &bitmap->xb_root);
|
||||
} else {
|
||||
/* add an extent */
|
||||
left = kmalloc(sizeof(struct xbitmap32_node), XCHK_GFP_FLAGS);
|
||||
if (!left)
|
||||
return -ENOMEM;
|
||||
left->bn_start = start;
|
||||
left->bn_last = last;
|
||||
xbitmap32_tree_insert(left, &bitmap->xb_root);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Free everything related to this bitmap. */
|
||||
void
|
||||
xbitmap32_destroy(
|
||||
struct xbitmap32 *bitmap)
|
||||
{
|
||||
struct xbitmap32_node *bn;
|
||||
|
||||
while ((bn = xbitmap32_tree_iter_first(&bitmap->xb_root, 0, -1U))) {
|
||||
xbitmap32_tree_remove(bn, &bitmap->xb_root);
|
||||
kfree(bn);
|
||||
}
|
||||
}
|
||||
|
||||
/* Set up a per-AG block bitmap. */
|
||||
void
|
||||
xbitmap32_init(
|
||||
struct xbitmap32 *bitmap)
|
||||
{
|
||||
bitmap->xb_root = RB_ROOT_CACHED;
|
||||
}
|
||||
|
||||
/*
|
||||
* Remove all the blocks mentioned in @sub from the extents in @bitmap.
|
||||
*
|
||||
* The intent is that callers will iterate the rmapbt for all of its records
|
||||
* for a given owner to generate @bitmap; and iterate all the blocks of the
|
||||
* metadata structures that are not being rebuilt and have the same rmapbt
|
||||
* owner to generate @sub. This routine subtracts all the extents
|
||||
* mentioned in sub from all the extents linked in @bitmap, which leaves
|
||||
* @bitmap as the list of blocks that are not accounted for, which we assume
|
||||
* are the dead blocks of the old metadata structure. The blocks mentioned in
|
||||
* @bitmap can be reaped.
|
||||
*
|
||||
* This is the logical equivalent of bitmap &= ~sub.
|
||||
*/
|
||||
int
|
||||
xbitmap32_disunion(
|
||||
struct xbitmap32 *bitmap,
|
||||
struct xbitmap32 *sub)
|
||||
{
|
||||
struct xbitmap32_node *bn;
|
||||
int error;
|
||||
|
||||
if (xbitmap32_empty(bitmap) || xbitmap32_empty(sub))
|
||||
return 0;
|
||||
|
||||
for_each_xbitmap32_extent(bn, sub) {
|
||||
error = xbitmap32_clear(bitmap, bn->bn_start,
|
||||
bn->bn_last - bn->bn_start + 1);
|
||||
if (error)
|
||||
return error;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* How many bits are set in this bitmap? */
|
||||
uint32_t
|
||||
xbitmap32_hweight(
|
||||
struct xbitmap32 *bitmap)
|
||||
{
|
||||
struct xbitmap32_node *bn;
|
||||
uint32_t ret = 0;
|
||||
|
||||
for_each_xbitmap32_extent(bn, bitmap)
|
||||
ret += bn->bn_last - bn->bn_start + 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call a function for every run of set bits in this bitmap. */
|
||||
int
|
||||
xbitmap32_walk(
|
||||
struct xbitmap32 *bitmap,
|
||||
xbitmap32_walk_fn fn,
|
||||
void *priv)
|
||||
{
|
||||
struct xbitmap32_node *bn;
|
||||
int error = 0;
|
||||
|
||||
for_each_xbitmap32_extent(bn, bitmap) {
|
||||
error = fn(bn->bn_start, bn->bn_last - bn->bn_start + 1, priv);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Does this bitmap have no bits set at all? */
|
||||
bool
|
||||
xbitmap32_empty(
|
||||
struct xbitmap32 *bitmap)
|
||||
{
|
||||
return bitmap->xb_root.rb_root.rb_node == NULL;
|
||||
}
|
||||
|
||||
/* Is the start of the range set or clear? And for how long? */
|
||||
bool
|
||||
xbitmap32_test(
|
||||
struct xbitmap32 *bitmap,
|
||||
uint32_t start,
|
||||
uint32_t *len)
|
||||
{
|
||||
struct xbitmap32_node *bn;
|
||||
uint32_t last = start + *len - 1;
|
||||
|
||||
bn = xbitmap32_tree_iter_first(&bitmap->xb_root, start, last);
|
||||
if (!bn)
|
||||
return false;
|
||||
if (bn->bn_start <= start) {
|
||||
if (bn->bn_last < last)
|
||||
*len = bn->bn_last - start + 1;
|
||||
return true;
|
||||
}
|
||||
*len = bn->bn_start - start;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* xfs_agblock_t bitmap */
|
||||
|
||||
/*
|
||||
* Record all btree blocks seen while iterating all records of a btree.
|
||||
*
|
||||
@ -316,66 +657,3 @@ xagb_bitmap_set_btcur_path(
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* How many bits are set in this bitmap? */
|
||||
uint64_t
|
||||
xbitmap_hweight(
|
||||
struct xbitmap *bitmap)
|
||||
{
|
||||
struct xbitmap_node *bn;
|
||||
uint64_t ret = 0;
|
||||
|
||||
for_each_xbitmap_extent(bn, bitmap)
|
||||
ret += bn->bn_last - bn->bn_start + 1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Call a function for every run of set bits in this bitmap. */
|
||||
int
|
||||
xbitmap_walk(
|
||||
struct xbitmap *bitmap,
|
||||
xbitmap_walk_fn fn,
|
||||
void *priv)
|
||||
{
|
||||
struct xbitmap_node *bn;
|
||||
int error = 0;
|
||||
|
||||
for_each_xbitmap_extent(bn, bitmap) {
|
||||
error = fn(bn->bn_start, bn->bn_last - bn->bn_start + 1, priv);
|
||||
if (error)
|
||||
break;
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Does this bitmap have no bits set at all? */
|
||||
bool
|
||||
xbitmap_empty(
|
||||
struct xbitmap *bitmap)
|
||||
{
|
||||
return bitmap->xb_root.rb_root.rb_node == NULL;
|
||||
}
|
||||
|
||||
/* Is the start of the range set or clear? And for how long? */
|
||||
bool
|
||||
xbitmap_test(
|
||||
struct xbitmap *bitmap,
|
||||
uint64_t start,
|
||||
uint64_t *len)
|
||||
{
|
||||
struct xbitmap_node *bn;
|
||||
uint64_t last = start + *len - 1;
|
||||
|
||||
bn = xbitmap_tree_iter_first(&bitmap->xb_root, start, last);
|
||||
if (!bn)
|
||||
return false;
|
||||
if (bn->bn_start <= start) {
|
||||
if (bn->bn_last < last)
|
||||
*len = bn->bn_last - start + 1;
|
||||
return true;
|
||||
}
|
||||
*len = bn->bn_start - start;
|
||||
return false;
|
||||
}
|
||||
|
@ -6,17 +6,19 @@
|
||||
#ifndef __XFS_SCRUB_BITMAP_H__
|
||||
#define __XFS_SCRUB_BITMAP_H__
|
||||
|
||||
struct xbitmap {
|
||||
/* u64 bitmap */
|
||||
|
||||
struct xbitmap64 {
|
||||
struct rb_root_cached xb_root;
|
||||
};
|
||||
|
||||
void xbitmap_init(struct xbitmap *bitmap);
|
||||
void xbitmap_destroy(struct xbitmap *bitmap);
|
||||
void xbitmap64_init(struct xbitmap64 *bitmap);
|
||||
void xbitmap64_destroy(struct xbitmap64 *bitmap);
|
||||
|
||||
int xbitmap_clear(struct xbitmap *bitmap, uint64_t start, uint64_t len);
|
||||
int xbitmap_set(struct xbitmap *bitmap, uint64_t start, uint64_t len);
|
||||
int xbitmap_disunion(struct xbitmap *bitmap, struct xbitmap *sub);
|
||||
uint64_t xbitmap_hweight(struct xbitmap *bitmap);
|
||||
int xbitmap64_clear(struct xbitmap64 *bitmap, uint64_t start, uint64_t len);
|
||||
int xbitmap64_set(struct xbitmap64 *bitmap, uint64_t start, uint64_t len);
|
||||
int xbitmap64_disunion(struct xbitmap64 *bitmap, struct xbitmap64 *sub);
|
||||
uint64_t xbitmap64_hweight(struct xbitmap64 *bitmap);
|
||||
|
||||
/*
|
||||
* Return codes for the bitmap iterator functions are 0 to continue iterating,
|
||||
@ -25,79 +27,93 @@ uint64_t xbitmap_hweight(struct xbitmap *bitmap);
|
||||
* iteration, because neither bitmap iterator ever generates that error code on
|
||||
* its own. Callers must not modify the bitmap while walking it.
|
||||
*/
|
||||
typedef int (*xbitmap_walk_fn)(uint64_t start, uint64_t len, void *priv);
|
||||
int xbitmap_walk(struct xbitmap *bitmap, xbitmap_walk_fn fn,
|
||||
typedef int (*xbitmap64_walk_fn)(uint64_t start, uint64_t len, void *priv);
|
||||
int xbitmap64_walk(struct xbitmap64 *bitmap, xbitmap64_walk_fn fn,
|
||||
void *priv);
|
||||
|
||||
bool xbitmap_empty(struct xbitmap *bitmap);
|
||||
bool xbitmap_test(struct xbitmap *bitmap, uint64_t start, uint64_t *len);
|
||||
bool xbitmap64_empty(struct xbitmap64 *bitmap);
|
||||
bool xbitmap64_test(struct xbitmap64 *bitmap, uint64_t start, uint64_t *len);
|
||||
|
||||
/* u32 bitmap */
|
||||
|
||||
struct xbitmap32 {
|
||||
struct rb_root_cached xb_root;
|
||||
};
|
||||
|
||||
void xbitmap32_init(struct xbitmap32 *bitmap);
|
||||
void xbitmap32_destroy(struct xbitmap32 *bitmap);
|
||||
|
||||
int xbitmap32_clear(struct xbitmap32 *bitmap, uint32_t start, uint32_t len);
|
||||
int xbitmap32_set(struct xbitmap32 *bitmap, uint32_t start, uint32_t len);
|
||||
int xbitmap32_disunion(struct xbitmap32 *bitmap, struct xbitmap32 *sub);
|
||||
uint32_t xbitmap32_hweight(struct xbitmap32 *bitmap);
|
||||
|
||||
/*
|
||||
* Return codes for the bitmap iterator functions are 0 to continue iterating,
|
||||
* and non-zero to stop iterating. Any non-zero value will be passed up to the
|
||||
* iteration caller. The special value -ECANCELED can be used to stop
|
||||
* iteration, because neither bitmap iterator ever generates that error code on
|
||||
* its own. Callers must not modify the bitmap while walking it.
|
||||
*/
|
||||
typedef int (*xbitmap32_walk_fn)(uint32_t start, uint32_t len, void *priv);
|
||||
int xbitmap32_walk(struct xbitmap32 *bitmap, xbitmap32_walk_fn fn,
|
||||
void *priv);
|
||||
|
||||
bool xbitmap32_empty(struct xbitmap32 *bitmap);
|
||||
bool xbitmap32_test(struct xbitmap32 *bitmap, uint32_t start, uint32_t *len);
|
||||
|
||||
/* Bitmaps, but for type-checked for xfs_agblock_t */
|
||||
|
||||
struct xagb_bitmap {
|
||||
struct xbitmap agbitmap;
|
||||
struct xbitmap32 agbitmap;
|
||||
};
|
||||
|
||||
static inline void xagb_bitmap_init(struct xagb_bitmap *bitmap)
|
||||
{
|
||||
xbitmap_init(&bitmap->agbitmap);
|
||||
xbitmap32_init(&bitmap->agbitmap);
|
||||
}
|
||||
|
||||
static inline void xagb_bitmap_destroy(struct xagb_bitmap *bitmap)
|
||||
{
|
||||
xbitmap_destroy(&bitmap->agbitmap);
|
||||
xbitmap32_destroy(&bitmap->agbitmap);
|
||||
}
|
||||
|
||||
static inline int xagb_bitmap_clear(struct xagb_bitmap *bitmap,
|
||||
xfs_agblock_t start, xfs_extlen_t len)
|
||||
{
|
||||
return xbitmap_clear(&bitmap->agbitmap, start, len);
|
||||
return xbitmap32_clear(&bitmap->agbitmap, start, len);
|
||||
}
|
||||
static inline int xagb_bitmap_set(struct xagb_bitmap *bitmap,
|
||||
xfs_agblock_t start, xfs_extlen_t len)
|
||||
{
|
||||
return xbitmap_set(&bitmap->agbitmap, start, len);
|
||||
return xbitmap32_set(&bitmap->agbitmap, start, len);
|
||||
}
|
||||
|
||||
static inline bool
|
||||
xagb_bitmap_test(
|
||||
struct xagb_bitmap *bitmap,
|
||||
xfs_agblock_t start,
|
||||
xfs_extlen_t *len)
|
||||
static inline bool xagb_bitmap_test(struct xagb_bitmap *bitmap,
|
||||
xfs_agblock_t start, xfs_extlen_t *len)
|
||||
{
|
||||
uint64_t biglen = *len;
|
||||
bool ret;
|
||||
|
||||
ret = xbitmap_test(&bitmap->agbitmap, start, &biglen);
|
||||
|
||||
if (start + biglen >= UINT_MAX) {
|
||||
ASSERT(0);
|
||||
biglen = UINT_MAX - start;
|
||||
}
|
||||
|
||||
*len = biglen;
|
||||
return ret;
|
||||
return xbitmap32_test(&bitmap->agbitmap, start, len);
|
||||
}
|
||||
|
||||
static inline int xagb_bitmap_disunion(struct xagb_bitmap *bitmap,
|
||||
struct xagb_bitmap *sub)
|
||||
{
|
||||
return xbitmap_disunion(&bitmap->agbitmap, &sub->agbitmap);
|
||||
return xbitmap32_disunion(&bitmap->agbitmap, &sub->agbitmap);
|
||||
}
|
||||
|
||||
static inline uint32_t xagb_bitmap_hweight(struct xagb_bitmap *bitmap)
|
||||
{
|
||||
return xbitmap_hweight(&bitmap->agbitmap);
|
||||
return xbitmap32_hweight(&bitmap->agbitmap);
|
||||
}
|
||||
static inline bool xagb_bitmap_empty(struct xagb_bitmap *bitmap)
|
||||
{
|
||||
return xbitmap_empty(&bitmap->agbitmap);
|
||||
return xbitmap32_empty(&bitmap->agbitmap);
|
||||
}
|
||||
|
||||
static inline int xagb_bitmap_walk(struct xagb_bitmap *bitmap,
|
||||
xbitmap_walk_fn fn, void *priv)
|
||||
xbitmap32_walk_fn fn, void *priv)
|
||||
{
|
||||
return xbitmap_walk(&bitmap->agbitmap, fn, priv);
|
||||
return xbitmap32_walk(&bitmap->agbitmap, fn, priv);
|
||||
}
|
||||
|
||||
int xagb_bitmap_set_btblocks(struct xagb_bitmap *bitmap,
|
||||
|
@ -430,13 +430,12 @@ xreap_agextent_iter(
|
||||
*/
|
||||
STATIC int
|
||||
xreap_agmeta_extent(
|
||||
uint64_t fsbno,
|
||||
uint64_t len,
|
||||
uint32_t agbno,
|
||||
uint32_t len,
|
||||
void *priv)
|
||||
{
|
||||
struct xreap_state *rs = priv;
|
||||
struct xfs_scrub *sc = rs->sc;
|
||||
xfs_agblock_t agbno = fsbno;
|
||||
xfs_agblock_t agbno_next = agbno + len;
|
||||
int error = 0;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user