~psusi/ubuntu/precise/dmraid/fix-gpt

« back to all changes in this revision

Viewing changes to 1.0.0.rc15/lib/display/display.c

  • Committer: Bazaar Package Importer
  • Author(s): Artur Rona
  • Date: 2010-02-04 21:34:22 UTC
  • mfrom: (1.1.4 upstream) (2.4.3 sid)
  • Revision ID: james.westby@ubuntu.com-20100204213422-tdag8lcxpr7ahmg4
Tags: 1.0.0.rc16-3ubuntu1
* Merge from debian testing. (LP: #503136)  Remaining changes:
  - debian/dmraid-activate: Remove the special-casing of the root
    device which breaks in many situations and leaves the raw devices
    exposed. This was introduced in Debian to accommodate some broken
    configurations which wanted to access "partitions" on the raid
    raw devices. In Ubuntu, broken configurations has not been supported.
  - debian/dmraid.postinst: Comment out "udevadm trigger" call in postinst
    for now as it has severeconsequences when mountall is installed
    (clears /tmp).  If dmraid is installed, then presumably the important
    system devices are up and one canbe bothered with a reboot to take 
    the change into account. Let update-initramfs flag the system
    as needing a reboot.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright (C) 2004,2005  Heinz Mauelshagen, Red Hat GmbH.
3
 
 *                          All rights reserved.
4
 
 *
5
 
 * See file LICENSE at the top of this source tree for license information.
6
 
 */
7
 
 
8
 
#include "internal.h"
9
 
#include "activate/devmapper.h"
10
 
 
11
 
#define ARRAY_LIMIT(array, idx) \
12
 
        ((idx) < ARRAY_SIZE(array) ? (idx) : ARRAY_SIZE(array) - 1)
13
 
 
14
 
struct log_handler {
15
 
        const char *field;
16
 
        const unsigned char minlen;
17
 
        void (*log_func) (struct lib_context *, void *arg);
18
 
        void *arg;
19
 
};
20
 
 
21
 
static void
22
 
log_string(struct lib_context *lc, void *arg)
23
 
{
24
 
        log_print_nnl(lc, "%s", (char *) arg);
25
 
}
26
 
 
27
 
static void
28
 
log_uint64(struct lib_context *lc, void *arg)
29
 
{
30
 
        log_print_nnl(lc, "%" PRIu64, *((uint64_t *) arg));
31
 
}
32
 
 
33
 
static void
34
 
log_uint(struct lib_context *lc, void *arg)
35
 
{
36
 
        log_print_nnl(lc, "%u", *((unsigned int *) arg));
37
 
}
38
 
 
39
 
/* Log a structure member by field name. */
40
 
static int
41
 
log_field(struct lib_context *lc, const struct log_handler *lh,
42
 
          size_t lh_size, char *field)
43
 
{
44
 
        const struct log_handler *h;
45
 
 
46
 
        for (h = lh; h < lh + lh_size; h++) {
47
 
                size_t len = strlen(field);
48
 
 
49
 
                if (!strncmp(field, h->field,
50
 
                             len > h->minlen ? len : h->minlen)) {
51
 
                        h->log_func(lc, h->arg);
52
 
                        return 1;
53
 
                }
54
 
        }
55
 
 
56
 
        log_print_nnl(lc, "*ERR*");
57
 
 
58
 
        return 1;
59
 
}
60
 
 
61
 
/* Log a list of structure members by field name. */
62
 
static void
63
 
log_fields(struct lib_context *lc, const struct log_handler *lh, size_t lh_size)
64
 
{
65
 
        int logged = 0, last_logged = 0;
66
 
        const char delim = *OPT_STR_SEPARATOR(lc);
67
 
        char *p, *sep, *sep_sav;
68
 
 
69
 
        if (!(sep_sav = dbg_strdup((char *) OPT_STR_COLUMN(lc)))) {
70
 
                log_alloc_err(lc, __func__);
71
 
                return;
72
 
        }
73
 
 
74
 
        sep = sep_sav;
75
 
        do {
76
 
                sep = remove_delimiter((p = sep), delim);
77
 
                if (last_logged)
78
 
                        log_print_nnl(lc, "%c", delim);
79
 
 
80
 
                last_logged = log_field(lc, lh, lh_size, p);
81
 
                logged += last_logged;
82
 
                add_delimiter(&sep, delim);
83
 
        } while (sep);
84
 
 
85
 
        dbg_free(sep_sav);
86
 
        if (logged)
87
 
                log_print(lc, "");
88
 
}
89
 
 
90
 
/* Display information about a block device */
91
 
static void
92
 
log_disk(struct lib_context *lc, struct list_head *pos)
93
 
{
94
 
        struct dev_info *di = list_entry(pos, typeof(*di), list);
95
 
 
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},
104
 
                };
