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