diff --git a/sys/kern/subr_devstat.c b/sys/kern/subr_devstat.c index e3d6d87..7f883df 100644 --- a/sys/kern/subr_devstat.c +++ b/sys/kern/subr_devstat.c @@ -312,3 +312,83 @@ SYSCTL_LONG(_kern_devstat, OID_AUTO, generation, CTLFLAG_RD, &devstat_generation, 0, "Devstat list generation"); SYSCTL_INT(_kern_devstat, OID_AUTO, version, CTLFLAG_RD, &devstat_version, 0, "Devstat list version number"); + +struct cdev_prop_ctx { + prop_array_t cdevs; + int error; +}; + +static +int +dict_from_cdev(cdev_t cdev, void *arg) +{ + prop_string_t str; + prop_number_t num; + prop_dictionary_t dict; + struct cdev_prop_ctx *ctx = arg; + + KKASSERT(arg != NULL); + if (ctx->error) + return; + if (!(dict = prop_dictionary_create())) { + ctx->error = ENOMEM; + return; + } + if (!(str = prop_string_create_cstring(cdev->si_name))) + goto cleanup; + if (!prop_dictionary_set(dict, "name", str)) + goto cleanup; + if (!(num = prop_number_create_unsigned_integer((uint64_t)&cdev))) + goto cleanup; + if (!prop_dictionary_set(dict, "kptr", str)) + goto cleanup; + if !(prop_array_add(cdevs, dict)) + goto free_array; + + return !0; + +} + +static int +sysctl_cdevinfo(SYSCTL_HANDLER_ARGS) +{ + struct plistref prefp; + prop_array_t cdevs; + cdev_t cdev; + devfs_scan_t *scan; + struct cdev_prop_ctx ctx; + + if (!(cdevs = prop_array_create())) + return ENOMEM; + ctx.cdevs = cdevs; + ctx.error = 0; + devfs_scan_callback(&dict_from_cdev, &ctx); + + TAILQ_FOREACH(cdev, &devfs_dev_list, link) { + prop_dictionary_t dict; + if (!(dict = prop_dictionary_create())) + goto free_array; + if (!dict_from_cdev(dict, cdev)) + goto free_array; + if !(prop_array_add(cdevs, dict)) + goto free_array; + } + + if (!prop_array_externalize_to_pref(cdevs, &prefp)) + goto free_array; + SYSCTL_OUT(req, prefp + /* + * First push out the generation number. + */ + error = SYSCTL_OUT(req, &devstat_generation, sizeof(long)); + + /* + * Now push out all the devices. + */ + for (i = 0, nds = STAILQ_FIRST(devstat_head); + (nds != NULL) && (i < devstat_num_devs) && (error == 0); + nds = STAILQ_NEXT(nds, dev_links), i++) + error = SYSCTL_OUT(req, nds, sizeof(struct devstat)); + + return(error); +} diff --git a/sys/kern/vfs_conf.c b/sys/kern/vfs_conf.c index 5628474..8a63c82 100644 --- a/sys/kern/vfs_conf.c +++ b/sys/kern/vfs_conf.c @@ -455,8 +455,12 @@ end: return(error); } - -static void vfs_mountroot_ask_callback(cdev_t); +static void +vfs_mountroot_ask_callback(cdev_t dev, void *arg __unused) +{ + if (dev_is_good(dev) && (dev_dflags(dev) & D_DISK)) + kprintf(" \"%s\" ", dev->si_name); +} /* * Spin prompting on the console for a suitable root filesystem @@ -483,7 +487,7 @@ vfs_mountroot_ask(void) } else if (name[0] == '?') { kprintf("Possibly valid devices for root FS:\n"); //enumerate all disk devices - devfs_scan_callback(vfs_mountroot_ask_callback); + devfs_scan_callback(vfs_mountroot_ask_callback, NULL); kprintf("\n"); continue; } else if (strcmp(name, "panic") == 0) { @@ -497,15 +501,6 @@ vfs_mountroot_ask(void) return(1); } - -static void -vfs_mountroot_ask_callback(cdev_t dev) -{ - if (dev_is_good(dev) && (dev_dflags(dev) & D_DISK)) - kprintf(" \"%s\" ", dev->si_name); -} - - static int getline(char *cp, int limit) { diff --git a/sys/sys/devfs.h b/sys/sys/devfs.h index 63a5f00..c1bb3bb 100644 --- a/sys/sys/devfs.h +++ b/sys/sys/devfs.h @@ -173,6 +173,7 @@ typedef struct devfs_msg { } __m_chandler; struct { void *load; + void *load2; } __m_gen; struct { void *resp; @@ -218,6 +219,7 @@ typedef struct devfs_msg { #define mdv_chandler __m_u.__m_chandler #define mdv_mnt __m_u.__m_mnt.mnt #define mdv_load __m_u.__m_gen.load +#define mdv_load2 __m_u.__m_gen.load2 #define mdv_response __m_u.__m_resp.resp #define mdv_dev __m_u.__m_dev #define mdv_link __m_u.__m_link diff --git a/sys/vfs/devfs/devfs_core.c b/sys/vfs/devfs/devfs_core.c index 9de7aba..9a51106 100644 --- a/sys/vfs/devfs/devfs_core.c +++ b/sys/vfs/devfs/devfs_core.c @@ -127,7 +127,7 @@ static int devfs_find_device_by_udev_worker(devfs_msg_t); static int devfs_apply_reset_rules_caller(char *, int); -static int devfs_scan_callback_worker(devfs_scan_t *); +static int devfs_scan_callback_worker(devfs_scan_t *, void *); static struct devfs_node *devfs_resolve_or_create_dir(struct devfs_node *, char *, size_t, int); @@ -857,7 +857,7 @@ devfs_reset_rules(char *mntto) * It just sends a message with the relevant details to the devfs core. */ int -devfs_scan_callback(devfs_scan_t *callback) +devfs_scan_callback(devfs_scan_t *callback, void *arg) { devfs_msg_t msg; @@ -865,6 +865,7 @@ devfs_scan_callback(devfs_scan_t *callback) msg = devfs_msg_get(); msg->mdv_load = callback; + msg->mdv_load2 = arg; msg = devfs_msg_send_sync(DEVFS_SCAN_CALLBACK, msg); devfs_msg_put(msg); @@ -1140,7 +1141,8 @@ devfs_msg_exec(devfs_msg_t msg) devfs_apply_reset_rules_caller(msg->mdv_name, 0); break; case DEVFS_SCAN_CALLBACK: - devfs_scan_callback_worker((devfs_scan_t *)msg->mdv_load); + devfs_scan_callback_worker((devfs_scan_t *)msg->mdv_load, + msg->mdv_load2); break; case DEVFS_CLR_SUBNAMES_FLAG: devfs_clr_subnames_flag_worker(msg->mdv_flags.name, @@ -1646,12 +1648,12 @@ devfs_apply_reset_rules_caller(char *mountto, int apply) * every dev node in the devfs dev list. */ static int -devfs_scan_callback_worker(devfs_scan_t *callback) +devfs_scan_callback_worker(devfs_scan_t *callback, void *arg) { cdev_t dev, dev1; TAILQ_FOREACH_MUTABLE(dev, &devfs_dev_list, link, dev1) { - callback(dev); + callback(dev, arg); } return 0;