105
 
 
106
 
                log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers));
107
 
        }
108
 
        else {
109
 
                const char *fmt[] = {
110
 
                        "%s: %12" PRIu64 " total, \"%s\"",
111
 
                        "%s",
112
 
                        "%s:%" PRIu64 ":\"%s\"",
113
 
                };
114
 
 
115
 
                log_print(lc, fmt[ARRAY_LIMIT(fmt, OPT_COLUMN(lc))],
116
 
                          di->path, di->sectors,
117
 
                          di->serial ? di->serial : "N/A");
118
 
        }
119
 
}
120
 
 
121
 
/* Turn NULL (= "unknown") into a displayable string. */
122
 
static const char *
123
 
check_null(const char *str)
124
 
{
125
 
        return str ? str : "unknown";
126
 
}
127
 
 
128
 
/* Log native RAID device information. */
129
 
static void
130
 
log_rd_native(struct lib_context *lc, struct list_head *pos)
131
 
{
132
 
        struct raid_dev *rd = list_entry(pos, typeof(*rd), list);
133
 
 
134
 
        if (rd->fmt->log) {
135
 
                rd->fmt->log(lc, rd);
136
 
                log_print(lc, "");
137
 
        }
138
 
        else
139
 
                log_print(lc, "\"%s\" doesn't support native logging of RAID "
140
 
                          "device information", rd->fmt->name);
141
 
}
142
 
 
143
 
/* Display information about a RAID device */
144
 
static void
145
 
log_rd(struct lib_context *lc, struct list_head *pos)
146
 
{
147
 
        struct raid_dev *rd = list_entry(pos, typeof(*rd), list);
148
 
 
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))},
163
 
                };
164
 
 
165
 
                log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers));
166
 
        }
167
 
        else {
168
 
                const char *fmt[] = {
169
 
                        "%s: %s, \"%s\", %s, %s, %" PRIu64 " sectors, "
170
 
                                "data@ %" PRIu64,
171
 
                        "%s",
172
 
                        "%s:%s:%s:%s:%s:%" PRIu64 ":%" PRIu64,
173
 
                };
174
 
 
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);
180
 
        }
181
 
}
182
 
 
183
 
/* Dispatch log functions. */
184
 
static void
185
 
log_devices(struct lib_context *lc, enum dev_type type)
186
 
{
187
 
        struct list_head *pos;
188
 
        struct {
189
 
                enum dev_type type;
190
 
                struct list_head *list;
191
 
                void (*log) (struct lib_context *, struct list_head *);
192
 
        } types[] = {
193
 
                { DEVICE, LC_DI(lc), log_disk },
194
 
                { NATIVE, LC_RD(lc), log_rd_native },
195
 
                { RAID, LC_RD(lc), log_rd },
196
 
        }, *t = types;
197
 
 
198
 
        do {
199
 
                if (t->type == type) {
200
 
                        list_for_each(pos, t->list)
201
 
                                t->log(lc, pos);
202
 
 
203
 
                        return;
204
 
                }
205
 
        } while (++t < ARRAY_END(types));
206
 
 
207
 
        LOG_ERR(lc,, "%s: unknown device type", __func__);
208
 
}
209
 
 
210
 
/* Display information about a dmraid format handler */
211
 
static void
212
 
log_format(struct lib_context *lc, struct dmraid_format *fmt)
213
 
{
214
 
        log_print_nnl(lc, "%-7s : %s", fmt->name, fmt->descr);
215
 
        if (fmt->caps)
216
 
                log_print_nnl(lc, " (%s)", fmt->caps);
217
 
 
218
 
        log_print(lc, "");
219
 
}
220
 
 
221
 
/* Pretty print a mapping table. */
222
 
void
223
 
display_table(struct lib_context *lc, char *rs_name, char *table)
224
 
{
225
 
        char *nl = table, *p;
226
 
 
227
 
        do {
228
 
                nl = remove_delimiter((p = nl), '\n');
229
 
                log_print(lc, "%s: %s", rs_name, p);
230
 
                add_delimiter(&nl, '\n');
231
 
        } while (nl);
232
 
}
233
 
 
234
 
/* Display information about devices depending on device type. */
235
 
void
236
 
display_devices(struct lib_context *lc, enum dev_type type)
237
 
