hostres_partition_tbl.c (154133) | hostres_partition_tbl.c (154856) |
---|---|
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 154133 2006-01-09 12:33:45Z harti $ | 29 * $FreeBSD: head/usr.sbin/bsnmpd/modules/snmp_hostres/hostres_partition_tbl.c 154856 2006-01-26 10:13:32Z 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> | 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 <libdisk.h> | 41#include <inttypes.h> 42#include <libgeom.h> |
42#include <paths.h> 43#include <stdlib.h> 44#include <string.h> 45#include <syslog.h> 46 47#include "hostres_snmp.h" 48#include "hostres_oid.h" 49#include "hostres_tree.h" 50 | 43#include <paths.h> 44#include <stdlib.h> 45#include <string.h> 46#include <syslog.h> 47 48#include "hostres_snmp.h" 49#include "hostres_oid.h" 50#include "hostres_tree.h" 51 |
52#ifdef PC98 53#define HR_FREEBSD_PART_TYPE 0xc494 54#else 55#define HR_FREEBSD_PART_TYPE 165 56#endif 57 |
|
51/* 52 * One row in the hrPartitionTable 53 */ 54struct partition_entry { 55 struct asn_oid index; 56 u_char label[128 + 1]; 57 u_char id[128 + 1]; 58 int32_t size; --- 31 unchanged lines hidden (view full) --- 90 91/* next int available for indexing the hrPartitionTable */ 92static uint32_t next_partition_index = 1; 93 94/** 95 * Create a new partition table entry 96 */ 97static struct partition_entry * | 58/* 59 * One row in the hrPartitionTable 60 */ 61struct partition_entry { 62 struct asn_oid index; 63 u_char label[128 + 1]; 64 u_char id[128 + 1]; 65 int32_t size; --- 31 unchanged lines hidden (view full) --- 97 98/* next int available for indexing the hrPartitionTable */ 99static uint32_t next_partition_index = 1; 100 101/** 102 * Create a new partition table entry 103 */ 104static struct partition_entry * |
98partition_entry_create(int32_t ds_index, const struct chunk *chunk) | 105partition_entry_create(int32_t ds_index, const char *chunk_name) |
99{ 100 struct partition_entry *entry; 101 struct partition_map_entry *map = NULL; 102 103 /* sanity checks */ | 106{ 107 struct partition_entry *entry; 108 struct partition_map_entry *map = NULL; 109 110 /* sanity checks */ |
104 assert(chunk != NULL); 105 assert(chunk->name != NULL); 106 if (chunk == NULL || chunk->name == NULL || chunk->name[0] == '\0') | 111 assert(chunk_name != NULL); 112 if (chunk_name == NULL || chunk_name[0] == '\0') |
107 return (NULL); 108 109 if ((entry = malloc(sizeof(*entry))) == NULL) { 110 syslog(LOG_WARNING, "hrPartitionTable: %s: %m", __func__); 111 return (NULL); 112 } 113 memset(entry, 0, sizeof(*entry)); 114 115 /* check whether we already have seen this partition */ 116 STAILQ_FOREACH(map, &partition_map, link) | 113 return (NULL); 114 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) |
117 if (strcmp(map->id, chunk->name) == 0 ) { | 123 if (strcmp(map->id, chunk_name) == 0 ) { |
118 map->entry = entry; 119 break; 120 } 121 122 if (map == NULL) { 123 /* new object - get a new index and create a map */ 124 if (next_partition_index > INT_MAX) { 125 syslog(LOG_ERR, "%s: hrPartitionTable index wrap", --- 4 unchanged lines hidden (view full) --- 130 if ((map = malloc(sizeof(*map))) == NULL) { 131 syslog(LOG_ERR, "hrPartitionTable: %s: %m", __func__); 132 free(entry); 133 return (NULL); 134 } 135 136 map->index = next_partition_index++; 137 | 124 map->entry = entry; 125 break; 126 } 127 128 if (map == NULL) { 129 /* new object - get a new index and create a map */ 130 if (next_partition_index > INT_MAX) { 131 syslog(LOG_ERR, "%s: hrPartitionTable index wrap", --- 4 unchanged lines hidden (view full) --- 136 if ((map = malloc(sizeof(*map))) == NULL) { 137 syslog(LOG_ERR, "hrPartitionTable: %s: %m", __func__); 138 free(entry); 139 return (NULL); 140 } 141 142 map->index = next_partition_index++; 143 |
138 memset(map->id, 0, sizeof(map->id)); 139 strncpy(map->id, chunk->name, sizeof(map->id) - 1); | 144 strlcpy(map->id, chunk_name, sizeof(map->id)); |
140 141 map->entry = entry; 142 STAILQ_INSERT_TAIL(&partition_map, map, link); 143 144 HRDBG("%s added into hrPartitionMap at index=%d", | 145 146 map->entry = entry; 147 STAILQ_INSERT_TAIL(&partition_map, map, link); 148 149 HRDBG("%s added into hrPartitionMap at index=%d", |
145 chunk->name, map->index); | 150 chunk_name, map->index); |
146 147 } else { 148 HRDBG("%s exists in hrPartitionMap index=%d", | 151 152 } else { 153 HRDBG("%s exists in hrPartitionMap index=%d", |
149 chunk->name, map->index); | 154 chunk_name, map->index); |
150 } 151 152 /* create the index */ 153 entry->index.len = 2; 154 entry->index.subs[0] = ds_index; 155 entry->index.subs[1] = map->index; 156 | 155 } 156 157 /* create the index */ 158 entry->index.len = 2; 159 entry->index.subs[0] = ds_index; 160 entry->index.subs[1] = map->index; 161 |
157 memset(&entry->id[0], 0, sizeof(entry->id)); 158 strncpy(entry->id, chunk->name, sizeof(entry->id) - 1); | 162 strlcpy(entry->id, chunk_name, sizeof(entry->id)); |
159 160 snprintf(entry->label, sizeof(entry->label) - 1, | 163 164 snprintf(entry->label, sizeof(entry->label) - 1, |
161 "%s%s", _PATH_DEV, chunk->name); | 165 "%s%s", _PATH_DEV, chunk_name); |
162 163 INSERT_OBJECT_OID(entry, &partition_tbl); 164 165 return (entry); 166} 167 168/** 169 * Delete a partition table entry but keep the map entry intact. --- 41 unchanged lines hidden (view full) --- 211 TAILQ_FOREACH(entry, &partition_tbl, link) 212 if (strcmp(entry->label, name) == 0) 213 return (entry); 214 215 return (NULL); 216} 217 218/** | 166 167 INSERT_OBJECT_OID(entry, &partition_tbl); 168 169 return (entry); 170} 171 172/** 173 * Delete a partition table entry but keep the map entry intact. --- 41 unchanged lines hidden (view full) --- 215 TAILQ_FOREACH(entry, &partition_tbl, link) 216 if (strcmp(entry->label, name) == 0) 217 return (entry); 218 219 return (NULL); 220} 221 222/** |
219 * Process a chunk from libdisk. A chunk is either a slice or a partition. | 223 * Process a chunk from libgeom(4). A chunk is either a slice or a partition. |
220 * If necessary create a new partition table entry for it. In any case 221 * set the size field of the entry and set the FOUND flag. 222 */ 223static void | 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 |
224handle_chunk(int32_t ds_index, const struct chunk* chunk, 225 const struct disk *disk) | 228handle_chunk(int32_t ds_index, const char *chunk_name, off_t chunk_size) |
226{ 227 struct partition_entry *entry = NULL; 228 daddr_t k_size; 229 | 229{ 230 struct partition_entry *entry = NULL; 231 daddr_t k_size; 232 |
230 assert(chunk != NULL); 231 if (chunk == NULL) | 233 assert(chunk_name != NULL); 234 assert(chunk_name[0] != '\0'); 235 if (chunk_name == NULL || chunk_name == '\0') |
232 return; 233 | 236 return; 237 |
234 if (chunk->type == unused) { 235 HRDBG("SKIP unused chunk %s", chunk->name); 236 return; 237 } 238 HRDBG("ANALYZE chunk %s", chunk->name); | 238 HRDBG("ANALYZE chunk %s", chunk_name); |
239 | 239 |
240 if ((entry = partition_entry_find_by_name(chunk->name)) == NULL) 241 if ((entry = partition_entry_create(ds_index, chunk)) == NULL) | 240 if ((entry = partition_entry_find_by_name(chunk_name)) == NULL) 241 if ((entry = partition_entry_create(ds_index, 242 chunk_name)) == NULL) |
242 return; 243 244 entry->flags |= HR_PARTITION_FOUND; 245 246 /* actual size may overflow the SNMP type */ | 243 return; 244 245 entry->flags |= HR_PARTITION_FOUND; 246 247 /* actual size may overflow the SNMP type */ |
247 k_size = chunk->size / (1024 / disk->sector_size); 248 entry->size = (k_size > (daddr_t)INT_MAX ? INT_MAX : k_size); | 248 k_size = chunk_size / 1024; 249 entry->size = (k_size > (off_t)INT_MAX ? INT_MAX : k_size); |
249} 250 251/** 252 * Start refreshing the partition table. A call to this function will 253 * be followed by a call to handleDiskStorage() for every disk, followed 254 * by a single call to the post_refresh function. 255 */ 256void 257partition_tbl_pre_refresh(void) 258{ 259 struct partition_entry *entry = NULL; 260 261 /* mark each entry as missing */ 262 TAILQ_FOREACH(entry, &partition_tbl, link) 263 entry->flags &= ~HR_PARTITION_FOUND; 264} 265 266/** | 250} 251 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{ 260 struct partition_entry *entry = NULL; 261 262 /* mark each entry as missing */ 263 TAILQ_FOREACH(entry, &partition_tbl, link) 264 entry->flags &= ~HR_PARTITION_FOUND; 265} 266 267/** |
267 * Called from the DiskStorage table for every row. Open the device and 268 * process all the partitions in it. ds_index is the index into the DiskStorage 269 * table. | 268 * Try to find a geom(4) class by its name. Returns a pointer to that 269 * class if found NULL otherways. |
270 */ | 270 */ |
271static struct gclass * 272find_class(struct gmesh *mesh, const char *name) 273{ 274 struct gclass *classp; 275 276 LIST_FOREACH(classp, &mesh->lg_class, lg_class) 277 if (strcmp(classp->lg_name, name) == 0) 278 return (classp); 279 return (NULL); 280} 281 282/** 283 * Process all MBR-type partitions from the given disk. 284 */ 285static void 286get_mbr(struct gclass *classp, int32_t ds_index, const char *disk_dev_name) 287{ 288 struct ggeom *gp; 289 struct gprovider *pp; 290 struct gconfig *conf; 291 long part_type; 292 293 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 294 /* We are only interested in partitions from this disk */ 295 if (strcmp(gp->lg_name, disk_dev_name) != 0) 296 continue; 297 298 /* 299 * Find all the non-BSD providers (these are handled in get_bsd) 300 */ 301 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 302 LIST_FOREACH(conf, &pp->lg_config, lg_config) { 303 if (conf->lg_name == NULL || 304 conf->lg_val == NULL || 305 strcmp(conf->lg_name, "type") != 0) 306 continue; 307 308 /* 309 * We are not interested in BSD partitions 310 * (ie ad0s1 is not interesting at this point). 311 * We'll take care of them in detail (slice 312 * by slice) in get_bsd. 313 */ 314 part_type = strtol(conf->lg_val, NULL, 10); 315 if (part_type == HR_FREEBSD_PART_TYPE) 316 break; 317 HRDBG("-> MBR PROVIDER Name: %s", pp->lg_name); 318 HRDBG("Mediasize: %jd", 319 (intmax_t)pp->lg_mediasize / 1024); 320 HRDBG("Sectorsize: %u", pp->lg_sectorsize); 321 HRDBG("Mode: %s", pp->lg_mode); 322 HRDBG("CONFIG: %s: %s", 323 conf->lg_name, conf->lg_val); 324 325 handle_chunk(ds_index, pp->lg_name, 326 pp->lg_mediasize); 327 } 328 } 329 } 330} 331 332/** 333 * Process all BSD-type partitions from the given disk. 334 */ 335static void 336get_bsd_sun(struct gclass *classp, int32_t ds_index, const char *disk_dev_name) 337{ 338 struct ggeom *gp; 339 struct gprovider *pp; 340 341 LIST_FOREACH(gp, &classp->lg_geom, lg_geom) { 342 /* 343 * We are only interested in those geoms starting with 344 * the disk_dev_name passed as parameter to this function. 345 */ 346 if (strncmp(gp->lg_name, disk_dev_name, 347 strlen(disk_dev_name)) != 0) 348 continue; 349 350 LIST_FOREACH(pp, &gp->lg_provider, lg_provider) { 351 if (pp->lg_name == NULL) 352 continue; 353 handle_chunk(ds_index, pp->lg_name, pp->lg_mediasize); 354 } 355 } 356} 357 358/** 359 * Called from the DiskStorage table for every row. Open the GEOM(4) framework 360 * and process all the partitions in it. 361 * ds_index is the index into the DiskStorage table. 362 * This is done in two steps: for non BSD partitions the geom class "MBR" is 363 * used, for our BSD slices the "BSD" geom class. 364 */ |
|
271void 272partition_tbl_handle_disk(int32_t ds_index, const char *disk_dev_name) 273{ | 365void 366partition_tbl_handle_disk(int32_t ds_index, const char *disk_dev_name) 367{ |
274 struct disk *disk; 275 struct chunk *chunk; 276 struct chunk *partt; | 368 struct gmesh mesh; /* GEOM userland tree */ 369 struct gclass *classp; 370 int error; |
277 278 assert(disk_dev_name != NULL); 279 assert(ds_index > 0); 280 | 371 372 assert(disk_dev_name != NULL); 373 assert(ds_index > 0); 374 |
281 if ((disk = Open_Disk(disk_dev_name)) == NULL) { 282 syslog(LOG_ERR, "%s: cannot Open_Disk()", disk_dev_name); | 375 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"); |
283 return; 284 } 285 | 380 return; 381 } 382 |
286 for (chunk = disk->chunks->part; chunk != NULL; chunk = chunk->next) { 287 handle_chunk(ds_index, chunk, disk); 288 for (partt = chunk->part; partt != NULL; partt = partt->next) 289 handle_chunk(ds_index, partt, disk); 290 } 291 Free_Disk(disk); | 383 /* 384 * First try the GEOM "MBR" class. 385 * This is needed for non-BSD slices (aka partitions) 386 * on PC architectures. 387 */ 388 if ((classp = find_class(&mesh, "MBR")) != NULL) { 389 get_mbr(classp, ds_index, disk_dev_name); 390 } else { 391 HRDBG("cannot find \"MBR\" geom class"); 392 } 393 394 /* 395 * Get the "BSD" GEOM class. 396 * Here we'll find all the info needed about the BSD slices. 397 */ 398 if ((classp = find_class(&mesh, "BSD")) != NULL) { 399 get_bsd_sun(classp, ds_index, disk_dev_name); 400 } else { 401 /* no problem on sparc64 */ 402 HRDBG("cannot find \"BSD\" geom class"); 403 } 404 405 /* 406 * Get the "SUN" GEOM class. 407 * Here we'll find all the info needed about the BSD slices. 408 */ 409 if ((classp = find_class(&mesh, "SUN")) != NULL) { 410 get_bsd_sun(classp, ds_index, disk_dev_name); 411 } else { 412 /* no problem on i386 */ 413 HRDBG("cannot find \"SUN\" geom class"); 414 } 415 416 geom_deletetree(&mesh); |
292} 293 294/** 295 * Finish refreshing the table. 296 */ 297void 298partition_tbl_post_refresh(void) 299{ --- 116 unchanged lines hidden --- | 417} 418 419/** 420 * Finish refreshing the table. 421 */ 422void 423partition_tbl_post_refresh(void) 424{ --- 116 unchanged lines hidden --- |