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

« back to all changes in this revision

Viewing changes to 1.0.0.rc15/lib/format/ataraid/lsi.c

  • Committer: Bazaar Package Importer
  • Author(s): Giuseppe Iuculano, 6af052c
  • Date: 2009-03-25 22:34:59 UTC
  • mfrom: (2.1.9 sid)
  • mto: (2.4.1 squeeze)
  • mto: This revision was merged to the branch mainline in revision 39.
  • Revision ID: james.westby@ubuntu.com-20090325223459-y54f0rmxem7htn6r
Tags: 1.0.0.rc15-6
[6af052c] Remove 15_isw_incorrect_status_fix.patch, it causes a
segfault. (Closes: #521104)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * LSI Logic MegaRAID (and MegaIDE ?) ATARAID metadata format handler.
 
3
 *
 
4
 * Copyright (C) 2004-2008  Heinz Mauelshagen, Red Hat GmbH.
 
5
 *                          All rights reserved.
 
6
 *
 
7
 * See file LICENSE at the top of this source tree for license information.
 
8
 */
 
9
 
 
10
/*
 
11
 * FIXME: needs more metadata reengineering and grouping logic coding.
 
12
 */
 
13
 
 
14
#define HANDLER "lsi"
 
15
 
 
16
#include "internal.h"
 
17
#define FORMAT_HANDLER
 
18
#include "lsi.h"
 
19
 
 
20
#if     BYTE_ORDER != LITTLE_ENDIAN
 
21
#  define       DM_BYTEORDER_SWAB
 
22
#  include      <datastruct/byteorder.h>
 
23
#endif
 
24
 
 
25
static const char *handler = HANDLER;
 
26
 
 
27
/* Make up RAID device name. */
 
28
/* FIXME: senseful name ;) */
 
29
static unsigned int
 
30
get_disk_slot(struct lsi *lsi)
 
31
{
 
32
        return lsi->set_number * 2 + lsi->disk_number;
 
33
}
 
34
 
 
35
static struct lsi_disk *
 
36
get_disk(struct lsi *lsi)
 
37
{
 
38
        return lsi->disks + get_disk_slot(lsi);
 
39
}
 
40
 
 
41
static size_t
 
42
_name(struct lsi *lsi, char *str, size_t len, unsigned int subset)
 
43
{
 
44
        return snprintf(str, len,
 
45
                        subset ? "lsi_%u%u-%u" : "lsi_%u%u",
 
46
                        lsi->set_id, lsi->set_number,
 
47
                        get_disk(lsi)->raid10_mirror);
 
48
}
 
49
 
 
50
static char *
 
51
name(struct lib_context *lc, struct raid_dev *rd, unsigned int subset)
 
52
{
 
53
        size_t len;
 
54
        char *ret;
 
55
        struct lsi *lsi = META(rd, lsi);
 
56
 
 
57
        subset = subset && (lsi->type == LSI_T_RAID10);
 
58
        if ((ret = dbg_malloc((len = _name(lsi, NULL, 0, subset) + 1)))) {
 
59
                _name(lsi, ret, len, subset);
 
60
                mk_alpha(lc, ret + HANDLER_LEN, strlen(ret) - HANDLER_LEN -
 
61
                         (subset ? 2 : 0));
 
62
        } else
 
63
                log_alloc_err(lc, handler);
 
64
 
 
65
        return ret;
 
66
}
 
67
 
 
68
/* Neutralize disk type */
 
69
static enum type
 
70
type(struct lsi *lsi)
 
71
{
 
72
        /* Mapping of LSI Logic types to generic types */
 
73
        static struct types types[] = {
 
74
                { LSI_T_RAID0, t_raid0 },
 
75
                { LSI_T_RAID1, t_raid1 },
 
76
                { LSI_T_RAID10, t_raid0 },
 
77
                { 0, t_undef }
 
78
        };
 
79
 
 
80
        return rd_type(types, (unsigned int) lsi->type);
 
81
}
 
82
 
 
83
/* LSI device status. */
 
84
/* FIXME: add flesh. */
 
85
static int
 
86
status(struct lsi *lsi)
 
87
{
 
88
        return s_ok;
 
89
}
 
90
 
 
91
/* Decide about ordering sequence of RAID device. */
 
92
static int
 
93
dev_sort(struct list_head *pos, struct list_head *new)
 
94
{
 
95
        struct lsi *p = META(RD(pos), lsi), *n = META(RD(new), lsi);
 
96
 
 
97
        switch (n->type) {
 
98
        case LSI_T_RAID10:
 
99
                return (get_disk(n))->raid10_stripe <
 
100
                        (get_disk(p))->raid10_stripe;
 
101
 
 
102
        default:                /* RAID0 + RAID01 */
 
103
                return get_disk_slot(n) < get_disk_slot(p);
 
104
        }
 
105
}
 
106
 
 
107
/* Decide about ordering sequence of RAID subset. */
 
108
static int
 
109
set_sort(struct list_head *pos, struct list_head *new)
 
110
{
 
111
        struct lsi *p = META(RD_RS(pos), lsi), *n = META(RD_RS(new), lsi);
 
112
 
 
113
        return n->disks[get_disk_slot(n)].raid10_mirror <
 
114
               p->disks[get_disk_slot(p)].raid10_mirror;
 
115
}
 
116
 
 
117
/*
 
118
 * Read an LSI Logic RAID device
 
119
 */
 
120
/* Endianess conversion. */
 
121
#if     BYTE_ORDER == LITTLE_ENDIAN
 
122
#  define       to_cpu  NULL
 
123
#else
 
124
static void
 
125
to_cpu(void *meta)
 
126
{
 
127
        struct lsi *lsi = meta;
 
128
        struct lsi_disk *disk;
 
129
 
 
130
        CVT16(lsi->stride);
 
131
 
 
132
        for (disk = lsi->disks; disk < &lsi->disks[LSI_MAX_DISKS]; disk++) {
 
133
                CVT16(disk->magic_0);
 
134
                CVT16(disk->magic_1);
 
135
        }
 
136
 
 
137
        CVT32(lsi->set_id);
 
138
}
 
139
#endif
 
140
 
 
141
static int
 
142
is_lsi(struct lib_context *lc, struct dev_info *di, void *meta)
 
143
{
 
144
        return !strncmp((const char *) ((struct lsi *) meta)->magic_name,
 
145
                        LSI_MAGIC_NAME, LSI_MAGIC_NAME_LEN);
 
146
}
 
147
 
 
148
static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
 
149
                    struct dev_info *di, void *meta, union read_info *info);
 
