📄 lsraid.c
字号:
if (ctxt->action == '\0') ctxt->action = LSR_ARRAY;} /* parse_options() */static int read_md_super(LSRContext *ctxt, LSRDisk *disk){ int fd, rc, tot; mdp_super_t *sb; struct stat stat_buf; unsigned long dsize; if (!disk) return(-EINVAL); sb = &disk->sb; sb->md_magic = 0; if (!disk->name) return(-EINVAL); fd = open(disk->name, O_RDONLY); if (fd < 0) { rc = -errno; if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Unable to open device \"%s\": %s\n", disk->name, strerror(errno)); goto out; } rc = fstat(fd, &stat_buf); if (rc) { rc = -errno; if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Unable to query device \"%s\": %s\n", disk->name, strerror(errno)); goto out_close; } if (!S_ISBLK(stat_buf.st_mode)) { rc = -EINVAL; if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: \"%s\" is not a block device\n", disk->name); goto out_close; } disk->major = major(stat_buf.st_rdev); disk->minor = minor(stat_buf.st_rdev); rc = ioctl(fd, BLKGETSIZE, &dsize); if (rc) { rc = -errno; if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Unable to query size of \"%s\": %s\n", disk->name, strerror(errno)); goto out_close; } /* Shift to 1k blocks because MD_NEW_SIZE_BLOCKS wants it */ dsize >>= 1; if (raidseek(fd, MD_NEW_SIZE_BLOCKS(dsize)) == (long long)-1) { rc = -errno; if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Unable to find superblock for \"%s\": %s\n", disk->name, strerror(errno)); goto out_close; } tot = 0; while (tot < MD_SB_BYTES) { rc = read(fd, sb + tot, MD_SB_BYTES - tot); if (rc == 0) break; else if (rc < 0) { if ((errno == EAGAIN) || (errno == EINTR)) continue; else break; } else tot += rc; } if (tot < MD_SB_BYTES) { if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Unable to read raid superblock from device \"%s\": %s\n", disk->name, rc ? strerror(errno) : "Unexpected EOF"); rc = -EAGAIN; } else rc = 0; if (sb->md_magic != MD_SB_MAGIC) { if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Device \"%s\" does not have a valid raid superblock\n", disk->name); rc = -EINVAL; goto out_close; } if ((sb->major_version < 0) || (sb->minor_version < 90)) { if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Device \"%s\" is too old (raid version %d.%d)\n", disk->name, sb->major_version, sb->minor_version); rc = -EINVAL; }out_close: close(fd);out: if (rc) sb->md_magic = 0; return(rc);} /* read_md_super() */static int query_array(LSRContext *ctxt, LSRArray *array){ int fd, rc, i, numdisks; mdu_disk_info_t dinfo; struct stat stat_buf; LSRDisk *disk; rc = -EINVAL; if (!array || !array->name) goto out; fd = open(array->name, O_RDONLY); if (fd < 0) { if ((errno == ENXIO) || (errno == ENODEV)) rc = 0; else { rc = -errno; if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Unable to query md device \"%s\": %s\n", array->name, strerror(errno)); } goto out; } rc = fstat(fd, &stat_buf); if (rc) { rc = -errno; if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Unable to query md device \"%s\": %s\n", array->name, strerror(errno)); goto out_close; } if (!S_ISBLK(stat_buf.st_mode) || (major(stat_buf.st_rdev) != MD_MAJOR)) { rc = -EINVAL; if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: \"%s\" is not an md device\n", array->name); goto out_close; } array->minor = minor(stat_buf.st_rdev); /* * Ok, here we consider the array "valid." IOW, it can be * considered to exist, at least in a possibly offline state. * This is important, because if the array is online, calling * find_add_disk() below is going to be looking for the array. It * had better be there. */ list_add_tail(&array->a_list, &ctxt->arrays); rc = ioctl(fd, GET_ARRAY_INFO, &array->info); if (rc) { /* Array is offline */ rc = 0; goto out_close; } for (i = 0, numdisks = 0; (numdisks < array->info.nr_disks) && (i < (array->info.raid_disks + array->info.spare_disks)) && (i < MD_SB_DISKS); i++) { memset(&dinfo, 0, sizeof(mdu_disk_info_t)); dinfo.number = i; rc = ioctl(fd, GET_DISK_INFO, &dinfo); if (rc) { /* * Note, older raid 0.90 as a bug where it thinks * dinfo.number > array->info.nr_disks is -EINVAL. This is * not the case, as a missing disk counts in .number but * not in .nr_disks. Oh, well, get a newer raid. */ if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Unable to query disk %d of md device \"%s\": %s\n", i, array->name, strerror(errno)); break; } /* Empty entry */ if (!dinfo.major) continue; disk = find_add_disk(ctxt, NULL, dinfo.major, dinfo.minor); if (!disk) continue; if (disk->info.major) { /* * disk->info has been filled already. That's weird, since * only one online array should have it. Let's check it. */ if ((disk->info.major != dinfo.major) || (disk->info.minor != dinfo.minor) || (disk->sb.md_minor != array->minor)) { fprintf(stderr, "lsraid: Very weird. Array %s [dev %d, %d] is online and claims to have disk\n" " %s [dev %d, %d]. However, the disk believes it belongs to\n" " md device [dev %d, %d].\n", array->name ? array->name : "(unknown)", MD_MAJOR, array->minor, disk->name ? disk->name : "(unknown)", dinfo.major, dinfo.minor, MD_MAJOR, disk->sb.md_minor); } } else disk->info = dinfo; numdisks++; } /* Disk errors are not array errors */ rc = 0;out_close: close(fd);out: return(rc);} /* query_array() */static int fill_array(LSRContext *ctxt, LSRArray *array){ if (!array) return(-EINVAL); if (!array->name) { if (find_device(ctxt, &array->name, MD_MAJOR, array->minor)) { if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: md device [dev %d, %d] has no entry on this system\n", MD_MAJOR, array->minor); return(-ENOENT); } } return(query_array(ctxt, array));} /* fill_array() */static int fill_disk(LSRContext *ctxt, LSRDisk *disk){ int i, numdisks; if (!disk) return(-EINVAL); if (!disk->name) { if (!disk->major) return(-EINVAL); if (find_device(ctxt, &disk->name, disk->major, disk->minor)) { if (!(ctxt->flags & LSR_DEV_SCAN)) fprintf(stderr, "lsraid: Device [dev %d, %d] has no entry on this system\n", disk->major, disk->minor); return(-ENOENT); } } read_md_super(ctxt, disk); if (!disk->sb.md_magic) return(-ENOENT); /* * We consider the disk "valid" here. It has a md superblock * and can be looked at, even if it no longer belongs to anything. * This is important because the find_add_array() call below will * be looking for the disk. */ list_add_tail(&disk->d_list, &ctxt->disks); find_add_array(ctxt, NULL, disk->sb.md_minor); for (i = 0, numdisks = 0; (numdisks < disk->sb.nr_disks) && (i < (disk->sb.raid_disks + disk->sb.spare_disks)) && (i < MD_SB_DISKS); i++) { /* Only if non-empty */ if (disk->sb.disks[i].major) { find_add_disk(ctxt, NULL, disk->sb.disks[i].major, disk->sb.disks[i].minor); numdisks++; } } return(0);} /* fill_disk() *//* minor is ignored if -1, name is ignored if NULL */static LSRArray *find_add_array(LSRContext *ctxt, char *name, int minor){ LSRArray *array; struct list_head *pos; /* No valid search */ if ((name == NULL) && (minor == -1)) { fprintf(stderr, "lsraid: find_add_array() called with no valid search\n"); return(NULL); } array = NULL; list_for_each(pos, &ctxt->arrays) { array = list_entry(pos, LSRArray, a_list); if (!name && (minor == array->minor)) break; if ((minor == -1) && array->name && !strcmp(name, array->name)) break; if ((minor == array->minor) && array->name && !strcmp(name, array->name)) break; array = NULL; } if (array == NULL) { array = alloc_array(); if (!array) { if (name) fprintf(stderr, "lsraid: Unable to allocate memory for information on array \"%s\": %s\n", name, strerror(errno)); else fprintf(stderr, "lsraid: Unable to allocate memory for information on array [dev %d, %d]: %s\n", MD_MAJOR, minor, strerror(errno)); return(NULL); } if (name) array->name = name; if (minor > -1) array->minor = minor; /* Will add array to ctxt->arrays */ if (fill_array(ctxt, array)) { free(array); array = NULL; } } return(array);} /* find_add_array() *//* major/minor is ignored if major is 0, name is ignored if NULL */static LSRDisk *find_add_disk(LSRContext *ctxt, char *name, int major, int minor){ LSRDisk *disk; struct list_head *pos; /* No valid search */ if ((name == NULL) && (major == 0)) { fprintf(stderr, "lsraid: find_add_disk() called with no valid search\n"); return(NULL); } disk = NULL; list_for_each(pos, &ctxt->disks) { disk = list_entry(pos, LSRDisk, d_list); if (!name && (major == disk->major) && (minor == disk->minor)) break; if ((major == 0) && disk->name && !strcmp(name, disk->name)) break; if ((major == disk->major) && (minor == disk->minor) && disk->name && !strcmp(name, disk->name)) break; disk = NULL; } if (disk == NULL) { disk = alloc_disk(); if (!disk) { if (name) fprintf(stderr, "lsraid: Unable to allocate memory for information on disk \"%s\": %s\n", name, strerror(errno)); else fprintf(stderr, "lsraid: Unable to allocate memory for information on adisk [dev %d, %d]: %s\n", major, minor, strerror(errno)); return(NULL); } if (name) disk->name = name; if (major > 0) { disk->major = major; disk->minor = minor; } /* Will add the disk to ctxt->disks */ if (fill_disk(ctxt, disk)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -