diff options
Diffstat (limited to 'Grow.c')
-rw-r--r-- | Grow.c | 204 |
1 files changed, 115 insertions, 89 deletions
@@ -26,7 +26,6 @@ #include <sys/mman.h> #include <stddef.h> #include <stdint.h> -#include <signal.h> #include <sys/wait.h> #if ! defined(__BIG_ENDIAN) && ! defined(__LITTLE_ENDIAN) @@ -197,7 +196,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) info.disk.minor = minor(rdev); info.disk.raid_disk = d; info.disk.state = (1 << MD_DISK_SYNC) | (1 << MD_DISK_ACTIVE); - if (st->ss->update_super(st, &info, "linear-grow-new", newdev, + if (st->ss->update_super(st, &info, UOPT_SPEC_LINEAR_GROW_NEW, newdev, 0, 0, NULL) != 0) { pr_err("Preparing new metadata failed on %s\n", newdev); close(nfd); @@ -255,7 +254,7 @@ int Grow_Add_device(char *devname, int fd, char *newdev) info.array.active_disks = nd+1; info.array.working_disks = nd+1; - if (st->ss->update_super(st, &info, "linear-grow-update", dv, + if (st->ss->update_super(st, &info, UOPT_SPEC_LINEAR_GROW_UPDATE, dv, 0, 0, NULL) != 0) { pr_err("Updating metadata failed on %s\n", dv); close(fd2); @@ -430,9 +429,10 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) dv = map_dev(disk.major, disk.minor, 1); if (!dv) continue; - if (((disk.state & (1 << MD_DISK_WRITEMOSTLY)) == 0) && + if ((disk.state & (1 << MD_DISK_WRITEMOSTLY)) && (strcmp(s->bitmap_file, "clustered") == 0)) { pr_err("%s disks marked write-mostly are not supported with clustered bitmap\n",devname); + free(mdi); return 1; } fd2 = dev_open(dv, O_RDWR); @@ -454,8 +454,10 @@ int Grow_addbitmap(char *devname, int fd, struct context *c, struct shape *s) pr_err("failed to load super-block.\n"); } close(fd2); - if (rv) + if (rv) { + free(mdi); return 1; + } } if (offset_setable) { st->ss->getinfo_super(st, mdi, NULL); @@ -548,7 +550,7 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha if (s->consistency_policy != CONSISTENCY_POLICY_RESYNC && s->consistency_policy != CONSISTENCY_POLICY_PPL) { pr_err("Operation not supported for consistency policy %s\n", - map_num(consistency_policies, s->consistency_policy)); + map_num_s(consistency_policies, s->consistency_policy)); return 1; } @@ -579,14 +581,14 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha if (sra->consistency_policy == (unsigned)s->consistency_policy) { pr_err("Consistency policy is already %s\n", - map_num(consistency_policies, s->consistency_policy)); + map_num_s(consistency_policies, s->consistency_policy)); ret = 1; goto free_info; } else if (sra->consistency_policy != CONSISTENCY_POLICY_RESYNC && sra->consistency_policy != CONSISTENCY_POLICY_PPL) { pr_err("Current consistency policy is %s, cannot change to %s\n", - map_num(consistency_policies, sra->consistency_policy), - map_num(consistency_policies, s->consistency_policy)); + map_num_s(consistency_policies, sra->consistency_policy), + map_num_s(consistency_policies, s->consistency_policy)); ret = 1; goto free_info; } @@ -603,12 +605,12 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha } if (subarray) { - char *update; + enum update_opt update; if (s->consistency_policy == CONSISTENCY_POLICY_PPL) - update = "ppl"; + update = UOPT_PPL; else - update = "no-ppl"; + update = UOPT_NO_PPL; sprintf(container_dev, "/dev/%s", st->container_devnm); @@ -666,7 +668,7 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha goto free_info; } - ret = st->ss->update_super(st, sra, "ppl", + ret = st->ss->update_super(st, sra, UOPT_PPL, devname, c->verbose, 0, NULL); if (ret) { @@ -705,8 +707,8 @@ int Grow_consistency_policy(char *devname, int fd, struct context *c, struct sha } ret = sysfs_set_str(sra, NULL, "consistency_policy", - map_num(consistency_policies, - s->consistency_policy)); + map_num_s(consistency_policies, + s->consistency_policy)); if (ret) pr_err("Failed to change array consistency policy\n"); @@ -955,7 +957,7 @@ int start_reshape(struct mdinfo *sra, int already_running, err = sysfs_set_str(sra, NULL, "sync_action", "reshape"); if (err) - sleep(1); + sleep_for(1, 0, true); } while (err && errno == EBUSY && cnt-- > 0); } return err; @@ -1001,8 +1003,8 @@ int remove_disks_for_takeover(struct supertype *st, rv = 1; sysfs_free(arrays); if (rv) { - pr_err("Error. Cannot perform operation on /dev/%s\n", st->devnm); - pr_err("For this operation it MUST be single array in container\n"); + pr_err("Error. Cannot perform operation on %s- for this operation " + "it MUST be single array in container\n", st->devnm); return rv; } } @@ -1774,9 +1776,67 @@ static int reshape_container(char *container, char *devname, char *backup_file, int verbose, int forked, int restart, int freeze_reshape); +/** + * prepare_external_reshape() - prepares update on external metadata if supported. + * @devname: Device name. + * @subarray: Subarray. + * @st: Supertype. + * @container: Container. + * @cfd: Container file descriptor. + * + * Function checks that the requested reshape is supported on external metadata, + * and performs an initial check that the container holds the pre-requisite + * spare devices (mdmon owns final validation). + * + * Return: 0 on success, else 1 + */ +static int prepare_external_reshape(char *devname, char *subarray, + struct supertype *st, char *container, + const int cfd) +{ + struct mdinfo *cc = NULL; + struct mdinfo *content = NULL; + + if (st->ss->load_container(st, cfd, NULL)) { + pr_err("Cannot read superblock for %s\n", devname); + return 1; + } + + if (!st->ss->container_content) + return 1; + + cc = st->ss->container_content(st, subarray); + for (content = cc; content ; content = content->next) { + /* + * check if reshape is allowed based on metadata + * indications stored in content.array.status + */ + if (is_bit_set(&content->array.state, MD_SB_BLOCK_VOLUME) || + is_bit_set(&content->array.state, MD_SB_BLOCK_CONTAINER_RESHAPE)) { + pr_err("Cannot reshape arrays in container with unsupported metadata: %s(%s)\n", + devname, container); + goto error; + } + if (content->consistency_policy == CONSISTENCY_POLICY_PPL) { + pr_err("Operation not supported when ppl consistency policy is enabled\n"); + goto error; + } + if (content->consistency_policy == CONSISTENCY_POLICY_BITMAP) { + pr_err("Operation not supported when write-intent bitmap consistency policy is enabled\n"); + goto error; + } + } + sysfs_free(cc); + if (mdmon_running(container)) + st->update_tail = &st->updates; + return 0; +error: + sysfs_free(cc); + return 1; +} + int Grow_reshape(char *devname, int fd, struct mddev_dev *devlist, - unsigned long long data_offset, struct context *c, struct shape *s) { /* Make some changes in the shape of an array. @@ -1801,7 +1861,7 @@ int Grow_reshape(char *devname, int fd, struct supertype *st; char *subarray = NULL; - int frozen; + int frozen = 0; int changed = 0; char *container = NULL; int cfd = -1; @@ -1810,7 +1870,7 @@ int Grow_reshape(char *devname, int fd, int added_disks; struct mdinfo info; - struct mdinfo *sra; + struct mdinfo *sra = NULL; if (md_get_array_info(fd, &array) < 0) { pr_err("%s is not an active md array - aborting\n", @@ -1822,7 +1882,7 @@ int Grow_reshape(char *devname, int fd, return 1; } - if (data_offset != INVALID_SECTORS && array.level != 10 && + if (s->data_offset != INVALID_SECTORS && array.level != 10 && (array.level < 4 || array.level > 6)) { pr_err("--grow --data-offset not yet supported\n"); return 1; @@ -1867,13 +1927,7 @@ int Grow_reshape(char *devname, int fd, } } - /* in the external case we need to check that the requested reshape is - * supported, and perform an initial check that the container holds the - * pre-requisite spare devices (mdmon owns final validation) - */ if (st->ss->external) { - int retval; - if (subarray) { container = st->container_devnm; cfd = open_dev_excl(st->container_devnm); @@ -1889,58 +1943,20 @@ int Grow_reshape(char *devname, int fd, return 1; } - retval = st->ss->load_container(st, cfd, NULL); - - if (retval) { - pr_err("Cannot read superblock for %s\n", devname); + rv = prepare_external_reshape(devname, subarray, st, + container, cfd); + if (rv > 0) { free(subarray); - return 1; + close(cfd); + goto release; } - /* check if operation is supported for metadata handler */ - if (st->ss->container_content) { - struct mdinfo *cc = NULL; - struct mdinfo *content = NULL; - - cc = st->ss->container_content(st, subarray); - for (content = cc; content ; content = content->next) { - int allow_reshape = 1; - - /* check if reshape is allowed based on metadata - * indications stored in content.array.status - */ - if (content->array.state & - (1 << MD_SB_BLOCK_VOLUME)) - allow_reshape = 0; - if (content->array.state & - (1 << MD_SB_BLOCK_CONTAINER_RESHAPE)) - allow_reshape = 0; - if (!allow_reshape) { - pr_err("cannot reshape arrays in container with unsupported metadata: %s(%s)\n", - devname, container); - sysfs_free(cc); - free(subarray); - return 1; - } - if (content->consistency_policy == - CONSISTENCY_POLICY_PPL) { - pr_err("Operation not supported when ppl consistency policy is enabled\n"); - sysfs_free(cc); - free(subarray); - return 1; - } - if (content->consistency_policy == - CONSISTENCY_POLICY_BITMAP) { - pr_err("Operation not supported when write-intent bitmap is enabled\n"); - sysfs_free(cc); - free(subarray); - return 1; - } - } - sysfs_free(cc); + if (s->raiddisks && subarray) { + pr_err("--raid-devices operation can be performed on a container only\n"); + close(cfd); + free(subarray); + return 1; } - if (mdmon_running(container)) - st->update_tail = &st->updates; } added_disks = 0; @@ -1998,6 +2014,12 @@ int Grow_reshape(char *devname, int fd, goto release; } + if (array.level == 0) { + pr_err("Component size change is not supported for RAID0\n"); + rv = 1; + goto release; + } + if (reshape_super(st, s->size, UnSet, UnSet, 0, 0, UnSet, NULL, devname, APPLY_METADATA_CHANGES, c->verbose > 0)) { @@ -2156,7 +2178,7 @@ size_change_error: devname, s->size); } changed = 1; - } else if (array.level != LEVEL_CONTAINER) { + } else if (!is_container(array.level)) { s->size = get_component_size(fd)/2; if (s->size == 0) s->size = array.size; @@ -2166,7 +2188,7 @@ size_change_error: if ((s->level == UnSet || s->level == array.level) && (s->layout_str == NULL) && (s->chunk == 0 || s->chunk == array.chunk_size) && - data_offset == INVALID_SECTORS && + s->data_offset == INVALID_SECTORS && (s->raiddisks == 0 || s->raiddisks == array.raid_disks)) { /* Nothing more to do */ if (!changed && c->verbose >= 0) @@ -2212,7 +2234,7 @@ size_change_error: info.component_size = s->size*2; info.new_level = s->level; info.new_chunk = s->chunk * 1024; - if (info.array.level == LEVEL_CONTAINER) { + if (is_container(info.array.level)) { info.delta_disks = UnSet; info.array.raid_disks = s->raiddisks; } else if (s->raiddisks) @@ -2236,7 +2258,7 @@ size_change_error: info.new_layout = UnSet; if (info.array.level == 6 && info.new_level == UnSet) { char l[40], *h; - strcpy(l, map_num(r6layout, info.array.layout)); + strcpy(l, map_num_s(r6layout, info.array.layout)); h = strrchr(l, '-'); if (h && strcmp(h, "-6") == 0) { *h = 0; @@ -2261,7 +2283,7 @@ size_change_error: info.new_layout = info.array.layout; else if (info.array.level == 5 && info.new_level == 6) { char l[40]; - strcpy(l, map_num(r5layout, info.array.layout)); + strcpy(l, map_num_s(r5layout, info.array.layout)); strcat(l, "-6"); info.new_layout = map_name(r6layout, l); } else { @@ -2325,7 +2347,7 @@ size_change_error: printf("layout for %s set to %d\n", devname, array.layout); } - } else if (array.level == LEVEL_CONTAINER) { + } else if (is_container(array.level)) { /* This change is to be applied to every array in the * container. This is only needed when the metadata imposes * restraints of the various arrays in the container. @@ -2366,7 +2388,7 @@ size_change_error: } sync_metadata(st); rv = reshape_array(container, fd, devname, st, &info, c->force, - devlist, data_offset, c->backup_file, + devlist, s->data_offset, c->backup_file, c->verbose, 0, 0, 0); frozen = 0; } @@ -2931,7 +2953,7 @@ static int impose_level(int fd, int level, char *devname, int verbose) } md_get_array_info(fd, &array); - if (level == 0 && (array.level >= 4 && array.level <= 6)) { + if (level == 0 && is_level456(array.level)) { /* To convert to RAID0 we need to fail and * remove any non-data devices. */ int found = 0; @@ -3221,7 +3243,7 @@ static int reshape_array(char *container, int fd, char *devname, * level and frozen, we can safely add them. */ if (devlist) { - if (Manage_subdevs(devname, fd, devlist, verbose, 0, NULL, 0)) + if (Manage_subdevs(devname, fd, devlist, verbose, 0, UOPT_UNDEFINED, 0)) goto release; } @@ -3501,7 +3523,6 @@ started: return 0; } - close(fd); /* Now we just need to kick off the reshape and watch, while * handling backups of the data... * This is all done by a forked background process. @@ -3522,6 +3543,9 @@ started: break; } + /* Close unused file descriptor in the forked process */ + close_fd(&fd); + /* If another array on the same devices is busy, the * reshape will wait for them. This would mean that * the first section that we suspend will stay suspended @@ -3560,7 +3584,8 @@ started: fd = -1; mlockall(MCL_FUTURE); - signal(SIGTERM, catch_term); + if (signal_s(SIGTERM, catch_term) == SIG_ERR) + goto release; if (st->ss->external) { /* metadata handler takes it from here */ @@ -4925,7 +4950,8 @@ int Grow_restart(struct supertype *st, struct mdinfo *info, int *fdlist, continue; st->ss->getinfo_super(st, &dinfo, NULL); dinfo.reshape_progress = info->reshape_progress; - st->ss->update_super(st, &dinfo, "_reshape_progress", + st->ss->update_super(st, &dinfo, + UOPT_SPEC__RESHAPE_PROGRESS, NULL,0, 0, NULL); st->ss->store_super(st, fdlist[j]); st->ss->free_super(st); @@ -5042,7 +5068,7 @@ int Grow_continue_command(char *devname, int fd, } st->ss->getinfo_super(st, content, NULL); if (!content->reshape_active) - sleep(3); + sleep_for(3, 0, true); else break; } while (cnt-- > 0); |