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

« back to all changes in this revision

Viewing changes to 1.0.0.rc14/lib/format/ataraid/hpt45x.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
 
 * Highpoint 45X ATARAID series metadata format handler.
3
 
 *
4
 
 * Copyright (C) 2004,2005  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
 
 * hpt45x_read(), hpt45x_group() and group_rd() profited from
12
 
 * Carl-Daniel Hailfinger's raiddetect code.
13
 
 */
14
 
#define HANDLER "hpt45x"
15
 
 
16
 
#include "internal.h"
17
 
#define FORMAT_HANDLER
18
 
#include "hpt45x.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 set name from magic_0 number */
28
 
/* FIXME: better name ? */
29
 
static size_t _name(struct hpt45x *hpt, char *str, size_t len,
30
 
                    unsigned int subset)
31
 
{
32
 
        const char *fmt;
33
 
 
34
 
        if (hpt->magic_0)
35
 
                fmt = subset ? "hpt45x_%u-%u" : "hpt45x_%u";
36
 
        else
37
 
                fmt = "hpt45x_SPARE";
38
 
 
39
 
        return snprintf(str, len, fmt, hpt->magic_0, hpt->raid1_disk_number);
40
 
}
41
 
 
42
 
static char *name(struct lib_context *lc, struct raid_dev *rd,
43
 
                  unsigned int subset)
44
 
{
45
 
        size_t len;
46
 
        char *ret;
47
 
        struct hpt45x *hpt = META(rd, hpt45x);
48
 
 
49
 
        if ((ret = dbg_malloc((len = _name(hpt, NULL, 0, subset) + 1)))) {
50
 
                _name(hpt, ret, len, subset);
51
 
                mk_alpha(lc, ret + HANDLER_LEN, len - HANDLER_LEN -
52
 
                         (strrchr(ret, '-') ? 3 : 1));
53
 
        } else
54
 
                log_alloc_err(lc, handler);
55
 
 
56
 
        return ret;
57
 
}
58
 
 
59
 
/*
60
 
 * Retrieve status of device.
61
 
 * FIXME: is this sufficient to cover all state ?
62
 
 */
63
 
static enum status status(struct hpt45x *hpt)
64
 
{
65
 
        return hpt->magic == HPT45X_MAGIC_BAD ? s_broken : s_ok;
66
 
}
67
 
 
68
 
/* Neutralize disk type */
69
 
static enum type type(struct hpt45x *hpt)
70
 
{
71
 
        /* Mapping of HPT 45X types to generic types */
72
 
        static struct types types[] = {
73
 
                { HPT45X_T_SPAN, t_linear},
74
 
                { HPT45X_T_RAID0, t_raid0},
75
 
                { HPT45X_T_RAID1, t_raid1},
76
 
                /* FIXME: handle RAID 4+5 */
77
 
                { 0, t_undef},
78
 
        };
79
 
 
80
 
        return hpt->magic_0 ? rd_type(types, (unsigned int) hpt->type) :
81
 
               t_spare;
82
 
}
83
 
 
84
 
/* Decide about ordering sequence of RAID device. */
85
 
static int dev_sort(struct list_head *pos, struct list_head *new)
86
 
{
87
 
        return (META(RD(new), hpt45x))->disk_number <
88
 
               (META(RD(pos), hpt45x))->disk_number;
89
 
}
90
 
 
91
 
/* Decide about ordering sequence of RAID subset. */
92
 
static int set_sort(struct list_head *pos, struct list_head *new)
93
 
{
94
 
        return (META(RD_RS(RS(new)), hpt45x))->raid1_disk_number <
95
 
               (META(RD_RS(RS(pos)), hpt45x))->raid1_disk_number;
96
 
}
97
 
 
98
 
/*
99
 
 * Group the RAID disk into a HPT45X set.
100
 
 *
101
 
 * Check device hierarchy and create super set appropriately.
102
 
 */
103
 
static unsigned int stride(unsigned int shift)
104
 
{
105
 
        return shift ? 1 << shift : 0;
106
 
}
107
 
 
108
 
static void super_created(struct raid_set *super, void *private)
109
 
{
110
 
        super->type   = t_raid1;
111
 
        super->stride = stride(META((private), hpt45x)->raid1_shift);
112
 
}
113
 
 
114
 
static int group_rd(struct lib_context *lc, struct raid_set *rs,
115
 
                    struct raid_set **ss, struct raid_dev *rd)
116
 
{
117
 
        struct hpt45x *hpt = META(rd, hpt45x);
118
 
 
119
 
        if (!init_raid_set(lc, rs, rd, stride(hpt->raid0_shift),
120
 
                           hpt->type, handler))
121
 
                return 0;
122
 
 
123
 
        list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort);
