X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=super-intel.c;h=b47371ee63be36e03b63555c11a3f0c4db19b78d;hb=cf3a3d7888ea5f5ba465ed6d36d76c3c12ac520b;hp=f55d707667b17baa47b31172eea02a8e8f78ffa6;hpb=db575f3b9ebfdf0d7ac8dd5f9b1d4b4d0e446e80;p=thirdparty%2Fmdadm.git diff --git a/super-intel.c b/super-intel.c index f55d7076..b47371ee 100644 --- a/super-intel.c +++ b/super-intel.c @@ -233,6 +233,7 @@ struct intel_super { int fd; int extent_cnt; struct extent *e; /* for determining freespace @ create */ + int raiddisk; /* slot to fill in autolayout */ } *disks; struct dl *add; /* list of disks to add while mdmon active */ struct dl *missing; /* disks removed while we weren't looking */ @@ -979,6 +980,23 @@ static int detail_platform_imsm(int verbose, int enumerate_only) imsm_orom_has_raid1e(orom) ? " raid1e" : "", imsm_orom_has_raid10(orom) ? " raid10" : "", imsm_orom_has_raid5(orom) ? " raid5" : ""); + printf(" Chunk Sizes :%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", + imsm_orom_has_chunk(orom, 2) ? " 2k" : "", + imsm_orom_has_chunk(orom, 4) ? " 4k" : "", + imsm_orom_has_chunk(orom, 8) ? " 8k" : "", + imsm_orom_has_chunk(orom, 16) ? " 16k" : "", + imsm_orom_has_chunk(orom, 32) ? " 32k" : "", + imsm_orom_has_chunk(orom, 64) ? " 64k" : "", + imsm_orom_has_chunk(orom, 128) ? " 128k" : "", + imsm_orom_has_chunk(orom, 256) ? " 256k" : "", + imsm_orom_has_chunk(orom, 512) ? " 512k" : "", + imsm_orom_has_chunk(orom, 1024*1) ? " 1M" : "", + imsm_orom_has_chunk(orom, 1024*2) ? " 2M" : "", + imsm_orom_has_chunk(orom, 1024*4) ? " 4M" : "", + imsm_orom_has_chunk(orom, 1024*8) ? " 8M" : "", + imsm_orom_has_chunk(orom, 1024*16) ? " 16M" : "", + imsm_orom_has_chunk(orom, 1024*32) ? " 32M" : "", + imsm_orom_has_chunk(orom, 1024*64) ? " 64M" : ""); printf(" Max Disks : %d\n", orom->tds); printf(" Max Volumes : %d\n", orom->vpa); printf(" I/O Controller : %s\n", hba_path); @@ -1119,7 +1137,11 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info) struct intel_super *super = st->sb; struct imsm_dev *dev = get_imsm_dev(super, super->current_vol); struct imsm_map *map = get_imsm_map(dev, 0); + struct dl *dl; + for (dl = super->disks; dl; dl = dl->next) + if (dl->raiddisk == info->disk.raid_disk) + break; info->container_member = super->current_vol; info->array.raid_disks = map->num_members; info->array.level = get_imsm_raid_level(map); @@ -1132,6 +1154,10 @@ static void getinfo_super_imsm_volume(struct supertype *st, struct mdinfo *info) info->disk.major = 0; info->disk.minor = 0; + if (dl) { + info->disk.major = dl->major; + info->disk.minor = dl->minor; + } info->data_offset = __le32_to_cpu(map->pba_of_lba0); info->component_size = __le32_to_cpu(map->blocks_per_member); @@ -1976,9 +2002,14 @@ static int load_super_imsm_all(struct supertype *st, int fd, void **sbp, int rv; int devnum = fd2devnum(fd); int retry; + enum sysfs_read_flags flags; + + flags = GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE; + if (mdmon_running(devnum)) + flags |= SKIP_GONE_DEVS; - /* check if this disk is a member of an active array */ - sra = sysfs_read(fd, 0, GET_LEVEL|GET_VERSION|GET_DEVS|GET_STATE); + /* check if 'fd' an opened container */ + sra = sysfs_read(fd, 0, flags); if (!sra) return 1; @@ -2393,10 +2424,19 @@ static int add_to_super_imsm_volume(struct supertype *st, mdu_disk_info_t *dk, return 1; } - for (dl = super->disks; dl ; dl = dl->next) - if (dl->major == dk->major && - dl->minor == dk->minor) - break; + if (fd == -1) { + /* we're doing autolayout so grab the pre-marked (in + * validate_geometry) raid_disk + */ + for (dl = super->disks; dl; dl = dl->next) + if (dl->raiddisk == dk->raid_disk) + break; + } else { + for (dl = super->disks; dl ; dl = dl->next) + if (dl->major == dk->major && + dl->minor == dk->minor) + break; + } if (!dl) { fprintf(stderr, Name ": %s is not a member of the same container\n", devname); @@ -2790,7 +2830,7 @@ static unsigned long long merge_extents(struct intel_super *super, int sum_exten int i, j; int start_extent; unsigned long long pos; - unsigned long long start; + unsigned long long start = 0; unsigned long long maxsize; unsigned long reserve; @@ -3047,6 +3087,78 @@ static int validate_geometry_imsm_volume(struct supertype *st, int level, return 1; } +static int reserve_space(struct supertype *st, int raiddisks, + unsigned long long size, int chunk, + unsigned long long *freesize) +{ + struct intel_super *super = st->sb; + struct imsm_super *mpb = super->anchor; + struct dl *dl; + int i; + int extent_cnt; + struct extent *e; + unsigned long long maxsize; + unsigned long long minsize; + int cnt; + int used; + + /* find the largest common start free region of the possible disks */ + used = 0; + extent_cnt = 0; + cnt = 0; + for (dl = super->disks; dl; dl = dl->next) { + dl->raiddisk = -1; + + if (dl->index >= 0) + used++; + + /* don't activate new spares if we are orom constrained + * and there is already a volume active in the container + */ + if (super->orom && dl->index < 0 && mpb->num_raid_devs) + continue; + + e = get_extents(super, dl); + if (!e) + continue; + for (i = 1; e[i-1].size; i++) + ; + dl->e = e; + dl->extent_cnt = i; + extent_cnt += i; + cnt++; + } + + maxsize = merge_extents(super, extent_cnt); + minsize = size; + if (size == 0) + minsize = chunk; + + if (cnt < raiddisks || + (super->orom && used && used != raiddisks) || + maxsize < minsize) { + fprintf(stderr, Name ": not enough devices with space to create array.\n"); + return 0; /* No enough free spaces large enough */ + } + + if (size == 0) { + size = maxsize; + if (chunk) { + size /= chunk; + size *= chunk; + } + } + + cnt = 0; + for (dl = super->disks; dl; dl = dl->next) + if (dl->e) + dl->raiddisk = cnt++; + + *freesize = size; + + return 1; +} + static int validate_geometry_imsm(struct supertype *st, int level, int layout, int raiddisks, int chunk, unsigned long long size, char *dev, unsigned long long *freesize, @@ -3068,9 +3180,15 @@ static int validate_geometry_imsm(struct supertype *st, int level, int layout, if (!dev) { if (st->sb && freesize) { - /* Should do auto-layout here */ - fprintf(stderr, Name ": IMSM does not support auto-layout yet\n"); - return 0; + /* we are being asked to automatically layout a + * new volume based on the current contents of + * the container. If the the parameters can be + * satisfied reserve_space will record the disks, + * start offset, and size of the volume to be + * created. add_to_super and getinfo_super + * detect when autolayout is in progress. + */ + return reserve_space(st, raiddisks, size, chunk, freesize); } return 1; }