X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=sysfs.c;h=13558c5fd0516e1c4a19f355a77f5df62b57e924;hb=ca36d7073509dd23aef8a29bbcaa3892ec441c1b;hp=6bc28651fd4f8f81c582eb4d5e98b4de80cdc90a;hpb=e6fc80a8958d4dc73d0f69784e0b79687c154759;p=thirdparty%2Fmdadm.git diff --git a/sysfs.c b/sysfs.c index 6bc28651..13558c5f 100644 --- a/sysfs.c +++ b/sysfs.c @@ -88,7 +88,6 @@ void sysfs_init(struct mdinfo *mdi, int fd, char *devnm) strcpy(mdi->sys_name, devnm); } - struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options) { char fname[PATH_MAX]; @@ -96,7 +95,7 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options) char *base; char *dbase; struct mdinfo *sra; - struct mdinfo *dev; + struct mdinfo *dev, **devp; DIR *dir = NULL; struct dirent *de; @@ -235,6 +234,8 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options) goto abort; sra->array.spare_disks = 0; + devp = &sra->devs; + sra->devs = NULL; while ((de = readdir(dir)) != NULL) { char *ep; if (de->d_ino == 0 || @@ -266,7 +267,7 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options) free(dev); goto abort; } - + } strcpy(dev->sys_name, de->d_name); dev->disk.raid_disk = strtoul(buf, &ep, 10); @@ -292,8 +293,9 @@ struct mdinfo *sysfs_read(int fd, char *devnm, unsigned long options) } /* finally add this disk to the array */ - dev->next = sra->devs; - sra->devs = dev; + *devp = dev; + devp = & dev->next; + dev->next = NULL; if (options & GET_OFFSET) { strcpy(dbase, "offset"); @@ -453,7 +455,7 @@ int sysfs_uevent(struct mdinfo *sra, char *event) return -1; } return 0; -} +} int sysfs_attribute_available(struct mdinfo *sra, struct mdinfo *dev, char *name) { @@ -511,6 +513,49 @@ int sysfs_get_ll(struct mdinfo *sra, struct mdinfo *dev, return n; } +int sysfs_fd_get_two(int fd, unsigned long long *v1, unsigned long long *v2) +{ + /* two numbers in this sysfs file, either + * NNN (NNN) + * or + * NNN / NNN + */ + char buf[80]; + int n; + char *ep, *ep2; + + lseek(fd, 0, 0); + n = read(fd, buf, sizeof(buf)); + if (n <= 0) + return -2; + buf[n] = 0; + *v1 = strtoull(buf, &ep, 0); + if (ep == buf || (*ep != 0 && *ep != '\n' && *ep != ' ')) + return -1; + while (*ep == ' ' || *ep == '/' || *ep == '(') + ep++; + *v2 = strtoull(ep, &ep2, 0); + if (ep2 == ep || (*ep2 != 0 && *ep2 != '\n' && *ep2 != ' ' && *ep2 != ')')) { + *v2 = *v1; + return 1; + } + return 2; +} + +int sysfs_get_two(struct mdinfo *sra, struct mdinfo *dev, + char *name, unsigned long long *v1, unsigned long long *v2) +{ + int n; + int fd; + + fd = sysfs_get_fd(sra, dev, name); + if (fd < 0) + return -1; + n = sysfs_fd_get_two(fd, v1, v2); + close(fd); + return n; +} + int sysfs_fd_get_str(int fd, char *val, int size) { int n; @@ -768,7 +813,6 @@ int sysfs_disk_to_scsi_id(int fd, __u32 *id) return 0; } - int sysfs_unique_holder(char *devnm, long rdev) { /* Check that devnm is a holder of rdev, @@ -837,9 +881,41 @@ int sysfs_freeze_array(struct mdinfo *sra) if (strcmp(buf, "frozen\n") == 0) /* Already frozen */ return 0; - if (strcmp(buf, "idle\n") != 0) + if (strcmp(buf, "idle\n") != 0 && strcmp(buf, "recover\n") != 0) return -1; if (sysfs_set_str(sra, NULL, "sync_action", "frozen") < 0) return 0; return 1; } + +int sysfs_wait(int fd, int *msec) +{ + /* Wait up to '*msec' for fd to have an exception condition. + * if msec == NULL, wait indefinitely. + */ + fd_set fds; + int n; + FD_ZERO(&fds); + FD_SET(fd, &fds); + if (msec == NULL) + n = select(fd+1, NULL, NULL, &fds, NULL); + else if (*msec < 0) + n = 0; + else { + struct timeval start, end, tv; + gettimeofday(&start, NULL); + if (*msec < 1000) { + tv.tv_sec = 0; + tv.tv_usec = (*msec)*1000; + } else { + tv.tv_sec = (*msec)/1000; + tv.tv_usec = 0; + } + n = select(fd+1, NULL, NULL, &fds, &tv); + gettimeofday(&end, NULL); + end.tv_sec -= start.tv_sec; + *msec -= (end.tv_sec * 1000 + end.tv_usec/1000 + - start.tv_usec/1000) + 1; + } + return n; +}