124
 
 
125
 
        switch (hpt->type) {
126
 
        case HPT45X_T_SPAN:
127
 
        case HPT45X_T_RAID1:
128
 
  no_raid10:
129
 
                if (!find_set(lc, NULL, rs->name, FIND_TOP))
130
 
                        list_add_tail(&rs->list, LC_RS(lc));
131
 
 
132
 
                break;
133
 
 
134
 
        case HPT45X_T_RAID0:
135
 
                if (hpt->raid1_type != HPT45X_T_RAID1)
136
 
                        goto no_raid10;
137
 
                /*
138
 
                 * RAID10:
139
 
                 *
140
 
                 * We've got a striped raid set with a mirror on top
141
 
                 * when we get here.
142
 
                 * Let's find and optionally allocate the mirror set on top.
143
 
                 */
144
 
                if (!(*ss = join_superset(lc, name, super_created,
145
 
                                          set_sort, rs, rd)))
146
 
                        return 0;
147
 
        }
148
 
 
149
 
        return 1;
150
 
}
151
 
 
152
 
/*
153
 
 * Add a Highpoint RAID device to a set.
154
 
 */
155
 
static struct raid_set *hpt45x_group(struct lib_context *lc,
156
 
                                       struct raid_dev *rd)
157
 
{
158
 
        struct raid_set *rs, *ss = NULL;
159
 
 
160
 
        if (T_SPARE(rd))
161
 
                return NULL;
162
 
 
163
 
        if ((rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL, rd,
164
 
                                         NO_LIST, NO_CREATE, NO_CREATE_ARG)))
165
 
                return group_rd(lc, rs, &ss, rd) ? (ss ? ss : rs) : NULL;
166
 
 
167
 
        return NULL;
168
 
}
169
 
 
170
 
/*
171
 
 * Read a Highpoint 45X RAID device.
172
 
 */
173
 
/* Endianess conversion. */
174
 
#if     BYTE_ORDER == LITTLE_ENDIAN
175
 
#  define       to_cpu  NULL
176
 
#else
177
 
static void to_cpu(void *meta)
178
 
{
179
 
        struct hpt45x *hpt = meta;
180
 
 
181
 
        CVT32(hpt->magic);
182
 
        CVT32(hpt->magic_0);
183
 
        CVT32(hpt->magic_1);
184
 
        CVT32(hpt->total_secs);
185
 
}
186
 
#endif
187
 
 
188
 
/* Magic check. */
189
 
static int is_hpt45x(struct lib_context *lc, struct dev_info *di, void *meta)
190
 
{
191
 
        struct hpt45x *hpt = meta;
192
 
 
193
 
        return (hpt->magic == HPT45X_MAGIC_OK ||
194
 
                hpt->magic == HPT45X_MAGIC_BAD) &&
195
 
                hpt->disk_number < 8;
196
 
}
197
 
 
198
 
static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
199
 
                    struct dev_info *di, void *meta, union read_info *info);
200
 
static struct raid_dev *hpt45x_read(struct lib_context *lc,
201
 
                                      struct dev_info *di)
202
 
{
203
 
        return read_raid_dev(lc, di, NULL,
204
 
                             sizeof(struct hpt45x), HPT45X_CONFIGOFFSET,
205
 
                             to_cpu, is_hpt45x, NULL, setup_rd, handler);
206
 
}
207
 
 
208
 
/*
209
 
 * Write a Highpoint 45X RAID device.
210
 
 */
211
 
static int hpt45x_write(struct lib_context *lc,
212
 
                        struct raid_dev *rd, int erase)
213
 
{
214
 
        int ret;
215
 
#if     BYTE_ORDER != LITTLE_ENDIAN
216
 
        struct hpt45x *hpt = META(rd, hpt45x);
217
 
 
218
 
        to_disk(hpt);
219
 
#endif
220
 
        ret = write_metadata(lc, handler, rd, -1, erase);
221
 
#if     BYTE_ORDER != LITTLE_ENDIAN
222
 
        to_cpu(hpt);
223
 
#endif
224
 
        return ret;
225
 
}
226
 
 
227
 
/*
228
 
 * Check a Highpoint 45X RAID set.
229
 
 *
230
 
 * FIXME: more sanity checks.
231
 
 */
232
 
static unsigned int devices(struct raid_dev *rd, void *context)
233
 
{
234
 
        return (META(rd, hpt45x))->raid_disks;
235
 
}
236
 
 
237
 
static int hpt45x_check(struct lib_context *lc, struct raid_set *rs)
238
 
{
239
 
        return check_raid_set(lc, rs, devices, NULL,
240
 
                              NO_CHECK_RD, NULL, handler);
241
 
}
242
 
 
243
 
/*
244
 
 * IO error event handler.
245
 
 */
246
 
static int event_io(struct lib_context *lc, struct event_io *e_io)
247
 
{
248
 
        struct raid_dev *rd = e_io->rd;
249
 
        struct hpt45x *hpt = META(rd, hpt45x);
250
 
 
251
 
        /* Avoid write trashing. */
252
 
        if (S_BROKEN(status(hpt)))
253
 
                return 0;
254
 
 
255
 
        hpt->magic = HPT45X_MAGIC_BAD;
256
 
 
257
 
        return 1;
258
 
}
259
 
 
260
 