150
static struct raid_dev *
 
151
lsi_read(struct lib_context *lc, struct dev_info *di)
 
152
{
 
153
        return read_raid_dev(lc, di, NULL,
 
154
                             sizeof(struct lsi), LSI_CONFIGOFFSET,
 
155
                             to_cpu, is_lsi, NULL, setup_rd, handler);
 
156
}
 
157
 
 
158
/*
 
159
 * Write a LSI Logic RAID device.
 
160
 */
 
161
static int
 
162
lsi_write(struct lib_context *lc, struct raid_dev *rd, int erase)
 
163
{
 
164
        int ret;
 
165
#if     BYTE_ORDER != LITTLE_ENDIAN
 
166
        struct lsi *lsi = META(rd, lsi);
 
167
 
 
168
        to_disk(lsi);
 
169
#endif
 
170
        ret = write_metadata(lc, handler, rd, -1, erase);
 
171
#if     BYTE_ORDER != LITTLE_ENDIAN
 
172
        to_cpu(lsi);
 
173
#endif
 
174
        return ret;
 
175
}
 
176
 
 
177
/*
 
178
 * Group the RAID disk into a set.
 
179
 *
 
180
 * FIXME: this needs more work together with the metadata reengineering.
 
181
 */
 
182
static void
 
183
super_created(struct raid_set *ss, void *private)
 
184
{
 
185
        ss->type = t_raid1;
 
186
        ss->stride = META(private, lsi)->stride;
 
187
}
 
188
 
 
189
static int
 
190
group_rd(struct lib_context *lc, struct raid_set *rs,
 
191
         struct raid_set **ss, struct raid_dev *rd)
 
