Deleted Added
full compact
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 ---