From e8689b4ce474bb903246a212ce7d4138bb19786e Mon Sep 17 00:00:00 2001 From: Hartmut Brandt Date: Thu, 26 Jan 2006 10:13:32 +0000 Subject: [PATCH] Fix the MIB to use libgeom instead of libdisk. Submitted by: Victor Cruceru --- usr.sbin/bsnmpd/modules/snmp_hostres/Makefile | 6 +- .../snmp_hostres/hostres_diskstorage_tbl.c | 5 +- .../snmp_hostres/hostres_partition_tbl.c | 207 ++++++++++++++---- 3 files changed, 170 insertions(+), 48 deletions(-) diff --git a/usr.sbin/bsnmpd/modules/snmp_hostres/Makefile b/usr.sbin/bsnmpd/modules/snmp_hostres/Makefile index 475ad994cb46..2922f45aa8b1 100644 --- a/usr.sbin/bsnmpd/modules/snmp_hostres/Makefile +++ b/usr.sbin/bsnmpd/modules/snmp_hostres/Makefile @@ -48,7 +48,7 @@ SRCS= hostres_begemot.c \ printcap.c #Not having NDEBUG defined will enable assertions and a lot of output on stderr -CFLAGS+= -DNDEBUG -I${LPRSRC} +CFLAGS+= -DNDEBUG -I${LPRSRC} XSYM= host hrStorageOther hrStorageRam hrStorageVirtualMemory \ hrStorageFixedDisk hrStorageRemovableDisk hrStorageFloppyDisk \ hrStorageCompactDisc hrStorageRamDisk hrStorageFlashMemory \ @@ -69,8 +69,8 @@ MAN= snmp_hostres.3 DEFS= ${MOD}_tree.def BMIBS= BEGEMOT-HOSTRES-MIB.txt -DPADD= ${LIBKVM} ${LIBDEVINFO} ${LIBM} ${LIBDISK} ${LIBMEMSTAT} -LDADD= -lkvm -ldevinfo -lm -ldisk -lmemstat +DPADD= ${LIBKVM} ${LIBDEVINFO} ${LIBM} ${LIBGEOM} ${LIBMEMSTAT} +LDADD= -lkvm -ldevinfo -lm -lgeom -lmemstat .include diff --git a/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_diskstorage_tbl.c b/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_diskstorage_tbl.c index e3d33a0763d6..42f78cb8f028 100644 --- a/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_diskstorage_tbl.c +++ b/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_diskstorage_tbl.c @@ -225,11 +225,8 @@ disk_query_disk(struct disk_entry *entry) mediasize = mediasize / 1024; entry->capacity = (mediasize > INT_MAX ? INT_MAX : mediasize); + partition_tbl_handle_disk(entry->index, entry->dev_name); - if (entry->media == DSM_HARDDISK) { - /* XXX libdisk crashes if a empty cdrom device is opened */ - partition_tbl_handle_disk(entry->index, entry->dev_name); - } (void)close(fd); } diff --git a/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_partition_tbl.c b/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_partition_tbl.c index d6e55c01dd51..f56513b9e006 100644 --- a/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_partition_tbl.c +++ b/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_partition_tbl.c @@ -38,7 +38,8 @@ #include #include -#include +#include +#include #include #include #include @@ -48,6 +49,12 @@ #include "hostres_oid.h" #include "hostres_tree.h" +#ifdef PC98 +#define HR_FREEBSD_PART_TYPE 0xc494 +#else +#define HR_FREEBSD_PART_TYPE 165 +#endif + /* * One row in the hrPartitionTable */ @@ -95,15 +102,14 @@ static uint32_t next_partition_index = 1; * Create a new partition table entry */ static struct partition_entry * -partition_entry_create(int32_t ds_index, const struct chunk *chunk) +partition_entry_create(int32_t ds_index, const char *chunk_name) { struct partition_entry *entry; struct partition_map_entry *map = NULL; /* sanity checks */ - assert(chunk != NULL); - assert(chunk->name != NULL); - if (chunk == NULL || chunk->name == NULL || chunk->name[0] == '\0') + assert(chunk_name != NULL); + if (chunk_name == NULL || chunk_name[0] == '\0') return (NULL); if ((entry = malloc(sizeof(*entry))) == NULL) { @@ -114,7 +120,7 @@ partition_entry_create(int32_t ds_index, const struct chunk *chunk) /* check whether we already have seen this partition */ STAILQ_FOREACH(map, &partition_map, link) - if (strcmp(map->id, chunk->name) == 0 ) { + if (strcmp(map->id, chunk_name) == 0 ) { map->entry = entry; break; } @@ -135,18 +141,17 @@ partition_entry_create(int32_t ds_index, const struct chunk *chunk) map->index = next_partition_index++; - memset(map->id, 0, sizeof(map->id)); - strncpy(map->id, chunk->name, sizeof(map->id) - 1); + strlcpy(map->id, chunk_name, sizeof(map->id)); map->entry = entry; STAILQ_INSERT_TAIL(&partition_map, map, link); HRDBG("%s added into hrPartitionMap at index=%d", - chunk->name, map->index); + chunk_name, map->index); } else { HRDBG("%s exists in hrPartitionMap index=%d", - chunk->name, map->index); + chunk_name, map->index); } /* create the index */ @@ -154,11 +159,10 @@ partition_entry_create(int32_t ds_index, const struct chunk *chunk) entry->index.subs[0] = ds_index; entry->index.subs[1] = map->index; - memset(&entry->id[0], 0, sizeof(entry->id)); - strncpy(entry->id, chunk->name, sizeof(entry->id) - 1); + strlcpy(entry->id, chunk_name, sizeof(entry->id)); snprintf(entry->label, sizeof(entry->label) - 1, - "%s%s", _PATH_DEV, chunk->name); + "%s%s", _PATH_DEV, chunk_name); INSERT_OBJECT_OID(entry, &partition_tbl); @@ -216,36 +220,33 @@ partition_entry_find_by_label(const char *name) } /** - * Process a chunk from libdisk. A chunk is either a slice or a partition. + * Process a chunk from libgeom(4). A chunk is either a slice or a partition. * If necessary create a new partition table entry for it. In any case * set the size field of the entry and set the FOUND flag. */ static void -handle_chunk(int32_t ds_index, const struct chunk* chunk, - const struct disk *disk) +handle_chunk(int32_t ds_index, const char *chunk_name, off_t chunk_size) { struct partition_entry *entry = NULL; daddr_t k_size; - assert(chunk != NULL); - if (chunk == NULL) + assert(chunk_name != NULL); + assert(chunk_name[0] != '\0'); + if (chunk_name == NULL || chunk_name == '\0') return; - if (chunk->type == unused) { - HRDBG("SKIP unused chunk %s", chunk->name); - return; - } - HRDBG("ANALYZE chunk %s", chunk->name); + HRDBG("ANALYZE chunk %s", chunk_name); - if ((entry = partition_entry_find_by_name(chunk->name)) == NULL) - if ((entry = partition_entry_create(ds_index, chunk)) == NULL) + if ((entry = partition_entry_find_by_name(chunk_name)) == NULL) + if ((entry = partition_entry_create(ds_index, + chunk_name)) == NULL) return; entry->flags |= HR_PARTITION_FOUND; /* actual size may overflow the SNMP type */ - k_size = chunk->size / (1024 / disk->sector_size); - entry->size = (k_size > (daddr_t)INT_MAX ? INT_MAX : k_size); + k_size = chunk_size / 1024; + entry->size = (k_size > (off_t)INT_MAX ? INT_MAX : k_size); } /** @@ -264,31 +265,155 @@ partition_tbl_pre_refresh(void) } /** - * Called from the DiskStorage table for every row. Open the device and - * process all the partitions in it. ds_index is the index into the DiskStorage - * table. + * Try to find a geom(4) class by its name. Returns a pointer to that + * class if found NULL otherways. + */ +static struct gclass * +find_class(struct gmesh *mesh, const char *name) +{ + struct gclass *classp; + + LIST_FOREACH(classp, &mesh->lg_class, lg_class) + if (strcmp(classp->lg_name, name) == 0) + return (classp); + return (NULL); +} + +/** + * Process all MBR-type partitions from the given disk. + */ +static void +get_mbr(struct gclass *classp, int32_t ds_index, const char *disk_dev_name) +{ + struct ggeom *gp; + struct gprovider *pp; + struct gconfig *conf; + long part_type; + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + /* We are only interested in partitions from this disk */ + if (strcmp(gp->lg_name, disk_dev_name) != 0) + continue; + + /* + * Find all the non-BSD providers (these are handled in get_bsd) + */ + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + LIST_FOREACH(conf, &pp->lg_config, lg_config) { + if (conf->lg_name == NULL || + conf->lg_val == NULL || + strcmp(conf->lg_name, "type") != 0) + continue; + + /* + * We are not interested in BSD partitions + * (ie ad0s1 is not interesting at this point). + * We'll take care of them in detail (slice + * by slice) in get_bsd. + */ + part_type = strtol(conf->lg_val, NULL, 10); + if (part_type == HR_FREEBSD_PART_TYPE) + break; + HRDBG("-> MBR PROVIDER Name: %s", pp->lg_name); + HRDBG("Mediasize: %jd", + (intmax_t)pp->lg_mediasize / 1024); + HRDBG("Sectorsize: %u", pp->lg_sectorsize); + HRDBG("Mode: %s", pp->lg_mode); + HRDBG("CONFIG: %s: %s", + conf->lg_name, conf->lg_val); + + handle_chunk(ds_index, pp->lg_name, + pp->lg_mediasize); + } + } + } +} + +/** + * Process all BSD-type partitions from the given disk. + */ +static void +get_bsd_sun(struct gclass *classp, int32_t ds_index, const char *disk_dev_name) +{ + struct ggeom *gp; + struct gprovider *pp; + + LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { + /* + * We are only interested in those geoms starting with + * the disk_dev_name passed as parameter to this function. + */ + if (strncmp(gp->lg_name, disk_dev_name, + strlen(disk_dev_name)) != 0) + continue; + + LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { + if (pp->lg_name == NULL) + continue; + handle_chunk(ds_index, pp->lg_name, pp->lg_mediasize); + } + } +} + +/** + * Called from the DiskStorage table for every row. Open the GEOM(4) framework + * and process all the partitions in it. + * ds_index is the index into the DiskStorage table. + * This is done in two steps: for non BSD partitions the geom class "MBR" is + * used, for our BSD slices the "BSD" geom class. */ void partition_tbl_handle_disk(int32_t ds_index, const char *disk_dev_name) { - struct disk *disk; - struct chunk *chunk; - struct chunk *partt; + struct gmesh mesh; /* GEOM userland tree */ + struct gclass *classp; + int error; assert(disk_dev_name != NULL); assert(ds_index > 0); - if ((disk = Open_Disk(disk_dev_name)) == NULL) { - syslog(LOG_ERR, "%s: cannot Open_Disk()", disk_dev_name); + HRDBG("===> getting partitions for %s <===", disk_dev_name); + + /* try to construct the GEOM tree */ + if ((error = geom_gettree(&mesh)) != 0) { + syslog(LOG_WARNING, "cannot get GEOM tree: %m"); return; } - for (chunk = disk->chunks->part; chunk != NULL; chunk = chunk->next) { - handle_chunk(ds_index, chunk, disk); - for (partt = chunk->part; partt != NULL; partt = partt->next) - handle_chunk(ds_index, partt, disk); - } - Free_Disk(disk); + /* + * First try the GEOM "MBR" class. + * This is needed for non-BSD slices (aka partitions) + * on PC architectures. + */ + if ((classp = find_class(&mesh, "MBR")) != NULL) { + get_mbr(classp, ds_index, disk_dev_name); + } else { + HRDBG("cannot find \"MBR\" geom class"); + } + + /* + * Get the "BSD" GEOM class. + * Here we'll find all the info needed about the BSD slices. + */ + if ((classp = find_class(&mesh, "BSD")) != NULL) { + get_bsd_sun(classp, ds_index, disk_dev_name); + } else { + /* no problem on sparc64 */ + HRDBG("cannot find \"BSD\" geom class"); + } + + /* + * Get the "SUN" GEOM class. + * Here we'll find all the info needed about the BSD slices. + */ + if ((classp = find_class(&mesh, "SUN")) != NULL) { + get_bsd_sun(classp, ds_index, disk_dev_name); + } else { + /* no problem on i386 */ + HRDBG("cannot find \"SUN\" geom class"); + } + + geom_deletetree(&mesh); } /**