192
{
 
193
        struct lsi *lsi = META(rd, lsi);
 
194
 
 
195
        /* Refuse to add drives that are not online */
 
196
        if (get_disk(lsi)->offline)
 
197
                return 0;
 
198
 
 
199
        if (!init_raid_set(lc, rs, rd, lsi->stride, type(lsi), handler))
 
200
                return 0;
 
201
 
 
202
        list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort);
 
203
 
 
204
        switch (lsi->type) {
 
205
        case LSI_T_RAID0:
 
206
        case LSI_T_RAID1:
 
207
                if (!find_set(lc, NULL, rs->name, FIND_TOP))
 
208
                        list_add_tail(&rs->list, LC_RS(lc));
 
209
                break;
 
210
 
 
211
        case LSI_T_RAID10:
 
212
                if (!(*ss = join_superset(lc, name, super_created,
 
213
                                          set_sort, rs, rd)))
 
214
                        return 0;
 
215
        }
 
216
 
 
217
        return 1;
 
218
}
 
219
 
 
220
static struct raid_set *
 
221
lsi_group(struct lib_context *lc, struct raid_dev *rd)
 
222
{
 
223
        struct raid_set *rs, *ss = NULL;
 
224
 
 
225
        if (T_SPARE(rd))
 
226
                return NULL;
 
227
 
 
228
        if ((rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL, rd,
 
229
                                         NO_LIST, NO_CREATE, NO_CREATE_ARG)))
 
230
                return group_rd(lc, rs, &ss, rd) ? (ss ? ss : rs) : NULL;
 
231
 
 
232
        return NULL;
 
233
}
 
234
 
 
235
/* Figure total number of disks depending on RAID type. */
 
236
static unsigned int
 
237
devices(struct raid_dev *rd, void *context)
 
238
{
 
239
        switch (META(rd, lsi)->type) {
 
240
        case LSI_T_RAID10:
 
241
                return 4;
 
242
 
 
243
        case LSI_T_RAID0:
 
244
        case LSI_T_RAID1:
 
245
                return 2;
 
246
        }
 
247
 
 
248
        return 0;
 
249
}
 
250
 
 
251
/*
 
252
 * Check an LSI RAID set.
 
253
 *
 
254
 * FIXME: more sanity checks!!!
 
255
 */
 
256
static int
 
257
lsi_check(struct lib_context *lc, struct raid_set *rs)
 
258
{
 
259
        return check_raid_set(lc, rs, devices, NULL,
 
260
                              NO_CHECK_RD, NULL, handler);
 
261
}
 
262
 
 
263
/*
 
264
 * IO error event handler.
 
265
 */
 
266
static int
 
267
event_io(struct lib_context *lc, struct event_io *e_io)
 
268
{
 
269
        struct raid_dev *rd = e_io->rd;
 
270
        struct lsi *lsi = META(rd, lsi);
 
271
 
 
272
        /* Avoid write trashing. */
 
273
        if (status(lsi) & s_broken)
 
274
                return 0;
 
275
 
 
276
        // FIXME: lsi->? = BAD;
 
277
        return 1;
 
278
}
 
279
 
 
280
static struct event_handlers lsi_event_handlers = {
 
281
        .io = event_io,
 
282
        .rd = NULL,             /* FIXME: no device add/remove event handler yet. */
 
283
};
 
284
 
 
285
#ifdef DMRAID_NATIVE_LOG
 
286
/* Log native information about an LSI Logic RAID device. */
 
287
static void
 
288
lsi_log(struct lib_context *lc, struct raid_dev *rd)
 
