hostres_partition_tbl.c (154856) | hostres_partition_tbl.c (160341) |
---|---|
1/*- 2 * Copyright (c) 2005-2006 The FreeBSD Project 3 * All rights reserved. 4 * 5 * Author: Victor Cruceru <soc-victor@freebsd.org> 6 * 7 * Redistribution of this software and documentation and use in source and 8 * binary forms, with or without modification, are permitted provided that --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * | 1/*- 2 * Copyright (c) 2005-2006 The FreeBSD Project 3 * All rights reserved. 4 * 5 * Author: Victor Cruceru <soc-victor@freebsd.org> 6 * 7 * Redistribution of this software and documentation and use in source and 8 * binary forms, with or without modification, are permitted provided that --- 12 unchanged lines hidden (view full) --- 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 * |
29 * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_partition_tbl.c 154856 2006-01-26 10:13:32Z harti $ | 29 * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_partition_tbl.c 160341 2006-07-14 09:07:56Z harti $ |
30 */ 31 32/* 33 * Host Resources MIB: hrPartitionTable implementation for SNMPd. 34 */ 35 36#include <sys/types.h> 37#include <sys/limits.h> 38 39#include <assert.h> 40#include <err.h> 41#include <inttypes.h> 42#include <libgeom.h> 43#include <paths.h> 44#include <stdlib.h> 45#include <string.h> 46#include <syslog.h> | 30 */ 31 32/* 33 * Host Resources MIB: hrPartitionTable implementation for SNMPd. 34 */ 35 36#include <sys/types.h> 37#include <sys/limits.h> 38 39#include <assert.h> 40#include <err.h> 41#include <inttypes.h> 42#include <libgeom.h> 43#include <paths.h> 44#include <stdlib.h> 45#include <string.h> 46#include <syslog.h> |
47#include <sysexits.h> |
|
47 48#include "hostres_snmp.h" 49#include "hostres_oid.h" 50#include "hostres_tree.h" 51 52#ifdef PC98 | 48 49#include "hostres_snmp.h" 50#include "hostres_oid.h" 51#include "hostres_tree.h" 52 53#ifdef PC98 |
53#define HR_FREEBSD_PART_TYPE 0xc494 | 54#define HR_FREEBSD_PART_TYPE 0xc494 |
54#else 55#define HR_FREEBSD_PART_TYPE 165 56#endif 57 | 55#else 56#define HR_FREEBSD_PART_TYPE 165 57#endif 58 |
59/* Maximum length for label and id including \0 */ 60#define PART_STR_MLEN (128 + 1) 61 |
|
58/* 59 * One row in the hrPartitionTable 60 */ 61struct partition_entry { | 62/* 63 * One row in the hrPartitionTable 64 */ 65struct partition_entry { |
62 struct asn_oid index; 63 u_char label[128 + 1]; 64 u_char id[128 + 1]; | 66 asn_subid_t index[2]; 67 u_char *label; /* max allocated len will be PART_STR_MLEN */ 68 u_char *id; /* max allocated len will be PART_STR_MLEN */ |
65 int32_t size; 66 int32_t fs_Index; 67 TAILQ_ENTRY(partition_entry) link; | 69 int32_t size; 70 int32_t fs_Index; 71 TAILQ_ENTRY(partition_entry) link; |
68#define HR_PARTITION_FOUND 0x001 | 72#define HR_PARTITION_FOUND 0x001 |
69 uint32_t flags; 70}; 71TAILQ_HEAD(partition_tbl, partition_entry); 72 73/* 74 * This table is used to get a consistent indexing. It saves the name -> index 75 * mapping while we rebuild the partition table. 76 */ 77struct partition_map_entry { | 73 uint32_t flags; 74}; 75TAILQ_HEAD(partition_tbl, partition_entry); 76 77/* 78 * This table is used to get a consistent indexing. It saves the name -> index 79 * mapping while we rebuild the partition table. 80 */ 81struct partition_map_entry { |
78 int32_t index; /* hrPartitionTblEntry::index */ 79 u_char id[128 + 1]; | 82 int32_t index; /* partition_entry::index */ 83 u_char *id; /* max allocated len will be PART_STR_MLEN */ |
80 81 /* 82 * next may be NULL if the respective partition_entry 83 * is (temporally) gone. 84 */ 85 struct partition_entry *entry; 86 STAILQ_ENTRY(partition_map_entry) link; 87}; --- 5 unchanged lines hidden (view full) --- 93 94/* THE partition table. */ 95static struct partition_tbl partition_tbl = 96 TAILQ_HEAD_INITIALIZER(partition_tbl); 97 98/* next int available for indexing the hrPartitionTable */ 99static uint32_t next_partition_index = 1; 100 | 84 85 /* 86 * next may be NULL if the respective partition_entry 87 * is (temporally) gone. 88 */ 89 struct partition_entry *entry; 90 STAILQ_ENTRY(partition_map_entry) link; 91}; --- 5 unchanged lines hidden (view full) --- 97 98/* THE partition table. */ 99static struct partition_tbl partition_tbl = 100 TAILQ_HEAD_INITIALIZER(partition_tbl); 101 102/* next int available for indexing the hrPartitionTable */ 103static uint32_t next_partition_index = 1; 104 |
105/* 106 * Partition_entry_cmp is used for INSERT_OBJECT_FUNC_LINK 107 * macro. 108 */ 109static int 110partition_entry_cmp(const struct partition_entry *a, 111 const struct partition_entry *b) 112{ 113 assert(a != NULL); 114 assert(b != NULL); 115 116 if (a->index[0] < b->index[0]) 117 return (-1); 118 119 if (a->index[0] > b->index[0]) 120 return (+1); 121 122 if (a->index[1] < b->index[1]) 123 return (-1); 124 125 if (a->index[1] > b->index[1]) 126 return (+1); 127 128 return (0); 129} 130 131/* 132 * Partition_idx_cmp is used for NEXT_OBJECT_FUNC and FIND_OBJECT_FUNC 133 * macros 134 */ 135static int 136partition_idx_cmp(const struct asn_oid *oid, u_int sub, 137 const struct partition_entry *entry) 138{ 139 u_int i; 140 141 for (i = 0; i < 2 && i < oid->len - sub; i++) { 142 if (oid->subs[sub + i] < entry->index[i]) 143 return (-1); 144 if (oid->subs[sub + i] > entry->index[i]) 145 return (+1); 146 } 147 if (oid->len - sub < 2) 148 return (-1); 149 if (oid->len - sub > 2) 150 return (+1); 151 152 return (0); 153} 154 |
|
101/** 102 * Create a new partition table entry 103 */ 104static struct partition_entry * 105partition_entry_create(int32_t ds_index, const char *chunk_name) 106{ 107 struct partition_entry *entry; | 155/** 156 * Create a new partition table entry 157 */ 158static struct partition_entry * 159partition_entry_create(int32_t ds_index, const char *chunk_name) 160{ 161 struct partition_entry *entry; |
108 struct partition_map_entry *map = NULL; | 162 struct partition_map_entry *map; 163 size_t id_len; |
109 110 /* sanity checks */ 111 assert(chunk_name != NULL); 112 if (chunk_name == NULL || chunk_name[0] == '\0') 113 return (NULL); 114 | 164 165 /* sanity checks */ 166 assert(chunk_name != NULL); 167 if (chunk_name == NULL || chunk_name[0] == '\0') 168 return (NULL); 169 |
115 if ((entry = malloc(sizeof(*entry))) == NULL) { 116 syslog(LOG_WARNING, "hrPartitionTable: %s: %m", __func__); 117 return (NULL); 118 } 119 memset(entry, 0, sizeof(*entry)); 120 | |
121 /* check whether we already have seen this partition */ 122 STAILQ_FOREACH(map, &partition_map, link) | 170 /* check whether we already have seen this partition */ 171 STAILQ_FOREACH(map, &partition_map, link) |
123 if (strcmp(map->id, chunk_name) == 0 ) { 124 map->entry = entry; | 172 if (strcmp(map->id, chunk_name) == 0) |
125 break; | 173 break; |
126 } | |
127 128 if (map == NULL) { 129 /* new object - get a new index and create a map */ | 174 175 if (map == NULL) { 176 /* new object - get a new index and create a map */ |
177 |
|
130 if (next_partition_index > INT_MAX) { | 178 if (next_partition_index > INT_MAX) { |
179 /* Unrecoverable error - die clean and quicly*/ |
|
131 syslog(LOG_ERR, "%s: hrPartitionTable index wrap", 132 __func__); | 180 syslog(LOG_ERR, "%s: hrPartitionTable index wrap", 181 __func__); |
133 errx(1, "hrPartitionTable index wrap"); | 182 errx(EX_SOFTWARE, "hrPartitionTable index wrap"); |
134 } 135 136 if ((map = malloc(sizeof(*map))) == NULL) { 137 syslog(LOG_ERR, "hrPartitionTable: %s: %m", __func__); | 183 } 184 185 if ((map = malloc(sizeof(*map))) == NULL) { 186 syslog(LOG_ERR, "hrPartitionTable: %s: %m", __func__); |
138 free(entry); | |
139 return (NULL); 140 } 141 | 187 return (NULL); 188 } 189 |
190 id_len = strlen(chunk_name) + 1; 191 if (id_len > PART_STR_MLEN) 192 id_len = PART_STR_MLEN; 193 194 if ((map->id = malloc(id_len)) == NULL) { 195 free(map); 196 return (NULL); 197 } 198 |
|
142 map->index = next_partition_index++; 143 | 199 map->index = next_partition_index++; 200 |
144 strlcpy(map->id, chunk_name, sizeof(map->id)); | 201 strlcpy(map->id, chunk_name, id_len); |
145 | 202 |
146 map->entry = entry; | 203 map->entry = NULL; 204 |
147 STAILQ_INSERT_TAIL(&partition_map, map, link); 148 149 HRDBG("%s added into hrPartitionMap at index=%d", 150 chunk_name, map->index); 151 152 } else { 153 HRDBG("%s exists in hrPartitionMap index=%d", 154 chunk_name, map->index); 155 } 156 | 205 STAILQ_INSERT_TAIL(&partition_map, map, link); 206 207 HRDBG("%s added into hrPartitionMap at index=%d", 208 chunk_name, map->index); 209 210 } else { 211 HRDBG("%s exists in hrPartitionMap index=%d", 212 chunk_name, map->index); 213 } 214 |
215 if ((entry = malloc(sizeof(*entry))) == NULL) { 216 syslog(LOG_WARNING, "hrPartitionTable: %s: %m", __func__); 217 return (NULL); 218 } 219 memset(entry, 0, sizeof(*entry)); 220 |
|
157 /* create the index */ | 221 /* create the index */ |
158 entry->index.len = 2; 159 entry->index.subs[0] = ds_index; 160 entry->index.subs[1] = map->index; | 222 entry->index[0] = ds_index; 223 entry->index[1] = map->index; |
161 | 224 |
162 strlcpy(entry->id, chunk_name, sizeof(entry->id)); | 225 map->entry = entry; |
163 | 226 |
164 snprintf(entry->label, sizeof(entry->label) - 1, 165 "%s%s", _PATH_DEV, chunk_name); | 227 if ((entry->id = strdup(map->id)) == NULL) { 228 free(entry); 229 return (NULL); 230 } |
166 | 231 |
167 INSERT_OBJECT_OID(entry, &partition_tbl); | 232 /* 233 * reuse id_len from here till the end of this function 234 * for partition_entry::label 235 */ 236 id_len = strlen(_PATH_DEV) + strlen(chunk_name) + 1; |
168 | 237 |
238 if (id_len > PART_STR_MLEN) 239 id_len = PART_STR_MLEN; 240 241 if ((entry->label = malloc(id_len )) == NULL) { 242 free(entry->id); 243 free(entry); 244 return (NULL); 245 } 246 247 snprintf(entry->label, id_len, "%s%s", _PATH_DEV, chunk_name); 248 249 INSERT_OBJECT_FUNC_LINK(entry, &partition_tbl, link, 250 partition_entry_cmp); 251 |
|
169 return (entry); 170} 171 172/** 173 * Delete a partition table entry but keep the map entry intact. 174 */ 175static void 176partition_entry_delete(struct partition_entry *entry) 177{ 178 struct partition_map_entry *map; 179 180 assert(entry != NULL); 181 182 TAILQ_REMOVE(&partition_tbl, entry, link); 183 STAILQ_FOREACH(map, &partition_map, link) 184 if (map->entry == entry) { 185 map->entry = NULL; 186 break; 187 } | 252 return (entry); 253} 254 255/** 256 * Delete a partition table entry but keep the map entry intact. 257 */ 258static void 259partition_entry_delete(struct partition_entry *entry) 260{ 261 struct partition_map_entry *map; 262 263 assert(entry != NULL); 264 265 TAILQ_REMOVE(&partition_tbl, entry, link); 266 STAILQ_FOREACH(map, &partition_map, link) 267 if (map->entry == entry) { 268 map->entry = NULL; 269 break; 270 } |
188 | 271 free(entry->id); 272 free(entry->label); |
189 free(entry); 190} 191 192/** 193 * Find a partition table entry by name. If none is found, return NULL. 194 */ 195static struct partition_entry * 196partition_entry_find_by_name(const char *name) --- 25 unchanged lines hidden (view full) --- 222/** 223 * Process a chunk from libgeom(4). A chunk is either a slice or a partition. 224 * If necessary create a new partition table entry for it. In any case 225 * set the size field of the entry and set the FOUND flag. 226 */ 227static void 228handle_chunk(int32_t ds_index, const char *chunk_name, off_t chunk_size) 229{ | 273 free(entry); 274} 275 276/** 277 * Find a partition table entry by name. If none is found, return NULL. 278 */ 279static struct partition_entry * 280partition_entry_find_by_name(const char *name) --- 25 unchanged lines hidden (view full) --- 306/** 307 * Process a chunk from libgeom(4). A chunk is either a slice or a partition. 308 * If necessary create a new partition table entry for it. In any case 309 * set the size field of the entry and set the FOUND flag. 310 */ 311static void 312handle_chunk(int32_t ds_index, const char *chunk_name, off_t chunk_size) 313{ |
230 struct partition_entry *entry = NULL; | 314 struct partition_entry *entry; |
231 daddr_t k_size; 232 233 assert(chunk_name != NULL); 234 assert(chunk_name[0] != '\0'); 235 if (chunk_name == NULL || chunk_name == '\0') 236 return; 237 238 HRDBG("ANALYZE chunk %s", chunk_name); --- 13 unchanged lines hidden (view full) --- 252/** 253 * Start refreshing the partition table. A call to this function will 254 * be followed by a call to handleDiskStorage() for every disk, followed 255 * by a single call to the post_refresh function. 256 */ 257void 258partition_tbl_pre_refresh(void) 259{ | 315 daddr_t k_size; 316 317 assert(chunk_name != NULL); 318 assert(chunk_name[0] != '\0'); 319 if (chunk_name == NULL || chunk_name == '\0') 320 return; 321 322 HRDBG("ANALYZE chunk %s", chunk_name); --- 13 unchanged lines hidden (view full) --- 336/** 337 * Start refreshing the partition table. A call to this function will 338 * be followed by a call to handleDiskStorage() for every disk, followed 339 * by a single call to the post_refresh function. 340 */ 341void 342partition_tbl_pre_refresh(void) 343{ |
260 struct partition_entry *entry = NULL; | 344 struct partition_entry *entry; |
261 262 /* mark each entry as missing */ 263 TAILQ_FOREACH(entry, &partition_tbl, link) 264 entry->flags &= ~HR_PARTITION_FOUND; 265} 266 267/** 268 * Try to find a geom(4) class by its name. Returns a pointer to that --- 98 unchanged lines hidden (view full) --- 367{ 368 struct gmesh mesh; /* GEOM userland tree */ 369 struct gclass *classp; 370 int error; 371 372 assert(disk_dev_name != NULL); 373 assert(ds_index > 0); 374 | 345 346 /* mark each entry as missing */ 347 TAILQ_FOREACH(entry, &partition_tbl, link) 348 entry->flags &= ~HR_PARTITION_FOUND; 349} 350 351/** 352 * Try to find a geom(4) class by its name. Returns a pointer to that --- 98 unchanged lines hidden (view full) --- 451{ 452 struct gmesh mesh; /* GEOM userland tree */ 453 struct gclass *classp; 454 int error; 455 456 assert(disk_dev_name != NULL); 457 assert(ds_index > 0); 458 |
375 HRDBG("===> getting partitions for %s <===", disk_dev_name); | 459 HRDBG("===> getting partitions for %s <===", disk_dev_name); |
376 377 /* try to construct the GEOM tree */ 378 if ((error = geom_gettree(&mesh)) != 0) { 379 syslog(LOG_WARNING, "cannot get GEOM tree: %m"); 380 return; 381 } 382 383 /* --- 52 unchanged lines hidden (view full) --- 436 * Finalization routine for hrPartitionTable 437 * It destroys the lists and frees any allocated heap memory 438 */ 439void 440fini_partition_tbl(void) 441{ 442 struct partition_map_entry *m; 443 | 460 461 /* try to construct the GEOM tree */ 462 if ((error = geom_gettree(&mesh)) != 0) { 463 syslog(LOG_WARNING, "cannot get GEOM tree: %m"); 464 return; 465 } 466 467 /* --- 52 unchanged lines hidden (view full) --- 520 * Finalization routine for hrPartitionTable 521 * It destroys the lists and frees any allocated heap memory 522 */ 523void 524fini_partition_tbl(void) 525{ 526 struct partition_map_entry *m; 527 |
444 while ((m = STAILQ_FIRST(&partition_map)) != NULL) { | 528 while ((m = STAILQ_FIRST(&partition_map)) != NULL) { |
445 STAILQ_REMOVE_HEAD(&partition_map, link); 446 if(m->entry != NULL) { 447 TAILQ_REMOVE(&partition_tbl, m->entry, link); | 529 STAILQ_REMOVE_HEAD(&partition_map, link); 530 if(m->entry != NULL) { 531 TAILQ_REMOVE(&partition_tbl, m->entry, link); |
532 free(m->entry->id); 533 free(m->entry->label); |
|
448 free(m->entry); 449 } | 534 free(m->entry); 535 } |
536 free(m->id); |
|
450 free(m); | 537 free(m); |
451 } | 538 } |
452 assert(TAILQ_EMPTY(&partition_tbl)); 453} 454 455/** 456 * Called from the file system code to insert the file system table index 457 * into the partition table entry. Note, that an partition table entry exists 458 * only for local file systems. 459 */ --- 25 unchanged lines hidden (view full) --- 485 * Refresh the disk storage table (which refreshes the partition 486 * table) if necessary. 487 */ 488 refresh_disk_storage_tbl(0); 489 490 switch (op) { 491 492 case SNMP_OP_GETNEXT: | 539 assert(TAILQ_EMPTY(&partition_tbl)); 540} 541 542/** 543 * Called from the file system code to insert the file system table index 544 * into the partition table entry. Note, that an partition table entry exists 545 * only for local file systems. 546 */ --- 25 unchanged lines hidden (view full) --- 572 * Refresh the disk storage table (which refreshes the partition 573 * table) if necessary. 574 */ 575 refresh_disk_storage_tbl(0); 576 577 switch (op) { 578 579 case SNMP_OP_GETNEXT: |
493 if ((entry = NEXT_OBJECT_OID(&partition_tbl, 494 &value->var, sub)) == NULL) | 580 if ((entry = NEXT_OBJECT_FUNC(&partition_tbl, 581 &value->var, sub, partition_idx_cmp)) == NULL) |
495 return (SNMP_ERR_NOSUCHNAME); 496 | 582 return (SNMP_ERR_NOSUCHNAME); 583 |
497 index_append(&value->var, sub, &entry->index); | 584 value->var.len = sub + 2; 585 value->var.subs[sub] = entry->index[0]; 586 value->var.subs[sub + 1] = entry->index[1]; 587 |
498 goto get; 499 500 case SNMP_OP_GET: | 588 goto get; 589 590 case SNMP_OP_GET: |
501 if ((entry = FIND_OBJECT_OID(&partition_tbl, 502 &value->var, sub)) == NULL) | 591 if ((entry = FIND_OBJECT_FUNC(&partition_tbl, 592 &value->var, sub, partition_idx_cmp)) == NULL) |
503 return (SNMP_ERR_NOSUCHNAME); 504 goto get; 505 506 case SNMP_OP_SET: | 593 return (SNMP_ERR_NOSUCHNAME); 594 goto get; 595 596 case SNMP_OP_SET: |
507 if ((entry = FIND_OBJECT_OID(&partition_tbl, 508 &value->var, sub)) == NULL) | 597 if ((entry = FIND_OBJECT_FUNC(&partition_tbl, 598 &value->var, sub, partition_idx_cmp)) == NULL) |
509 return (SNMP_ERR_NOT_WRITEABLE); 510 return (SNMP_ERR_NO_CREATION); 511 512 case SNMP_OP_ROLLBACK: 513 case SNMP_OP_COMMIT: 514 abort(); 515 } 516 abort(); 517 518 get: 519 switch (value->var.subs[sub - 1]) { 520 521 case LEAF_hrPartitionIndex: | 599 return (SNMP_ERR_NOT_WRITEABLE); 600 return (SNMP_ERR_NO_CREATION); 601 602 case SNMP_OP_ROLLBACK: 603 case SNMP_OP_COMMIT: 604 abort(); 605 } 606 abort(); 607 608 get: 609 switch (value->var.subs[sub - 1]) { 610 611 case LEAF_hrPartitionIndex: |
522 value->v.integer = entry->index.subs[1]; | 612 value->v.integer = entry->index[1]; |
523 return (SNMP_ERR_NOERROR); 524 525 case LEAF_hrPartitionLabel: 526 return (string_get(value, entry->label, -1)); 527 528 case LEAF_hrPartitionID: 529 return(string_get(value, entry->id, -1)); 530 531 case LEAF_hrPartitionSize: 532 value->v.integer = entry->size; 533 return (SNMP_ERR_NOERROR); 534 535 case LEAF_hrPartitionFSIndex: 536 value->v.integer = entry->fs_Index; 537 return (SNMP_ERR_NOERROR); 538 } 539 abort(); 540} | 613 return (SNMP_ERR_NOERROR); 614 615 case LEAF_hrPartitionLabel: 616 return (string_get(value, entry->label, -1)); 617 618 case LEAF_hrPartitionID: 619 return(string_get(value, entry->id, -1)); 620 621 case LEAF_hrPartitionSize: 622 value->v.integer = entry->size; 623 return (SNMP_ERR_NOERROR); 624 625 case LEAF_hrPartitionFSIndex: 626 value->v.integer = entry->fs_Index; 627 return (SNMP_ERR_NOERROR); 628 } 629 abort(); 630} |