2
* Copyright (C) 2004,2005 Heinz Mauelshagen, Red Hat GmbH.
5
* See file LICENSE at the top of this source tree for license information.
9
#include "activate/devmapper.h"
11
#define ARRAY_LIMIT(array, idx) \
12
((idx) < ARRAY_SIZE(array) ? (idx) : ARRAY_SIZE(array) - 1)
16
const unsigned char minlen;
17
void (*log_func) (struct lib_context *, void *arg);
22
log_string(struct lib_context *lc, void *arg)
24
log_print_nnl(lc, "%s", (char *) arg);
28
log_uint64(struct lib_context *lc, void *arg)
30
log_print_nnl(lc, "%" PRIu64, *((uint64_t *) arg));
34
log_uint(struct lib_context *lc, void *arg)
36
log_print_nnl(lc, "%u", *((unsigned int *) arg));
39
/* Log a structure member by field name. */
41
log_field(struct lib_context *lc, const struct log_handler *lh,
42
size_t lh_size, char *field)
44
const struct log_handler *h;
46
for (h = lh; h < lh + lh_size; h++) {
47
size_t len = strlen(field);
49
if (!strncmp(field, h->field,
50
len > h->minlen ? len : h->minlen)) {
51
h->log_func(lc, h->arg);
56
log_print_nnl(lc, "*ERR*");
61
/* Log a list of structure members by field name. */
63
log_fields(struct lib_context *lc, const struct log_handler *lh, size_t lh_size)
65
int logged = 0, last_logged = 0;
66
const char delim = *OPT_STR_SEPARATOR(lc);
67
char *p, *sep, *sep_sav;
69
if (!(sep_sav = dbg_strdup((char *) OPT_STR_COLUMN(lc)))) {
70
log_alloc_err(lc, __func__);
76
sep = remove_delimiter((p = sep), delim);
78
log_print_nnl(lc, "%c", delim);
80
last_logged = log_field(lc, lh, lh_size, p);
81
logged += last_logged;
82
add_delimiter(&sep, delim);
90
/* Display information about a block device */
92
log_disk(struct lib_context *lc, struct list_head *pos)
94
struct dev_info *di = list_entry(pos, typeof(*di), list);
96
if (OPT_STR_COLUMN(lc)) {
97
const struct log_handler log_handlers[] = {
98
{"devpath", 1, log_string, di->path},
99
{"path", 1, log_string, di->path},
100
{"sectors", 3, log_uint64, &di->sectors},
101
{"serialnumber", 3, log_string,
102
di->serial ? (void *) di->serial : (void *) "N/A"},
103
{"size", 2, log_uint64, &di->sectors},
106
log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers));
109
const char *fmt[] = {
110
"%s: %12" PRIu64 " total, \"%s\"",
112
"%s:%" PRIu64 ":\"%s\"",
115
log_print(lc, fmt[ARRAY_LIMIT(fmt, OPT_COLUMN(lc))],
116
di->path, di->sectors,
117
di->serial ? di->serial : "N/A");
121
/* Turn NULL (= "unknown") into a displayable string. */
123
check_null(const char *str)
125
return str ? str : "unknown";
128
/* Log native RAID device information. */
130
log_rd_native(struct lib_context *lc, struct list_head *pos)
132
struct raid_dev *rd = list_entry(pos, typeof(*rd), list);
135
rd->fmt->log(lc, rd);
139
log_print(lc, "\"%s\" doesn't support native logging of RAID "
140
"device information", rd->fmt->name);
143
/* Display information about a RAID device */
145
log_rd(struct lib_context *lc, struct list_head *pos)
147
struct raid_dev *rd = list_entry(pos, typeof(*rd), list);
149
if (OPT_STR_COLUMN(lc)) {
150
const struct log_handler log_handlers[] = {
151
{"dataoffset", 2, log_uint64, &rd->offset},
152
{"devpath", 2, log_string, rd->di->path},
153
{"format", 1, log_string, (void *) rd->fmt->name},
154
{"offset", 1, log_uint64, &rd->offset},
155
{"path", 1, log_string, rd->di->path},
156
{"raidname", 1, log_string, rd->name},
157
{"type", 1, log_string,
158
(void *) check_null(get_type(lc, rd->type))},
159
{"sectors", 2, log_uint64, &rd->sectors},
160
{"size", 2, log_uint64, &rd->sectors},
161
{"status", 2, log_string,
162
(void *) check_null(get_status(lc, rd->status))},
165
log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers));
168
const char *fmt[] = {
169
"%s: %s, \"%s\", %s, %s, %" PRIu64 " sectors, "
172
"%s:%s:%s:%s:%s:%" PRIu64 ":%" PRIu64,
175
log_print(lc, fmt[ARRAY_LIMIT(fmt, OPT_COLUMN(lc))],
176
rd->di->path, rd->fmt->name, rd->name,
177
check_null(get_type(lc, rd->type)),
178
check_null(get_status(lc, rd->status)),
179
rd->sectors, rd->offset);
183
/* Dispatch log functions. */
185
log_devices(struct lib_context *lc, enum dev_type type)
187
struct list_head *pos;
190
struct list_head *list;
191
void (*log) (struct lib_context *, struct list_head *);
193
{ DEVICE, LC_DI(lc), log_disk },
194
{ NATIVE, LC_RD(lc), log_rd_native },
195
{ RAID, LC_RD(lc), log_rd },
199
if (t->type == type) {
200
list_for_each(pos, t->list)
205
} while (++t < ARRAY_END(types));
207
LOG_ERR(lc,, "%s: unknown device type", __func__);
210
/* Display information about a dmraid format handler */
212
log_format(struct lib_context *lc, struct dmraid_format *fmt)
214
log_print_nnl(lc, "%-7s : %s", fmt->name, fmt->descr);
216
log_print_nnl(lc, " (%s)", fmt->caps);
221
/* Pretty print a mapping table. */
223
display_table(struct lib_context *lc, char *rs_name, char *table)
225
char *nl = table, *p;
228
nl = remove_delimiter((p = nl), '\n');
229
log_print(lc, "%s: %s", rs_name, p);
230
add_delimiter(&nl, '\n');
234
/* Display information about devices depending on device type. */
236
display_devices(struct lib_context *lc, enum dev_type type)
240
if ((devs = count_devices(lc, type))) {
241
log_info(lc, "%s device%s discovered:\n",
242
(type & (RAID | NATIVE)) ? "RAID" : "Block",
243
devs == 1 ? "" : "s");
245
log_devices(lc, type);
249
/* Retrieve format name from (hierarchical) raid set. */
251
get_format_name(struct raid_set *rs)
253
struct dmraid_format *fmt = get_format(rs);
255
return (void *) check_null(fmt ? fmt->name : NULL);
259
log_rs(struct lib_context *lc, struct raid_set *rs)
261
unsigned int devs = 0, spares = 0, subsets = 0;
262
uint64_t sectors = 0;
264
if (T_GROUP(rs) && !OPT_GROUP(lc))
267
sectors = total_sectors(lc, rs);
268
subsets = count_sets(lc, &rs->sets);
269
devs = count_devs(lc, rs, ct_dev);
270
spares = count_devs(lc, rs, ct_spare);
272
if (OPT_STR_COLUMN(lc)) {
273
const struct log_handler log_handlers[] = {
274
{"devices", 1, log_uint, &devs},
275
{"format", 1, log_string, get_format_name(rs)},
276
{"raidname", 1, log_string, rs->name},
277
{"sectors", 2, log_uint64, §ors},
278
{"size", 2, log_uint64, §ors},
279
{"spares", 2, log_uint, &spares},
280
{"status", 3, log_string,
281
(void *) check_null(get_status(lc, rs->status))},
282
{"stride", 3, log_uint, &rs->stride},
283
{"subsets", 2, log_uint, &subsets},
284
{"type", 1, log_string,
285
(void *) check_null(get_set_type(lc, rs))},
288
log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers));
291
const char *fmt[] = {
293
"size : %" PRIu64 "\n"
297
"subsets: %u\n" "devs : %u\n" "spares : %u",
299
"%s:%" PRIu64 ":%u:%s:%s:%u:%u:%u",
301
unsigned int o = ARRAY_LIMIT(fmt, lc_opt(lc, LC_COLUMN));
303
log_print(lc, fmt[o],
304
rs->name, sectors, rs->stride,
305
check_null(get_set_type(lc, rs)),
306
check_null(get_status(lc, rs->status)),
307
subsets, devs, spares);
311
if (OPT_COLUMN(lc) > 2) {
314
list_for_each_entry(rd, &rs->devs, devs)
315
log_rd(lc, &rd->list);
320
group_active(struct lib_context *lc, struct raid_set *rs)
324
list_for_each_entry(r, &rs->sets, list) {
325
if (dm_status(lc, r))
332
/* FIXME: Spock, do something better (neater). */
334
display_set(struct lib_context *lc, void *v, enum active_type active, int top)
336
struct raid_set *rs = v;
338
int dmstatus = T_GROUP(rs) ? group_active(lc, rs) : dm_status(lc, rs);
340
if (((active & D_ACTIVE) && !dmstatus) ||
341
((active & D_INACTIVE) && dmstatus))
344
if (!OPT_COLUMN(lc)) {
345
if (T_GROUP(rs) && !OPT_GROUP(lc))
346
log_print(lc, "*** Group superset %s", rs->name);
348
log_print(lc, "%s %s%s%set",
350
S_INCONSISTENT(rs->status) ?
351
"*Inconsistent* " : "",
352
dm_status(lc, rs) ? "Active " : "",
353
SETS(rs) ? "Supers" : (top ? "Subs" : "S"));
359
/* Optionally display subsets. */
360
if (T_GROUP(rs) || /* Always display for GROUP sets. */
361
OPT_SETS(lc) > 1 || OPT_COLUMN(lc) > 2) {
362
list_for_each_entry(r, &rs->sets, list)
363
display_set(lc, r, active, ++top);
368
* Display information about supported RAID metadata formats
369
* (ie. registered format handlers)
372
_list_formats(struct lib_context *lc, enum fmt_type type)
374
struct format_list *fmt_list;
376
list_for_each_entry(fmt_list, LC_FMT(lc), list) {
377
if (type == fmt_list->fmt->format)
378
log_format(lc, fmt_list->fmt);
383
list_formats(struct lib_context *lc, int arg)
385
log_info(lc, "supported metadata formats:");
386
_list_formats(lc, FMT_RAID);
387
_list_formats(lc, FMT_PARTITION);