⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lsraid.c

📁 create raid tool at linux
💻 C
📖 第 1 页 / 共 5 页
字号:
    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 + -