1d76947f3SHartmut Brandt /*- 2d76947f3SHartmut Brandt * Copyright (c) 2005-2006 The FreeBSD Project 3d76947f3SHartmut Brandt * All rights reserved. 4d76947f3SHartmut Brandt * 5d76947f3SHartmut Brandt * Author: Victor Cruceru <soc-victor@freebsd.org> 6d76947f3SHartmut Brandt * 7d76947f3SHartmut Brandt * Redistribution of this software and documentation and use in source and 8d76947f3SHartmut Brandt * binary forms, with or without modification, are permitted provided that 9d76947f3SHartmut Brandt * the following conditions are met: 10d76947f3SHartmut Brandt * 11d76947f3SHartmut Brandt * 1. Redistributions of source code or documentation must retain the above 12d76947f3SHartmut Brandt * copyright notice, this list of conditions and the following disclaimer. 13d76947f3SHartmut Brandt * 2. Redistributions in binary form must reproduce the above copyright 14d76947f3SHartmut Brandt * notice, this list of conditions and the following disclaimer in the 15d76947f3SHartmut Brandt * documentation and/or other materials provided with the distribution. 16d76947f3SHartmut Brandt * 17d76947f3SHartmut Brandt * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 18d76947f3SHartmut Brandt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19d76947f3SHartmut Brandt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20d76947f3SHartmut Brandt * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 21d76947f3SHartmut Brandt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22d76947f3SHartmut Brandt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23d76947f3SHartmut Brandt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24d76947f3SHartmut Brandt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25d76947f3SHartmut Brandt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26d76947f3SHartmut Brandt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27d76947f3SHartmut Brandt * SUCH DAMAGE. 28d76947f3SHartmut Brandt * 29d76947f3SHartmut Brandt * $FreeBSD$ 30d76947f3SHartmut Brandt */ 31d76947f3SHartmut Brandt 32d76947f3SHartmut Brandt /* 33d76947f3SHartmut Brandt * Host Resources MIB: hrPartitionTable implementation for SNMPd. 34d76947f3SHartmut Brandt */ 35d76947f3SHartmut Brandt 36d76947f3SHartmut Brandt #include <sys/types.h> 37d76947f3SHartmut Brandt #include <sys/limits.h> 38d76947f3SHartmut Brandt 39d76947f3SHartmut Brandt #include <assert.h> 40d76947f3SHartmut Brandt #include <err.h> 41e8689b4cSHartmut Brandt #include <inttypes.h> 42e8689b4cSHartmut Brandt #include <libgeom.h> 43d76947f3SHartmut Brandt #include <paths.h> 44d76947f3SHartmut Brandt #include <stdlib.h> 45d76947f3SHartmut Brandt #include <string.h> 46d76947f3SHartmut Brandt #include <syslog.h> 47e55adffcSHartmut Brandt #include <sysexits.h> 48d76947f3SHartmut Brandt 49d76947f3SHartmut Brandt #include "hostres_snmp.h" 50d76947f3SHartmut Brandt #include "hostres_oid.h" 51d76947f3SHartmut Brandt #include "hostres_tree.h" 52d76947f3SHartmut Brandt 53e8689b4cSHartmut Brandt #define HR_FREEBSD_PART_TYPE 165 54e8689b4cSHartmut Brandt 55e55adffcSHartmut Brandt /* Maximum length for label and id including \0 */ 56e55adffcSHartmut Brandt #define PART_STR_MLEN (128 + 1) 57e55adffcSHartmut Brandt 58d76947f3SHartmut Brandt /* 59d76947f3SHartmut Brandt * One row in the hrPartitionTable 60d76947f3SHartmut Brandt */ 61d76947f3SHartmut Brandt struct partition_entry { 62e55adffcSHartmut Brandt asn_subid_t index[2]; 63e55adffcSHartmut Brandt u_char *label; /* max allocated len will be PART_STR_MLEN */ 64e55adffcSHartmut Brandt u_char *id; /* max allocated len will be PART_STR_MLEN */ 65d76947f3SHartmut Brandt int32_t size; 66d76947f3SHartmut Brandt int32_t fs_Index; 67d76947f3SHartmut Brandt TAILQ_ENTRY(partition_entry) link; 68d76947f3SHartmut Brandt #define HR_PARTITION_FOUND 0x001 69d76947f3SHartmut Brandt uint32_t flags; 70d76947f3SHartmut Brandt }; 71d76947f3SHartmut Brandt TAILQ_HEAD(partition_tbl, partition_entry); 72d76947f3SHartmut Brandt 73d76947f3SHartmut Brandt /* 74d76947f3SHartmut Brandt * This table is used to get a consistent indexing. It saves the name -> index 75d76947f3SHartmut Brandt * mapping while we rebuild the partition table. 76d76947f3SHartmut Brandt */ 77d76947f3SHartmut Brandt struct partition_map_entry { 78e55adffcSHartmut Brandt int32_t index; /* partition_entry::index */ 79e55adffcSHartmut Brandt u_char *id; /* max allocated len will be PART_STR_MLEN */ 80d76947f3SHartmut Brandt 81d76947f3SHartmut Brandt /* 82d76947f3SHartmut Brandt * next may be NULL if the respective partition_entry 83d76947f3SHartmut Brandt * is (temporally) gone. 84d76947f3SHartmut Brandt */ 85d76947f3SHartmut Brandt struct partition_entry *entry; 86d76947f3SHartmut Brandt STAILQ_ENTRY(partition_map_entry) link; 87d76947f3SHartmut Brandt }; 88d76947f3SHartmut Brandt STAILQ_HEAD(partition_map, partition_map_entry); 89d76947f3SHartmut Brandt 90d76947f3SHartmut Brandt /* Mapping table for consistent indexing */ 91d76947f3SHartmut Brandt static struct partition_map partition_map = 92d76947f3SHartmut Brandt STAILQ_HEAD_INITIALIZER(partition_map); 93d76947f3SHartmut Brandt 94d76947f3SHartmut Brandt /* THE partition table. */ 95d76947f3SHartmut Brandt static struct partition_tbl partition_tbl = 96d76947f3SHartmut Brandt TAILQ_HEAD_INITIALIZER(partition_tbl); 97d76947f3SHartmut Brandt 98d76947f3SHartmut Brandt /* next int available for indexing the hrPartitionTable */ 99d76947f3SHartmut Brandt static uint32_t next_partition_index = 1; 100d76947f3SHartmut Brandt 101e55adffcSHartmut Brandt /* 102e55adffcSHartmut Brandt * Partition_entry_cmp is used for INSERT_OBJECT_FUNC_LINK 103e55adffcSHartmut Brandt * macro. 104e55adffcSHartmut Brandt */ 105e55adffcSHartmut Brandt static int 106e55adffcSHartmut Brandt partition_entry_cmp(const struct partition_entry *a, 107e55adffcSHartmut Brandt const struct partition_entry *b) 108e55adffcSHartmut Brandt { 109e55adffcSHartmut Brandt assert(a != NULL); 110e55adffcSHartmut Brandt assert(b != NULL); 111e55adffcSHartmut Brandt 112e55adffcSHartmut Brandt if (a->index[0] < b->index[0]) 113e55adffcSHartmut Brandt return (-1); 114e55adffcSHartmut Brandt 115e55adffcSHartmut Brandt if (a->index[0] > b->index[0]) 116e55adffcSHartmut Brandt return (+1); 117e55adffcSHartmut Brandt 118e55adffcSHartmut Brandt if (a->index[1] < b->index[1]) 119e55adffcSHartmut Brandt return (-1); 120e55adffcSHartmut Brandt 121e55adffcSHartmut Brandt if (a->index[1] > b->index[1]) 122e55adffcSHartmut Brandt return (+1); 123e55adffcSHartmut Brandt 124e55adffcSHartmut Brandt return (0); 125e55adffcSHartmut Brandt } 126e55adffcSHartmut Brandt 127e55adffcSHartmut Brandt /* 128e55adffcSHartmut Brandt * Partition_idx_cmp is used for NEXT_OBJECT_FUNC and FIND_OBJECT_FUNC 129e55adffcSHartmut Brandt * macros 130e55adffcSHartmut Brandt */ 131e55adffcSHartmut Brandt static int 132e55adffcSHartmut Brandt partition_idx_cmp(const struct asn_oid *oid, u_int sub, 133e55adffcSHartmut Brandt const struct partition_entry *entry) 134e55adffcSHartmut Brandt { 135e55adffcSHartmut Brandt u_int i; 136e55adffcSHartmut Brandt 137e55adffcSHartmut Brandt for (i = 0; i < 2 && i < oid->len - sub; i++) { 138e55adffcSHartmut Brandt if (oid->subs[sub + i] < entry->index[i]) 139e55adffcSHartmut Brandt return (-1); 140e55adffcSHartmut Brandt if (oid->subs[sub + i] > entry->index[i]) 141e55adffcSHartmut Brandt return (+1); 142e55adffcSHartmut Brandt } 143e55adffcSHartmut Brandt if (oid->len - sub < 2) 144e55adffcSHartmut Brandt return (-1); 145e55adffcSHartmut Brandt if (oid->len - sub > 2) 146e55adffcSHartmut Brandt return (+1); 147e55adffcSHartmut Brandt 148e55adffcSHartmut Brandt return (0); 149e55adffcSHartmut Brandt } 150e55adffcSHartmut Brandt 151d76947f3SHartmut Brandt /** 152d76947f3SHartmut Brandt * Create a new partition table entry 153d76947f3SHartmut Brandt */ 154d76947f3SHartmut Brandt static struct partition_entry * 155e8689b4cSHartmut Brandt partition_entry_create(int32_t ds_index, const char *chunk_name) 156d76947f3SHartmut Brandt { 157d76947f3SHartmut Brandt struct partition_entry *entry; 158e55adffcSHartmut Brandt struct partition_map_entry *map; 159e55adffcSHartmut Brandt size_t id_len; 160d76947f3SHartmut Brandt 161d76947f3SHartmut Brandt /* sanity checks */ 162e8689b4cSHartmut Brandt assert(chunk_name != NULL); 163e8689b4cSHartmut Brandt if (chunk_name == NULL || chunk_name[0] == '\0') 164d76947f3SHartmut Brandt return (NULL); 165d76947f3SHartmut Brandt 166d76947f3SHartmut Brandt /* check whether we already have seen this partition */ 167d76947f3SHartmut Brandt STAILQ_FOREACH(map, &partition_map, link) 168e55adffcSHartmut Brandt if (strcmp(map->id, chunk_name) == 0) 169d76947f3SHartmut Brandt break; 170d76947f3SHartmut Brandt 171d76947f3SHartmut Brandt if (map == NULL) { 172d76947f3SHartmut Brandt /* new object - get a new index and create a map */ 173e55adffcSHartmut Brandt 174d76947f3SHartmut Brandt if (next_partition_index > INT_MAX) { 175e55adffcSHartmut Brandt /* Unrecoverable error - die clean and quicly*/ 176d76947f3SHartmut Brandt syslog(LOG_ERR, "%s: hrPartitionTable index wrap", 177d76947f3SHartmut Brandt __func__); 178e55adffcSHartmut Brandt errx(EX_SOFTWARE, "hrPartitionTable index wrap"); 179d76947f3SHartmut Brandt } 180d76947f3SHartmut Brandt 181d76947f3SHartmut Brandt if ((map = malloc(sizeof(*map))) == NULL) { 182d76947f3SHartmut Brandt syslog(LOG_ERR, "hrPartitionTable: %s: %m", __func__); 183e55adffcSHartmut Brandt return (NULL); 184e55adffcSHartmut Brandt } 185e55adffcSHartmut Brandt 186e55adffcSHartmut Brandt id_len = strlen(chunk_name) + 1; 187e55adffcSHartmut Brandt if (id_len > PART_STR_MLEN) 188e55adffcSHartmut Brandt id_len = PART_STR_MLEN; 189e55adffcSHartmut Brandt 190e55adffcSHartmut Brandt if ((map->id = malloc(id_len)) == NULL) { 191e55adffcSHartmut Brandt free(map); 192d76947f3SHartmut Brandt return (NULL); 193d76947f3SHartmut Brandt } 194d76947f3SHartmut Brandt 195d76947f3SHartmut Brandt map->index = next_partition_index++; 196d76947f3SHartmut Brandt 197e55adffcSHartmut Brandt strlcpy(map->id, chunk_name, id_len); 198d76947f3SHartmut Brandt 199e55adffcSHartmut Brandt map->entry = NULL; 200e55adffcSHartmut Brandt 201d76947f3SHartmut Brandt STAILQ_INSERT_TAIL(&partition_map, map, link); 202d76947f3SHartmut Brandt 203d76947f3SHartmut Brandt HRDBG("%s added into hrPartitionMap at index=%d", 204e8689b4cSHartmut Brandt chunk_name, map->index); 205d76947f3SHartmut Brandt 206d76947f3SHartmut Brandt } else { 207d76947f3SHartmut Brandt HRDBG("%s exists in hrPartitionMap index=%d", 208e8689b4cSHartmut Brandt chunk_name, map->index); 209d76947f3SHartmut Brandt } 210d76947f3SHartmut Brandt 211e55adffcSHartmut Brandt if ((entry = malloc(sizeof(*entry))) == NULL) { 212e55adffcSHartmut Brandt syslog(LOG_WARNING, "hrPartitionTable: %s: %m", __func__); 213e55adffcSHartmut Brandt return (NULL); 214e55adffcSHartmut Brandt } 215e55adffcSHartmut Brandt memset(entry, 0, sizeof(*entry)); 216e55adffcSHartmut Brandt 217d76947f3SHartmut Brandt /* create the index */ 218e55adffcSHartmut Brandt entry->index[0] = ds_index; 219e55adffcSHartmut Brandt entry->index[1] = map->index; 220d76947f3SHartmut Brandt 221e55adffcSHartmut Brandt map->entry = entry; 222d76947f3SHartmut Brandt 223e55adffcSHartmut Brandt if ((entry->id = strdup(map->id)) == NULL) { 224e55adffcSHartmut Brandt free(entry); 225e55adffcSHartmut Brandt return (NULL); 226e55adffcSHartmut Brandt } 227d76947f3SHartmut Brandt 228e55adffcSHartmut Brandt /* 229e55adffcSHartmut Brandt * reuse id_len from here till the end of this function 230e55adffcSHartmut Brandt * for partition_entry::label 231e55adffcSHartmut Brandt */ 232e55adffcSHartmut Brandt id_len = strlen(_PATH_DEV) + strlen(chunk_name) + 1; 233e55adffcSHartmut Brandt 234e55adffcSHartmut Brandt if (id_len > PART_STR_MLEN) 235e55adffcSHartmut Brandt id_len = PART_STR_MLEN; 236e55adffcSHartmut Brandt 237e55adffcSHartmut Brandt if ((entry->label = malloc(id_len )) == NULL) { 238e55adffcSHartmut Brandt free(entry->id); 239e55adffcSHartmut Brandt free(entry); 240e55adffcSHartmut Brandt return (NULL); 241e55adffcSHartmut Brandt } 242e55adffcSHartmut Brandt 243e55adffcSHartmut Brandt snprintf(entry->label, id_len, "%s%s", _PATH_DEV, chunk_name); 244e55adffcSHartmut Brandt 245e55adffcSHartmut Brandt INSERT_OBJECT_FUNC_LINK(entry, &partition_tbl, link, 246e55adffcSHartmut Brandt partition_entry_cmp); 247d76947f3SHartmut Brandt 248d76947f3SHartmut Brandt return (entry); 249d76947f3SHartmut Brandt } 250d76947f3SHartmut Brandt 251d76947f3SHartmut Brandt /** 252d76947f3SHartmut Brandt * Delete a partition table entry but keep the map entry intact. 253d76947f3SHartmut Brandt */ 254d76947f3SHartmut Brandt static void 255d76947f3SHartmut Brandt partition_entry_delete(struct partition_entry *entry) 256d76947f3SHartmut Brandt { 257d76947f3SHartmut Brandt struct partition_map_entry *map; 258d76947f3SHartmut Brandt 259d76947f3SHartmut Brandt assert(entry != NULL); 260d76947f3SHartmut Brandt 261d76947f3SHartmut Brandt TAILQ_REMOVE(&partition_tbl, entry, link); 262d76947f3SHartmut Brandt STAILQ_FOREACH(map, &partition_map, link) 263d76947f3SHartmut Brandt if (map->entry == entry) { 264d76947f3SHartmut Brandt map->entry = NULL; 265d76947f3SHartmut Brandt break; 266d76947f3SHartmut Brandt } 267e55adffcSHartmut Brandt free(entry->id); 268e55adffcSHartmut Brandt free(entry->label); 269d76947f3SHartmut Brandt free(entry); 270d76947f3SHartmut Brandt } 271d76947f3SHartmut Brandt 272d76947f3SHartmut Brandt /** 273d76947f3SHartmut Brandt * Find a partition table entry by name. If none is found, return NULL. 274d76947f3SHartmut Brandt */ 275d76947f3SHartmut Brandt static struct partition_entry * 276d76947f3SHartmut Brandt partition_entry_find_by_name(const char *name) 277d76947f3SHartmut Brandt { 278d76947f3SHartmut Brandt struct partition_entry *entry = NULL; 279d76947f3SHartmut Brandt 280d76947f3SHartmut Brandt TAILQ_FOREACH(entry, &partition_tbl, link) 281d76947f3SHartmut Brandt if (strcmp(entry->id, name) == 0) 282d76947f3SHartmut Brandt return (entry); 283d76947f3SHartmut Brandt 284d76947f3SHartmut Brandt return (NULL); 285d76947f3SHartmut Brandt } 286d76947f3SHartmut Brandt 287d76947f3SHartmut Brandt /** 288d76947f3SHartmut Brandt * Find a partition table entry by label. If none is found, return NULL. 289d76947f3SHartmut Brandt */ 290d76947f3SHartmut Brandt static struct partition_entry * 291d76947f3SHartmut Brandt partition_entry_find_by_label(const char *name) 292d76947f3SHartmut Brandt { 293d76947f3SHartmut Brandt struct partition_entry *entry = NULL; 294d76947f3SHartmut Brandt 295d76947f3SHartmut Brandt TAILQ_FOREACH(entry, &partition_tbl, link) 296d76947f3SHartmut Brandt if (strcmp(entry->label, name) == 0) 297d76947f3SHartmut Brandt return (entry); 298d76947f3SHartmut Brandt 299d76947f3SHartmut Brandt return (NULL); 300d76947f3SHartmut Brandt } 301d76947f3SHartmut Brandt 302d76947f3SHartmut Brandt /** 303e8689b4cSHartmut Brandt * Process a chunk from libgeom(4). A chunk is either a slice or a partition. 304d76947f3SHartmut Brandt * If necessary create a new partition table entry for it. In any case 305d76947f3SHartmut Brandt * set the size field of the entry and set the FOUND flag. 306d76947f3SHartmut Brandt */ 307d76947f3SHartmut Brandt static void 308e8689b4cSHartmut Brandt handle_chunk(int32_t ds_index, const char *chunk_name, off_t chunk_size) 309d76947f3SHartmut Brandt { 310e55adffcSHartmut Brandt struct partition_entry *entry; 311d76947f3SHartmut Brandt daddr_t k_size; 312d76947f3SHartmut Brandt 313e8689b4cSHartmut Brandt assert(chunk_name != NULL); 314e8689b4cSHartmut Brandt assert(chunk_name[0] != '\0'); 315e5cb99d5SAndriy Voskoboinyk if (chunk_name == NULL || chunk_name[0] == '\0') 316d76947f3SHartmut Brandt return; 317d76947f3SHartmut Brandt 318e8689b4cSHartmut Brandt HRDBG("ANALYZE chunk %s", chunk_name); 319d76947f3SHartmut Brandt 320e8689b4cSHartmut Brandt if ((entry = partition_entry_find_by_name(chunk_name)) == NULL) 321e8689b4cSHartmut Brandt if ((entry = partition_entry_create(ds_index, 322e8689b4cSHartmut Brandt chunk_name)) == NULL) 323d76947f3SHartmut Brandt return; 324d76947f3SHartmut Brandt 325d76947f3SHartmut Brandt entry->flags |= HR_PARTITION_FOUND; 326d76947f3SHartmut Brandt 327d76947f3SHartmut Brandt /* actual size may overflow the SNMP type */ 328e8689b4cSHartmut Brandt k_size = chunk_size / 1024; 329e8689b4cSHartmut Brandt entry->size = (k_size > (off_t)INT_MAX ? INT_MAX : k_size); 330d76947f3SHartmut Brandt } 331d76947f3SHartmut Brandt 332d76947f3SHartmut Brandt /** 333d76947f3SHartmut Brandt * Start refreshing the partition table. A call to this function will 334d76947f3SHartmut Brandt * be followed by a call to handleDiskStorage() for every disk, followed 335d76947f3SHartmut Brandt * by a single call to the post_refresh function. 336d76947f3SHartmut Brandt */ 337d76947f3SHartmut Brandt void 338d76947f3SHartmut Brandt partition_tbl_pre_refresh(void) 339d76947f3SHartmut Brandt { 340e55adffcSHartmut Brandt struct partition_entry *entry; 341d76947f3SHartmut Brandt 342d76947f3SHartmut Brandt /* mark each entry as missing */ 343d76947f3SHartmut Brandt TAILQ_FOREACH(entry, &partition_tbl, link) 344d76947f3SHartmut Brandt entry->flags &= ~HR_PARTITION_FOUND; 345d76947f3SHartmut Brandt } 346d76947f3SHartmut Brandt 347d76947f3SHartmut Brandt /** 348e8689b4cSHartmut Brandt * Try to find a geom(4) class by its name. Returns a pointer to that 349e8689b4cSHartmut Brandt * class if found NULL otherways. 350e8689b4cSHartmut Brandt */ 351e8689b4cSHartmut Brandt static struct gclass * 352e8689b4cSHartmut Brandt find_class(struct gmesh *mesh, const char *name) 353e8689b4cSHartmut Brandt { 354e8689b4cSHartmut Brandt struct gclass *classp; 355e8689b4cSHartmut Brandt 356e8689b4cSHartmut Brandt LIST_FOREACH(classp, &mesh->lg_class, lg_class) 357e8689b4cSHartmut Brandt if (strcmp(classp->lg_name, name) == 0) 358e8689b4cSHartmut Brandt return (classp); 359e8689b4cSHartmut Brandt return (NULL); 360e8689b4cSHartmut Brandt } 361e8689b4cSHartmut Brandt 362e8689b4cSHartmut Brandt /** 363e8689b4cSHartmut Brandt * Process all MBR-type partitions from the given disk. 364e8689b4cSHartmut Brandt */ 365e8689b4cSHartmut Brandt static void 366e8689b4cSHartmut Brandt get_mbr(struct gclass *classp, int32_t ds_index, const char *disk_dev_name) 367e8689b4cSHartmut Brandt { 368e8689b4cSHartmut Brandt struct ggeom *gp; 369e8689b4cSHartmut Brandt struct gprovider *pp; 370e8689b4cSHartmut Brandt struct gconfig *conf; 371e8689b4cSHartmut Brandt long part_type; 372e8689b4cSHartmut Brandt 373e8689b4cSHartmut Brandt LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 374e8689b4cSHartmut Brandt /* We are only interested in partitions from this disk */ 375e8689b4cSHartmut Brandt if (strcmp(gp->lg_name, disk_dev_name) != 0) 376e8689b4cSHartmut Brandt continue; 377e8689b4cSHartmut Brandt 378e8689b4cSHartmut Brandt /* 379e8689b4cSHartmut Brandt * Find all the non-BSD providers (these are handled in get_bsd) 380e8689b4cSHartmut Brandt */ 381e8689b4cSHartmut Brandt LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 382e8689b4cSHartmut Brandt LIST_FOREACH(conf, &pp->lg_config, lg_config) { 383e8689b4cSHartmut Brandt if (conf->lg_name == NULL || 384e8689b4cSHartmut Brandt conf->lg_val == NULL || 385e8689b4cSHartmut Brandt strcmp(conf->lg_name, "type") != 0) 386e8689b4cSHartmut Brandt continue; 387e8689b4cSHartmut Brandt 388e8689b4cSHartmut Brandt /* 389e8689b4cSHartmut Brandt * We are not interested in BSD partitions 390e8689b4cSHartmut Brandt * (ie ad0s1 is not interesting at this point). 391e8689b4cSHartmut Brandt * We'll take care of them in detail (slice 392e8689b4cSHartmut Brandt * by slice) in get_bsd. 393e8689b4cSHartmut Brandt */ 394e8689b4cSHartmut Brandt part_type = strtol(conf->lg_val, NULL, 10); 395e8689b4cSHartmut Brandt if (part_type == HR_FREEBSD_PART_TYPE) 396e8689b4cSHartmut Brandt break; 397e8689b4cSHartmut Brandt HRDBG("-> MBR PROVIDER Name: %s", pp->lg_name); 398e8689b4cSHartmut Brandt HRDBG("Mediasize: %jd", 399e8689b4cSHartmut Brandt (intmax_t)pp->lg_mediasize / 1024); 400e8689b4cSHartmut Brandt HRDBG("Sectorsize: %u", pp->lg_sectorsize); 401e8689b4cSHartmut Brandt HRDBG("Mode: %s", pp->lg_mode); 402e8689b4cSHartmut Brandt HRDBG("CONFIG: %s: %s", 403e8689b4cSHartmut Brandt conf->lg_name, conf->lg_val); 404e8689b4cSHartmut Brandt 405e8689b4cSHartmut Brandt handle_chunk(ds_index, pp->lg_name, 406e8689b4cSHartmut Brandt pp->lg_mediasize); 407e8689b4cSHartmut Brandt } 408e8689b4cSHartmut Brandt } 409e8689b4cSHartmut Brandt } 410e8689b4cSHartmut Brandt } 411e8689b4cSHartmut Brandt 412e8689b4cSHartmut Brandt /** 413e8689b4cSHartmut Brandt * Process all BSD-type partitions from the given disk. 414e8689b4cSHartmut Brandt */ 415e8689b4cSHartmut Brandt static void 416e8689b4cSHartmut Brandt get_bsd_sun(struct gclass *classp, int32_t ds_index, const char *disk_dev_name) 417e8689b4cSHartmut Brandt { 418e8689b4cSHartmut Brandt struct ggeom *gp; 419e8689b4cSHartmut Brandt struct gprovider *pp; 420e8689b4cSHartmut Brandt 421e8689b4cSHartmut Brandt LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 422e8689b4cSHartmut Brandt /* 423e8689b4cSHartmut Brandt * We are only interested in those geoms starting with 424e8689b4cSHartmut Brandt * the disk_dev_name passed as parameter to this function. 425e8689b4cSHartmut Brandt */ 426e8689b4cSHartmut Brandt if (strncmp(gp->lg_name, disk_dev_name, 427e8689b4cSHartmut Brandt strlen(disk_dev_name)) != 0) 428e8689b4cSHartmut Brandt continue; 429e8689b4cSHartmut Brandt 430e8689b4cSHartmut Brandt LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 431e8689b4cSHartmut Brandt if (pp->lg_name == NULL) 432e8689b4cSHartmut Brandt continue; 433e8689b4cSHartmut Brandt handle_chunk(ds_index, pp->lg_name, pp->lg_mediasize); 434e8689b4cSHartmut Brandt } 435e8689b4cSHartmut Brandt } 436e8689b4cSHartmut Brandt } 437e8689b4cSHartmut Brandt 438e8689b4cSHartmut Brandt /** 439e8689b4cSHartmut Brandt * Called from the DiskStorage table for every row. Open the GEOM(4) framework 440e8689b4cSHartmut Brandt * and process all the partitions in it. 441e8689b4cSHartmut Brandt * ds_index is the index into the DiskStorage table. 442e8689b4cSHartmut Brandt * This is done in two steps: for non BSD partitions the geom class "MBR" is 443e8689b4cSHartmut Brandt * used, for our BSD slices the "BSD" geom class. 444d76947f3SHartmut Brandt */ 445d76947f3SHartmut Brandt void 446d76947f3SHartmut Brandt partition_tbl_handle_disk(int32_t ds_index, const char *disk_dev_name) 447d76947f3SHartmut Brandt { 448e8689b4cSHartmut Brandt struct gmesh mesh; /* GEOM userland tree */ 449e8689b4cSHartmut Brandt struct gclass *classp; 450e8689b4cSHartmut Brandt int error; 451d76947f3SHartmut Brandt 452d76947f3SHartmut Brandt assert(disk_dev_name != NULL); 453d76947f3SHartmut Brandt assert(ds_index > 0); 454d76947f3SHartmut Brandt 455e8689b4cSHartmut Brandt HRDBG("===> getting partitions for %s <===", disk_dev_name); 456e8689b4cSHartmut Brandt 457e8689b4cSHartmut Brandt /* try to construct the GEOM tree */ 458e8689b4cSHartmut Brandt if ((error = geom_gettree(&mesh)) != 0) { 459e8689b4cSHartmut Brandt syslog(LOG_WARNING, "cannot get GEOM tree: %m"); 460d76947f3SHartmut Brandt return; 461d76947f3SHartmut Brandt } 462d76947f3SHartmut Brandt 463e8689b4cSHartmut Brandt /* 464e8689b4cSHartmut Brandt * First try the GEOM "MBR" class. 465e8689b4cSHartmut Brandt * This is needed for non-BSD slices (aka partitions) 466e8689b4cSHartmut Brandt * on PC architectures. 467e8689b4cSHartmut Brandt */ 468e8689b4cSHartmut Brandt if ((classp = find_class(&mesh, "MBR")) != NULL) { 469e8689b4cSHartmut Brandt get_mbr(classp, ds_index, disk_dev_name); 470e8689b4cSHartmut Brandt } else { 471e8689b4cSHartmut Brandt HRDBG("cannot find \"MBR\" geom class"); 472d76947f3SHartmut Brandt } 473e8689b4cSHartmut Brandt 474e8689b4cSHartmut Brandt /* 475e8689b4cSHartmut Brandt * Get the "BSD" GEOM class. 476e8689b4cSHartmut Brandt * Here we'll find all the info needed about the BSD slices. 477e8689b4cSHartmut Brandt */ 478e8689b4cSHartmut Brandt if ((classp = find_class(&mesh, "BSD")) != NULL) { 479e8689b4cSHartmut Brandt get_bsd_sun(classp, ds_index, disk_dev_name); 480e8689b4cSHartmut Brandt } else { 481e8689b4cSHartmut Brandt /* no problem on sparc64 */ 482e8689b4cSHartmut Brandt HRDBG("cannot find \"BSD\" geom class"); 483e8689b4cSHartmut Brandt } 484e8689b4cSHartmut Brandt 485e8689b4cSHartmut Brandt /* 486e8689b4cSHartmut Brandt * Get the "SUN" GEOM class. 4870d94b31aSWarner Losh * Here we'll find all the info needed about the SUN slices. 488e8689b4cSHartmut Brandt */ 489e8689b4cSHartmut Brandt if ((classp = find_class(&mesh, "SUN")) != NULL) { 490e8689b4cSHartmut Brandt get_bsd_sun(classp, ds_index, disk_dev_name); 491e8689b4cSHartmut Brandt } else { 492e8689b4cSHartmut Brandt /* no problem on i386 */ 493e8689b4cSHartmut Brandt HRDBG("cannot find \"SUN\" geom class"); 494e8689b4cSHartmut Brandt } 495e8689b4cSHartmut Brandt 496e8689b4cSHartmut Brandt geom_deletetree(&mesh); 497d76947f3SHartmut Brandt } 498d76947f3SHartmut Brandt 499d76947f3SHartmut Brandt /** 500d76947f3SHartmut Brandt * Finish refreshing the table. 501d76947f3SHartmut Brandt */ 502d76947f3SHartmut Brandt void 503d76947f3SHartmut Brandt partition_tbl_post_refresh(void) 504d76947f3SHartmut Brandt { 505d76947f3SHartmut Brandt struct partition_entry *e, *etmp; 506d76947f3SHartmut Brandt 507d76947f3SHartmut Brandt /* 508d76947f3SHartmut Brandt * Purge items that disappeared 509d76947f3SHartmut Brandt */ 510d76947f3SHartmut Brandt TAILQ_FOREACH_SAFE(e, &partition_tbl, link, etmp) 511d76947f3SHartmut Brandt if (!(e->flags & HR_PARTITION_FOUND)) 512d76947f3SHartmut Brandt partition_entry_delete(e); 513d76947f3SHartmut Brandt } 514d76947f3SHartmut Brandt 515d76947f3SHartmut Brandt /* 516d76947f3SHartmut Brandt * Finalization routine for hrPartitionTable 517d76947f3SHartmut Brandt * It destroys the lists and frees any allocated heap memory 518d76947f3SHartmut Brandt */ 519d76947f3SHartmut Brandt void 520d76947f3SHartmut Brandt fini_partition_tbl(void) 521d76947f3SHartmut Brandt { 522d76947f3SHartmut Brandt struct partition_map_entry *m; 523d76947f3SHartmut Brandt 524d76947f3SHartmut Brandt while ((m = STAILQ_FIRST(&partition_map)) != NULL) { 525d76947f3SHartmut Brandt STAILQ_REMOVE_HEAD(&partition_map, link); 526d76947f3SHartmut Brandt if(m->entry != NULL) { 527d76947f3SHartmut Brandt TAILQ_REMOVE(&partition_tbl, m->entry, link); 528e55adffcSHartmut Brandt free(m->entry->id); 529e55adffcSHartmut Brandt free(m->entry->label); 530d76947f3SHartmut Brandt free(m->entry); 531d76947f3SHartmut Brandt } 532e55adffcSHartmut Brandt free(m->id); 533d76947f3SHartmut Brandt free(m); 534d76947f3SHartmut Brandt } 535d76947f3SHartmut Brandt assert(TAILQ_EMPTY(&partition_tbl)); 536d76947f3SHartmut Brandt } 537d76947f3SHartmut Brandt 538d76947f3SHartmut Brandt /** 539d76947f3SHartmut Brandt * Called from the file system code to insert the file system table index 540d76947f3SHartmut Brandt * into the partition table entry. Note, that an partition table entry exists 541d76947f3SHartmut Brandt * only for local file systems. 542d76947f3SHartmut Brandt */ 543d76947f3SHartmut Brandt void 544d76947f3SHartmut Brandt handle_partition_fs_index(const char *name, int32_t fs_idx) 545d76947f3SHartmut Brandt { 546d76947f3SHartmut Brandt struct partition_entry *entry; 547d76947f3SHartmut Brandt 548d76947f3SHartmut Brandt if ((entry = partition_entry_find_by_label(name)) == NULL) { 549d76947f3SHartmut Brandt HRDBG("%s IS MISSING from hrPartitionTable", name); 550d76947f3SHartmut Brandt return; 551d76947f3SHartmut Brandt } 552d76947f3SHartmut Brandt HRDBG("%s [FS index = %d] IS in hrPartitionTable", name, fs_idx); 553d76947f3SHartmut Brandt entry->fs_Index = fs_idx; 554d76947f3SHartmut Brandt } 555d76947f3SHartmut Brandt 556d76947f3SHartmut Brandt /* 557d76947f3SHartmut Brandt * This is the implementation for a generated (by our SNMP tool) 558d76947f3SHartmut Brandt * function prototype, see hostres_tree.h 559d76947f3SHartmut Brandt * It handles the SNMP operations for hrPartitionTable 560d76947f3SHartmut Brandt */ 561d76947f3SHartmut Brandt int 562d76947f3SHartmut Brandt op_hrPartitionTable(struct snmp_context *ctx __unused, struct snmp_value *value, 563d76947f3SHartmut Brandt u_int sub, u_int iidx __unused, enum snmp_op op) 564d76947f3SHartmut Brandt { 565d76947f3SHartmut Brandt struct partition_entry *entry; 566d76947f3SHartmut Brandt 567d76947f3SHartmut Brandt /* 568d76947f3SHartmut Brandt * Refresh the disk storage table (which refreshes the partition 569d76947f3SHartmut Brandt * table) if necessary. 570d76947f3SHartmut Brandt */ 571d76947f3SHartmut Brandt refresh_disk_storage_tbl(0); 572d76947f3SHartmut Brandt 573d76947f3SHartmut Brandt switch (op) { 574d76947f3SHartmut Brandt 575d76947f3SHartmut Brandt case SNMP_OP_GETNEXT: 576e55adffcSHartmut Brandt if ((entry = NEXT_OBJECT_FUNC(&partition_tbl, 577e55adffcSHartmut Brandt &value->var, sub, partition_idx_cmp)) == NULL) 578d76947f3SHartmut Brandt return (SNMP_ERR_NOSUCHNAME); 579d76947f3SHartmut Brandt 580e55adffcSHartmut Brandt value->var.len = sub + 2; 581e55adffcSHartmut Brandt value->var.subs[sub] = entry->index[0]; 582e55adffcSHartmut Brandt value->var.subs[sub + 1] = entry->index[1]; 583e55adffcSHartmut Brandt 584d76947f3SHartmut Brandt goto get; 585d76947f3SHartmut Brandt 586d76947f3SHartmut Brandt case SNMP_OP_GET: 587e55adffcSHartmut Brandt if ((entry = FIND_OBJECT_FUNC(&partition_tbl, 588e55adffcSHartmut Brandt &value->var, sub, partition_idx_cmp)) == NULL) 589d76947f3SHartmut Brandt return (SNMP_ERR_NOSUCHNAME); 590d76947f3SHartmut Brandt goto get; 591d76947f3SHartmut Brandt 592d76947f3SHartmut Brandt case SNMP_OP_SET: 593e55adffcSHartmut Brandt if ((entry = FIND_OBJECT_FUNC(&partition_tbl, 594e55adffcSHartmut Brandt &value->var, sub, partition_idx_cmp)) == NULL) 595d76947f3SHartmut Brandt return (SNMP_ERR_NOT_WRITEABLE); 596d76947f3SHartmut Brandt return (SNMP_ERR_NO_CREATION); 597d76947f3SHartmut Brandt 598d76947f3SHartmut Brandt case SNMP_OP_ROLLBACK: 599d76947f3SHartmut Brandt case SNMP_OP_COMMIT: 600d76947f3SHartmut Brandt abort(); 601d76947f3SHartmut Brandt } 602d76947f3SHartmut Brandt abort(); 603d76947f3SHartmut Brandt 604d76947f3SHartmut Brandt get: 605d76947f3SHartmut Brandt switch (value->var.subs[sub - 1]) { 606d76947f3SHartmut Brandt 607d76947f3SHartmut Brandt case LEAF_hrPartitionIndex: 608e55adffcSHartmut Brandt value->v.integer = entry->index[1]; 609d76947f3SHartmut Brandt return (SNMP_ERR_NOERROR); 610d76947f3SHartmut Brandt 611d76947f3SHartmut Brandt case LEAF_hrPartitionLabel: 612d76947f3SHartmut Brandt return (string_get(value, entry->label, -1)); 613d76947f3SHartmut Brandt 614d76947f3SHartmut Brandt case LEAF_hrPartitionID: 615d76947f3SHartmut Brandt return(string_get(value, entry->id, -1)); 616d76947f3SHartmut Brandt 617d76947f3SHartmut Brandt case LEAF_hrPartitionSize: 618d76947f3SHartmut Brandt value->v.integer = entry->size; 619d76947f3SHartmut Brandt return (SNMP_ERR_NOERROR); 620d76947f3SHartmut Brandt 621d76947f3SHartmut Brandt case LEAF_hrPartitionFSIndex: 622d76947f3SHartmut Brandt value->v.integer = entry->fs_Index; 623d76947f3SHartmut Brandt return (SNMP_ERR_NOERROR); 624d76947f3SHartmut Brandt } 625d76947f3SHartmut Brandt abort(); 626d76947f3SHartmut Brandt } 627