X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=sysfs.c;h=0ea17eb9d00b0020192930bae809eab6ad830c15;hb=836759d561453e7777a233122ec6acba8663a180;hp=5f0c212741cae8792b4689f4a13f149de90d8c57;hpb=f1665f720035ab37913a68838d3310188f3a4b08;p=thirdparty%2Fmdadm.git diff --git a/sysfs.c b/sysfs.c index 5f0c2127..0ea17eb9 100644 --- a/sysfs.c +++ b/sysfs.c @@ -37,7 +37,7 @@ int load_sys(char *path, char *buf) if (n <0 || n >= 1024) return -1; buf[n] = 0; - if (buf[n-1] == '\n') + if (n && buf[n-1] == '\n') buf[n-1] = 0; return 0; } @@ -59,15 +59,9 @@ void sysfs_free(struct mdinfo *sra) int sysfs_open(int devnum, char *devname, char *attr) { char fname[50]; - char sys_name[16]; int fd; - if (devnum >= 0) - sprintf(sys_name, "md%d", devnum); - else - sprintf(sys_name, "md_d%d", - -1-devnum); - sprintf(fname, "/sys/block/%s/md/", sys_name); + sprintf(fname, "/sys/block/%s/md/", devnum2devname(devnum)); if (devname) { strcat(fname, devname); strcat(fname, "/"); @@ -134,10 +128,12 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options) sra->array.major_version = -1; sra->array.minor_version = -2; strcpy(sra->text_version, buf+9); - } else + } else { sscanf(buf, "%d.%d", &sra->array.major_version, &sra->array.minor_version); + strcpy(sra->text_version, buf); + } } if (options & GET_LEVEL) { strcpy(base, "level"); @@ -232,7 +228,7 @@ struct mdinfo *sysfs_read(int fd, int devnum, unsigned long options) strcpy(dbase, "size"); if (load_sys(fname, buf)) goto abort; - dev->component_size = strtoull(buf, NULL, 0); + dev->component_size = strtoull(buf, NULL, 0) * 2; } if (options & GET_STATE) { dev->disk.state = 0; @@ -357,7 +353,7 @@ int sysfs_set_array(struct mdinfo *sra, rv |= sysfs_set_num(sra, NULL, "raid_disks", info->array.raid_disks); rv |= sysfs_set_num(sra, NULL, "chunk_size", info->array.chunk_size); rv |= sysfs_set_num(sra, NULL, "layout", info->array.layout); - rv |= sysfs_set_num(sra, NULL, "component_size", info->component_size); + rv |= sysfs_set_num(sra, NULL, "component_size", info->component_size/2); rv |= sysfs_set_num(sra, NULL, "resync_start", info->resync_start); sra->array = info->array; return rv; @@ -378,14 +374,16 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd) memset(nm, 0, sizeof(nm)); sprintf(dv, "/sys/dev/block/%d:%d", sd->disk.major, sd->disk.minor); - if (readlink(dv, nm, sizeof(nm)) < 0) + rv = readlink(dv, nm, sizeof(nm)); + 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); - rv |= sysfs_set_num(sra, sd, "offset", sd->data_offset); + 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) { rv |= sysfs_set_num(sra, sd, "slot", sd->disk.raid_disk); @@ -400,6 +398,7 @@ int sysfs_add_disk(struct mdinfo *sra, struct mdinfo *sd) return rv; } +#if 0 int sysfs_disk_to_sg(int fd) { /* from an open block device, try find and open its corresponding @@ -463,6 +462,7 @@ int sysfs_disk_to_sg(int fd) return -1; } +#endif int sysfs_disk_to_scsi_id(int fd, __u32 *id) { @@ -513,3 +513,66 @@ int sysfs_disk_to_scsi_id(int fd, __u32 *id) return 0; } + + +int sysfs_unique_holder(int devnum, long rdev) +{ + /* Check that devnum is a holder of rdev, + * and is the only holder. + * we should be locked against races by + * an O_EXCL on devnum + */ + DIR *dir; + struct dirent *de; + char dirname[100]; + char l; + int found = 0; + sprintf(dirname, "/sys/dev/block/%d:%d/holders", + major(rdev), minor(rdev)); + dir = opendir(dirname); + errno = ENOENT; + if (!dir) + return 0; + l = strlen(dirname); + while ((de = readdir(dir)) != NULL) { + char buf[10]; + int n; + int mj, mn; + char c; + int fd; + + if (de->d_ino == 0) + continue; + if (de->d_name[0] == '.') + continue; + strcpy(dirname+l, "/"); + strcat(dirname+l, de->d_name); + strcat(dirname+l, "/dev"); + fd = open(dirname, O_RDONLY); + if (fd < 0) { + errno = ENOENT; + break; + } + n = read(fd, buf, sizeof(buf)-1); + close(fd); + buf[n] = 0; + if (sscanf(buf, "%d:%d%c", &mj, &mn, &c) != 3 || + c != '\n') { + errno = ENOENT; + break; + } + if (mj != MD_MAJOR) + mn = -1-(mn>>6); + + if (devnum != mn) { + errno = EEXIST; + break; + } + found = 1; + } + closedir(dir); + if (de) + return 0; + else + return found; +}