+int experimental(void)
+{
+ if (check_env("MDADM_EXPERIMENTAL"))
+ return 1;
+ else {
+ pr_err("To use this feature MDADM_EXPERIMENTAL"
+ " environment variable has to be defined.\n");
+ return 0;
+ }
+}
+
+/* Pick all spares matching given criteria from a container
+ * if min_size == 0 do not check size
+ * if domlist == NULL do not check domains
+ * if spare_group given add it to domains of each spare
+ * metadata allows to test domains using metadata of destination array */
+struct mdinfo *container_choose_spares(struct supertype *st,
+ unsigned long long min_size,
+ struct domainlist *domlist,
+ char *spare_group,
+ const char *metadata, int get_one)
+{
+ struct mdinfo *d, **dp, *disks = NULL;
+
+ /* get list of all disks in container */
+ if (st->ss->getinfo_super_disks)
+ disks = st->ss->getinfo_super_disks(st);
+
+ if (!disks)
+ return disks;
+ /* find spare devices on the list */
+ dp = &disks->devs;
+ disks->array.spare_disks = 0;
+ while (*dp) {
+ int found = 0;
+ d = *dp;
+ if (d->disk.state == 0) {
+ /* check if size is acceptable */
+ unsigned long long dev_size;
+ dev_t dev = makedev(d->disk.major,d->disk.minor);
+
+ if (!min_size ||
+ (dev_size_from_id(dev, &dev_size) &&
+ dev_size >= min_size))
+ found = 1;
+ /* check if domain matches */
+ if (found && domlist) {
+ struct dev_policy *pol = devid_policy(dev);
+ if (spare_group)
+ pol_add(&pol, pol_domain,
+ spare_group, NULL);
+ if (domain_test(domlist, pol, metadata) != 1)
+ found = 0;
+ dev_policy_free(pol);
+ }
+ }
+ if (found) {
+ dp = &d->next;
+ disks->array.spare_disks++;
+ if (get_one) {
+ sysfs_free(*dp);
+ d->next = NULL;
+ }
+ } else {
+ *dp = d->next;
+ d->next = NULL;
+ sysfs_free(d);
+ }
+ }
+ return disks;
+}
+
+/* Checks if paths point to the same device
+ * Returns 0 if they do.
+ * Returns 1 if they don't.
+ * Returns -1 if something went wrong,
+ * e.g. paths are empty or the files
+ * they point to don't exist */
+int compare_paths (char* path1, char* path2)
+{
+ struct stat st1,st2;
+
+ if (path1 == NULL || path2 == NULL)
+ return -1;
+ if (stat(path1,&st1) != 0)
+ return -1;
+ if (stat(path2,&st2) != 0)
+ return -1;
+ if ((st1.st_ino == st2.st_ino) && (st1.st_dev == st2.st_dev))
+ return 0;
+ return 1;
+}
+
+/* Make sure we can open as many devices as needed */
+void enable_fds(int devices)
+{
+ unsigned int fds = 20 + devices;
+ struct rlimit lim;
+ if (getrlimit(RLIMIT_NOFILE, &lim) != 0
+ || lim.rlim_cur >= fds)
+ return;
+ if (lim.rlim_max < fds)
+ lim.rlim_max = fds;
+ lim.rlim_cur = fds;
+ setrlimit(RLIMIT_NOFILE, &lim);
+}
+
+int in_initrd(void)
+{
+ /* This is based on similar function in systemd. */
+ struct statfs s;
+ return statfs("/", &s) >= 0 &&
+ (s.f_type == TMPFS_MAGIC ||
+ s.f_type == RAMFS_MAGIC);
+}