From: Neil Brown <neilb@suse.de>
To: Adam Kwolek <adam.kwolek@intel.com>
Cc: linux-raid@vger.kernel.org, dan.j.williams@intel.com,
ed.ciechanowski@intel.com
Subject: Re: [PATCH 20/53] imsm: Add reshape_update for grow array case
Date: Mon, 29 Nov 2010 12:48:14 +1100 [thread overview]
Message-ID: <20101129124814.174f2506@notabene.brown> (raw)
In-Reply-To: <20101126080629.5221.70482.stgit@gklab-170-024.igk.intel.com>
On Fri, 26 Nov 2010 09:06:29 +0100 Adam Kwolek <adam.kwolek@intel.com> wrote:
> Store metadata update during Online Capacity Expansion initialization to currently reshaped array in container.
> New update type imsm_update_reshape is added to perform this action.
> Active array is extended with reshape_delta_disk variable that triggers additional actions in managemon.
>
> 1. reshape_super() prepares metadata update and send it to mdmon 2. managemon in prepare_update() allocates required memory for bigger device object 3. monitor in
> process_update() updates (replaces) device object with information
> passed from mdadm (memory was allocated by managemon) 4. set reshape_delta_disks variable to delta_disks value from update.
> This signals managemon to add devices to md and start reshape for this array
I haven't applied this patch because there is too much of it that doesn't
make sense to me. Maybe you need to break it up and explain it better. But
see below
>
> Signed-off-by: Adam Kwolek <adam.kwolek@intel.com>
> Signed-off-by: Krzysztof Wojcik <krzysztof.wojcik@intel.com>
> ---
>
> Makefile | 6
> managemon.c | 2
> mdadm.h | 4
> mdmon.h | 5
> super-intel.c | 792 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> sysfs.c | 144 ++++++++++
> util.c | 148 +++++++++++
> 7 files changed, 1094 insertions(+), 7 deletions(-)
>
> diff --git a/Makefile b/Makefile
> index e2c65a5..e3fb949 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -112,17 +112,17 @@ SRCS = mdadm.c config.c mdstat.c ReadMe.c util.c Manage.c Assemble.c Build.c \
> MON_OBJS = mdmon.o monitor.o managemon.o util.o mdstat.o sysfs.o config.o \
> Kill.o sg_io.o dlink.o ReadMe.o super0.o super1.o super-intel.o \
> super-ddf.o sha1.o crc32.o msg.o bitmap.o \
> - platform-intel.o probe_roms.o
> + platform-intel.o probe_roms.o mapfile.o
>
> MON_SRCS = mdmon.c monitor.c managemon.c util.c mdstat.c sysfs.c config.c \
> Kill.c sg_io.c dlink.c ReadMe.c super0.c super1.c super-intel.c \
> super-ddf.c sha1.c crc32.c msg.c bitmap.c \
> - platform-intel.c probe_roms.c
> + platform-intel.c probe_roms.c mapfile.c
I can see no justification for adding mapfile to mdmon. If you find you need
to do that, you have done something wrong.
>
> STATICSRC = pwgr.c
> STATICOBJS = pwgr.o
>
> -ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c dlink.c util.c \
> +ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c dlink.c util.c mapfile.c\
> super0.c super1.c super-ddf.c super-intel.c sha1.c crc32.c sg_io.c mdstat.c \
> platform-intel.c probe_roms.c sysfs.c
> ASSEMBLE_AUTO_SRCS := mdopen.c
> diff --git a/managemon.c b/managemon.c
> index 53ab4a9..d495014 100644
> --- a/managemon.c
> +++ b/managemon.c
> @@ -536,6 +536,8 @@ static void manage_new(struct mdstat_ent *mdstat,
>
> new->container = container;
>
> + new->reshape_state = reshape_not_active;
> +
> inst = to_subarray(mdstat, container->devname);
>
> new->info.array = mdi->array;
> diff --git a/mdadm.h b/mdadm.h
> index bf3c1d3..4777ad2 100644
> --- a/mdadm.h
> +++ b/mdadm.h
> @@ -447,6 +447,7 @@ extern int sysfs_disk_to_scsi_id(int fd, __u32 *id);
> extern int sysfs_unique_holder(int devnum, long rdev);
> extern int sysfs_freeze_array(struct mdinfo *sra);
> extern int load_sys(char *path, char *buf);
> +extern struct mdinfo *sysfs_get_unused_spares(int container_fd, int fd);
>
>
> extern int save_stripes(int *source, unsigned long long *offsets,
> @@ -473,6 +474,7 @@ extern char *map_dev(int major, int minor, int create);
>
> struct active_array;
> struct metadata_update;
> +enum state_of_reshape;
Why declare state_of_reshape like this in mdadm.h if it isn't used at all in
mdadm.h??
>
> /* A superswitch provides entry point the a metadata handler.
> *
> @@ -891,6 +893,8 @@ extern int conf_name_is_free(char *name);
> extern int devname_matches(char *name, char *match);
> extern struct mddev_ident_s *conf_match(struct mdinfo *info, struct supertype *st);
> extern inline int experimental(void);
> +extern int find_array_minor(char *text_version, int external, int container, int *minor);
> +extern int find_array_minor2(char *text_version, int external, int container, int *minor);
>
> extern void free_line(char *line);
> extern int match_oneof(char *devices, char *devname);
> diff --git a/mdmon.h b/mdmon.h
> index 8190358..9ea0b93 100644
> --- a/mdmon.h
> +++ b/mdmon.h
> @@ -24,6 +24,8 @@ enum array_state { clear, inactive, suspended, readonly, read_auto,
> enum sync_action { idle, reshape, resync, recover, check, repair, bad_action };
>
>
> +enum state_of_reshape { reshape_not_active, reshape_is_starting, reshape_in_progress, reshape_cancel_request };
> +
> struct active_array {
> struct mdinfo info;
> struct supertype *container;
> @@ -45,6 +47,9 @@ struct active_array {
> enum array_state prev_state, curr_state, next_state;
> enum sync_action prev_action, curr_action, next_action;
>
> + enum state_of_reshape reshape_state;
> + int reshape_delta_disks;
> +
Adding these fields seems correct, but I would really like a separate patch
which adds the fields, and the definition and the initialisation.
If it had a comment explaining the stages and how each state change happens,
that would be an added bonus.
> int check_degraded; /* flag set by mon, read by manage */
>
> int devnum;
> diff --git a/super-intel.c b/super-intel.c
> index 90faff6..98e4c6d 100644
> --- a/super-intel.c
> +++ b/super-intel.c
> @@ -286,6 +286,7 @@ enum imsm_update_type {
> update_rename_array,
> update_add_disk,
> update_level,
> + update_reshape,
> };
>
> struct imsm_update_activate_spare {
> @@ -296,6 +297,43 @@ struct imsm_update_activate_spare {
> struct imsm_update_activate_spare *next;
> };
>
> +struct geo_params {
> + int dev_id;
> + char *dev_name;
> + long long size;
> + int level;
> + int layout;
> + int chunksize;
> + int raid_disks;
> +};
> +
> +
> +struct imsm_update_reshape {
> + enum imsm_update_type type;
> + int update_memory_size;
> + int reshape_delta_disks;
> + int disks_count;
> + int spares_in_update;
> + int devnum;
> + /* pointers to memory that will be allocated
> + * by manager during prepare_update()
> + */
> + struct intel_dev devs_mem;
> + /* status of update preparation
> + */
> + int update_prepared;
> + /* anchor data prepared by mdadm */
> + int upd_devs_offset;
> + int device_size;
> + struct dl upd_disks[1];
> + /* here goes added spares
> + */
> + /* and here goes imsm_devs pointed by upd_devs
> + * devs are put here as row data every device_size bytes
> + *
> + */
> +};
> +
> struct disk_info {
> __u8 serial[MAX_RAID_SERIAL_LEN];
> };
> @@ -5189,6 +5227,7 @@ static int disks_overlap(struct intel_super *super, int idx, struct imsm_update_
> }
>
> static void imsm_delete(struct intel_super *super, struct dl **dlp, unsigned index);
> +int imsm_get_new_device_name(struct dl *dl);
>
> static void imsm_process_update(struct supertype *st,
> struct metadata_update *update)
> @@ -5224,6 +5263,102 @@ static void imsm_process_update(struct supertype *st,
> mpb = super->anchor;
>
> switch (type) {
> + case update_reshape: {
> + struct imsm_update_reshape *u = (void *)update->buf;
> + struct dl *new_disk;
> + struct active_array *a;
> + int i;
> + __u32 new_mpb_size;
> + int new_disk_num;
> + struct intel_dev *current_dev;
> +
> + dprintf("imsm: imsm_process_update() for update_reshape [u->update_prepared = %i]\n", u->update_prepared);
> + if ((u->update_prepared == -1) ||
> + (u->devnum < 0)) {
> + dprintf("imsm: Error: update_reshape not prepared\n");
> + goto update_reshape_exit;
> + }
> +
> + if (u->spares_in_update) {
> + new_disk_num = mpb->num_disks + u->reshape_delta_disks;
> + new_mpb_size = disks_to_mpb_size(new_disk_num);
> + if (mpb->mpb_size < new_mpb_size)
> + mpb->mpb_size = new_mpb_size;
> +
> + /* enable spares to use in array
> + */
> + for (i = 0; i < u->reshape_delta_disks; i++) {
> + char buf[PATH_MAX];
> +
> + new_disk = super->disks;
> + while (new_disk) {
> + if ((new_disk->major == u->upd_disks[i].major) &&
> + (new_disk->minor == u->upd_disks[i].minor))
> + break;
> + new_disk = new_disk->next;
> + }
> + if (new_disk == NULL) {
> + u->update_prepared = -1;
> + goto update_reshape_exit;
> + }
> + if (new_disk->index < 0) {
> + new_disk->index = i + mpb->num_disks;
> + new_disk->raiddisk = new_disk->index; /* slot to fill in autolayout */
> + new_disk->disk.status |= CONFIGURED_DISK;
> + new_disk->disk.status &= ~SPARE_DISK;
> + }
> + sprintf(buf, "%d:%d", new_disk->major, new_disk->minor);
> + if (new_disk->fd < 0)
> + new_disk->fd = dev_open(buf, O_RDWR);
> + imsm_get_new_device_name(new_disk);
> + }
> + }
> +
> + dprintf("imsm: process_update(): update_reshape: volume set mpb->num_raid_devs = %i\n", mpb->num_raid_devs);
> + /* manage changes in volumes
> + */
> + /* check if array is in RESHAPE_NOT_ACTIVE reshape state
> + */
> + for (a = st->arrays; a; a = a->next)
> + if (a->devnum == u->devnum)
> + break;
> + if ((a == NULL) || (a->reshape_state != reshape_not_active)) {
> + u->update_prepared = -1;
> + goto update_reshape_exit;
> + }
> + /* find current dev in intel_super
> + */
> + dprintf("\t\tLooking for volume %s\n", (char *)u->devs_mem.dev->volume);
> + current_dev = super->devlist;
> + while (current_dev) {
> + if (strcmp((char *)current_dev->dev->volume,
> + (char *)u->devs_mem.dev->volume) == 0)
> + break;
> + current_dev = current_dev->next;
> + }
> + if (current_dev == NULL) {
> + u->update_prepared = -1;
> + goto update_reshape_exit;
> + }
> +
> + dprintf("Found volume %s\n", (char *)current_dev->dev->volume);
> + /* replace current device with provided in update
> + */
> + free(current_dev->dev);
> + current_dev->dev = u->devs_mem.dev;
> + u->devs_mem.dev = NULL;
> +
> + /* set reshape_delta_disks
> + */
> + a->reshape_delta_disks = u->reshape_delta_disks;
> + a->reshape_state = reshape_is_starting;
> +
> + super->updates_pending++;
> +update_reshape_exit:
> + if (u->devs_mem.dev)
> + free(u->devs_mem.dev);
> + break;
> + }
> case update_level: {
> struct imsm_update_level *u = (void *)update->buf;
> struct imsm_dev *dev_new, *dev = NULL;
> @@ -5592,8 +5727,58 @@ static void imsm_prepare_update(struct supertype *st,
> struct imsm_super *mpb = super->anchor;
> size_t buf_len;
> size_t len = 0;
> + void *upd_devs;
>
> switch (type) {
> + case update_reshape: {
> + struct imsm_update_reshape *u = (void *)update->buf;
> + struct dl *dl = NULL;
> +
> + u->update_prepared = -1;
> + u->devs_mem.dev = NULL;
> + dprintf("imsm: imsm_prepare_update() for update_reshape\n");
> + if (u->devnum < 0) {
> + dprintf("imsm: No passed device.\n");
> + break;
> + }
> + dprintf("imsm: reshape delta disks is = %i\n", u->reshape_delta_disks);
> + if (u->reshape_delta_disks < 0)
> + break;
> + u->update_prepared = 1;
> + if (u->reshape_delta_disks == 0) {
> + /* for non growing reshape buffers sizes are not affected
> + * but check some parameters
> + */
> + break;
> + }
> + /* count HDDs
> + */
> + u->disks_count = 0;
> + for (dl = super->disks; dl; dl = dl->next)
> + if (dl->index >= 0)
> + u->disks_count++;
> +
> + /* set pointer in monitor address space
> + */
> + upd_devs = (struct imsm_dev *)((void *)u + u->upd_devs_offset);
> + /* allocate memory for new volumes */
> + if (((struct imsm_dev *)(upd_devs))->vol.migr_type != MIGR_GEN_MIGR) {
> + dprintf("imsm: Error.Device is not in migration state.\n");
> + u->update_prepared = -1;
> + break;
> + }
> + dprintf("passed device : %s\n", ((struct imsm_dev *)(upd_devs))->volume);
> + u->devs_mem.dev = calloc(1, u->device_size);
> + if (u->devs_mem.dev == NULL) {
> + u->update_prepared = -1;
> + break;
> + }
> + dprintf("METADATA Copy - using it.\n");
> + memcpy(u->devs_mem.dev, upd_devs, u->device_size);
> + len = disks_to_mpb_size(u->spares_in_update + mpb->num_disks);
> + dprintf("New anchor length is %llu\n", (unsigned long long)len);
> + break;
> + }
> case update_level: {
> struct imsm_update_level *u = (void *) update->buf;
> struct active_array *a;
> @@ -5818,6 +6003,525 @@ static int update_level_imsm(struct supertype *st, struct mdinfo *info,
> return 0;
> }
>
> +int imsm_reshape_is_allowed_on_container(struct supertype *st,
> + struct geo_params *geo)
> +{
> + int ret_val = 0;
> + struct mdinfo *info = NULL;
> + char buf[PATH_MAX];
> + int fd = -1;
> + int device_num = -1;
> + int devices_that_can_grow = 0;
> +
> + dprintf("imsm: imsm_reshape_is_allowed_on_container(ENTER): st->devnum = (%i)\n", st->devnum);
> +
> + if (geo == NULL ||
> + (geo->size != -1) || (geo->level != UnSet) ||
> + (geo->layout != UnSet) || (geo->chunksize != 0)) {
> + dprintf("imsm: Container operation is allowed for raid disks number change only.\n");
> + return ret_val;
> + }
> +
> + snprintf(buf, PATH_MAX, "/dev/md%i", st->devnum);
> + dprintf("imsm: open device (%s)\n", buf);
> + fd = open(buf , O_RDONLY | O_DIRECT);
> + if (fd < 0) {
> + dprintf("imsm: cannot open device\n");
> + return ret_val;
> + }
> +
> + if (geo->raid_disks == UnSet) {
> + dprintf("imsm: for container operation raid disks change is required\n");
> + goto exit_imsm_reshape_is_allowed_on_container;
> + }
> +
> + device_num = 0; /* start from first device (skip container info) */
> + while (device_num > -1) {
> + int result;
> + int minor;
> + unsigned long long array_blocks;
> + struct imsm_map *map = NULL;
> + struct imsm_dev *dev = NULL;
> + struct intel_super *super = NULL;
> + int used_disks;
> +
> +
> + dprintf("imsm: checking device_num: %i\n", device_num);
> + sprintf(st->subarray, "%i", device_num);
> + st->ss->load_super(st, fd, NULL);
> + if (st->sb == NULL) {
> + if (device_num == 0) {
> + /* for the first checked device this is error
> + there should be at least one device to check
> + */
> + dprintf("imsm: error: superblock is NULL during container operation\n");
> + } else {
> + dprintf("imsm: no more devices to check, number of forund devices: %i\n",
> + devices_that_can_grow);
> + /* check if any device in container can be groved
> + */
> + if (devices_that_can_grow)
> + ret_val = 1;
> + /* restore superblock, for last device not loaded */
> + sprintf(st->subarray, "%i", 0);
> + st->ss->load_super(st, fd, NULL);
> + }
> + break;
> + }
> + info = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE);
> + if (info == NULL) {
> + dprintf("imsm: Cannot get device info.\n");
> + break;
> + }
> + st->ss->getinfo_super(st, info);
> +
> + if (geo->raid_disks < info->array.raid_disks) {
> + /* we work on container for Online Capacity Expansion
> + * only so raid_disks has to grow
> + */
> + dprintf("imsm: for container operation raid disks increase is required\n");
> + break;
> + }
> + /* check if size is set corectly
> + * wrong conditions could happend when previous reshape wes interrupted
> + */
> + super = st->sb;
> + dev = get_imsm_dev(super, device_num);
> + if (dev == NULL) {
> + dprintf("cannot get imsm device\n");
> + ret_val = 0;
> + break;
> + }
> + map = get_imsm_map(dev, 0);
> + if (dev == NULL) {
> + dprintf("cannot get imsm device map\n");
> + ret_val = 0;
> + break;
> + }
> + used_disks = imsm_num_data_members(dev);
> + dprintf("read raid_disks = %i\n", used_disks);
> + dprintf("read requested disks = %i\n", geo->raid_disks);
> + array_blocks = map->blocks_per_member * used_disks;
> + /* round array size down to closest MB
> + */
> + array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
> + if (sysfs_set_num(info, NULL, "array_size", array_blocks/2) < 0)
> + dprintf("cannot set array size to %llu\n", array_blocks/2);
> +
> + if (geo->raid_disks > info->array.raid_disks)
> + devices_that_can_grow++;
> +
> + if ((info->array.level != 0) &&
> + (info->array.level != 5)) {
> + /* we cannot use this container other raid level
> + */
> + dprintf("imsm: for container operation wrong raid level (%i) detected\n", info->array.level);
> + break;
> + } else {
> + /* check for platform support for this raid level configuration
> + */
> + struct intel_super *super = st->sb;
> + if (!is_raid_level_supported(super->orom, info->array.level, geo->raid_disks)) {
> + dprintf("platform does not support raid%d with %d disk%s\n",
> + info->array.level, geo->raid_disks, geo->raid_disks > 1 ? "s" : "");
> + break;
> + }
> + }
> +
> + /* all raid5 and raid0 volumes in container
> + * has to be ready for Online Capacity Expansion
> + */
> + result = find_array_minor2(info->text_version, st->ss->external, st->devnum, &minor);
> + if (result < 0) {
> + dprintf("imsm: cannot find array\n");
> + break;
> + }
> + sprintf(info->sys_name, "md%i", minor);
> + if (sysfs_get_str(info, NULL, "array_state", buf, 20) <= 0) {
> + dprintf("imsm: cannot read array state\n");
> + break;
> + }
> + if ((strncmp(buf, "clean", 5) != 0) &&
> + (strncmp(buf, "clear", 5) != 0) &&
> + (strncmp(buf, "active", 6) != 0)) {
> + int index = strlen(buf) - 1;
> +
> + if (index < 0)
> + index = 0;
> + *(buf + index) = 0;
> + fprintf(stderr, "imsm: Error: Array %s is not in proper state (current state: %s). Cannot continue.\n", info->sys_name, buf);
> + break;
> + }
> + if (info->array.level > 0) {
> + if (sysfs_get_str(info, NULL, "sync_action", buf, 20) <= 0) {
> + dprintf("imsm: for container operation no sync action\n");
> + break;
> + }
> + /* check if any reshape is not in progress
> + */
> + if (strncmp(buf, "reshape", 7) == 0) {
> + dprintf("imsm: for container operation reshape is currently in progress\n");
> + break;
> + }
> + }
> + sysfs_free(info);
> + info = NULL;
> + device_num++;
> + }
> + sysfs_free(info);
> + info = NULL;
> +
> +exit_imsm_reshape_is_allowed_on_container:
> + if (fd >= 0)
> + close(fd);
> +
> + dprintf("imsm: imsm_reshape_is_allowed_on_container(Exit) device_num = %i, ret_val = %i\n", device_num, ret_val);
> + if (ret_val)
> + dprintf("\tContainer operation allowed\n");
> + else
> + dprintf("\tError: %i\n", ret_val);
> +
> + return ret_val;
> +}
> +struct mdinfo *get_spares_imsm(int devnum)
> +{
> + int fd = -1;
> + char buf[PATH_MAX];
> + struct mdinfo *info = NULL;
> + struct mdinfo *ret_val = NULL;
> + int cont_id = -1;
> + struct supertype *st = NULL;
> + int find_result;
> +
> + dprintf("imsm: get_spares_imsm for device: %i.\n", devnum);
> +
> + sprintf(buf, "/dev/md%i", devnum);
> + dprintf("try to read container %s\n", buf);
> +
> + cont_id = open(buf, O_RDONLY);
> + if (cont_id < 0) {
> + dprintf("imsm: ERROR: Cannot open container.\n");
> + goto abort;
> + }
> +
> + /* get first volume */
> + st = super_by_fd(cont_id);
> + if (st == NULL) {
> + dprintf("imsm: ERROR: Cannot load container information.\n");
> + goto abort;
> + }
> + sprintf(buf, "/md%i/0", devnum);
> + find_result = find_array_minor2(buf, 1, devnum, &devnum);
> + if (find_result < 0) {
> + dprintf("imsm: ERROR: Cannot find array.\n");
> + goto abort;
> + }
> + sprintf(buf, "/dev/md%i", devnum);
> + fd = open(buf, O_RDONLY);
> + if (fd < 0) {
> + dprintf("imsm: ERROR: Cannot open device.\n");
> + goto abort;
> + }
> + sprintf(st->subarray, "0");
> + st->ss->load_super(st, cont_id, NULL);
> + if (st->sb == NULL) {
> + dprintf("imsm: ERROR: Cannot load array information.\n");
> + goto abort;
> + }
> + info = sysfs_read(fd, 0, GET_LEVEL | GET_VERSION | GET_DEVS | GET_STATE);
> + if (info == NULL) {
> + dprintf("imsm: Cannot get device info.\n");
> + goto abort;
> + }
> + st->ss->getinfo_super(st, info);
> + sprintf(buf, "/dev/md/%s", info->name);
> + ret_val = sysfs_get_unused_spares(cont_id, fd);
> + if (ret_val == NULL) {
> + dprintf("imsm: ERROR: Cannot get spare devices.\n");
> + goto abort;
> + }
> + if (ret_val->array.spare_disks == 0) {
> + dprintf("imsm: ERROR: No available spares.\n");
> + free(ret_val);
> + ret_val = NULL;
> + goto abort;
> + }
> +
> +abort:
> + if (st)
> + st->ss->free_super(st);
> + sysfs_free(info);
> + if (fd > -1)
> + close(fd);
> + if (cont_id > -1)
> + close(cont_id);
> +
> + return ret_val;
> +}
> +
> +/******************************************************************************
> + * function: imsm_create_metadata_update_for_reshape
> + * Function creates update for whole IMSM container.
> + * Slot number for new devices are guesed only. Managemon will correct them
> + * when reshape will be triggered and md sets slot numbers.
> + * Slot numbers in metadata will be updated with stage_2 update
> + ******************************************************************************/
> +struct imsm_update_reshape *imsm_create_metadata_update_for_reshape(struct supertype *st, struct geo_params *geo)
> +{
> + struct imsm_update_reshape *ret_val = NULL;
> + struct intel_super *super = st->sb;
> + int update_memory_size = 0;
> + struct imsm_update_reshape *u = NULL;
> + struct imsm_map *new_map = NULL;
> + struct mdinfo *spares = NULL;
> + int i;
> + unsigned long long array_blocks;
> + int used_disks;
> + int delta_disks = 0;
> + struct dl *new_disks;
> + int device_size;
> + void *upd_devs;
> +
> + dprintf("imsm imsm_update_metadata_for_reshape(enter) raid_disks = %i\n", geo->raid_disks);
> +
> + if ((geo->raid_disks < super->anchor->num_disks) ||
> + (geo->raid_disks == UnSet))
> + geo->raid_disks = super->anchor->num_disks;
> + delta_disks = geo->raid_disks - super->anchor->num_disks;
> +
> + /* size of all update data without anchor */
> + update_memory_size = sizeof(struct imsm_update_reshape);
> + /* add space for all devices,
> + * then add maps space
> + */
> + device_size = sizeof(struct imsm_dev);
> + device_size += sizeof(struct imsm_map);
> + device_size += 2 * (geo->raid_disks - 1) * sizeof(__u32);
> +
> + update_memory_size += device_size * super->anchor->num_raid_devs;
> + if (delta_disks > 1) {
> + /* now add space for spare disks information
> + */
> + update_memory_size += sizeof(struct dl) * (delta_disks - 1);
> + }
> +
> + u = calloc(1, update_memory_size);
> + if (u == NULL) {
> + dprintf("error: cannot get memory for imsm_update_reshape update\n");
> + return ret_val;
> + }
> + u->reshape_delta_disks = delta_disks;
> + u->update_prepared = -1;
> + u->update_memory_size = update_memory_size;
> + u->type = update_reshape;
> + u->spares_in_update = 0;
> + u->upd_devs_offset = sizeof(struct imsm_update_reshape) + sizeof(struct dl) * (delta_disks - 1);
> + upd_devs = (struct imsm_dev *)((void *)u + u->upd_devs_offset);
> + u->device_size = device_size;
> +
> + for (i = 0; i < super->anchor->num_raid_devs; i++) {
> + struct imsm_dev *old_dev = __get_imsm_dev(super->anchor, i);
> + int old_disk_number;
> + int devnum = -1;
> +
> + u->devnum = -1;
> + if (old_dev == NULL)
> + break;
> +
> + find_array_minor((char *)old_dev->volume, 1, st->devnum, &devnum);
> + if (devnum == geo->dev_id) {
> + __u8 to_state;
> + struct imsm_map *new_map2;
> + int idx;
> +
> + new_map = NULL;
> + imsm_copy_dev(upd_devs, old_dev);
> + new_map = get_imsm_map(upd_devs, 0);
> + old_disk_number = new_map->num_members;
> + new_map->num_members = geo->raid_disks;
> + u->reshape_delta_disks = new_map->num_members - old_disk_number;
> + /* start migration on new device
> + * it puts second map there also
> + */
> +
> + to_state = imsm_check_degraded(super, old_dev, 0);
> + migrate(upd_devs, to_state, MIGR_GEN_MIGR);
> + /* second map length is equal to first map
> + * correct second map length to old value
> + */
> + new_map2 = get_imsm_map(upd_devs, 1);
> + if (new_map2) {
> + if (new_map2->num_members != old_disk_number) {
> + new_map2->num_members = old_disk_number;
> + /* guess new disk indexes
> + */
> + for (idx = new_map2->num_members; idx < new_map->num_members; idx++)
> + set_imsm_ord_tbl_ent(new_map, idx, idx);
> + }
> + u->devnum = geo->dev_id;
> + break;
> + }
> + }
> + }
> +
> + if (delta_disks <= 0) {
> + dprintf("imsm: reshape without grow (disk add).\n");
> + /* finalize update */
> + goto calculate_size_only;
> + }
> +
> + /* now get spare disks list
> + */
> + spares = get_spares_imsm(st->container_dev);
> +
> + if (spares == NULL) {
> + dprintf("imsm: ERROR: Cannot get spare devices.\n");
> + goto exit_imsm_create_metadata_update_for_reshape;
> + }
> + if ((spares->array.spare_disks == 0) ||
> + (u->reshape_delta_disks > spares->array.spare_disks)) {
> + dprintf("imsm: ERROR: No available spares.\n");
> + goto exit_imsm_create_metadata_update_for_reshape;
> + }
> + /* we have got spares
> + * update disk list in imsm_disk list table in anchor
> + */
> + dprintf("imsm: %i spares are available.\n\n", spares->array.spare_disks);
> + new_disks = u->upd_disks;
> + for (i = 0; i < u->reshape_delta_disks; i++) {
> + struct mdinfo *dev = spares->devs;
> + __u32 id;
> + int fd;
> + char buf[PATH_MAX];
> + int rv;
> + unsigned long long size;
> +
> + sprintf(buf, "%d:%d", dev->disk.major, dev->disk.minor);
> + dprintf("open spare disk %s (%s)\n", buf, dev->sys_name);
> + fd = dev_open(buf, O_RDWR);
> + if (fd < 0) {
> + dprintf("\topen failed\n");
> + goto exit_imsm_create_metadata_update_for_reshape;
> + }
> + if (sysfs_disk_to_scsi_id(fd, &id) == 0)
> + new_disks[i].disk.scsi_id = __cpu_to_le32(id);
> + else
> + new_disks[i].disk.scsi_id = __cpu_to_le32(0);
> + new_disks[i].disk.status = CONFIGURED_DISK;
> + rv = imsm_read_serial(fd, NULL, new_disks[i].disk.serial);
> + if (rv != 0) {
> + dprintf("\tcannot read disk serial\n");
> + close(fd);
> + goto exit_imsm_create_metadata_update_for_reshape;
> + }
> + dprintf("\tdisk serial: %s\n", new_disks[i].disk.serial);
> + get_dev_size(fd, NULL, &size);
> + size /= 512;
> + new_disks[i].disk.total_blocks = __cpu_to_le32(size);
> + new_disks[i].disk.owner_cfg_num = super->anchor->disk->owner_cfg_num;
> +
> + new_disks[i].major = dev->disk.major;
> + new_disks[i].minor = dev->disk.minor;
> + /* no relink in update
> + * use table access
> + */
> + new_disks[i].next = NULL;
> +
> + close(fd);
> + spares->devs = dev->next;
> + u->spares_in_update++;
> +
> + free(dev);
> + dprintf("\n");
> + }
> +calculate_size_only:
> + /* calculate new size
> + */
> + if (new_map != NULL) {
> +
> + used_disks = imsm_num_data_members(upd_devs);
> + if (used_disks) {
> + array_blocks = new_map->blocks_per_member * used_disks;
> + /* round array size down to closest MB
> + */
> + array_blocks = (array_blocks >> SECT_PER_MB_SHIFT) << SECT_PER_MB_SHIFT;
> + ((struct imsm_dev *)(upd_devs))->size_low = __cpu_to_le32((__u32)array_blocks);
> + ((struct imsm_dev *)(upd_devs))->size_high = __cpu_to_le32((__u32)(array_blocks >> 32));
> + /* finalize update */
> + ret_val = u;
> + }
> + }
> +
> +exit_imsm_create_metadata_update_for_reshape:
> + /* free spares
> + */
> + if (spares) {
> + while (spares->devs) {
> + struct mdinfo *dev = spares->devs;
> + spares->devs = dev->next;
> + free(dev);
> + }
> + free(spares);
> + }
> +
> + if (ret_val == NULL)
> + free(u);
> +
> + return ret_val;
> +}
> +
> +char *get_volume_for_olce(struct supertype *st, int raid_disks)
> +{
> + char *ret_val = NULL;
> + struct mdinfo *sra = NULL;
> + struct mdinfo info;
> + char *ret_buf;
> + struct intel_super *super = st->sb;
> + int i;
> + int fd = -1;
> + char buf[PATH_MAX];
> +
> + snprintf(buf, PATH_MAX, "/dev/md%i", st->devnum);
> + dprintf("imsm: open device (%s)\n", buf);
> + fd = open(buf , O_RDONLY | O_DIRECT);
> + if (fd < 0) {
> + dprintf("imsm: cannot open device\n");
> + return ret_val;
> + }
> +
> + ret_buf = malloc(PATH_MAX);
> + if (ret_buf == NULL)
> + goto exit_get_volume_for_olce;
> +
> + super = st->sb;
> + for (i = 0; i < super->anchor->num_raid_devs; i++) {
> + sprintf(st->subarray, "%i", i);
> + st->ss->load_super(st, fd, NULL);
> + if (st->sb == NULL)
> + goto exit_get_volume_for_olce;
> + info.devs = NULL;
> + st->ss->getinfo_super(st, &info);
> +
> + if (raid_disks > info.array.raid_disks) {
> + snprintf(ret_buf, PATH_MAX,
> + "%s", info.name);
> + dprintf("Found device for OLCE requested raid_disks = %i, array raid_disks = %i\n",
> + raid_disks, info.array.raid_disks);
> + ret_val = ret_buf;
> + break;
> + }
> + }
> +
> +exit_get_volume_for_olce:
> + if ((ret_val == NULL) && ret_buf)
> + free(ret_buf);
> + sysfs_free(sra);
> + if (fd > -1)
> + close(fd);
> +
> + return ret_val;
> +}
> +
>
> int imsm_reshape_super(struct supertype *st, long long size, int level,
> int layout, int chunksize, int raid_disks,
> @@ -5827,7 +6531,20 @@ int imsm_reshape_super(struct supertype *st, long long size, int level,
> struct mdinfo *sra = NULL;
> int fd = -1;
> char buf[PATH_MAX];
> + struct geo_params geo;
> +
> + memset(&geo, sizeof (struct geo_params), 0);
> +
> + geo.dev_name = dev;
> + geo.size = size;
> + geo.level = level;
> + geo.layout = layout;
> + geo.chunksize = chunksize;
> + geo.raid_disks = raid_disks;
>
> + dprintf("imsm: reshape_super called().\n");
> + dprintf("\tfor level : %i\n", geo.level);
> + dprintf("\tfor raid_disks : %i\n", geo.raid_disks);
>
> if (experimental() == 0)
> return ret_val;
> @@ -5839,7 +6556,46 @@ int imsm_reshape_super(struct supertype *st, long long size, int level,
> goto imsm_reshape_super_exit;
> }
>
> - if ((size == -1) && (layout == UnSet) && (raid_disks == 0) && (level != UnSet)) {
> + /* verify reshape conditions
> + * on container level we can do almost everything */
> + if (st->subarray[0] == 0) {
> + /* check for delta_disks > 0 and supported raid levels 0 and 5 only in container */
> + if (imsm_reshape_is_allowed_on_container(st, &geo)) {
> + struct imsm_update_reshape *u;
> + char *array;
> +
> + array = get_volume_for_olce(st, geo.raid_disks);
> + if (array) {
> + find_array_minor(array, 1, st->devnum, &geo.dev_id);
> + if (geo.dev_id > 0) {
> + dprintf("imsm: Preparing metadata update for: %s\n", array);
> +
> + st->update_tail = &st->updates;
> + u = imsm_create_metadata_update_for_reshape(st, &geo);
> +
> + if (u) {
> + ret_val = 0;
> + append_metadata_update(st, u, u->update_memory_size);
> + } else
> + dprintf("imsm: Cannot prepare update\n");
> + } else
> + dprintf("imsm: Cannot find array in container\n");
> + free(array);
> + }
> + } else
> + dprintf("imsm: Operation is not allowed on container\n");
> + *st->subarray = 0;
> + goto imsm_reshape_super_exit;
> + } else
> + dprintf("imsm: not a container operation\n");
> +
> + geo.dev_id = -1;
> + find_array_minor(geo.dev_name, 1, st->devnum, &geo.dev_id);
> +
> + /* we have volume so takeover can be performed for single volume only
> + */
> + if ((geo.size == -1) && (geo.layout == UnSet) && (geo.raid_disks == 0) && (geo.level != UnSet) &&
> + (geo.dev_id > -1)) {
> /* ok - this is takeover */
> int container_fd;
> int dn;
> @@ -5867,9 +6623,9 @@ int imsm_reshape_super(struct supertype *st, long long size, int level,
> * to/from different than raid10 level
> * if source level is raid0 mdmon is sterted only
> */
> - if (((level == 10) || (sra->array.level == 10) || (sra->array.level == 0)) &&
> - (level != sra->array.level) &&
> - (level > 0)) {
> + if (((geo.level == 10) || (sra->array.level == 10) || (sra->array.level == 0)) &&
> + (geo.level != sra->array.level) &&
> + (geo.level > 0)) {
> st->update_tail = &st->updates;
> err = update_level_imsm(st, sra, sra->name, 0, 0, NULL);
> ret_val = 0;
> @@ -5887,6 +6643,34 @@ imsm_reshape_super_exit:
> return ret_val;
> }
>
> +int imsm_get_new_device_name(struct dl *dl)
> +{
> + int rv;
> + char dv[PATH_MAX];
> + char nm[PATH_MAX];
> + char *dname;
> +
> + if (dl->devname != NULL)
> + return 0;
> +
> + sprintf(dv, "/sys/dev/block/%d:%d", dl->major, dl->minor);
> + memset(nm, 0, sizeof(nm));
> + rv = readlink(dv, nm, sizeof(nm));
> + if (rv > 0) {
> + nm[rv] = '\0';
> + dname = strrchr(nm, '/');
> + if (dname) {
> + char buf[PATH_MAX];
> +
> + dname++;
> + sprintf(buf, "/dev/%s", dname);
> + dl->devname = strdup(buf);
> + }
> + }
> +
> + return rv;
> +}
> +
> struct superswitch super_imsm = {
> #ifndef MDASSEMBLE
> .examine_super = examine_super_imsm,
> diff --git a/sysfs.c b/sysfs.c
> index 3582fed..e316785 100644
> --- a/sysfs.c
> +++ b/sysfs.c
> @@ -800,6 +800,150 @@ int sysfs_unique_holder(int devnum, long rdev)
> return found;
> }
>
> +int sysfs_is_spare_device_belongs_to(int fd, char *devname)
> +{
> + int ret_val = -1;
> + char fname[PATH_MAX];
> + char *base;
> + char *dbase;
> + struct mdinfo *sra;
> + DIR *dir = NULL;
> + struct dirent *de;
> +
> + sra = malloc(sizeof(*sra));
> + if (sra == NULL)
> + goto abort;
> + memset(sra, 0, sizeof(*sra));
> + sysfs_init(sra, fd, -1);
> + if (sra->sys_name[0] == 0)
> + goto abort;
> +
> + memset(fname, PATH_MAX, 0);
> + sprintf(fname, "/sys/block/%s/md/", sra->sys_name);
> + base = fname + strlen(fname);
> +
> + /* Get all the devices as well */
> + *base = 0;
> + dir = opendir(fname);
> + if (!dir)
> + goto abort;
> + while ((de = readdir(dir)) != NULL) {
> + if (de->d_ino == 0 ||
> + strncmp(de->d_name, "dev-", 4) != 0)
> + continue;
> + strcpy(base, de->d_name);
> + dbase = base + strlen(base);
> + *dbase = '\0';
> + dbase = strstr(fname, "/md/");
> + if (dbase && strcmp(devname, dbase) == 0) {
> + ret_val = 1;
> + goto abort;
> + }
> + }
> +abort:
> + if (dir)
> + closedir(dir);
> + sysfs_free(sra);
> +
> + return ret_val;
> +}
This at least needs a comment at the tops saying what it does, and why.
Why don't you do a sysfs_read, then do a search based on device id rather
than name? It is always safer to use device id than device name if possible.
> +
> +struct mdinfo *sysfs_get_unused_spares(int container_fd, int fd)
> +{
> + char fname[PATH_MAX];
> + char buf[PATH_MAX];
> + char *base;
> + char *dbase;
> + struct mdinfo *ret_val;
> + struct mdinfo *dev;
> + DIR *dir = NULL;
> + struct dirent *de;
> + int is_in;
> + char *to_check;
> +
> + ret_val = malloc(sizeof(*ret_val));
> + if (ret_val == NULL)
> + goto abort;
> + memset(ret_val, 0, sizeof(*ret_val));
> + sysfs_init(ret_val, container_fd, -1);
> + if (ret_val->sys_name[0] == 0)
> + goto abort;
> +
> + sprintf(fname, "/sys/block/%s/md/", ret_val->sys_name);
> + base = fname + strlen(fname);
> +
> + strcpy(base, "raid_disks");
> + if (load_sys(fname, buf))
> + goto abort;
> + ret_val->array.raid_disks = strtoul(buf, NULL, 0);
> +
> + /* Get all the devices as well */
> + *base = 0;
> + dir = opendir(fname);
> + if (!dir)
> + goto abort;
> + ret_val->array.spare_disks = 0;
> + while ((de = readdir(dir)) != NULL) {
> + char *ep;
> + if (de->d_ino == 0 ||
> + strncmp(de->d_name, "dev-", 4) != 0)
> + continue;
> + strcpy(base, de->d_name);
> + dbase = base + strlen(base);
> + *dbase = '\0';
> +
> + to_check = strstr(fname, "/md/");
> + is_in = sysfs_is_spare_device_belongs_to(fd, to_check);
> + if (is_in == -1) {
> + dev = malloc(sizeof(*dev));
> + if (!dev)
> + goto abort;
> + strncpy(dev->text_version, fname, 50);
> +
> + *dbase++ = '/';
> +
> + dev->disk.raid_disk = strtoul(buf, &ep, 10);
> + dev->disk.raid_disk = -1;
> +
> + strcpy(dbase, "block/dev");
> + if (load_sys(fname, buf)) {
> + free(dev);
> + continue;
> + }
> + sscanf(buf, "%d:%d", &dev->disk.major, &dev->disk.minor);
> + strcpy(dbase, "block/device/state");
> + if (load_sys(fname, buf) != 0) {
> + free(dev);
> + continue;
> + }
> + if (strncmp(buf, "offline", 7) == 0) {
> + free(dev);
> + continue;
> + }
> + if (strncmp(buf, "failed", 6) == 0) {
> + free(dev);
> + continue;
> + }
> +
> + /* add this disk to spares list */
> + dev->next = ret_val->devs;
> + ret_val->devs = dev;
> + ret_val->array.spare_disks++;
> + *(dbase-1) = '\0';
> + dprintf("sysfs: found spare: (%s)\n", fname);
> + }
> + }
> + closedir(dir);
> + return ret_val;
> +
> +abort:
> + if (dir)
> + closedir(dir);
> + sysfs_free(ret_val);
> +
> + return NULL;
> +}
Again, why not sysfs_read, then process that data structure?
> +
> int sysfs_freeze_array(struct mdinfo *sra)
> {
> /* Try to freeze resync/rebuild on this array/container.
> diff --git a/util.c b/util.c
> index f220792..396f6d8 100644
> --- a/util.c
> +++ b/util.c
> @@ -1869,3 +1869,151 @@ inline int experimental(void)
> }
> }
>
> +int path2devnum(char *pth)
> +{
> + char *ep;
> + int fd = -1;
> + char *dev_pth = NULL;
> + char *dev_str;
> + int dev_num = -1;
> +
> + fd = open(pth, O_RDONLY);
> + if (fd < 0)
> + return dev_num;
> + close(fd);
> + dev_pth = canonicalize_file_name(pth);
> + if (dev_pth == NULL)
> + return dev_num;
> + dev_str = strrchr(dev_pth, '/');
> + if (dev_str) {
> + while (!isdigit(dev_str[0]))
> + dev_str++;
> + dev_num = strtoul(dev_str, &ep, 10);
> + if (*ep != '\0')
> + dev_num = -1;
> + }
> +
> + if (dev_pth)
> + free(dev_pth);
> +
> + return dev_num;
> +}
> +
> +extern void map_read(struct map_ent **map);
> +extern void map_free(struct map_ent *map);
> +int find_array_minor(char *text_version, int external, int container, int *minor)
> +{
> + int i;
> + char path[PATH_MAX];
> + struct stat s;
> +
> + if (minor == NULL)
> + return -2;
> +
> + snprintf(path, PATH_MAX, "/dev/md/%s", text_version);
> + i = path2devnum(path);
> + if (i > -1) {
> + *minor = i;
> + return 0;
> + }
> +
> + i = path2devnum(text_version);
> + if (i > -1) {
> + *minor = i;
> + return 0;
> + }
> +
> + if (container > 0) {
> + struct map_ent *map = NULL;
> + struct map_ent *m;
> + char cont[PATH_MAX];
> +
> + snprintf(cont, PATH_MAX, "/md%i/", container);
> + map_read(&map);
> + for (m = map; m; m = m->next) {
> + int index;
> + unsigned int len = 0;
> + char buf[PATH_MAX];
> +
> + /* array have belongs to proper container
> + */
> + if (strncmp(cont, m->metadata, 6) != 0)
> + continue;
> + /* begin of array name in map have to be the same
> + * as array name in metadata
> + */
> + if (strncmp(m->path, path, strlen(path)) != 0)
> + continue;
> + /* array name has to be followed by '_' char
> + */
> + len = strlen(path);
> + if (*(m->path + len) != '_')
> + continue;
> + /* then we have to have valid index
> + */
> + len++;
> + if (strlen(m->path + len) <= 0)
> + continue;
> + /* index has to be las position in array name
> + */
> + index = atoi(m->path + strlen(path) + 1);
> + snprintf(buf, PATH_MAX, "%i", index);
> + len += strlen(buf);
> + if (len != strlen(m->path))
> + continue;
> + dprintf("Found %s device based on mdadm maps\n", m->path);
> + *minor = m->devnum;
> + map_free(map);
> + return 0;
> + }
> + map_free(map);
> + }
> +
> + for (i = 127; i >= 0; i--) {
> + char buf[PATH_MAX];
> +
> + snprintf(path, PATH_MAX, "/sys/block/md%d/md/", i);
> + if (stat(path, &s) != -1) {
> + strcat(path, "metadata_version");
> + if (load_sys(path, buf))
> + continue;
> + if (external) {
> + char *version = strchr(buf, ':');
> + if (version && strcmp(version + 1,
> + text_version))
> + continue;
> + } else {
> + if (strcmp(buf, text_version))
> + continue;
> + }
> + *minor = i;
> + return 0;
> + }
> + }
> +
> +
> + return -1;
> +}
> +
> +/* find_array_minor2 looks for frozen devices also
> + */
> +int find_array_minor2(char *text_version, int external, int container, int *minor)
> +{
> + int result;
> + char buf[PATH_MAX];
> +
> + strcpy(buf, text_version);
> + result = find_array_minor(text_version, external, container, minor);
> + if (result < 0) {
> + /* try to find frozen array also
> + */
> + char buf[PATH_MAX];
> +
> + strcpy(buf, text_version);
> +
> + *buf = '-';
> + result = find_array_minor(buf, external, container, minor);
> + }
> + return result;
> +}
> +
This all looks way to complicated, should be using map_read, and it totally
undocumented so it is too hard to figure out what you were really trying to
do.
NeilBrown
next prev parent reply other threads:[~2010-11-29 1:48 UTC|newest]
Thread overview: 76+ messages / expand[flat|nested] mbox.gz Atom feed top
2010-11-26 8:03 [PATCH 00/53] External Metadata Reshape Adam Kwolek
2010-11-26 8:03 ` [PATCH 01/53] Provide a mdstat_ent to subarray helper Adam Kwolek
2010-11-26 8:04 ` [PATCH 02/53] block monitor: freeze spare assignment for external arrays Adam Kwolek
2010-11-26 8:04 ` [PATCH 03/53] Manage: allow manual control of external raid0 readonly flag Adam Kwolek
2010-11-26 8:04 ` [PATCH 04/53] Grow: mark some functions static Adam Kwolek
2010-11-26 8:04 ` [PATCH 05/53] Assemble: fix assembly in the delta_disks > max_degraded case Adam Kwolek
2010-11-26 8:04 ` [PATCH 06/53] Grow: fix check for raid6 layout normalization Adam Kwolek
2010-11-26 8:04 ` [PATCH 07/53] Grow: add missing raid4 geometries to geo_map() Adam Kwolek
2010-11-26 8:04 ` [PATCH 08/53] fix a get_linux_version() comparison typo Adam Kwolek
2010-11-26 8:05 ` [PATCH 09/53] Create: cleanup/unify default geometry handling Adam Kwolek
2010-11-26 8:05 ` [PATCH 10/53] Initialize st->devnum and st->container_dev in super_by_fd Adam Kwolek
2010-11-26 8:05 ` [PATCH 11/53] Document the external reshape implementation Adam Kwolek
2010-11-26 8:05 ` [PATCH 12/53] External reshape (step 1): container reshape and ->reshape_super() Adam Kwolek
2010-11-26 8:05 ` [PATCH 13/53] External reshape (step 2): Freeze container Adam Kwolek
2010-11-26 8:05 ` [PATCH 14/53] FIX: Cannot exit monitor after takeover Adam Kwolek
2010-11-28 23:38 ` Neil Brown
2010-11-30 16:03 ` Kwolek, Adam
2010-11-30 22:06 ` Neil Brown
2010-11-26 8:05 ` [PATCH 15/53] FIX: Unfreeze not only container for external metadata Adam Kwolek
2010-11-28 23:48 ` Neil Brown
2010-11-30 16:03 ` Kwolek, Adam
2010-11-26 8:05 ` [PATCH 16/53] Add takeover support for external meta Adam Kwolek
2010-11-29 0:31 ` Neil Brown
2010-11-26 8:06 ` [PATCH 17/53] Disk removal support for Raid10->Raid0 takeover Adam Kwolek
2010-11-29 1:00 ` Neil Brown
2010-11-26 8:06 ` [PATCH 18/53] Treat feature as experimental Adam Kwolek
2010-11-29 1:13 ` Neil Brown
2010-11-26 8:06 ` [PATCH 19/53] imsm: Add support for general migration Adam Kwolek
2010-11-29 1:17 ` Neil Brown
2010-11-29 1:29 ` Neil Brown
2010-11-26 8:06 ` [PATCH 20/53] imsm: Add reshape_update for grow array case Adam Kwolek
2010-11-29 1:48 ` Neil Brown [this message]
2010-11-26 8:06 ` [PATCH 21/53] imsm: FIX: core dump during imsm metadata writing Adam Kwolek
2010-11-29 1:54 ` Neil Brown
2010-11-26 8:06 ` [PATCH 22/53] Send information to managemon about reshape request Adam Kwolek
2010-11-29 1:56 ` Neil Brown
2010-11-26 8:06 ` [PATCH 23/53] Process reshape initialization by managemon Adam Kwolek
2010-11-26 8:07 ` [PATCH 24/53] Add support to skip slot configuration Adam Kwolek
2010-11-26 8:07 ` [PATCH 25/53] imsm: Verify slots in meta against slot numbers set by md Adam Kwolek
2010-11-26 8:07 ` [PATCH 26/53] imsm: Cancel metadata changes on reshape start failure Adam Kwolek
2010-11-26 8:07 ` [PATCH 27/53] imsm: Do not accept messages sent by mdadm Adam Kwolek
2010-11-26 8:07 ` [PATCH 28/53] imsm: Do not indicate resync during reshape Adam Kwolek
2010-11-26 8:07 ` [PATCH 29/53] Add spares to raid0 array using takeover Adam Kwolek
2010-11-30 2:00 ` Neil Brown
2010-11-26 8:07 ` [PATCH 30/53] imsm: FIX: Fill sys_name field in getinfo_super() Adam Kwolek
2010-11-30 2:06 ` Neil Brown
2010-11-26 8:07 ` [PATCH 31/53] imsm: FIX: Fill delta_disks " Adam Kwolek
2010-11-30 2:07 ` Neil Brown
2010-11-26 8:08 ` [PATCH 32/53] imsm: FIX: spare list contains one device several times Adam Kwolek
2010-11-30 2:17 ` Neil Brown
2010-11-26 8:08 ` [PATCH 33/53] Prepare and free fdlist in functions Adam Kwolek
2010-11-30 2:28 ` Neil Brown
2010-11-26 8:08 ` [PATCH 34/53] Compute backup blocks in function Adam Kwolek
2010-11-30 2:32 ` Neil Brown
2010-11-26 8:08 ` [PATCH 35/53] Control reshape in mdadm Adam Kwolek
2010-11-30 2:37 ` Neil Brown
2010-11-26 8:08 ` [PATCH 36/53] Finalize reshape after adding disks to array Adam Kwolek
2010-11-26 8:08 ` [PATCH 37/53] mdadm: second_map enhancement for imsm_get_map() Adam Kwolek
2010-11-26 8:08 ` [PATCH 38/53] mdadm: read chunksize and layout from mdstat Adam Kwolek
2010-11-26 8:08 ` [PATCH 39/53] mdadm: Add IMSM migration record to intel_super Adam Kwolek
2010-11-26 8:09 ` [PATCH 40/53] mdadm: add backup methods to superswitch Adam Kwolek
2010-11-26 8:09 ` [PATCH 41/53] mdadm: support restore_stripes() from the given buffer Adam Kwolek
2010-11-26 8:09 ` [PATCH 42/53] mdadm: support backup operations for imsm Adam Kwolek
2010-11-26 8:09 ` [PATCH 43/53] mdadm: migration restart for external meta Adam Kwolek
2010-11-26 8:09 ` [PATCH 44/53] Add mdadm->mdmon sync_max command message Adam Kwolek
2010-11-26 8:09 ` [PATCH 45/53] mdadm: support grow operation for external meta Adam Kwolek
2010-11-26 8:09 ` [PATCH 46/53] FIX: Allow for reshape without backup file Adam Kwolek
2010-11-26 8:09 ` [PATCH 47/53] FIX: Honor !reshape state on wait_reshape() entry Adam Kwolek
2010-11-26 8:10 ` [PATCH 48/53] WORKAROUND: md reports idle state during reshape start Adam Kwolek
2010-11-26 8:10 ` [PATCH 49/53] imsm Fix: Core during rebuild on array details read Adam Kwolek
2010-11-26 8:10 ` [PATCH 50/53] Change manage_reshape() placement Adam Kwolek
2010-11-26 8:10 ` [PATCH 51/53] Migration: raid5->raid0 Adam Kwolek
2010-11-26 8:10 ` [PATCH 52/53] Migration raid0->raid5 Adam Kwolek
2010-11-26 8:10 ` [PATCH 53/53] Migration: Chunk size migration Adam Kwolek
2010-11-29 3:32 ` [PATCH 00/53] External Metadata Reshape Neil Brown
2010-11-29 4:07 ` Neil Brown
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20101129124814.174f2506@notabene.brown \
--to=neilb@suse.de \
--cc=adam.kwolek@intel.com \
--cc=dan.j.williams@intel.com \
--cc=ed.ciechanowski@intel.com \
--cc=linux-raid@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).