From e8e4accd16d85239f29fefb2fe4ee7f65da117dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Axel=20D=C3=B6rfler?= Date: Thu, 18 Aug 2005 15:07:38 +0000 Subject: [PATCH] Add some useful debugger commands to the VFS layer for dumping a vnode, an fs_mount, and the mounts/vnodes list. git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@13971 a95241bf-73f2-0310-859d-f6bbb57e9c96 --- src/system/kernel/fs/vfs.cpp | 222 +++++++++++++++++++++++++++++++++++ 1 file changed, 222 insertions(+) diff --git a/src/system/kernel/fs/vfs.cpp b/src/system/kernel/fs/vfs.cpp index 5a2416c179..26577e8734 100644 --- a/src/system/kernel/fs/vfs.cpp +++ b/src/system/kernel/fs/vfs.cpp @@ -52,6 +52,8 @@ # define FUNCTION(x) ; #endif +#define ADD_DEBUGGER_COMMANDS + #define MAX_SYM_LINKS SYMLINKS_MAX const static uint32 kMaxUnusedVnodes = 8192; @@ -1978,6 +1980,217 @@ get_new_fd(int type, struct fs_mount *mount, struct vnode *vnode, return fd; } +#ifdef ADD_DEBUGGER_COMMANDS + + +static void +_dump_advisory_locking(advisory_locking *locking) +{ + if (locking == NULL) + return; + + kprintf(" lock: %ld", locking->lock); + kprintf(" wait_sem: %ld", locking->wait_sem); + + struct advisory_lock *lock = NULL; + int32 index = 0; + while ((lock = (advisory_lock *)list_get_next_item(&locking->locks, lock)) != NULL) { + kprintf(" [%2ld] team: %ld\n", index, lock->team); + kprintf(" offset: %Ld\n", lock->offset); + kprintf(" length: %Ld\n", lock->length); + kprintf(" shared? %s\n", lock->shared ? "yes" : "no"); + } +} + + +static void +_dump_mount(struct fs_mount *mount) +{ + kprintf("MOUNT: %p\n", mount); + kprintf(" id: %ld\n", mount->id); + kprintf(" device_name: %s\n", mount->device_name); + kprintf(" fs_name: %s\n", mount->fs_name); + kprintf(" cookie: %p\n", mount->cookie); + kprintf(" root_vnode: %p\n", mount->root_vnode); + kprintf(" covers_vnode: %p\n", mount->covers_vnode); + kprintf(" partition: %p\n", mount->partition); + kprintf(" lock: %ld\n", mount->rlock.sem); + kprintf(" flags: %s%s\n", mount->unmounting ? " unmounting" : "", + mount->owns_file_device ? " owns_file_device" : ""); +} + + +static void +_dump_vnode(struct vnode *vnode) +{ + kprintf("VNODE: %p\n", vnode); + kprintf(" device: %ld\n", vnode->device); + kprintf(" id: %Ld\n", vnode->id); + kprintf(" ref_count: %ld\n", vnode->ref_count); + kprintf(" private_node: %p\n", vnode->private_node); + kprintf(" mount: %p\n", vnode->mount); + kprintf(" covered_by: %p\n", vnode->covered_by); + kprintf(" cache_ref: %p\n", vnode->cache); + kprintf(" flags: %s%s%s\n", vnode->remove ? "r" : "-", + vnode->busy ? "b" : "-", vnode->unpublished ? "u" : "-"); + kprintf(" advisory_lock: %p\n", vnode->advisory_locking); + + _dump_advisory_locking(vnode->advisory_locking); +} + + +static int +dump_mount(int argc, char **argv) +{ + if (argc != 2) { + kprintf("usage: mount [id/address]\n"); + return 0; + } + + struct fs_mount *mount = NULL; + + // if the argument looks like a hex number, treat it as such + if (strlen(argv[1]) > 2 && argv[1][0] == '0' && argv[1][1] == 'x') { + mount = (fs_mount *)strtoul(argv[1], NULL, 16); + if (IS_USER_ADDRESS(mount)) { + kprintf("invalid fs_mount address\n"); + return 0; + } + } else { + mount_id id = atoll(argv[1]); + mount = (fs_mount *)hash_lookup(sMountsTable, (void *)&id); + if (mount == NULL) { + kprintf("fs_mount not found\n"); + return 0; + } + } + + _dump_mount(mount); + return 0; +} + + +static int +dump_mounts(int argc, char **argv) +{ + struct hash_iterator iterator; + struct fs_mount *mount; + + kprintf("address id root covers fs_name\n"); + + hash_open(sMountsTable, &iterator); + while ((mount = (struct fs_mount *)hash_next(sMountsTable, &iterator)) != NULL) { + kprintf("%p%4ld %p %p %s\n", mount, mount->id, mount->root_vnode, + mount->covers_vnode, mount->fs_name); + } + + hash_close(sMountsTable, &iterator, false); + return 0; +} + + +static int +dump_vnode(int argc, char **argv) +{ + if (argc < 2) { + kprintf("usage: vnode [id/device id/address]\n"); + return 0; + } + + struct vnode *vnode = NULL; + + // if the argument looks like a hex number, treat it as such + if (strlen(argv[1]) > 2 && argv[1][0] == '0' && argv[1][1] == 'x') { + vnode = (struct vnode *)strtoul(argv[1], NULL, 16); + if (IS_USER_ADDRESS(vnode)) { + kprintf("invalid vnode address\n"); + return 0; + } + _dump_vnode(vnode); + return 0; + } + + struct hash_iterator iterator; + mount_id device = -1; + vnode_id id; + if (argc > 2) { + device = atoi(argv[1]); + id = atoll(argv[2]); + } else + id = atoll(argv[1]); + + hash_open(sVnodeTable, &iterator); + while ((vnode = (struct vnode *)hash_next(sVnodeTable, &iterator)) != NULL) { + if (vnode->id != id || device != -1 && vnode->device != device) + continue; + + _dump_vnode(vnode); + } + + hash_close(sVnodeTable, &iterator, false); + return 0; +} + + +static int +dump_vnodes(int argc, char **argv) +{ + // restrict dumped nodes to a certain device if requested + mount_id device = -1; + if (argc > 1) + device = atoi(argv[1]); + + struct hash_iterator iterator; + struct vnode *vnode; + + kprintf("address dev inode ref cache locking flags\n"); + + hash_open(sVnodeTable, &iterator); + while ((vnode = (struct vnode *)hash_next(sVnodeTable, &iterator)) != NULL) { + if (device != -1 && vnode->device != device) + continue; + + kprintf("%p%4ld%10Ld%5ld %p %p %s%s%s\n", vnode, vnode->device, vnode->id, + vnode->ref_count, vnode->cache, vnode->advisory_locking, + vnode->remove ? "r" : "-", vnode->busy ? "b" : "-", + vnode->unpublished ? "u" : "-"); + } + + hash_close(sVnodeTable, &iterator, false); + return 0; +} + + +static int +dump_vnode_caches(int argc, char **argv) +{ + struct hash_iterator iterator; + struct vnode *vnode; + + kprintf("address dev inode cache size pages\n"); + + hash_open(sVnodeTable, &iterator); + while ((vnode = (struct vnode *)hash_next(sVnodeTable, &iterator)) != NULL) { + if (vnode->cache == NULL) + continue; + + // count pages in cache + size_t numPages = 0; + for (struct vm_page *page = vnode->cache->cache->page_list; + page != NULL; page = page->cache_next) { + numPages++; + } + + kprintf("%p%4ld%10Ld %p %8Ld%8ld\n", vnode, vnode->device, vnode->id, vnode->cache, + (vnode->cache->cache->virtual_size + B_PAGE_SIZE - 1) / B_PAGE_SIZE, numPages); + } + + hash_close(sVnodeTable, &iterator, false); + return 0; +} + +#endif // ADD_DEBUGGER_COMMANDS + // #pragma mark - // Public VFS API @@ -2931,6 +3144,15 @@ vfs_init(kernel_args *args) if (block_cache_init() != B_OK) return B_ERROR; +#ifdef ADD_DEBUGGER_COMMANDS + // add some debugger commands + add_debugger_command("vnode", &dump_vnode, "info about the specified vnode"); + add_debugger_command("vnodes", &dump_vnodes, "list all vnodes (from the specified device)"); + add_debugger_command("vnode_caches", &dump_vnode_caches, "list all vnode caches"); + add_debugger_command("mount", &dump_mount, "info about the specified fs_mount"); + add_debugger_command("mounts", &dump_mounts, "list all fs_mounts"); +#endif + return file_cache_init(); }