289
{
 
290
        unsigned int i;
 
291
        struct lsi *lsi = META(rd, lsi);
 
292
        struct lsi_disk *disk;
 
293
 
 
294
        log_print(lc, "%s (%s):", rd->di->path, handler);
 
295
        DP("magic_name: %s", lsi, lsi->magic_name);
 
296
        P("dummy: %u, 0x%x", lsi, lsi->dummy, lsi->dummy, lsi->dummy);
 
297
        DP("seqno: %u", lsi, lsi->seqno);
 
298
        P("dummy2: %u, 0x%x", lsi, lsi->dummy2, lsi->dummy2, lsi->dummy2);
 
299
        P("dummy3: %u, 0x%x", lsi, lsi->dummy3, lsi->dummy3, lsi->dummy3);
 
300
        DP("type: %u", lsi, lsi->type);
 
301
        P("dummy4: %u, 0x%x", lsi, lsi->dummy4, lsi->dummy4, lsi->dummy4);
 
302
        DP("stride: %u", lsi, lsi->stride);
 
303
 
 
304
        for (disk = lsi->disks, i = 0; i < LSI_MAX_DISKS; disk++, i++) {
 
305
                P("disks[%u].raid10_stripe: %u", lsi, disk, i,
 
306
                  disk->raid10_stripe);
 
307
                P("disks[%u].raid10_mirror: %u", lsi, disk, i,
 
308
                  disk->raid10_mirror);
 
309
                P("disks[%u].unknown: %u, 0x%x", lsi, disk, i,
 
310
                  disk->unknown, disk->unknown);
 
311
                P("disks[%u].magic_0: 0x%x, %x, %x", lsi,
 
312
                  disk->magic_0, i, disk->magic_0,
 
313
                  (unsigned char) (((char *) &disk->magic_0)[0]),
 
314
                  (unsigned char) (((char *) &disk->magic_0)[1]));
 
315
                P("disks[%u].magic_1: 0x%x, %x, %x", lsi,
 
316
                  disk->magic_1, i, disk->magic_1,
 
317
                  (unsigned char) (((char *) &disk->magic_1)[0]),
 
318
                  (unsigned char) (((char *) &disk->magic_1)[1]));
 
319
                P("disks[%u].disk_number: %u", lsi, disk->disk_number,
 
320
                  i, disk->disk_number);
 
321
                P("disks[%u].set_number: %u", lsi, disk->set_number,
 
322
                  i, disk->set_number);
 
323
                P("disks[%u].unknown1: %lu, 0x%lX", lsi, disk->unknown1,
 
324
                  i, (uint64_t) disk->unknown1, (uint64_t) disk->unknown1);
 
325
        }
 
326
 
 
327
        DP("disk_number: %u", lsi, lsi->disk_number);
 
328
        DP("set_number: %u", lsi, lsi->set_number);
 
329
        DP("set_id: %u", lsi, lsi->set_id);
 
330
}
 
331
#endif
 
332
 
 
333
static struct dmraid_format lsi_format = {
 
334
        .name = HANDLER,
 
335
        .descr = "LSI Logic MegaRAID",
 
336
        .caps = "0,1,10",
 
337
        .format = FMT_RAID,
 
338
        .read = lsi_read,
 
339
        .write = lsi_write,
 
340
        .group = lsi_group,
 
341
        .check = lsi_check,
 
342
        .events = &lsi_event_handlers,
 
343
#ifdef DMRAID_NATIVE_LOG
 
344
        .log = lsi_log,
 
345
#endif
 
346
};
 
347
 
 
348
/* Register this format handler with the format core. */
 
349
int
 
350
register_lsi(struct lib_context *lc)
 
351
{
 
352
        return register_format_handler(lc, &lsi_format);
 
353
}
 
354
 
 
355
/* Set the RAID device contents up derived from the LSI ones */
 
356
static int
 
357
setup_rd(struct lib_context *lc, struct raid_dev *rd,
 
358
         struct dev_info *di, void *meta, union read_info *info)
 
359
{
 
360
        struct lsi *lsi = meta;
 
361
 
 
362
        if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1)))
 
363
                return 0;
 
364
 
 
365
        rd->meta_areas->offset = LSI_CONFIGOFFSET >> 9;
 
366
        rd->meta_areas->size = sizeof(*lsi);
 
367
        rd->meta_areas->area = (void *) lsi;
 
368
 
 
369
        rd->di = di;
 
370
        rd->fmt = &lsi_format;
 
371
 
 
372
        rd->status = status(lsi);
 
373
        rd->type = type(lsi);
 
374
 
 
375
        rd->offset = LSI_DATAOFFSET;
 
376
        /* FIXME: propper size ? */
 
377
        if (!(rd->sectors = rd->meta_areas->offset))
 
378
                return log_zero_sectors(lc, di->path, handler);
 
379
 
 
380
        return (rd->name = name(lc, rd, 1)) ? 1 : 0;
 
381
}