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