int stat2devnum(struct stat *st) { char path[30]; char link[200]; char *cp; int n; if ((S_IFMT & st->st_mode) == S_IFBLK) { if (major(st->st_rdev) == MD_MAJOR) return minor(st->st_rdev); else if (major(st->st_rdev) == (unsigned)get_mdp_major()) return -1- (minor(st->st_rdev)>>MdpMinorShift); /* must be an extended-minor partition. Look at the * /sys/dev/block/%d:%d link which must look like * ../../block/mdXXX/mdXXXpYY */ sprintf(path, "/sys/dev/block/%d:%d", major(st->st_rdev), minor(st->st_rdev)); n = readlink(path, link, sizeof(link)-1); if (n <= 0) return NoMdDev; link[n] = 0; cp = strrchr(link, '/'); if (cp) *cp = 0; cp = strrchr(link, '/'); if (cp && strncmp(cp, "/md", 3) == 0) return devname2devnum(cp+1); } return NoMdDev; }
unsigned long long get_component_size(int fd) { /* Find out the component size of the array. * We cannot trust GET_ARRAY_INFO ioctl as it's * size field is only 32bits. * So look in /sys/block/mdXXX/md/component_size * * This returns in units of sectors. */ struct stat stb; char fname[MAX_SYSFS_PATH_LEN]; int n; if (fstat(fd, &stb)) return 0; if (major(stb.st_rdev) != (unsigned)get_mdp_major()) snprintf(fname, MAX_SYSFS_PATH_LEN, "/sys/block/md%d/md/component_size", (int)minor(stb.st_rdev)); else snprintf(fname, MAX_SYSFS_PATH_LEN, "/sys/block/md_d%d/md/component_size", (int)minor(stb.st_rdev)>>MdpMinorShift); fd = open(fname, O_RDONLY); if (fd < 0) return 0; n = read(fd, fname, sizeof(fname)); close(fd); if (n < 0 || n == sizeof(fname)) return 0; fname[n] = 0; return strtoull(fname, NULL, 10) * 2; }