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

« back to all changes in this revision

Viewing changes to 1.0.0.rc16/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
}