Hi Huang,
Please check the following code change upon your v6, please note I haven't have the
code tested, just to illustrate my thoughts:
diff --git a/defs.h b/defs.h
index a2c2dcd..1b905df 100644
--- a/defs.h
+++ b/defs.h
@@ -5692,6 +5692,8 @@ struct xarray_ops {
uint radix;
uint type;
void *private;
+ uint (*update_off)(ulong node, uint height, char *path, ulong index,
+ ulong slot, uint off, ulong XA_CHUNK_SHIFT, struct xarray_ops
*ops);
};
int do_xarray_traverse(ulong ptr, int is_root, struct xarray_ops *ops);
int do_rdtree(struct tree_data *);
@@ -5998,7 +6000,6 @@ ulong do_radix_tree(ulong, int, struct list_pair *);
#define RADIX_TREE_EXCEPTIONAL_ENTRY 2
ulong do_xarray(ulong, int, struct list_pair *, int);
-#define XARRAY_TYPE_PAGE_CACHE 1
#define XARRAY_COUNT (1)
#define XARRAY_SEARCH (2)
@@ -6007,6 +6008,7 @@ ulong do_xarray(ulong, int, struct list_pair *, int);
#define XARRAY_DUMP_CB (5)
#define XARRAY_TAG_MASK (3UL)
#define XARRAY_TAG_INTERNAL (2UL)
+#define XARRAY_TYPE_PAGE_CACHE 0x8
int folio_order(ulong folio);
diff --git a/filesys.c b/filesys.c
index 08d7b1f..717fb85 100644
--- a/filesys.c
+++ b/filesys.c
@@ -2319,7 +2319,7 @@ dump_inode_page_cache_info(ulong inode, void *callback)
if (root_rnode)
count = do_radix_tree(root_rnode, RADIX_TREE_DUMP_CB, &lp);
else if (xarray)
- count = do_xarray(xarray, XARRAY_DUMP_CB, &lp,
XARRAY_TYPE_PAGE_CACHE);
+ count = do_xarray(xarray, XARRAY_DUMP_CB | XARRAY_TYPE_PAGE_CACHE,
&lp);
if (count != nrpages)
error(INFO, "%s page count: %ld nrpages: %ld\n",
@@ -4341,6 +4341,19 @@ static void do_xarray_dump_cb(ulong node, ulong slot, const char
*path,
do_xarray_count(node, slot, path, index, private);
}
+uint folio_xarray_update_off(ulong node, uint height, char *path, ulong index,
+ ulong slot, uint off, ulong shift, struct xarray_ops *ops)
+{
+ uint order = 1;
+
+ if ((slot & XARRAY_TAG_MASK) == 0) {
+ if (height != 1)
+ ops->entry(node, slot, path, index | off, ops->private);
+ order = folio_order(slot) % shift;
+ }
+ return order;
+}
+
/*
* do_xarray argument usage:
*
@@ -4373,7 +4386,7 @@ static void do_xarray_dump_cb(ulong node, ulong slot, const char
*path,
* type: different xarray use types.
*/
ulong
-do_xarray(ulong root, int flag, struct list_pair *xp, int type)
+do_xarray(ulong root, int flag, struct list_pair *xp)
{
struct do_xarray_info info = {
.count = 0,
@@ -4385,10 +4398,7 @@ do_xarray(ulong root, int flag, struct list_pair *xp, int type)
.private = &info,
};
- if (type == XARRAY_TYPE_PAGE_CACHE)
- info.update_count = folio_update_count;
-
- switch (flag)
+ switch (flag & 0x7)
{
case XARRAY_COUNT:
ops.entry = do_xarray_count;
@@ -4421,6 +4431,11 @@ do_xarray(ulong root, int flag, struct list_pair *xp, int type)
error(FATAL, "do_xarray: invalid flag: %lx\n", flag);
}
+ if (flag & XARRAY_TYPE_PAGE_CACHE) {
+ ops.update_off = folio_xarray_update_off;
+ info.update_count = folio_update_count;
+ }
+
do_xarray_traverse(root, 1, &ops);
return info.count;
}
diff --git a/tools.c b/tools.c
index 6b51423..82d3ed8 100644
--- a/tools.c
+++ b/tools.c
@@ -4737,19 +4737,16 @@ do_xarray_iter(ulong node, uint height, char *path,
ulong index, struct xarray_ops *ops)
{
uint off;
- uint order, is_folio;
+ uint update_off = 1;
if (!hq_enter(node))
error(FATAL,
"\nduplicate tree node: %lx\n", node);
- for (off = 0; off < XA_CHUNK_SIZE; off += 1 << order) {
+ for (off = 0; off < XA_CHUNK_SIZE; off += update_off) {
ulong slot;
ulong shift = (height - 1) * XA_CHUNK_SHIFT;
- order = 0;
- is_folio = 0;
-
readmem(node + OFFSET(xa_node_slots) +
sizeof(void *) * off, KVADDR, &slot, sizeof(void *),
"xa_node.slots[off]", FAULT_ON_ERROR);
@@ -4758,16 +4755,16 @@ do_xarray_iter(ulong node, uint height, char *path,
if ((slot & XARRAY_TAG_MASK) == XARRAY_TAG_INTERNAL)
slot &= ~XARRAY_TAG_INTERNAL;
- else if ((slot & XARRAY_TAG_MASK) == 0) {
- if (ops->type == XARRAY_TYPE_PAGE_CACHE)
- is_folio = 1;
+
+ if (ops->update_off) {
+ update_off = ops->update_off(node, height, path,
+ index, slot, off,
+ XA_CHUNK_SHIFT, ops);
}
- if (height == 1 || is_folio) {
+ if (height == 1)
ops->entry(node, slot, path, index | off, ops->private);
- if (ops->type == XARRAY_TYPE_PAGE_CACHE)
- order = folio_order(slot) % XA_CHUNK_SHIFT;
- } else {
+ else {
ulong child_index = index | (off << shift);
char child_path[BUFSIZE];
sprintf(child_path, "%s/%d", path, off);
1) XARRAY_TYPE_PAGE_CACHE can be put into do_xarray() flags argument, so
we don't need to introduce an extra "type" argument for do_xarray(), and
the
function signature can stay unchanged.
2) do_xarray_iter() shouldn't contain folio information, it is supposed to concern
nothing but the xarray itself. The ops->update_off() is a callback
for every xarray nodes, used as the off variable updator, within
which, you can deal with your folio case. Like I said previously,
we'd better decouple xarray iteration with folio, any special cases
are better to be handled within a callback, rather than hard code the
special cases into xarray iteration directly.
3) To be honest, I'd rather keep the base data/functions least changed than
introduce new features for crash, because that would make the maintenance
work easier.
Thanks,
Tao Liu