static struct event_handlers hpt45x_event_handlers = {
261
 
        .io = event_io,
262
 
        .rd = NULL,     /* FIXME: no device add/remove event handler yet. */
263
 
};
264
 
 
265
 
#ifdef DMRAID_NATIVE_LOG
266
 
/*
267
 
 * Log native information about an HPT45X RAID device.
268
 
 */
269
 
static void hpt45x_log(struct lib_context *lc, struct raid_dev *rd)
270
 
{
271
 
        unsigned int i;
272
 
        struct hpt45x *hpt = META(rd, hpt45x);
273
 
 
274
 
        log_print(lc, "%s (%s):", rd->di->path, handler);
275
 
        DP("magic: 0x%x", hpt, hpt->magic);
276
 
        DP("magic_0: 0x%x", hpt, hpt->magic_0);
277
 
        DP("magic_1: 0x%x", hpt, hpt->magic_1);
278
 
        DP("total_secs: %u", hpt, hpt->total_secs);
279
 
        DP("type: %u", hpt, hpt->type);
280
 
        DP("raid_disks: %u", hpt, hpt->raid_disks);
281
 
        DP("disk_number: %u", hpt, hpt->disk_number);
282
 
        DP("raid0_shift: %u", hpt, hpt->raid0_shift);
283
 
        for (i = 0; i < 3; i++)
284
 
                P2("dummy[%u]: 0x%x", hpt, i, hpt->dummy[i]);
285
 
        DP("raid1_type: %u", hpt, hpt->raid1_type);
286
 
        DP("raid1_raid_disks: %u", hpt, hpt->raid1_raid_disks);
287
 
        DP("raid1_disk_number: %u", hpt, hpt->raid1_disk_number);
288
 
        DP("raid1_shift: %u", hpt, hpt->raid1_shift);
289
 
 
290
 
        for (i = 0; i < 3; i++)
291
 
                P2("dummy1[%u]: 0x%x", hpt, i, hpt->dummy1[i]);
292
 
}
293
 
#endif
294
 
 
295
 
static struct dmraid_format hpt45x_format = {
296
 
        .name   = HANDLER,
297
 
        .descr  = "Highpoint HPT45X",
298
 
        .caps   = "S,0,1,10",
299
 
        .format = FMT_RAID,
300
 
        .read   = hpt45x_read,
301
 
        .write  = hpt45x_write,
302
 
        .group  = hpt45x_group,
303
 
        .check  = hpt45x_check,
304
 
        .events = &hpt45x_event_handlers,
305
 
#ifdef DMRAID_NATIVE_LOG
306
 
        .log    = hpt45x_log,
307
 
#endif
308
 
};
309
 
 
310
 
/* Register this format handler with the format core. */
311
 
int register_hpt45x(struct lib_context *lc)
312
 
{
313
 
        return register_format_handler(lc, &hpt45x_format);
314
 
}
315
 
 
316
 
/* Calculate RAID device size in sectors depending on RAID type. */
317
 
static uint64_t sectors(struct raid_dev *rd, void *meta)
318
 
{
319
 
        struct hpt45x *hpt = meta;
320
 
 
321
 
        switch (rd->type) {
322
 
        case t_raid0:
323
 
                return hpt->total_secs /
324
 
                       (hpt->raid_disks ? hpt->raid_disks : 1);
325
 
 
326
 
        case t_raid1:
327
 
                return hpt->total_secs;
328
 
 
329
 
        default:
330
 
                return rd->meta_areas->offset;
331
 
        }
332
 
}
333
 
 
334
 
/* Set the RAID device contents up derived from the Highpoint ones */
335
 
static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
336
 
                    struct dev_info *di, void *meta, union read_info *info)
337
 
{
338
 
        struct hpt45x *hpt = meta;
339
 
 
340
 
        if (!(rd->meta_areas = alloc_meta_areas(lc, rd, handler, 1)))
341
 
                return 0;
342
 
 
343
 
        rd->meta_areas->offset = HPT45X_CONFIGOFFSET >> 9;
344
 
        rd->meta_areas->size = sizeof(*hpt);
345
 
        rd->meta_areas->area = (void*) hpt;
346
 
 
347
 
        rd->di = di;
348
 
        rd->fmt = &hpt45x_format;
349
 
 
350
 
        rd->status = status(hpt);
351
 
        rd->type   = type(hpt);
352
 
 
353
 
        rd->offset = HPT45X_DATAOFFSET;
354
 
        if (!(rd->sectors = sectors(rd, hpt)))
355
 
                return log_zero_sectors(lc, di->path, handler);
356
 
 
357
 
        return (rd->name = name(lc, rd, hpt->raid1_type == HPT45X_T_RAID1)) ?
358
 
               1 : 0;
359
 
}