int unlock_all_stripes(struct mdinfo *info, sighandler_t *sig) { int rv; rv = sysfs_set_num(info, NULL, "suspend_lo", 0x7FFFFFFFFFFFFFFFULL); rv |= sysfs_set_num(info, NULL, "suspend_hi", 0); rv |= sysfs_set_num(info, NULL, "suspend_lo", 0); signal(SIGQUIT, sig[2]); signal(SIGINT, sig[1]); signal(SIGTERM, sig[0]); if(munlockall() != 0) return 3; return rv * 256; }
int lock_stripe(struct mdinfo *info, unsigned long long start, int chunk_size, int data_disks, sighandler_t *sig) { int rv; if(mlockall(MCL_CURRENT | MCL_FUTURE) != 0) { return 2; } sig[0] = signal(SIGTERM, SIG_IGN); sig[1] = signal(SIGINT, SIG_IGN); sig[2] = signal(SIGQUIT, SIG_IGN); rv = sysfs_set_num(info, NULL, "suspend_lo", start * chunk_size * data_disks); rv |= sysfs_set_num(info, NULL, "suspend_hi", (start + 1) * chunk_size * data_disks); return rv * 256; }
int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume) { char dv[PATH_MAX]; char nm[PATH_MAX]; char *dname; int rv; sprintf(dv, "%d:%d", sd->disk.major, sd->disk.minor); rv = sysfs_set_str(sra, NULL, "new_dev", dv); if (rv) return rv; memset(nm, 0, sizeof(nm)); sprintf(dv, "/sys/dev/block/%d:%d", sd->disk.major, sd->disk.minor); rv = readlink(dv, nm, sizeof(nm)-1); if (rv <= 0) return -1; nm[rv] = '\0'; dname = strrchr(nm, '/'); if (dname) dname++; strcpy(sd->sys_name, "dev-"); strcpy(sd->sys_name+4, dname); /* test write to see if 'recovery_start' is available */ if (resume && sd->recovery_start < MaxSector && sysfs_set_num(sra, sd, "recovery_start", 0)) { sysfs_set_str(sra, sd, "state", "remove"); return -1; } rv = sysfs_set_num(sra, sd, "offset", sd->data_offset); rv |= sysfs_set_num(sra, sd, "size", (sd->component_size+1) / 2); if (sra->array.level != LEVEL_CONTAINER) { if (sd->recovery_start == MaxSector) /* This can correctly fail if array isn't started, * yet, so just ignore status for now. */ sysfs_set_str(sra, sd, "state", "insync"); if (sd->disk.raid_disk >= 0) rv |= sysfs_set_num(sra, sd, "slot", sd->disk.raid_disk); if (resume) sysfs_set_num(sra, sd, "recovery_start", sd->recovery_start); } return rv; }
int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd, int resume) { char dv[PATH_MAX]; char nm[PATH_MAX]; char *dname; int rv; int i; sprintf(dv, "%d:%d", sd->disk.major, sd->disk.minor); rv = sysfs_set_str(sra, NULL, "new_dev", dv); if (rv) return rv; memset(nm, 0, sizeof(nm)); dname = devid2kname(makedev(sd->disk.major, sd->disk.minor)); strcpy(sd->sys_name, "dev-"); strcpy(sd->sys_name+4, dname); /* test write to see if 'recovery_start' is available */ if (resume && sd->recovery_start < MaxSector && sysfs_set_num(sra, sd, "recovery_start", 0)) { sysfs_set_str(sra, sd, "state", "remove"); return -1; } rv = sysfs_set_num(sra, sd, "offset", sd->data_offset); rv |= sysfs_set_num(sra, sd, "size", (sd->component_size+1) / 2); if (sra->array.level != LEVEL_CONTAINER) { if (sd->recovery_start == MaxSector) /* This can correctly fail if array isn't started, * yet, so just ignore status for now. */ sysfs_set_str(sra, sd, "state", "insync"); if (sd->disk.raid_disk >= 0) rv |= sysfs_set_num(sra, sd, "slot", sd->disk.raid_disk); if (resume) sysfs_set_num(sra, sd, "recovery_start", sd->recovery_start); } if (sd->bb.supported) { if (sysfs_set_str(sra, sd, "state", "external_bbl")) { /* * backward compatibility - if kernel doesn't support * bad blocks for external metadata, let it continue * as long as there are none known so far */ if (sd->bb.count) { pr_err("The kernel has no support for bad blocks in external metadata\n"); return -1; } } for (i = 0; i < sd->bb.count; i++) { char s[30]; const struct md_bb_entry *entry = &sd->bb.entries[i]; snprintf(s, sizeof(s) - 1, "%llu %d\n", entry->sector, entry->length); rv |= sysfs_set_str(sra, sd, "bad_blocks", s); } } return rv; }
int sysfs_set_array(struct mdinfo *info, int vers) { int rv = 0; char ver[100]; int raid_disks = info->array.raid_disks; ver[0] = 0; if (info->array.major_version == -1 && info->array.minor_version == -2) { char buf[1024]; strcat(strcpy(ver, "external:"), info->text_version); /* meta version might already be set if we are setting * new geometry for a reshape. In that case we don't * want to over-write the 'readonly' flag that is * stored in the metadata version. So read the current * version first, and preserve the flag */ if (sysfs_get_str(info, NULL, "metadata_version", buf, 1024) > 0) if (strlen(buf) >= 9 && buf[9] == '-') ver[9] = '-'; if ((vers % 100) < 2 || sysfs_set_str(info, NULL, "metadata_version", ver) < 0) { pr_err("This kernel does not support external metadata.\n"); return 1; } } if (info->array.level < 0) return 0; /* FIXME */ rv |= sysfs_set_str(info, NULL, "level", map_num(pers, info->array.level)); if (info->reshape_active && info->delta_disks != UnSet) raid_disks -= info->delta_disks; rv |= sysfs_set_num(info, NULL, "raid_disks", raid_disks); rv |= sysfs_set_num(info, NULL, "chunk_size", info->array.chunk_size); rv |= sysfs_set_num(info, NULL, "layout", info->array.layout); rv |= sysfs_set_num(info, NULL, "component_size", info->component_size/2); if (info->custom_array_size) { int rc; rc = sysfs_set_num(info, NULL, "array_size", info->custom_array_size/2); if (rc && errno == ENOENT) { pr_err("This kernel does not have the md/array_size attribute, the array may be larger than expected\n"); rc = 0; } rv |= rc; } if (info->array.level > 0) rv |= sysfs_set_num(info, NULL, "resync_start", info->resync_start); if (info->reshape_active) { rv |= sysfs_set_num(info, NULL, "reshape_position", info->reshape_progress); rv |= sysfs_set_num(info, NULL, "chunk_size", info->new_chunk); rv |= sysfs_set_num(info, NULL, "layout", info->new_layout); rv |= sysfs_set_num(info, NULL, "raid_disks", info->array.raid_disks); /* We don't set 'new_level' here. That can only happen * once the reshape completes. */ } return rv; }