X-Git-Url: http://git.ipfire.org/?a=blobdiff_plain;f=util.c;h=7f00b01201cb96826de473fac6f182047e9ec9f5;hb=refs%2Fheads%2Fmdadm-3.2.x;hp=0ea7e0d27d8a3cd347fbcc255141f0d11ef0aa30;hpb=01619b481883926f13da2b1b88f3125359a6a08b;p=thirdparty%2Fmdadm.git diff --git a/util.c b/util.c index 0ea7e0d2..7f00b012 100644 --- a/util.c +++ b/util.c @@ -32,6 +32,8 @@ #include #include +int __offroot; + /* * following taken from linux/blkpg.h because they aren't * anywhere else and it isn't safe to #include linux/ * stuff. @@ -192,6 +194,7 @@ long long parse_size(char *size) * followed by 'K', 'M', or 'G'. * Without a suffix, K is assumed. * Number returned is in sectors (half-K) + * -1 returned on error. */ char *c; long long s = strtoll(size, &c, 10); @@ -213,7 +216,7 @@ long long parse_size(char *size) } } if (*c) - s = 0; + s = -1; return s; } @@ -309,10 +312,15 @@ int test_partition_from_id(dev_t id) return rv; } -int enough(int level, int raid_disks, int layout, int clean, - char *avail, int avail_disks) +int enough(int level, int raid_disks, int layout, int clean, char *avail) { int copies, first; + int i; + int avail_disks = 0; + + for (i = 0; i < raid_disks; i++) + avail_disks += !!avail[i]; + switch (level) { case 10: /* This is the tricky one - we need to check @@ -324,14 +332,15 @@ int enough(int level, int raid_disks, int layout, int clean, /* there must be one of the 'copies' form 'first' */ int n = copies; int cnt=0; + int this = first; while (n--) { - if (avail[first]) + if (avail[this]) cnt++; - first = (first+1) % raid_disks; + this = (this+1) % raid_disks; } if (cnt == 0) return 0; - + first = (first+(layout&255)) % raid_disks; } while (first != 0); return 1; @@ -363,14 +372,14 @@ int enough_fd(int fd) struct mdu_array_info_s array; struct mdu_disk_info_s disk; int avail_disks = 0; - int i; + int i, rv; char *avail; if (ioctl(fd, GET_ARRAY_INFO, &array) != 0 || array.raid_disks <= 0) return 0; avail = calloc(array.raid_disks, 1); - for (i=0; i < 1024 && array.nr_disks > 0; i++) { + for (i=0; i < MAX_DISKS && array.nr_disks > 0; i++) { disk.number = i; if (ioctl(fd, GET_DISK_INFO, &disk) != 0) continue; @@ -386,9 +395,10 @@ int enough_fd(int fd) avail[disk.raid_disk] = 1; } /* This is used on an active array, so assume it is clean */ - return enough(array.level, array.raid_disks, array.layout, - 1, - avail, avail_disks); + rv = enough(array.level, array.raid_disks, array.layout, + 1, avail); + free(avail); + return rv; } @@ -702,6 +712,14 @@ void print_r10_layout(int layout) unsigned long long calc_array_size(int level, int raid_disks, int layout, int chunksize, unsigned long long devsize) +{ + if (level == 1) + return devsize; + devsize &= ~(unsigned long long)((chunksize>>9)-1); + return get_data_disks(level, layout, raid_disks) * devsize; +} + +int get_data_disks(int level, int layout, int raid_disks) { int data_disks = 0; switch (level) { @@ -713,8 +731,8 @@ unsigned long long calc_array_size(int level, int raid_disks, int layout, case 10: data_disks = raid_disks / (layout & 255) / ((layout>>8)&255); break; } - devsize &= ~(unsigned long long)((chunksize>>9)-1); - return data_disks * devsize; + + return data_disks; } #if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) @@ -779,10 +797,14 @@ int find_free_devnum(int use_partitions) devnum = devnum ? devnum-1 : (1<<20)-1) { char *dn; int _devnum; + char nbuf[50]; _devnum = use_partitions ? (-1-devnum) : devnum; if (mddev_busy(_devnum)) continue; + sprintf(nbuf, "%s%d", use_partitions?"mdp":"md", devnum); + if (!conf_name_is_free(nbuf)) + continue; /* make sure it is new to /dev too, at least as a * non-standard */ dn = map_dev(dev2major(_devnum), dev2minor(_devnum), 0); @@ -952,9 +974,10 @@ struct supertype *super_by_fd(int fd, char **subarrayp) char *dev = verstr+1; subarray = strchr(dev, '/'); - if (subarray) + if (subarray) { *subarray++ = '\0'; - subarray = strdup(subarray); + subarray = strdup(subarray); + } container = devname2devnum(dev); if (sra) sysfs_free(sra); @@ -1121,7 +1144,8 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart) { struct GPT gpt; unsigned char empty_gpt_entry[16]= {0}; - struct GPT_part_entry part; + struct GPT_part_entry *part; + char buf[512]; unsigned long long curr_part_end; unsigned all_partitions, entry_size; unsigned part_nr; @@ -1145,18 +1169,20 @@ static int get_gpt_last_partition_end(int fd, unsigned long long *endofpart) /* sanity checks */ if (all_partitions > 1024 || - entry_size > 512) + entry_size > sizeof(buf)) return -1; + part = (struct GPT_part_entry *)buf; + for (part_nr=0; part_nr < all_partitions; part_nr++) { /* read partition entry */ - if (read(fd, &part, entry_size) != (ssize_t)entry_size) + if (read(fd, buf, entry_size) != (ssize_t)entry_size) return 0; /* is this valid partition? */ - if (memcmp(part.type_guid, empty_gpt_entry, 16) != 0) { + if (memcmp(part->type_guid, empty_gpt_entry, 16) != 0) { /* check the last lba for the current partition */ - curr_part_end = __le64_to_cpu(part.ending_lba); + curr_part_end = __le64_to_cpu(part->ending_lba); if (curr_part_end > *endofpart) *endofpart = curr_part_end; } @@ -1254,7 +1280,7 @@ void get_one_disk(int mdfd, mdu_array_info_t *ainf, mdu_disk_info_t *disk) int d; ioctl(mdfd, GET_ARRAY_INFO, ainf); - for (d = 0 ; d < 1024 ; d++) { + for (d = 0 ; d < MAX_DISKS ; d++) { if (ioctl(mdfd, GET_DISK_INFO, disk) == 0 && (disk->major || disk->minor)) return; @@ -1289,6 +1315,20 @@ int open_container(int fd) continue; if (de->d_name[0] == '.') continue; + /* Need to make sure it is a container and not a volume */ + sprintf(e, "/%s/md/metadata_version", de->d_name); + dfd = open(path, O_RDONLY); + if (dfd < 0) + continue; + n = read(dfd, buf, sizeof(buf)); + close(dfd); + if (n <= 0 || (unsigned)n >= sizeof(buf)) + continue; + buf[n] = 0; + if (strncmp(buf, "external", 8) != 0 || + n < 10 || + buf[9] == '/') + continue; sprintf(e, "/%s/dev", de->d_name); dfd = open(path, O_RDONLY); if (dfd < 0) @@ -1588,7 +1628,7 @@ int start_mdmon(int devnum) if (check_env("MDADM_NO_MDMON")) return 0; - len = readlink("/proc/self/exe", pathbuf, sizeof(pathbuf)); + len = readlink("/proc/self/exe", pathbuf, sizeof(pathbuf)-1); if (len > 0) { char *sl; pathbuf[len] = 0; @@ -1612,10 +1652,17 @@ int start_mdmon(int devnum) skipped = 0; for (i=0; paths[i]; i++) - if (paths[i][0]) - execl(paths[i], "mdmon", - devnum2devname(devnum), - NULL); + if (paths[i][0]) { + if (__offroot) { + execl(paths[i], "mdmon", "--offroot", + devnum2devname(devnum), + NULL); + } else { + execl(paths[i], "mdmon", + devnum2devname(devnum), + NULL); + } + } exit(1); case -1: fprintf(stderr, Name ": cannot run mdmon. " "Array remains readonly\n"); @@ -1703,7 +1750,8 @@ int experimental(void) if (check_env("MDADM_EXPERIMENTAL")) return 1; else { - fprintf(stderr, Name ": To use this feature MDADM_EXPERIMENTAL enviroment variable has to defined.\n"); + fprintf(stderr, Name ": To use this feature MDADM_EXPERIMENTAL" + " environment variable has to be defined.\n"); return 0; } }