#include <dirent.h>
#include <signal.h>
-int __offroot;
-
/*
* following taken from linux/blkpg.h because they aren't
* anywhere else and it isn't safe to #include linux/ * stuff.
/* The argument structure */
struct blkpg_ioctl_arg {
- int op;
- int flags;
- int datalen;
- void *data;
+ int op;
+ int flags;
+ int datalen;
+ void *data;
};
/* The subfunctions (for the op field) */
int md_get_version(int fd)
{
- struct stat stb;
- mdu_version_t vers;
+ struct stat stb;
+ mdu_version_t vers;
- if (fstat(fd, &stb)<0)
- return -1;
- if ((S_IFMT&stb.st_mode) != S_IFBLK)
- return -1;
+ if (fstat(fd, &stb)<0)
+ return -1;
+ if ((S_IFMT&stb.st_mode) != S_IFBLK)
+ return -1;
- if (ioctl(fd, RAID_VERSION, &vers) == 0)
- return (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
- if (errno == EACCES)
- return -1;
- if (major(stb.st_rdev) == MD_MAJOR)
- return (3600);
- return -1;
+ if (ioctl(fd, RAID_VERSION, &vers) == 0)
+ return (vers.major*10000) + (vers.minor*100) + vers.patchlevel;
+ if (errno == EACCES)
+ return -1;
+ if (major(stb.st_rdev) == MD_MAJOR)
+ return (3600);
+ return -1;
}
int get_linux_version()
char *level;
struct supertype *st = guess_super(fd);
- if (!st) return 0;
- st->ignore_hw_compat = 1;
+ if (!st)
+ return 0;
st->ss->load_super(st, fd, name);
/* Looks like a raid array .. */
pr_err("%s appears to be part of a raid array:\n",
int devnum;
for (devnum = 127; devnum != 128;
devnum = devnum ? devnum-1 : (1<<20)-1) {
- char *dn;
int _devnum;
char nbuf[50];
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);
- if (dn && ! is_standard(dn, NULL))
- continue;
+ if (!use_udev()) {
+ /* make sure it is new to /dev too, at least as a
+ * non-standard */
+ char *dn = map_dev(dev2major(_devnum),
+ dev2minor(_devnum), 0);
+ if (dn && ! is_standard(dn, NULL))
+ continue;
+ }
break;
}
if (devnum == 128)
if (e > dev && *e == ':' && e[1] &&
(minor = strtoul(e+1, &e, 0)) >= 0 &&
*e == 0) {
- char *path = map_dev(major, minor, 0);
- if (path)
- fd = open(path, flags);
- if (fd < 0) {
- snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d:%d",
- (int)getpid(), major, minor);
- if (mknod(devname, S_IFBLK|0600, makedev(major, minor)) == 0) {
- fd = open(devname, flags);
- unlink(devname);
- }
+ snprintf(devname, sizeof(devname), "/dev/.tmp.md.%d:%d:%d",
+ (int)getpid(), major, minor);
+ if (mknod(devname, S_IFBLK|0600, makedev(major, minor)) == 0) {
+ fd = open(devname, flags);
+ unlink(devname);
}
if (fd < 0) {
+ /* Try /tmp as /dev appear to be read-only */
snprintf(devname, sizeof(devname), "/tmp/.tmp.md.%d:%d:%d",
(int)getpid(), major, minor);
if (mknod(devname, S_IFBLK|0600, makedev(major, minor)) == 0) {
st->ss = orig->ss;
st->max_devs = orig->max_devs;
st->minor_version = orig->minor_version;
+ st->ignore_hw_compat = orig->ignore_hw_compat;
st->sb = NULL;
st->info = NULL;
return st;
rv = superlist[bestsuper]->load_super(st, fd, NULL);
if (rv == 0) {
superlist[bestsuper]->free_super(st);
- st->ignore_hw_compat = 0;
return st;
}
}
return 0;
}
-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 < MAX_DISKS ; d++) {
- if (ioctl(mdfd, GET_DISK_INFO, disk) == 0 &&
- (disk->major || disk->minor))
- return;
- }
-}
-
int open_container(int fd)
{
/* 'fd' is a block device. Find out if it is in use
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)
} else
pathbuf[0] = '\0';
+ /* First try to run systemctl */
+ switch(fork()) {
+ case 0:
+ /* FIXME yuk. CLOSE_EXEC?? */
+ skipped = 0;
+ for (i = 3; skipped < 20; i++)
+ if (close(i) < 0)
+ skipped++;
+ else
+ skipped = 0;
+
+ snprintf(pathbuf, sizeof(pathbuf), "mdmon@%s.service",
+ devnum2devname(devnum));
+ status = execl("/usr/bin/systemctl", "systemctl", "start",
+ pathbuf, NULL);
+ status = execl("/bin/systemctl", "systemctl", "start",
+ pathbuf, NULL);
+ exit(1);
+ case -1: pr_err("cannot run mdmon. "
+ "Array remains readonly\n");
+ return -1;
+ default: /* parent - good */
+ pid = wait(&status);
+ if (pid >= 0 && status == 0)
+ return 0;
+ }
+
+ /* That failed, try running mdmon directly */
switch(fork()) {
case 0:
/* FIXME yuk. CLOSE_EXEC?? */
for (i = 0; paths[i]; i++)
if (paths[i][0]) {
- if (__offroot) {
- execl(paths[i], "mdmon", "--offroot",
- devnum2devname(devnum),
- NULL);
- } else {
- execl(paths[i], "mdmon",
- devnum2devname(devnum),
- NULL);
- }
+ execl(paths[i], "mdmon",
+ devnum2devname(devnum), NULL);
}
exit(1);
case -1: pr_err("cannot run mdmon. "
return -1;
default: /* parent - good */
pid = wait(&status);
- if (pid < 0 || status != 0)
+ if (pid < 0 || status != 0) {
+ pr_err("failed to launch mdmon. "
+ "Array remains readonly\n");
return -1;
+ }
}
return 0;
}