#include <sys/utsname.h>
#include <sys/wait.h>
#include <sys/un.h>
+#include <sys/resource.h>
#include <ctype.h>
#include <dirent.h>
#include <signal.h>
size = sb[4]|(sb[5]|(sb[6]|sb[7]<<8)<<8)<<8;
pr_err("%s appears to contain an ext2fs file system\n",
name);
- fprintf(stderr," size=%dK mtime=%s",
+ cont_err("size=%dK mtime=%s",
size*(1<<bsize), ctime(&mtime));
return 1;
}
return 0;
pr_err("%s appears to contain a reiserfs file system\n",name);
size = sb[0]|(sb[1]|(sb[2]|sb[3]<<8)<<8)<<8;
- fprintf(stderr, " size = %luK\n", size*4);
+ cont_err("size = %luK\n", size*4);
return 1;
}
crtime = info.array.ctime;
level = map_num(pers, info.array.level);
if (!level) level = "-unknown-";
- fprintf(stderr, " level=%s devices=%d ctime=%s",
- level, info.array.raid_disks, ctime(&crtime));
+ cont_err("level=%s devices=%d ctime=%s",
+ level, info.array.raid_disks, ctime(&crtime));
return 1;
}
return data_disks;
}
+int devnm2devid(char *devnm)
+{
+ /* First look in /sys/block/$DEVNM/dev for %d:%d
+ * If that fails, try parsing out a number
+ */
+ char path[100];
+ char *ep;
+ int fd;
+ int mjr,mnr;
+
+ sprintf(path, "/sys/block/%s/dev", devnm);
+ fd = open(path, O_RDONLY);
+ if (fd >= 0) {
+ char buf[20];
+ int n = read(fd, buf, sizeof(buf));
+ close(fd);
+ if (n > 0)
+ buf[n] = 0;
+ if (n > 0 && sscanf(buf, "%d:%d\n", &mjr, &mnr) == 2)
+ return makedev(mjr, mnr);
+ }
+ if (strncmp(devnm, "md_d", 4) == 0 &&
+ isdigit(devnm[4]) &&
+ (mnr = strtoul(devnm+4, &ep, 10)) >= 0 &&
+ ep > devnm && *ep == 0)
+ return makedev(get_mdp_major(), mnr << MdpMinorShift);
+
+ if (strncmp(devnm, "md", 2) == 0 &&
+ isdigit(devnm[2]) &&
+ (mnr = strtoul(devnm+2, &ep, 10)) >= 0 &&
+ ep > devnm && *ep == 0)
+ return makedev(MD_MAJOR, mnr);
+
+ return 0;
+}
+
#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)
-char *get_md_name(int dev)
+char *get_md_name(char *devnm)
{
/* find /dev/md%d or /dev/md/%d or make a device /dev/.tmp.md%d */
/* if dev < 0, want /dev/md/d%d or find mdp in /proc/devices ... */
+
static char devname[50];
struct stat stb;
- dev_t rdev;
+ dev_t rdev = devnm2devid(devnm);
char *dn;
- if (dev < 0) {
- int mdp = get_mdp_major();
- if (mdp < 0) return NULL;
- rdev = makedev(mdp, (-1-dev)<<6);
- snprintf(devname, sizeof(devname), "/dev/md/d%d", -1-dev);
- if (stat(devname, &stb) == 0
- && (S_IFMT&stb.st_mode) == S_IFBLK
- && (stb.st_rdev == rdev))
- return devname;
- } else {
- rdev = makedev(MD_MAJOR, dev);
- snprintf(devname, sizeof(devname), "/dev/md%d", dev);
- if (stat(devname, &stb) == 0
- && (S_IFMT&stb.st_mode) == S_IFBLK
- && (stb.st_rdev == rdev))
- return devname;
-
- snprintf(devname, sizeof(devname), "/dev/md/%d", dev);
+ if (rdev == 0)
+ return 0;
+ if (strncmp(devnm, "md_", 3) == 0) {
+ snprintf(devname, sizeof(devname), "/dev/md/%s",
+ devnm + 3);
if (stat(devname, &stb) == 0
&& (S_IFMT&stb.st_mode) == S_IFBLK
&& (stb.st_rdev == rdev))
return devname;
}
+ snprintf(devname, sizeof(devname), "/dev/%s", devnm);
+ if (stat(devname, &stb) == 0
+ && (S_IFMT&stb.st_mode) == S_IFBLK
+ && (stb.st_rdev == rdev))
+ return devname;
+
+ snprintf(devname, sizeof(devname), "/dev/md/%s", devnm+2);
+ if (stat(devname, &stb) == 0
+ && (S_IFMT&stb.st_mode) == S_IFBLK
+ && (stb.st_rdev == rdev))
+ return devname;
+
dn = map_dev(major(rdev), minor(rdev), 0);
if (dn)
return dn;
- snprintf(devname, sizeof(devname), "/dev/.tmp.md%d", dev);
+ snprintf(devname, sizeof(devname), "/dev/.tmp.%s", devnm);
if (mknod(devname, S_IFBLK | 0600, rdev) == -1)
if (errno != EEXIST)
return NULL;
if (strncmp(name, "/dev/.tmp.md", 12) == 0)
unlink(name);
}
-
-int find_free_devnum(int use_partitions)
-{
- int devnum;
- for (devnum = 127; devnum != 128;
- devnum = devnum ? devnum-1 : (1<<20)-1) {
- 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;
- 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)
- return NoMdDev;
- return use_partitions ? (-1-devnum) : devnum;
-}
#endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */
int dev_open(char *dev, int flags)
return fd;
}
-int open_dev_flags(int devnum, int flags)
+int open_dev_flags(char *devnm, int flags)
{
+ int devid;
char buf[20];
- sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum));
+ devid = devnm2devid(devnm);
+ sprintf(buf, "%d:%d", major(devid), minor(devid));
return dev_open(buf, flags);
}
-int open_dev(int devnum)
+int open_dev(char *devnm)
{
- return open_dev_flags(devnum, O_RDONLY);
+ return open_dev_flags(devnm, O_RDONLY);
}
-int open_dev_excl(int devnum)
+int open_dev_excl(char *devnm)
{
char buf[20];
int i;
int flags = O_RDWR;
+ int devid = devnm2devid(devnm);
+ long delay = 1000;
- sprintf(buf, "%d:%d", dev2major(devnum), dev2minor(devnum));
+ sprintf(buf, "%d:%d", major(devid), minor(devid));
for (i = 0 ; i < 25 ; i++) {
int fd = dev_open(buf, flags|O_EXCL);
if (fd >= 0)
}
if (errno != EBUSY)
return fd;
- usleep(200000);
+ usleep(delay);
+ if (delay < 200000)
+ delay *= 2;
}
return -1;
}
{
int i;
struct stat stb_want;
+ long delay = 1000;
if (fstat(fd, &stb_want) != 0 ||
(stb_want.st_mode & S_IFMT) != S_IFBLK)
(stb.st_mode & S_IFMT) == S_IFBLK &&
(stb.st_rdev == stb_want.st_rdev))
return;
- usleep(200000);
+ usleep(delay);
+ if (delay < 200000)
+ delay *= 2;
}
if (i == 25)
dprintf("%s: timeout waiting for %s\n", __func__, dev);
char version[20];
int i;
char *subarray = NULL;
- int container = NoMdDev;
+ char container[32] = "";
- sra = sysfs_read(fd, 0, GET_VERSION);
+ sra = sysfs_read(fd, NULL, GET_VERSION);
if (sra) {
vers = sra->array.major_version;
*subarray++ = '\0';
subarray = xstrdup(subarray);
}
- container = devname2devnum(dev);
+ strcpy(container, dev);
if (sra)
sysfs_free(sra);
sra = sysfs_read(-1, container, GET_VERSION);
st->sb = NULL;
if (subarrayp)
*subarrayp = subarray;
- st->container_dev = container;
- st->devnum = fd2devnum(fd);
+ strcpy(st->container_devnm, container);
+ strcpy(st->devnm, fd2devnm(fd));
} else
free(subarray);
int i;
st = xcalloc(1, sizeof(*st));
- st->container_dev = NoMdDev;
+ st->container_devnm[0] = 0;
for (i = 0 ; superlist[i]; i++) {
int rv;
return NULL;
}
+int metadata_container_matches(char *metadata, char *devnm)
+{
+ /* Check if 'devnm' is the container named in 'metadata'
+ * which is
+ * /containername/componentname or
+ * -containername/componentname
+ */
+ int l;
+ if (*metadata != '/' && *metadata != '-')
+ return 0;
+ l = strlen(devnm);
+ if (strncmp(metadata+1, devnm, l) != 0)
+ return 0;
+ if (metadata[l+1] != '/')
+ return 0;
+ return 1;
+}
+
+int metadata_subdev_matches(char *metadata, char *devnm)
+{
+ /* Check if 'devnm' is the subdev named in 'metadata'
+ * which is
+ * /containername/subdev or
+ * -containername/subdev
+ */
+ char *sl;
+ if (*metadata != '/' && *metadata != '-')
+ return 0;
+ sl = strchr(metadata+1, '/');
+ if (!sl)
+ return 0;
+ if (strcmp(sl+1, devnm) == 0)
+ return 1;
+ return 0;
+}
+
int is_container_member(struct mdstat_ent *mdstat, char *container)
{
if (mdstat->metadata_version == NULL ||
strncmp(mdstat->metadata_version, "external:", 9) != 0 ||
- !is_subarray(mdstat->metadata_version+9) ||
- strncmp(mdstat->metadata_version+10, container, strlen(container)) != 0 ||
- mdstat->metadata_version[10+strlen(container)] != '/')
+ !metadata_container_matches(mdstat->metadata_version+9, container))
return 0;
return 1;
struct mdinfo *mdi;
struct mdinfo *info;
int fd, err = 1;
+ char *_devnm;
fd = open(dev, O_RDWR|O_EXCL);
if (fd < 0) {
return -1;
}
- st->devnum = fd2devnum(fd);
- if (st->devnum == NoMdDev) {
+ _devnm = fd2devnm(fd);
+ if (_devnm == NULL) {
if (!quiet)
pr_err("Failed to determine device number for %s\n",
dev);
goto close_fd;
}
+ strcpy(st->devnm, _devnm);
- mdi = sysfs_read(fd, st->devnum, GET_VERSION|GET_LEVEL);
+ mdi = sysfs_read(fd, st->devnm, GET_VERSION|GET_LEVEL);
if (!mdi) {
if (!quiet)
pr_err("Failed to read sysfs for %s\n",
goto free_sysfs;
}
- st->devname = devnum2devname(st->devnum);
- if (!st->devname) {
+ if (st->devnm[0] == 0) {
if (!quiet)
pr_err("Failed to allocate device name\n");
goto free_sysfs;
if (!st->ss->load_container) {
if (!quiet)
pr_err("%s is not a container\n", dev);
- goto free_name;
+ goto free_sysfs;
}
if (st->ss->load_container(st, fd, NULL)) {
if (!quiet)
pr_err("Failed to load metadata for %s\n",
dev);
- goto free_name;
+ goto free_sysfs;
}
info = st->ss->container_content(st, subarray);
free_super:
if (err)
st->ss->free_super(st);
- free_name:
- if (err)
- free(st->devname);
free_sysfs:
sysfs_free(mdi);
close_fd:
return recovery_start;
}
-int mdmon_pid(int devnum)
+int mdmon_pid(char *devnm)
{
char path[100];
char pid[10];
int fd;
int n;
- char *devname = devnum2devname(devnum);
- sprintf(path, "%s/%s.pid", MDMON_DIR, devname);
- free(devname);
+ sprintf(path, "%s/%s.pid", MDMON_DIR, devnm);
fd = open(path, O_RDONLY | O_NOATIME, 0);
return atoi(pid);
}
-int mdmon_running(int devnum)
+int mdmon_running(char *devnm)
{
- int pid = mdmon_pid(devnum);
+ int pid = mdmon_pid(devnm);
if (pid <= 0)
return 0;
if (kill(pid, 0) == 0)
return 0;
}
-int start_mdmon(int devnum)
+int start_mdmon(char *devnm)
{
int i, skipped;
int len;
else
skipped = 0;
+ /* Don't want to see error messages from systemctl.
+ * If the service doesn't exist, we start mdmon ourselves.
+ */
+ close(2);
+ open("/dev/null", O_WRONLY);
snprintf(pathbuf, sizeof(pathbuf), "mdmon@%s.service",
- devnum2devname(devnum));
+ devnm);
status = execl("/usr/bin/systemctl", "systemctl", "start",
pathbuf, NULL);
status = execl("/bin/systemctl", "systemctl", "start",
for (i = 0; paths[i]; i++)
if (paths[i][0]) {
execl(paths[i], "mdmon",
- devnum2devname(devnum), NULL);
+ devnm, 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;
}
-int check_env(char *name)
-{
- char *val = getenv(name);
-
- if (val && atoi(val) == 1)
- return 1;
-
- return 0;
-}
-
__u32 random32(void)
{
__u32 rv;
return -1;
}
- sfd = connect_monitor(devnum2devname(st->container_dev));
+ sfd = connect_monitor(st->container_devnm);
if (sfd < 0)
return -1;
found = 1;
/* check if domain matches */
if (found && domlist) {
- struct dev_policy *pol = devnum_policy(dev);
+ struct dev_policy *pol = devid_policy(dev);
if (spare_group)
pol_add(&pol, pol_domain,
spare_group, NULL);
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);
+}