return NULL;
st = malloc(sizeof(*st));
+ if (!st)
+ return NULL;
memset(st, 0, sizeof(*st));
st->ss = &super_imsm;
st->max_devs = IMSM_MAX_DEVICES;
return rv;
}
-#ifndef MDASSEMBLE
static int is_spare(struct imsm_disk *disk)
{
return (disk->status & SPARE_DISK) == SPARE_DISK;
return (disk->status & FAILED_DISK) == FAILED_DISK;
}
+#ifndef MDASSEMBLE
static void print_imsm_dev(struct imsm_dev *dev, char *uuid, int disk_idx)
{
__u64 sz;
char str[MAX_RAID_SERIAL_LEN + 1];
__u64 sz;
- if (index < 0)
+ if (index < 0 || !disk)
return;
printf("\n");
/* chop device path to 'host%d' and calculate the port number */
c = strchr(&path[hba_len], '/');
+ if (!c) {
+ if (verbose)
+ fprintf(stderr, Name ": %s - invalid path name\n", path + hba_len);
+ err = 2;
+ break;
+ }
*c = '\0';
if (sscanf(&path[hba_len], "host%d", &port) == 1)
port -= host_base;
struct imsm_dev *dev = get_imsm_dev(super, super->current_vol);
struct imsm_map *map = get_imsm_map(dev, 0);
struct dl *dl;
+ char *devname;
for (dl = super->disks; dl; dl = dl->next)
if (dl->raiddisk == info->disk.raid_disk)
info->array.major_version = -1;
info->array.minor_version = -2;
- sprintf(info->text_version, "/%s/%d",
- devnum2devname(st->container_dev),
- info->container_member);
+ devname = devnum2devname(st->container_dev);
+ *info->text_version = '\0';
+ if (devname)
+ sprintf(info->text_version, "/%s/%d", devname, info->container_member);
+ free(devname);
info->safe_mode_delay = 4000; /* 4 secs like the Matrix driver */
uuid_from_super_imsm(st, info->uuid);
}
char *update, char *devname, int verbose,
int uuid_set, char *homehost)
{
- /* FIXME */
-
/* For 'assemble' and 'force' we need to return non-zero if any
* change was made. For others, the return value is ignored.
* Update options are:
* linear only
* resync: mark as dirty so a resync will happen.
* name: update the name - preserving the homehost
+ * uuid: Change the uuid of the array to match watch is given
*
* Following are not relevant for this imsm:
* sparc2.2 : update from old dodgey metadata
* super-minor: change the preferred_minor number
* summaries: update redundant counters.
- * uuid: Change the uuid of the array to match watch is given
* homehost: update the recorded homehost
* _reshape_progress: record new reshape_progress position.
*/
- int rv = 0;
- //struct intel_super *super = st->sb;
- //struct imsm_super *mpb = super->mpb;
+ int rv = 1;
+ struct intel_super *super = st->sb;
+ struct imsm_super *mpb;
- if (strcmp(update, "grow") == 0) {
- }
- if (strcmp(update, "resync") == 0) {
- /* dev->vol.dirty = 1; */
- }
+ /* we can only update container info */
+ if (!super || super->current_vol >= 0 || !super->anchor)
+ return 1;
+
+ mpb = super->anchor;
+
+ if (strcmp(update, "uuid") == 0 && uuid_set && !info->update_private)
+ fprintf(stderr,
+ Name ": '--uuid' not supported for imsm metadata\n");
+ else if (strcmp(update, "uuid") == 0 && uuid_set && info->update_private) {
+ mpb->orig_family_num = *((__u32 *) info->update_private);
+ rv = 0;
+ } else if (strcmp(update, "uuid") == 0) {
+ __u32 *new_family = malloc(sizeof(*new_family));
+
+ /* update orig_family_number with the incoming random
+ * data, report the new effective uuid, and store the
+ * new orig_family_num for future updates.
+ */
+ if (new_family) {
+ memcpy(&mpb->orig_family_num, info->uuid, sizeof(__u32));
+ uuid_from_super_imsm(st, info->uuid);
+ *new_family = mpb->orig_family_num;
+ info->update_private = new_family;
+ rv = 0;
+ }
+ } else if (strcmp(update, "assemble") == 0)
+ rv = 0;
+ else
+ fprintf(stderr,
+ Name ": '--update=%s' not supported for imsm metadata\n",
+ update);
- /* IMSM has no concept of UUID or homehost */
+ /* successful update? recompute checksum */
+ if (rv == 0)
+ mpb->check_sum = __le32_to_cpu(__gen_imsm_checksum(mpb));
return rv;
}
{
struct stat st;
char path[256];
- char dname[100];
+ char dname[PATH_MAX];
char *nm;
int rv;
strncpy((char *) dest, (char *) src, MAX_RAID_SERIAL_LEN);
}
+#ifndef MDASSEMBLE
static struct dl *serial_to_dl(__u8 *serial, struct intel_super *super)
{
struct dl *dl;
return dl;
}
+#endif
static struct imsm_disk *
__serial_to_disk(__u8 *serial, struct imsm_super *mpb, int *idx)
if (sra->array.major_version != -1 ||
sra->array.minor_version != -2 ||
- strcmp(sra->text_version, "imsm") != 0)
- return 1;
-
+ strcmp(sra->text_version, "imsm") != 0) {
+ err = 1;
+ goto error;
+ }
/* load all mpbs */
for (sd = sra->devs, i = 0; sd; sd = sd->next, i++) {
struct intel_super *s = alloc_super(0);
- char nm[20];
+ char nm[32];
int dfd;
err = 1;
super_list = super_list->next;
free_imsm(s);
}
+ sysfs_free(sra);
if (err)
return err;
map->ddf = 1;
if (info->level == 1 && info->raid_disks > 2) {
+ free(dev);
+ free(dv);
fprintf(stderr, Name": imsm does not support more than 2 disks"
"in a raid1 volume\n");
return 0;
size_t mpb_size;
char *version;
- if (!info) {
- st->sb = NULL;
- return 0;
- }
if (st->sb)
- return init_super_imsm_volume(st, info, size, name, homehost,
- uuid);
+ return init_super_imsm_volume(st, info, size, name, homehost, uuid);
+
+ if (info)
+ mpb_size = disks_to_mpb_size(info->nr_disks);
+ else
+ mpb_size = 512;
super = alloc_super(1);
- if (!super)
- return 0;
- mpb_size = disks_to_mpb_size(info->nr_disks);
- if (posix_memalign(&super->buf, 512, mpb_size) != 0) {
+ if (super && posix_memalign(&super->buf, 512, mpb_size) != 0) {
free(super);
+ super = NULL;
+ }
+ if (!super) {
+ fprintf(stderr, Name
+ ": %s could not allocate superblock\n", __func__);
return 0;
}
+ memset(super->buf, 0, mpb_size);
mpb = super->buf;
- memset(mpb, 0, mpb_size);
+ mpb->mpb_size = __cpu_to_le32(mpb_size);
+ st->sb = super;
+
+ if (info == NULL) {
+ /* zeroing superblock */
+ return 0;
+ }
mpb->attributes = MPB_ATTRIB_CHECKSUM_VERIFY;
strcpy(version, MPB_SIGNATURE);
version += strlen(MPB_SIGNATURE);
strcpy(version, MPB_VERSION_RAID0);
- mpb->mpb_size = mpb_size;
- st->sb = super;
return 1;
}
struct imsm_dev *_dev = __get_imsm_dev(mpb, 0);
struct imsm_disk *_disk = __get_imsm_disk(mpb, dl->index);
+ if (!_dev || !_disk) {
+ fprintf(stderr, Name ": BUG mpb setup error\n");
+ return 1;
+ }
*_dev = *dev;
*_disk = dl->disk;
sum = random32();
}
#endif
-static int store_zero_imsm(struct supertype *st, int fd)
+static int store_super_imsm(struct supertype *st, int fd)
{
- unsigned long long dsize;
- void *buf;
-
- get_dev_size(fd, NULL, &dsize);
-
- /* first block is stored on second to last sector of the disk */
- if (lseek64(fd, dsize - (512 * 2), SEEK_SET) < 0)
- return 1;
+ struct intel_super *super = st->sb;
+ struct imsm_super *mpb = super ? super->anchor : NULL;
- if (posix_memalign(&buf, 512, 512) != 0)
+ if (!mpb)
return 1;
- memset(buf, 0, 512);
- if (write(fd, buf, 512) != 512)
- return 1;
- return 0;
+#ifndef MDASSEMBLE
+ return store_imsm_mpb(fd, mpb);
+#else
+ return 1;
+#endif
}
static int imsm_bbm_log_size(struct imsm_super *mpb)
{
struct stat stb;
struct intel_super *super = st->sb;
- struct imsm_super *mpb = super->anchor;
+ struct imsm_super *mpb;
struct dl *dl;
unsigned long long pos = 0;
unsigned long long maxsize;
/* We must have the container info already read in. */
if (!super)
return 0;
+ mpb = super->anchor;
if (!is_raid_level_supported(super->orom, level, raiddisks)) {
pr_vrb(": platform does not support raid%d with %d disk%s\n",
{
int fd, cfd;
struct mdinfo *sra;
+ int is_member = 0;
/* if given unused devices create a container
* if given given devices in a container create a member volume
case 1:
case 10:
case 5:
- break;
+ return 0;
default:
+ if (verbose)
+ fprintf(stderr, Name
+ ": IMSM only supports levels 0,1,5,10\n");
return 1;
}
}
/* Well, it is in use by someone, maybe an 'imsm' container. */
cfd = open_container(fd);
+ close(fd);
if (cfd < 0) {
- close(fd);
if (verbose)
fprintf(stderr, Name ": Cannot use %s: It is busy\n",
dev);
return 0;
}
sra = sysfs_read(cfd, 0, GET_VERSION);
- close(fd);
if (sra && sra->array.major_version == -1 &&
- strcmp(sra->text_version, "imsm") == 0) {
+ strcmp(sra->text_version, "imsm") == 0)
+ is_member = 1;
+ sysfs_free(sra);
+ if (is_member) {
/* This is a member of a imsm container. Load the container
* and try to create a volume
*/
size, dev,
freesize, verbose);
}
- close(cfd);
- } else /* may belong to another container */
- return 0;
+ }
- return 1;
+ if (verbose)
+ fprintf(stderr, Name ": failed container membership check\n");
+
+ close(cfd);
+ return 0;
}
#endif /* MDASSEMBLE */
}
this = malloc(sizeof(*this));
+ if (!this) {
+ fprintf(stderr, Name ": failed to allocate %lu bytes\n",
+ sizeof(*this));
+ break;
+ }
memset(this, 0, sizeof(*this));
this->next = rest;
ord = get_imsm_ord_tbl_ent(dev, slot);
for (d = super->disks; d ; d = d->next)
if (d->index == idx)
- break;
+ break;
if (d == NULL)
skip = 1;
info_d->events = __le32_to_cpu(mpb->generation_num);
info_d->data_offset = __le32_to_cpu(map->pba_of_lba0);
info_d->component_size = __le32_to_cpu(map->blocks_per_member);
- if (d->devname)
- strcpy(info_d->name, d->devname);
}
rest = this;
}
.load_super = load_super_imsm,
.init_super = init_super_imsm,
- .store_super = store_zero_imsm,
+ .store_super = store_super_imsm,
.free_super = free_super_imsm,
.match_metadata_desc = match_metadata_desc_imsm,
.container_content = container_content_imsm,