static int default_layout(struct supertype *st, int level, int verbose) { int layout = UnSet; if (st && st->ss->default_geometry) st->ss->default_geometry(st, &level, &layout, NULL); if (layout == UnSet) switch(level) { default: /* no layout */ layout = 0; break; case 10: layout = 0x102; /* near=2, far=1 */ if (verbose > 0) pr_err("layout defaults to n2\n"); break; case 5: case 6: layout = map_name(r5layout, "default"); if (verbose > 0) pr_err("layout defaults to %s\n", map_num(r5layout, layout)); break; case LEVEL_FAULTY: layout = map_name(faultylayout, "default"); if (verbose > 0) pr_err("layout defaults to %s\n", map_num(faultylayout, layout)); break; } return layout; }
int Build(char *mddev, struct mddev_dev *devlist, struct shape *s, struct context *c) { /* Build a linear or raid0 arrays without superblocks * We cannot really do any checks, we just do it. * For md_version < 0.90.0, we call REGISTER_DEV * with the device numbers, and then * START_MD giving the "geometry" * geometry is 0xpp00cc * where pp is personality: 1==linear, 2=raid0 * cc = chunk size factor: 0==4k, 1==8k etc. * * For md_version >= 0.90.0 we call * SET_ARRAY_INFO, ADD_NEW_DISK, RUN_ARRAY * */ int i; int vers; struct stat stb; int subdevs = 0, missing_disks = 0; struct mddev_dev *dv; int bitmap_fd; unsigned long long bitmapsize; int mdfd; char chosen_name[1024]; int uuid[4] = {0,0,0,0}; struct map_ent *map = NULL; /* scan all devices, make sure they really are block devices */ for (dv = devlist; dv; dv=dv->next) { subdevs++; if (strcmp("missing", dv->devname) == 0) { missing_disks++; continue; } if (stat(dv->devname, &stb)) { pr_err("Cannot find %s: %s\n", dv->devname, strerror(errno)); return 1; } if ((stb.st_mode & S_IFMT) != S_IFBLK) { pr_err("%s is not a block device.\n", dv->devname); return 1; } } if (s->raiddisks != subdevs) { pr_err("requested %d devices in array but listed %d\n", s->raiddisks, subdevs); return 1; } if (s->layout == UnSet) switch(s->level) { default: /* no layout */ s->layout = 0; break; case 10: s->layout = 0x102; /* near=2, far=1 */ if (c->verbose > 0) pr_err("layout defaults to n1\n"); break; case 5: case 6: s->layout = map_name(r5layout, "default"); if (c->verbose > 0) pr_err("layout defaults to %s\n", map_num(r5layout, s->layout)); break; case LEVEL_FAULTY: s->layout = map_name(faultylayout, "default"); if (c->verbose > 0) pr_err("layout defaults to %s\n", map_num(faultylayout, s->layout)); break; } /* We need to create the device. It can have no name. */ map_lock(&map); mdfd = create_mddev(mddev, NULL, c->autof, LOCAL, chosen_name); if (mdfd < 0) { map_unlock(&map); return 1; } mddev = chosen_name; map_update(&map, fd2devnm(mdfd), "none", uuid, chosen_name); map_unlock(&map); vers = md_get_version(mdfd); /* looks Ok, go for it */ if (vers >= 9000) { mdu_array_info_t array; array.level = s->level; if (s->size == MAX_SIZE) s->size = 0; array.size = s->size; array.nr_disks = s->raiddisks; array.raid_disks = s->raiddisks; array.md_minor = 0; if (fstat(mdfd, &stb)==0) array.md_minor = minor(stb.st_rdev); array.not_persistent = 1; array.state = 0; /* not clean, but no errors */ if (s->assume_clean) array.state |= 1; array.active_disks = s->raiddisks - missing_disks; array.working_disks = s->raiddisks - missing_disks; array.spare_disks = 0; array.failed_disks = missing_disks; if (s->chunk == 0 && (s->level==0 || s->level==LEVEL_LINEAR)) s->chunk = 64; array.chunk_size = s->chunk*1024; array.layout = s->layout; if (ioctl(mdfd, SET_ARRAY_INFO, &array)) { pr_err("SET_ARRAY_INFO failed for %s: %s\n", mddev, strerror(errno)); goto abort; } } else if (s->bitmap_file) { pr_err("bitmaps not supported with this kernel\n"); goto abort; } if (s->bitmap_file && strcmp(s->bitmap_file, "none") == 0) s->bitmap_file = NULL; if (s->bitmap_file && s->level <= 0) { pr_err("bitmaps not meaningful with level %s\n", map_num(pers, s->level)?:"given"); goto abort; }
int Query(char *dev) { /* Give a brief description of the device, * whether it is an md device and whether it has * a superblock */ int fd = open(dev, O_RDONLY); int vers; int ioctlerr; int superror; struct mdinfo info; mdu_array_info_t array; struct supertype *st = NULL; unsigned long long larray_size; struct stat stb; char *mddev; mdu_disk_info_t disc; char *activity; if (fd < 0){ pr_err("cannot open %s: %s\n", dev, strerror(errno)); return 1; } vers = md_get_version(fd); if (ioctl(fd, GET_ARRAY_INFO, &array)<0) ioctlerr = errno; else ioctlerr = 0; fstat(fd, &stb); if (vers>=9000 && !ioctlerr) { if (!get_dev_size(fd, NULL, &larray_size)) larray_size = 0; } if (vers < 0) printf("%s: is not an md array\n", dev); else if (vers < 9000) printf("%s: is an md device, but kernel cannot provide details\n", dev); else if (ioctlerr == ENODEV) printf("%s: is an md device which is not active\n", dev); else if (ioctlerr) printf("%s: is an md device, but gives \"%s\" when queried\n", dev, strerror(ioctlerr)); else { printf("%s: %s %s %d devices, %d spare%s. Use mdadm --detail for more detail.\n", dev, human_size_brief(larray_size), map_num(pers, array.level), array.raid_disks, array.spare_disks, array.spare_disks==1?"":"s"); } st = guess_super(fd); if (st) superror = st->ss->load_super(st, fd, dev); else superror = -1; close(fd); if (superror == 0) { /* array might be active... */ st->ss->getinfo_super(st, &info, NULL); if (st->ss == &super0) { mddev = get_md_name(info.array.md_minor); disc.number = info.disk.number; activity = "undetected"; if (mddev && (fd = open(mddev, O_RDONLY))>=0) { if (md_get_version(fd) >= 9000 && ioctl(fd, GET_ARRAY_INFO, &array)>= 0) { if (ioctl(fd, GET_DISK_INFO, &disc) >= 0 && makedev((unsigned)disc.major,(unsigned)disc.minor) == stb.st_rdev) activity = "active"; else activity = "mismatch"; } close(fd); } } else { activity = "unknown"; mddev = "array"; } printf("%s: device %d in %d device %s %s %s. Use mdadm --examine for more detail.\n", dev, info.disk.number, info.array.raid_disks, activity, map_num(pers, info.array.level), mddev); if (st->ss == &super0) put_md_name(mddev); } return 0; }
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; }
const char *bitmap_state(int state_num) { char *state = map_num(bitmap_states, state_num); return state ? state : "Unknown"; }