[Dmraid-debian-commits] [SCM] Maintenance of the dmraid package branch, lenny, updated. cd7661ebfd968c212485e05af22308fcf9bfe673
Giuseppe Iuculano
giuseppe at iuculano.it
Fri Jan 23 22:42:59 UTC 2009
The following commit has been merged in the lenny branch:
commit cd7661ebfd968c212485e05af22308fcf9bfe673
Author: Giuseppe Iuculano <giuseppe at iuculano.it>
Date: Fri Jan 23 23:16:11 2009 +0100
Delete 1.0.0.rc14/lib/format/ddf/ddf1.c.orig
diff --git a/1.0.0.rc14/lib/format/ddf/ddf1.c.orig b/1.0.0.rc14/lib/format/ddf/ddf1.c.orig
deleted file mode 100644
index 2cccdfc..0000000
--- a/1.0.0.rc14/lib/format/ddf/ddf1.c.orig
+++ /dev/null
@@ -1,1047 +0,0 @@
-/*
- * SNIA DDF1 v1.0 metadata format handler.
- *
- * Copyright (C) 2005-2006 IBM, All rights reserved.
- * Written by Darrick Wong <djwong at us.ibm.com>
- *
- * Copyright (C) 2006 Heinz Mauelshage, Red Hat GmbH
- * All rights reserved.
- *
- * See file LICENSE at the top of this source tree for license information.
- */
-
-#include <errno.h>
-
-#define HANDLER "ddf1"
-
-#include "internal.h"
-
-#define FORMAT_HANDLER
-#include "ddf1.h"
-
-// #include "ddf1_crc.h"
-#include "ddf1_cvt.h"
-#include "ddf1_dump.h"
-
-static const char *handler = HANDLER;
-
-/* PCI IDs for Adaptec */
-#define PCI_VENDOR_ID_ADAPTEC 0x9004
-#define PCI_VENDOR_ID_ADAPTEC2 0x9005
-
-/* Find the beginning of all DDF metadata */
-static uint64_t find_ddf_beginning(struct ddf1 *ddf1)
-{
- uint64_t start;
- struct ddf1_header *h = &ddf1->anchor;
-
- start = ddf1->anchor_offset;
- if (h->primary_table_lba < start)
- start = h->primary_table_lba;
- if (h->secondary_table_lba < start)
- start = h->secondary_table_lba;
-#ifdef WORKSPACE_IS_PART_OF_DDF
- if (ddf1->primary->workspace_lba < start)
- start = ddf1->primary->workspace_lba;
-#endif
-
- return start;
-}
-
-/* Figure out what endian conversions we need */
-static void find_endian(struct lib_context *lc, struct ddf1 *ddf1)
-{
- uint8_t *ptr = (uint8_t*) &ddf1->anchor.signature;
-
- if (ptr[0] == 0xDE && ptr[1] == 0x11)
- ddf1->disk_format = BIG_ENDIAN;
- else if (ptr[0] == 0x11 && ptr[1] == 0xDE)
- ddf1->disk_format = LITTLE_ENDIAN;
- else {
- log_error(lc, "Can't figure out endianness!");
- ddf1->disk_format = 0;
- }
-}
-
-/* Map DDF1 disk status to dmraid status */
-static enum status disk_status(struct ddf1_phys_drive *disk) {
- struct {
- uint8_t flag;
- enum status status;
- } states[] = {
- { 0x72, s_broken },
- { 0x04, s_nosync },
- { 0x08, s_setup },
- { 0x01, s_ok },
- }, *s = states;
-
- if (disk) {
- do {
- if (disk->state & s->flag)
- return s->status;
- } while ((s++)->status != s_ok);
- }
-
- return s_undef;
-}
-
-/*
- * Compare two GUIDs. For some reason, Adaptec sometimes writes 0xFFFFFFFF
- * as the last four bytes (ala DDF2) and sometimes writes real data.
- * For now we'll compare the first twenty and only the last four if
- * both GUIDs don't have 0xFFFFFFFF in bytes 20-23. Gross.
- */
-static inline uint8_t _and(uint8_t *p)
-{
- return p[20] & p[21] & p[22] & p[23];
-}
-
-static int guidcmp(uint8_t *one, uint8_t *two)
-{
- int x = memcmp(one, two, DDF1_GUID_LENGTH - 4);
-
- if (x)
- return x;
-
- return (_and(one) || _and(two)) ? 0 : memcmp(one + 20, two + 20, 4);
-}
-
-/* Find the physical drive data for a drive */
-static struct ddf1_phys_drive *get_phys_drive(struct ddf1 *ddf1, uint32_t ref)
-{
- unsigned int i = ddf1->pd_header->max_drives;
- struct ddf1_phys_drive *pd;
-
- while (i--) {
- pd = ddf1->pds + i;
- if (pd->reference == ref)
- return pd;
- }
-
- return NULL;
-}
-
-/* Find this drive's physical data */
-static inline struct ddf1_phys_drive *get_this_phys_drive(struct ddf1 *ddf1)
-{
- return get_phys_drive(ddf1, ddf1->disk_data->reference);
-}
-
-/* Find the virtual drive that goes with this config record */
-static struct ddf1_virt_drive *get_virt_drive(struct ddf1 *ddf1,
- struct ddf1_config_record *cr)
-{
- int i = ddf1->vd_header->num_drives;
- struct ddf1_virt_drive *vd;
-
- while (i--) {
- vd = ddf1->vds + i;
- if (!guidcmp(vd->guid, cr->guid))
- return vd;
- }
-
- return NULL;
-}
-
-/*
- * Find the index of the VD config record given a physical drive and offset.
- */
-static int get_config_byoffset(struct ddf1 *ddf1, struct ddf1_phys_drive *pd,
- uint64_t offset)
-{
- int cfgs = NUM_CONFIG_ENTRIES(ddf1), i;
- uint32_t *cfg_drive_ids, j;
- uint64_t *cfg_drive_offsets;
- struct ddf1_config_record *cfg;
-
- for (i = 0; i < cfgs; i++) {
- cfg = CR(ddf1, i);
- if (cfg->signature == DDF1_VD_CONFIG_REC) {
- cfg_drive_ids = CR_IDS(ddf1, cfg);
- cfg_drive_offsets = CR_OFF(ddf1, cfg);
- for (j = 0; j < cfg->primary_element_count; j++) {
- if (cfg_drive_ids[j] == pd->reference &&
- cfg_drive_offsets[j] == offset)
- return i;
- }
- }
- }
-
- return -ENOENT;
-}
-
-/* Find the index of the nth VD config record for this physical drive. */
-static int get_config_index(struct ddf1 *ddf1, struct ddf1_phys_drive *pd,
- unsigned int *n)
-{
- int cfgs = NUM_CONFIG_ENTRIES(ddf1), i, j, nn = *n;
- uint32_t *ids;
- struct ddf1_config_record *cr;
-
- for (i = 0; i < cfgs; i++) {
- cr = CR(ddf1, i);
- if (cr->signature == DDF1_VD_CONFIG_REC) {
- ids = CR_IDS(ddf1, cr);
- for (j = 0; j < cr->primary_element_count; j++) {
- if (ids[j] == pd->reference && !nn--)
- return i;
- }
- }
- }
-
- *n -= nn;
- return nn < 0 ? -ENOENT : 0;
-}
-
-/*
- * Find the nth VD config record for this physical drive.
- */
-static inline struct ddf1_config_record *get_config(struct ddf1 *ddf1,
- struct ddf1_phys_drive *pd,
- unsigned int n)
-{
- int i = get_config_index(ddf1, pd, &n);
-
- return i < 0 ? NULL : CR(ddf1, i);
-}
-
-/* Find a config record for this drive, given the offset of the array. */
-static inline struct ddf1_config_record *get_this_config(struct ddf1 *ddf1,
- uint64_t offset)
-{
- struct ddf1_phys_drive *pd = get_this_phys_drive(ddf1);
- int i = get_config_byoffset(ddf1, pd, offset);
-
- return i < 0 ? NULL : get_config(ddf1, pd, i);
-}
-
-/* Find the config record disk/offset entry for this config/drive. */
-static int get_offset_entry(struct ddf1 *ddf1, struct ddf1_config_record *cr,
- struct ddf1_phys_drive *pd)
-{
- int i;
- uint32_t *ids;
-
- if (cr) {
- ids = CR_IDS(ddf1, cr);
- for (i = 0; i < ddf1->primary->max_phys_drives; i++) {
- if (ids[i] == pd->reference)
- return i;
- }
- }
-
- return -ENOENT;
-}
-
-/* Find the offset for this config/drive. */
-static uint64_t get_offset(struct ddf1 *ddf1, struct ddf1_config_record *cr,
- struct ddf1_phys_drive *pd)
-{
- int i = get_offset_entry(ddf1, cr, pd);
-
- return i < 0 ? pd->size : CR_OFF(ddf1, cr)[i];
-}
-
-/* Calculate the stripe size, in sectors */
-static inline unsigned int stride(struct ddf1_config_record *cr)
-{
- return 1 << cr->stripe_size; // * 512 * 2;
-}
-
-/* Mapping of template types to generic types */
-static struct types types[] = {
- { DDF1_RAID0, t_raid0 },
- { DDF1_RAID1, t_raid1 },
- { DDF1_RAID4, t_raid4 },
- { DDF1_CONCAT, t_linear },
- { DDF1_JBOD, t_linear },
- { 0, t_undef}
-};
-
-/* Seperate array for RAID5 qualifiers */
-static struct types qualifier_types[] = {
- /* FIXME: Is RLQ=0 really right symmetric? */
- { DDF1_RAID5_RS, t_raid5_rs },
- { DDF1_RAID5_LA, t_raid5_la },
- { DDF1_RAID5_LS, t_raid5_ls },
- { 0, t_undef}
-};
-
-/* Map the DDF1 raid type codes into dmraid type codes. */
-static enum type type(struct lib_context *lc, struct ddf1 *ddf1,
- struct ddf1_config_record *cr)
-{
- unsigned int l;
- struct types *t;
-
- if (!cr)
- return t_undef;
-
- l = cr->raid_level;
- if (l == DDF1_RAID5) {
- /*
- * FIXME: Do _all_ Adaptec controllers use left
- * asymmetric parity and write zero to RLQ?
- */
- if (ddf1->adaptec_mode)
- return t_raid5_la;
-
- l = cr->raid_qualifier;
- t = qualifier_types;
- } else
- t = types;
-
- return rd_type(t, l);
-}
-
-/* Read the whole metadata chunk at once */
-static uint8_t *read_metadata_chunk(struct lib_context *lc, struct dev_info *di,
- uint64_t start)
-{
- uint8_t *ret;
- size_t size = (di->sectors - start) * DDF1_BLKSIZE;
-
- if (!(ret = dbg_malloc(size)))
- LOG_ERR(lc, ret, "%s: unable to allocate memory.", di->path);
-
- if (!read_file(lc, handler, di->path, ret, size,
- start * DDF1_BLKSIZE)) {
- dbg_free(ret);
- LOG_ERR(lc, NULL, "%s: unable to read metadata.", di->path);
- }
-
- return ret;
-}
-
-static inline void cond_free(void *p)
-{
- if (p)
- dbg_free(p);
-}
-
-/*
- * Read an DDF1 RAID device. Fields are little endian, so
- * need to convert them if we're on a BE machine (ppc, etc).
- */
-static int read_extended(struct lib_context *lc, struct dev_info *di,
- struct ddf1 *ddf1)
-{
- int i;
- uint64_t where;
- size_t size;
- struct ddf1_header *pri, *sec;
- struct ddf1_adapter *adap;
- struct ddf1_disk_data *ddata;
- struct ddf1_phys_drives *pd;
- struct ddf1_virt_drives *vd;
-
- /* FIXME: We should verify the checksums... */
-
- /* Read the primary DDF header */
- where = ddf1->anchor.primary_table_lba * DDF1_BLKSIZE;
- if (!(pri = ddf1->primary =
- alloc_private_and_read(lc, handler, sizeof(*pri),
- di->path, where)))
- goto bad;
-
- /* Read the secondary header. */
- ddf1_cvt_header(ddf1, pri);
- if (!(sec = ddf1->secondary = alloc_private(lc, handler, sizeof(*sec))))
- goto bad;
-
- where = ddf1->anchor.secondary_table_lba * DDF1_BLKSIZE;
- if (ddf1->anchor.secondary_table_lba != 0xFFFFFFFFFFFFFFFFULL &&
- !read_file(lc, handler, di->path, sec, sizeof(*sec), where))
- goto bad;
-
- ddf1_cvt_header(ddf1, sec);
- if (pri->signature != DDF1_HEADER) {
- log_warn(lc, "%s: incorrect primary header signature %x",
- di->path, pri->signature);
- cond_free(ddf1->primary);
- ddf1->primary = NULL;
- };
-
- if (sec->signature == DDF1_HEADER) {
- /* If we encounter an error, we use the secondary table */
- if (!ddf1->primary) {
- log_warn(lc, "%s: using secondary header", di->path);
- ddf1->primary = ddf1->secondary;
- ddf1->secondary = NULL;
- }
- } else {
- if (sec->signature)
- log_warn(lc, "%s: bad secondary header signature %x",
- di->path, sec->signature);
-
- dbg_free(sec);
- ddf1->secondary = NULL;
- }
-
- if (!ddf1->primary) {
- log_error(lc, "%s: both header signatures bad", di->path);
- goto bad;
- }
-
- /* Read the adapter data */
- if (!(adap = ddf1->adapter = alloc_private(lc, handler, sizeof(*adap))))
- goto bad;
-
- where = (pri->primary_table_lba + pri->adapter_data_offset)
- * DDF1_BLKSIZE;
- if (pri->adapter_data_offset != 0xFFFFFFFF &&
- !read_file(lc, handler, di->path, adap, sizeof(*adap), where))
- goto bad;
-
- ddf1_cvt_adapter(ddf1, ddf1->adapter);
- if (ddf1->adapter->signature != DDF1_ADAPTER_DATA) {
- if (ddf1->adapter->signature)
- log_warn(lc, "%s: incorrect adapter data signature %x",
- di->path, ddf1->adapter->signature);
- free (ddf1->adapter);
- ddf1->adapter = NULL;
- }
-
- if (ddf1->adapter &&
- ddf1->adapter->pci_vendor == PCI_VENDOR_ID_ADAPTEC2)
- ddf1->adaptec_mode = 1;
-
- /* Read physical drive characteristic data */
- where = (pri->primary_table_lba + pri->disk_data_offset) * DDF1_BLKSIZE;
- if (!(ddata = ddf1->disk_data =
- alloc_private_and_read(lc, handler, sizeof(*ddata),
- di->path, where)))
- goto bad;
-
- /*
- * This table isn't technically required, but for now we rely
- * on it to give us a key into the physical drive table.
- */
- ddf1_cvt_disk_data(ddf1, ddata);
- if (ddata->signature != DDF1_FORCED_PD_GUID) {
- log_warn(lc, "%s: incorrect disk data signature %x",
- di->path, ddata->signature);
- goto bad;
- }
-
- /* Read physical drive data header */
- where = (pri->primary_table_lba + pri->phys_drive_offset) *
- DDF1_BLKSIZE;
- size = pri->phys_drive_len * DDF1_BLKSIZE;
- if (!(pd = ddf1->pd_header =
- alloc_private_and_read(lc, handler, size, di->path, where)))
- goto bad;
-
- ddf1_cvt_phys_drive_header(ddf1, pd);
- if (pd->signature != DDF1_PHYS_DRIVE_REC) {
- log_warn(lc, "%s: cannot find physical drive records",
- di->path);
- goto bad;
- }
-
- /* Now read the physical drive data */
- ddf1->pds = (struct ddf1_phys_drive *)(((uint8_t *)ddf1->pd_header) +
- sizeof (*pd));
- for (i = 0; i < pd->num_drives; i++) {
- ddf1_cvt_phys_drive(ddf1, &ddf1->pds[i]);
- /*
- * Adaptec controllers have a weird bug where this field is
- * only four bytes ... and the next four are 0xFF.
- */
- if (ddf1->pds[i].size >> 32 == 0xFFFFFFFF)
- ddf1->pds[i].size &= 0xFFFFFFFF;
- }
-
- /* Read virtual drive data header */
- where = (pri->primary_table_lba + pri->virt_drive_offset) *
- DDF1_BLKSIZE;
- size = pri->phys_drive_len * DDF1_BLKSIZE;
- if (!(vd = ddf1->vd_header =
- alloc_private_and_read(lc, handler, size, di->path, where)))
- goto bad;
-
- ddf1_cvt_virt_drive_header(ddf1, vd);
- if (vd->signature != DDF1_VIRT_DRIVE_REC) {
- log_warn(lc, "%s: cannot find virtual drive records",
- di->path);
- goto bad;
- }
-
- /* Now read the virtual drive data */
- ddf1->vds = (struct ddf1_virt_drive*)(((uint8_t*) vd) + sizeof (*pd));
- for (i = 0; i < vd->num_drives; i++)
- ddf1_cvt_virt_drive(ddf1, &ddf1->vds[i]);
-
- /* Read config data */
- where = (pri->primary_table_lba + pri->config_record_offset) *
- DDF1_BLKSIZE;
- size = pri->config_record_len * DDF1_BLKSIZE;
- if (!(ddf1->cfg = alloc_private_and_read(lc, handler, size,
- di->path, where)))
- goto bad;
-
- /*
- * Ensure each record is: a config table for VDs; a config table for
- * spare disks; or vendor-specifc data of some sort.
- */
- ddf1_cvt_records(lc, di, ddf1, 1);
-
- /*
- * FIXME: We don't pick up diagnostic logs, vendor specific logs,
- * bad block data, etc. That shouldn't cause a problem with reading
- * or writing metadata, but at some point we might want to do something
- * with them.
- */
- ddf1->in_cpu_format = 1;
- return 1;
-
-bad:
- ddf1->vds = NULL;
- ddf1->pds = NULL;
- cond_free(ddf1->cfg);
- cond_free(ddf1->pd_header);
- cond_free(ddf1->disk_data);
- cond_free(ddf1->adapter);
- cond_free(ddf1->secondary);
- cond_free(ddf1->primary);
- return 0;
-}
-
-
-/* Count the number of raid_devs we need to create for this drive */
-static unsigned int num_devs(struct lib_context *lc, void *meta)
-{
- struct ddf1 *ddf1 = meta;
- unsigned int num_drives = ~0;
-
- get_config_index(ddf1, get_this_phys_drive(ddf1), &num_drives);
- return num_drives;
-}
-
-/* Check CRC on a given struct */
-/*
-enum struct_type { ANCHOR, HEADER_PRIM, HEADER_SEC,
- ADAPTER, DISK_DATA, PHYS_DRIVES,
- VIRT_DRIVES, CONFIG_RECORD };
-static uint32_t checksum(struct ddf1 *ddf1, enum struct_type type)
-{
- struct {
- enum struct_type type;
- void *ptr;
- size_t len;
- } types[] = {
- { ANCHOR, &ddf1->anchor, sizeof(ddf1->anchor) },
- { HEADER_PRIM, ddf1->primary, sizeof(*ddf1->primary) },
- { HEADER_SEC, ddf1->secondary, sizeof(*ddf1->secondary) },
- { ADAPTER, ddf1->adapter, sizeof(*ddf1->adapter) },
- { DISK_DATA, ddf1->disk_data, sizeof(*ddf1->disk_data) },
- { PHYS_DRIVES, ddf1->pd_header, sizeof(*ddf1->pd_header) },
- { VIRT_DRIVES, ddf1->vd_header, sizeof(*ddf1->vd_header) },
- { CONFIG_RECORD, ddf1->cfg, sizeof(*ddf1->cfg) },
- }, *t = ARRAY_END(types);
-
- while (t-- > types) {
- if (type == t->type)
- return crc(t->ptr, t->len);
- }
-
- return 0;
-}
-*/
-
-/* Is this DDF1 metadata? */
-static inline int is_ddf1(struct lib_context *lc, struct dev_info *di,
- struct ddf1 *ddf1)
-{
- /*
- * Check our magic numbers and that the version == v2.
- * We don't support anything other than that right now.
- */
-
- /* FIXME: We should examine the version headers... */
- return ddf1->anchor.signature == DDF1_HEADER ||
- ddf1->anchor.signature == DDF1_HEADER_BACKWARDS;
-}
-
-/* Try to find DDF1 metadata at a given offset (ddf1_sboffset) */
-static struct ddf1 *try_to_find_ddf1(struct lib_context *lc,
- struct dev_info *di,
- size_t *sz, uint64_t *offset,
- union read_info *info,
- uint64_t ddf1_sboffset)
-{
- struct ddf1 *ddf1;
- // uint32_t crc;
-
- /*
- * Try to find a DDF1 anchor block at ddf1_sboffset. In theory this
- * should be the very last block, but some Adaptec controllers have
- * issues with standards compliance. So we have to try with various
- * offsets.
- */
- if (!(ddf1 = alloc_private(lc, handler, sizeof(*ddf1))))
- goto err;
-
- if (!read_file(lc, handler, di->path, &ddf1->anchor, DDF1_BLKSIZE,
- ddf1_sboffset) ||
- !is_ddf1(lc, di, ddf1))
- goto bad;
-
- ddf1->anchor_offset = ddf1_sboffset;
-
- /* Convert endianness */
- ddf1->in_cpu_format = 0;
- find_endian(lc, ddf1);
- ddf1_cvt_header(ddf1, &ddf1->anchor);
-
- /* FIXME: crc */
-/*
- crc = checksum(ddf1, ANCHOR);
- printf("crc=%08x ", crc);
- printf("ddf1=%08x\n", ddf1->anchor.crc);
-*/
-
- /* Read extended metadata. */
- if (read_extended(lc, di, ddf1))
- return ddf1;
-
- bad:
- dbg_free(ddf1);
- err:
- return NULL;
-}
-
-/*
- * Attempt to interpret DDF1 metadata from a block device. This function
- * returns either NULL or a pointer to a descriptor struct.
- * Note that the struct should be fully converted to the correct endianness
- * by the time this function returns.
- */
-static void *read_metadata_areas(struct lib_context *lc, struct dev_info *di,
- size_t *sz, uint64_t *offset,
- union read_info *info)
-{
- struct ddf1 *ddf1;
-
- if ((ddf1 = try_to_find_ddf1(lc, di, sz, offset,
- info, DDF1_CONFIGOFFSET)))
- goto out;
-
- if ((ddf1 = try_to_find_ddf1(lc, di, sz, offset,
- info, DDF1_CONFIGOFFSET_ADAPTEC)))
- ddf1->adaptec_mode = 1;
-
- out:
- return ddf1;
-}
-
-/* This is all hogwash since file_metadata can only be called once... */
-static void file_metadata_areas(struct lib_context *lc, struct dev_info *di,
- void *meta)
-{
- uint8_t *buf;
- uint64_t start = find_ddf_beginning(meta);
-
- if (!(buf = read_metadata_chunk(lc, di, start)))
- return;
-
- /* Record metadata. */
- file_metadata(lc, handler, di->path, buf,
- (di->sectors - start) * DDF1_BLKSIZE,
- start * DDF1_BLKSIZE);
-
- dbg_free(buf);
-
- /* Record the device size. */
- file_dev_size(lc, handler, di);
-}
-
-static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
- struct dev_info *di, void *meta, union read_info *info);
-static struct raid_dev *ddf1_read(struct lib_context *lc,
- struct dev_info *di)
-{
- /*
- * NOTE: Everything called after read_metadata_areas assumes that
- * the reserved block, raid table and config table have been
- * converted to the appropriate endianness.
- */
- return read_raid_dev(lc, di, read_metadata_areas, 0, 0, NULL, NULL,
- file_metadata_areas, setup_rd, handler);
-}
-
-/* Compose an "identifier" for use as a sort key for raid sets. */
-static inline int compose_id(struct ddf1 *ddf1, struct raid_dev *rd)
-{
- struct ddf1_phys_drive *pd = get_this_phys_drive(ddf1);
- int i = get_config_byoffset(ddf1, pd, rd->offset);
-
- return i < 0 ? -1 : get_offset_entry(ddf1, get_config(ddf1, pd, i), pd);
-}
-
-/* No sort. */
-static int no_sort(struct list_head *pos, struct list_head *new)
-{
- return 0;
-}
-
-/* Sort DDF1 devices by for a RAID set. */
-static int dev_sort(struct list_head *pos, struct list_head *new)
-{
- return compose_id(META(RD(new)->private.ptr, ddf1), RD(new)) <
- compose_id(META(RD(pos)->private.ptr, ddf1), RD(pos));
-}
-
-/*
- * IO error event handler.
- */
-static int event_io(struct lib_context *lc, struct event_io *e_io)
-{
- log_err(lc, "I/O error on device %s at sector %lu.\n",
- e_io->rd->di->path, e_io->sector);
-
- LOG_ERR(lc, 0, "PANIC: ddf1 doesn't know about event_io!\n");
-}
-
-#if 0
- /* FIXME: This should not use META() directly? */
- struct raid_dev *rd = e_io->rd;
- struct ddf1 *ddf1 = META(rd, ddf1);
- struct ddf1_raid_configline *cl = this_disk(ddf1);
- struct ddf1_raid_configline *fwl = find_logical(ddf1);
-
- /* Ignore if we've already marked this disk broken(?) */
- if (rd->status & s_broken)
- return 0;
-
- /* Mark the array as degraded and the disk as failed. */
- rd->status = s_broken;
- cl->raidstate = LSU_COMPONENT_STATE_FAILED;
- fwl->raidstate = LSU_COMPONENT_STATE_DEGRADED;
- /* FIXME: Do we have to mark a parent too? */
-
- /* Indicate that this is indeed a failure. */
- return 1;
-}
-#endif
-
-#define NAME_SIZE 64
-/* Formulate a RAID set name for this disk. */
-static char *name(struct lib_context *lc, struct ddf1 *ddf1,
- struct raid_dev *rd)
-{
- int i, prefix;
- char *buf, *r;
- struct ddf1_phys_drive *pd;
- struct ddf1_virt_drive *vd;
- struct ddf1_config_record *cr;
-
- if (!(pd = get_this_phys_drive(ddf1)))
- LOG_ERR(lc, NULL, "Cannot find physical drive description!");
-
- if (!(buf = dbg_malloc(NAME_SIZE)))
- LOG_ERR(lc, NULL, "Cannot allocate memory for name.");
-
- i = get_config_byoffset(ddf1, pd, rd->offset);
- cr = get_config(ddf1, pd, i);
- if (i < 0 || !cr) {
- sprintf(buf, ".ddf1_spares");
- goto out;
- }
-
- if (!(vd = get_virt_drive(ddf1, cr))) {
- dbg_free(buf);
- LOG_ERR(lc, NULL, "Cannot find virtual drive description!");
- }
-
- sprintf(buf, "%s_", handler);
- prefix = strlen(buf);
-
- if (vd->name[0]) {
- memcpy(buf + prefix, vd->name, 16);
- i = prefix + 16;
- while (!isgraph(buf[--i]));
- buf[i+1] = 0;
- } else {
- char *b;
-
- for (b = buf + prefix, i = 0; i < 24; b += 8, i += 4)
- sprintf(b, "%02x%02x%02x%02x",
- vd->guid[i], vd->guid[i+1],
- vd->guid[i+2], vd->guid[i+3]);
- }
-
- out:
- /* Just return the needed allocation */
- r = dbg_strdup(buf);
- dbg_free(buf);
-
- return r;
-}
-
-/* Figure out the real size of a disk... */
-static uint64_t get_size(struct lib_context *lc, struct ddf1 *ddf1,
- struct ddf1_config_record *cr,
- struct ddf1_phys_drive *pd)
-{
- if (cr)
- /* Some Adaptec controllers need this clamping. */
- return type(lc, ddf1, cr) == t_raid0 ?
- cr->sectors - cr->sectors % stride(cr) : cr->sectors;
-
- return pd->size;
-}
-
-/*
- * Create all the volumes of a DDF disk as subsets of the top level DDF
- * disk group. rs_group points to that raid set and is returned if the
- * function is successful, NULL if not. rd_group is the raid_dev that
- * represents the entire disk drive.
- */
-static struct raid_set *group_rd(struct lib_context *lc,
- struct raid_set *rs_group,
- struct raid_dev *rd_group)
-{
- struct ddf1 *ddf1 = META(rd_group, ddf1);
- struct raid_set *rs = NULL;
- struct raid_dev *rd;
- struct ddf1_config_record *cr;
- struct ddf1_phys_drive *pd;
- unsigned int devs, i;
-
- if (!(pd = get_this_phys_drive(ddf1)))
- return NULL;
-
- devs = num_devs(lc, ddf1);
- for (i = 0; i < devs; i++) {
- /* Allocate a raid_dev for this volume */
- if (!(rd = alloc_raid_dev(lc, handler)))
- return NULL;
-
- cr = get_config(ddf1, pd, i);
- rd->di = rd_group->di;
- rd->fmt = rd_group->fmt;
- rd->type = type(lc, ddf1, cr);
- rd->offset = get_offset(ddf1, cr, pd);
- rd->sectors = get_size(lc, ddf1, cr, pd);
- rd->name = name(lc, ddf1, rd);
-
- /* Stuff it into the appropriate raid set. */
- if (!(rs = find_or_alloc_raid_set(lc, rd->name, FIND_ALL,
- rd, &rs_group->sets,
- NO_CREATE, NO_CREATE_ARG))) {
- free_raid_dev(lc, &rd);
- return NULL;
- }
-
- rs->stride = stride(cr);
- rs->type = type(lc, ddf1, cr);
- rs->status = s_ok;
-
- if (!(rd->private.ptr = alloc_private(lc, handler,
- sizeof(*rd_group))))
- return NULL;
-
- memcpy(rd->private.ptr, rd_group, sizeof (*rd_group));
- list_add_sorted(lc, &rs->devs, &rd->devs, dev_sort);
- }
-
- return rs_group;
-}
-
-/*
- * Add an DDF1 device to a RAID set. This involves finding the raid set to
- * which this disk belongs, and then attaching it. Note that there are other
- * complications, such as two-layer arrays (RAID10).
- *
- * FIXME: We haven't been able to set up a RAID10 for testing...
- */
-static struct raid_set *ddf1_group(struct lib_context *lc, struct raid_dev *rd)
-{
- struct ddf1 *ddf1 = META(rd, ddf1);
- struct ddf1_phys_drive *pd;
- struct raid_set *rs;
- char *set_name;
-
- if (!(pd = get_this_phys_drive(ddf1)))
- LOG_ERR(lc, NULL, "Cannot find physical drive description!\n");
-
- if (!(set_name = rd->name))
- LOG_ERR(lc, NULL, "%s: Could not find RAID array name.\n",
- rd->di->path);
-
- /*
- * Find/create a raid set for all DDF drives and put this disk
- * into that set. The raid_sets for the real arrays will be created
- * as children of the disk's raid_set.
- *
- * (Is this really necessary?)
- */
- if (!(rs = find_or_alloc_raid_set(lc, set_name, FIND_TOP, rd,
- LC_RS(lc), NO_CREATE,
- NO_CREATE_ARG)))
- return NULL;
-
- rs->type = t_group;
- list_add_sorted(lc, &rs->devs, &rd->devs, no_sort);
-
- /* Go deal with the real arrays. */
- return group_rd(lc, rs, rd);
-}
-
-/* Write metadata. */
-static int ddf1_write(struct lib_context *lc, struct raid_dev *rd, int erase)
-{
- int ret;
- struct ddf1 *ddf1 = META(rd, ddf1);
-
- ddf1_cvt_all(lc, ddf1, rd->di);
- ret = write_metadata(lc, handler, rd, -1, erase);
- ddf1_cvt_all(lc, ddf1, rd->di);
-
- return ret;
-}
-
-/*
- * Check integrity of a RAID set.
- */
-
-/* Retrieve the number of devices that should be in this set. */
-static unsigned int device_count(struct raid_dev *rd, void *context)
-{
- /* Get the logical drive */
- struct ddf1_config_record *cr =
- get_this_config(META(rd->private.ptr, ddf1), rd->offset);
-
- return cr ? cr->primary_element_count : 0;
-}
-
-/* Check a RAID device */
-static int check_rd(struct lib_context *lc, struct raid_set *rs,
- struct raid_dev *rd, void *context)
-{
- /*
- * FIXME: Should we do more checking for brokenness here?
- * We could check SMART data, verify that nobody else is
- * putting non-ddf disks in our raid set, etc.
- */
- return rd->type != s_broken;
-}
-
-/* Start the recursive RAID set check. */
-static int ddf1_check(struct lib_context *lc, struct raid_set *rs)
-{
- return check_raid_set(lc, rs, device_count, NULL, check_rd,
- NULL, handler);
-}
-
-static struct event_handlers ddf1_event_handlers = {
- .io = event_io,
- .rd = NULL, /* FIXME: no device add/remove event handler yet. */
-};
-
-#ifdef DMRAID_NATIVE_LOG
-/*
- * Log native information about the RAID device.
- */
-static void ddf1_log(struct lib_context *lc, struct raid_dev *rd)
-{
- ddf1_dump_all(lc, handler, META(rd, ddf1), rd->di);
-}
-#endif /* #ifdef DMRAID_NATIVE_LOG */
-
-static struct dmraid_format ddf1_format = {
- .name = HANDLER,
- .descr = "SNIA DDF1",
- .caps = "0,1,4,5,linear",
- .format = FMT_RAID,
- .read = ddf1_read,
- .write = ddf1_write,
- .group = ddf1_group,
- .check = ddf1_check,
- .events = &ddf1_event_handlers,
-#ifdef DMRAID_NATIVE_LOG
- .log = ddf1_log,
-#endif
-};
-
-/* Register this format handler with the format core */
-int register_ddf1(struct lib_context *lc)
-{
- return register_format_handler(lc, &ddf1_format);
-}
-
-/*
- * Set up a RAID device from what we've assembled out of the metadata.
- */
-static int setup_rd(struct lib_context *lc, struct raid_dev *rd,
- struct dev_info *di, void *meta, union read_info *info)
-{
- unsigned int i, ma_count = 5;
- struct ddf1 *ddf1 = meta;
- struct meta_areas *ma;
- struct ddf1_phys_drive *pd;
-
- if (!(pd = get_this_phys_drive(ddf1)))
- LOG_ERR(lc, 0, "Cannot find physical drive description!\n");
-
- /* We need multiple metadata areas */
- ma_count += ddf1->adapter ? 1 : 0;
- ma_count += ddf1->secondary ? 1 : 0;
- ma_count += ddf1->disk_data ? 1 : 0;
- /* FIXME: metadata area for workspace_lba */
-
- if (!(ma = rd->meta_areas = alloc_meta_areas(lc, rd, handler,
- ma_count)))
- return 0;
-
- /* Preset metadata area offset and size and adjust below */
- for (i = 0; i < ma_count; i++) {
- ma[i].offset = ddf1->primary->primary_table_lba;
- ma[i].size = DDF1_BLKSIZE;
- }
-
- ma->offset = ddf1->anchor_offset;
- (ma++)->area = &ddf1->anchor;
-
- (ma++)->area = ddf1->primary;
-
- if (ddf1->secondary)
- (ma++)->offset = ddf1->primary->secondary_table_lba;
-
- if (ddf1->adapter) {
- ma->offset += ddf1->primary->adapter_data_offset;
- ma->size *= ddf1->primary->adapter_data_len;
- (ma++)->area = ddf1->adapter;
- }
-
- /* FIXME: set up workspace_lba */
-
- if (ddf1->disk_data) {
- ma->offset += ddf1->primary->disk_data_offset;
- ma->size *= ddf1->primary->disk_data_len;
- (ma++)->area = ddf1->disk_data;
- }
-
- ma->offset += ddf1->primary->phys_drive_offset;
- ma->size *= ddf1->primary->phys_drive_len;
- (ma++)->area = ddf1->pd_header;
-
- ma->offset += ddf1->primary->virt_drive_offset;
- ma->size *= ddf1->primary->virt_drive_len;
- (ma++)->area = ddf1->vd_header;
-
- ma->offset += ddf1->primary->config_record_offset;
- ma->size *= ddf1->primary->config_record_len;
- ma->area = ddf1->cfg;
-
- /* Now set up the rest of the metadata info */
- rd->di = di;
- rd->fmt = &ddf1_format;
- rd->status = disk_status(pd);
- rd->type = t_group;
- rd->offset = 0;
- rd->sectors = get_size(lc, ddf1, NULL, pd);
- rd->name = dbg_strdup((char*) ".ddf_disks"); /* FIXME: better name */
- return rd->name ? 1 : 0;
-}
--
Maintenance of the dmraid package
More information about the Dmraid-debian-commits
mailing list