return -1;
n = write(fd, event, strlen(event));
close(fd);
+ if (n != (int)strlen(event)) {
+ dprintf(Name ": failed to write '%s' to '%s' (%s)\n",
+ event, fname, strerror(errno));
+ return -1;
+ }
return 0;
}
lseek(fd, 0, 0);
n = read(fd, buf, sizeof(buf));
if (n <= 0)
- return -1;
+ return -2;
buf[n] = 0;
*val = strtoull(buf, &ep, 0);
if (ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' '))
{
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) {
return 0; /* FIXME */
rv |= sysfs_set_str(info, NULL, "level",
map_num(pers, info->array.level));
- rv |= sysfs_set_num(info, NULL, "raid_disks", info->array.raid_disks);
+ 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);
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 + info->delta_disks);
+ info->array.raid_disks);
/* We don't set 'new_level' here. That can only happen
* once the reshape completes.
*/
memset(nm, 0, sizeof(nm));
sprintf(dv, "/sys/dev/block/%d:%d", sd->disk.major, sd->disk.minor);
- rv = readlink(dv, nm, sizeof(nm));
+ rv = readlink(dv, nm, sizeof(nm)-1);
if (rv <= 0)
return -1;
nm[rv] = '\0';
/* from an open block device, try to retrieve it scsi_id */
struct stat st;
char path[256];
- char *c1, *c2;
DIR *dir;
struct dirent *de;
+ int host, bus, target, lun;
if (fstat(fd, &st))
return 1;
if (!dir)
return 1;
- de = readdir(dir);
- while (de) {
- if (strchr(de->d_name, ':'))
+ for (de = readdir(dir); de; de = readdir(dir)) {
+ int count;
+
+ if (de->d_type != DT_DIR)
+ continue;
+
+ count = sscanf(de->d_name, "%d:%d:%d:%d", &host, &bus, &target, &lun);
+ if (count == 4)
break;
- de = readdir(dir);
}
closedir(dir);
if (!de)
return 1;
- c1 = de->d_name;
- c2 = strchr(c1, ':');
- *c2 = '\0';
- *id = strtol(c1, NULL, 10) << 24; /* host */
- c1 = c2 + 1;
- c2 = strchr(c1, ':');
- *c2 = '\0';
- *id |= strtol(c1, NULL, 10) << 16; /* bus */
- c1 = c2 + 1;
- c2 = strchr(c1, ':');
- *c2 = '\0';
- *id |= strtol(c1, NULL, 10) << 8; /* target */
- c1 = c2 + 1;
- *id |= strtol(c1, NULL, 10); /* lun */
-
+ *id = (host << 24) | (bus << 16) | (target << 8) | (lun << 0);
return 0;
}
}
n = read(fd, buf, sizeof(buf)-1);
close(fd);
+ if (n < 0)
+ continue;
buf[n] = 0;
if (sscanf(buf, "%d:%d%c", &mj, &mn, &c) != 3 ||
c != '\n') {
return 0;
return 1;
}
-
-#ifndef MDASSEMBLE
-
-static char *clean_states[] = {
- "clear", "inactive", "readonly", "read-auto", "clean", NULL };
-
-int WaitClean(char *dev, int sock, int verbose)
-{
- int fd;
- struct mdinfo *mdi;
- int rv = 1;
- int devnum;
-
- fd = open(dev, O_RDONLY);
- if (fd < 0) {
- if (verbose)
- fprintf(stderr, Name ": Couldn't open %s: %s\n", dev, strerror(errno));
- return 1;
- }
-
- devnum = fd2devnum(fd);
- mdi = sysfs_read(fd, devnum, GET_VERSION|GET_LEVEL|GET_SAFEMODE);
- if (!mdi) {
- if (verbose)
- fprintf(stderr, Name ": Failed to read sysfs attributes for "
- "%s\n", dev);
- close(fd);
- return 0;
- }
-
- switch(mdi->array.level) {
- case LEVEL_LINEAR:
- case LEVEL_MULTIPATH:
- case 0:
- /* safemode delay is irrelevant for these levels */
- rv = 0;
-
- }
-
- /* for internal metadata the kernel handles the final clean
- * transition, containers can never be dirty
- */
- if (!is_subarray(mdi->text_version))
- rv = 0;
-
- /* safemode disabled ? */
- if (mdi->safe_mode_delay == 0)
- rv = 0;
-
- if (rv) {
- int state_fd = sysfs_open(fd2devnum(fd), NULL, "array_state");
- char buf[20];
- fd_set fds;
- struct timeval tm;
-
- /* minimize the safe_mode_delay and prepare to wait up to 5s
- * for writes to quiesce
- */
- sysfs_set_safemode(mdi, 1);
- tm.tv_sec = 5;
- tm.tv_usec = 0;
-
- FD_ZERO(&fds);
-
- /* wait for array_state to be clean */
- while (1) {
- rv = read(state_fd, buf, sizeof(buf));
- if (rv < 0)
- break;
- if (sysfs_match_word(buf, clean_states) <= 4)
- break;
- FD_SET(state_fd, &fds);
- rv = select(state_fd + 1, NULL, NULL, &fds, &tm);
- if (rv < 0 && errno != EINTR)
- break;
- lseek(state_fd, 0, SEEK_SET);
- }
- if (rv < 0)
- rv = 1;
- else if (fping_monitor(sock) == 0 ||
- ping_monitor(mdi->text_version) == 0) {
- /* we need to ping to close the window between array
- * state transitioning to clean and the metadata being
- * marked clean
- */
- rv = 0;
- } else
- rv = 1;
- if (rv && verbose)
- fprintf(stderr, Name ": Error waiting for %s to be clean\n",
- dev);
-
- /* restore the original safe_mode_delay */
- sysfs_set_safemode(mdi, mdi->safe_mode_delay);
- close(state_fd);
- }
-
- sysfs_free(mdi);
- close(fd);
-
- return rv;
-}
-#endif /* MDASSEMBLE */