{
238
 
        int devs;
239
 
 
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");
244
 
 
245
 
                log_devices(lc, type);
246
 
        }
247
 
}
248
 
 
249
 
/* Retrieve format name from (hierarchical) raid set. */
250
 
static void *
251
 
get_format_name(struct raid_set *rs)
252
 
{
253
 
        struct dmraid_format *fmt = get_format(rs);
254
 
 
255
 
        return (void *) check_null(fmt ? fmt->name : NULL);
256
 
}
257
 
 
258
 
static void
259
 
log_rs(struct lib_context *lc, struct raid_set *rs)
260
 
{
261
 
        unsigned int devs = 0, spares = 0, subsets = 0;
262
 
        uint64_t sectors = 0;
263
 
 
264
 
        if (T_GROUP(rs) && !OPT_GROUP(lc))
265
 
                return;
266
 
 
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);
271
 
 
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, &sectors},
278
 
                        {"size", 2, log_uint64, &sectors},
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))},
286
 
                };
287
 
 
288
 
                log_fields(lc, log_handlers, ARRAY_SIZE(log_handlers));
289
 
        }
290
 
        else {
291
 
                const char *fmt[] = {
292
 
                        "name   : %s\n"
293
 
                                "size   : %" PRIu64 "\n"
294
 
                                "stride : %u\n"
295
 
                                "type   : %s\n"
296
 
                                "status : %s\n"
297
 
                                "subsets: %u\n" "devs   : %u\n" "spares : %u",
298
 
                        "%s",
299
 
                        "%s:%" PRIu64 ":%u:%s:%s:%u:%u:%u",
300
 
                };
301
 
                unsigned int o = ARRAY_LIMIT(fmt, lc_opt(lc, LC_COLUMN));
302
 
 
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);
308
 
 
309
 
        }
310
 
 
311
 
        if (OPT_COLUMN(lc) > 2) {
312
 
                struct raid_dev *rd;
313
 
 
314
 
                list_for_each_entry(rd, &rs->devs, devs)
315
 
                        log_rd(lc, &rd->list);
316
 
        }
317
 
}
318
 
 
319
 
static int
320
 
group_active(struct lib_context *lc, struct raid_set *rs)
321
 
{
322
 
        struct raid_set *r;
323
 
 
324
 
        list_for_each_entry(r, &rs->sets, list) {
325
 
                if (dm_status(lc, r))
326
 
                        return 1;
327
 
        }
328
 
 
329
 
        return 0;
330
 
}
331
 
 
332
 
/* FIXME: Spock, do something better (neater). */
333
 
void
334
 
display_set(struct lib_context *lc, void *v, enum active_type active, int top)
335
 
{
336
 
        struct raid_set *rs = v;
337
 
        struct raid_set *r;
338
 
        int dmstatus = T_GROUP(rs) ? group_active(lc, rs) : dm_status(lc, rs);
339
 
 
340
 
        if (((active & D_ACTIVE) && !dmstatus) ||
341
 
            ((active & D_INACTIVE) && dmstatus))
342
 
                return;
343
 
 
344
 
        if (!OPT_COLUMN(lc)) {
345
 
                if (T_GROUP(rs) && !OPT_GROUP(lc))
346
 
                        log_print(lc, "*** Group superset %s", rs->name);
347
 
                else {
348
 
                        log_print(lc, "%s %s%s%set",
349
 
                                  top ? "-->" : "***",
350
 
                                  S_INCONSISTENT(rs->status) ?
351
 
                                  "*Inconsistent* " : "",
352
 
                                  dm_status(lc, rs) ? "Active " : "",
353
 
                                  SETS(rs) ? "Supers" : (top ? "Subs" : "S"));
354
 
                }
355
 
        }
356
 
 
357
 
        log_rs(lc, rs);
358
 
 
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);
364
 
        }
365
 
}
366
 
 
367
 
/*
368
 
 * Display information about supported RAID metadata formats
369
 
 * (ie. registered format handlers)
370
 
 */
371
 
static void
372
 
_list_formats(struct lib_context *lc, enum fmt_type type)
373
 
{
374
 
        struct format_list *fmt_list;
375
 
 
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);
379
 
        }
380
 
}
381
 
 
382
 
int
383
 
list_formats(struct lib_context *lc, int arg)
384
 
{
385
 
        log_info(lc, "supported metadata formats:");
386
 
        _list_formats(lc, FMT_RAID);
387
 
        _list_formats(lc, FMT_PARTITION);
388
 
 
389
 
        return 1;
390
 
}