DFS the mount tree starting from `root_mount_va`. We use mnt_mounts / mnt_child for the tree shape; mnt_parent/mnt_mountpoint for path composition.
| 77 | // mnt_child for the tree shape; mnt_parent/mnt_mountpoint for path |
| 78 | // composition. |
| 79 | void walk_mount_tree(const Engine& eng, const Off& o, |
| 80 | VAddr mount_va, VAddr parent_va, |
| 81 | const DentryOffsets& dop, |
| 82 | std::vector<MountInfo>& out, int depth = 0) |
| 83 | { |
| 84 | if (mount_va == 0 || depth > 1024) return; |
| 85 | |
| 86 | MountInfo mi{}; |
| 87 | mi.mount_va = mount_va; |
| 88 | mi.vfsmount_va = mount_va + o.m_mnt; |
| 89 | mi.parent_va = parent_va; |
| 90 | mi.is_root = (parent_va == 0) || (parent_va == mount_va); |
| 91 | |
| 92 | // vfsmount.mnt_sb |
| 93 | kva_read_pod(eng, mi.vfsmount_va + o.vfs_mnt_sb, mi.sb_va); |
| 94 | kva_read_pod(eng, mi.vfsmount_va + o.vfs_mnt_root, mi.mnt_root); |
| 95 | |
| 96 | // file-system name |
| 97 | if (mi.sb_va != 0) { |
| 98 | VAddr fst = 0; |
| 99 | if (kva_read_pod(eng, mi.sb_va + o.sb_s_type, fst) && fst != 0) |
| 100 | mi.fs_name = read_kernel_strp(eng, fst, o.fst_name, 32); |
| 101 | if (mi.fs_name.empty()) { |
| 102 | // s_id is an inline char array |
| 103 | std::string id(32, 0); |
| 104 | kva_read(eng, mi.sb_va + o.sb_s_id, id.data(), id.size()); |
| 105 | std::size_t k = 0; |
| 106 | while (k < id.size() && id[k]) ++k; |
| 107 | mi.fs_name = std::string(id.data(), k); |
| 108 | } |
| 109 | } |
| 110 | |
| 111 | if (o.m_mnt_devname) { |
| 112 | mi.devname = read_kernel_strp(eng, mount_va, o.m_mnt_devname, 64); |
| 113 | } |
| 114 | if (o.m_mnt_id) { |
| 115 | kva_read_pod(eng, mount_va + o.m_mnt_id, mi.mnt_id); |
| 116 | } |
| 117 | |
| 118 | // Compose the global path of THIS mount's mountpoint. |
| 119 | if (mi.is_root) { |
| 120 | mi.global_path = "/"; |
| 121 | } else { |
| 122 | // Look up mountpoint dentry, then resolve via parent's vfsmount. |
| 123 | VAddr mp_dentry = 0; |
| 124 | kva_read_pod(eng, mount_va + o.m_mnt_mountpt, mp_dentry); |
| 125 | VAddr parent_vfsmount = parent_va + o.m_mnt; |
| 126 | mi.global_path = dentry_to_path(eng, mp_dentry, parent_vfsmount, dop); |
| 127 | if (mi.global_path == "(null)" || mi.global_path.empty()) |
| 128 | mi.global_path = fmt::format("(unknown mount @ {:#x})", mount_va); |
| 129 | } |
| 130 | |
| 131 | out.push_back(mi); |
| 132 | |
| 133 | // Recurse into children via mnt_mounts list (head) → |
| 134 | // each child has its mnt_child linkage pointing here. |
| 135 | VAddr children_head = mount_va + o.m_mnt_mounts; |
| 136 | VAddr child_link = 0; |
no test coverage detected