/*
* mdadm - manage Linux "md" devices aka RAID arrays.
*
- * Copyright (C) 2001-2012 Neil Brown <neilb@suse.de>
+ * Copyright (C) 2001-2013 Neil Brown <neilb@suse.de>
*
*
* This program is free software; you can redistribute it and/or modify
#include <sys/wait.h>
#include <sys/un.h>
#include <sys/resource.h>
+#include <sys/vfs.h>
+#include <linux/magic.h>
#include <ctype.h>
#include <dirent.h>
#include <signal.h>
if (ioctl(fd, BLKPG, &a) == 0)
/* Very unlikely, but not a partition */
return 0;
- if (errno == ENXIO)
+ if (errno == ENXIO || errno == ENOTTY)
/* not a partition */
return 0;
{
struct mdu_array_info_s array;
struct mdu_disk_info_s disk;
- int avail_disks = 0;
int i, rv;
char *avail;
continue;
if (disk.raid_disk < 0 || disk.raid_disk >= array.raid_disks)
continue;
- avail_disks++;
avail[disk.raid_disk] = 1;
}
/* This is used on an active array, so assume it is clean */
*/
unsigned char sb[1024];
time_t mtime;
- int size, bsize;
+ unsigned long long size;
+ int bsize;
if (lseek(fd, 1024,0)!= 1024)
return 0;
if (read(fd, sb, 1024)!= 1024)
mtime = sb[44]|(sb[45]|(sb[46]|sb[47]<<8)<<8)<<8;
bsize = sb[24]|(sb[25]|(sb[26]|sb[27]<<8)<<8)<<8;
size = sb[4]|(sb[5]|(sb[6]|sb[7]<<8)<<8)<<8;
+ size <<= bsize;
pr_err("%s appears to contain an ext2fs file system\n",
name);
- cont_err("size=%dK mtime=%s",
- size*(1<<bsize), ctime(&mtime));
+ cont_err("size=%lluK mtime=%s", size, ctime(&mtime));
return 1;
}
*
*/
unsigned char sb[1024];
- unsigned long size;
+ unsigned long long size;
if (lseek(fd, 64*1024, 0) != 64*1024)
return 0;
if (read(fd, sb, 1024) != 1024)
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;
- cont_err("size = %luK\n", size*4);
+ cont_err("size = %lluK\n", size*4);
return 1;
}
if (strncmp(name, "/dev/.tmp.md", 12) == 0)
unlink(name);
}
-
-char *find_free_devnm(int use_partitions)
-{
- static char devnm[32];
- int devnum;
- for (devnum = 127; devnum != 128;
- devnum = devnum ? devnum-1 : (1<<20)-1) {
-
- if (use_partitions)
- sprintf(devnm, "md_d%d", devnum);
- else
- sprintf(devnm, "md%d", devnum);
- if (mddev_busy(devnm))
- continue;
- if (!conf_name_is_free(devnm))
- continue;
- if (!use_udev()) {
- /* make sure it is new to /dev too, at least as a
- * non-standard */
- int devid = devnm2devid(devnm);
- if (devid) {
- char *dn = map_dev(major(devid),
- minor(devid), 0);
- if (dn && ! is_standard(dn, NULL))
- continue;
- }
- }
- break;
- }
- if (devnum == 128)
- return NULL;
- return devnm;
-}
#endif /* !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO) */
int dev_open(char *dev, int flags)
int i;
int flags = O_RDWR;
int devid = devnm2devid(devnm);
+ long delay = 1000;
sprintf(buf, "%d:%d", major(devid), minor(devid));
for (i = 0 ; i < 25 ; i++) {
}
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);
st->max_devs = orig->max_devs;
st->minor_version = orig->minor_version;
st->ignore_hw_compat = orig->ignore_hw_compat;
+ st->data_offset = orig->data_offset;
st->sb = NULL;
st->info = NULL;
return st;
char pathbuf[1024];
char *paths[4] = {
pathbuf,
- "/sbin/mdmon",
- "mdmon",
+ BINDIR "/mdmon",
+ "./mdmon",
NULL
};
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;
-
- /* 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",
- devnm);
- 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;
- }
+ if (!check_env("MDADM_NO_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;
+
+ /* 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",
+ devnm);
+ 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()) {
for (i = 0; paths[i]; i++)
if (paths[i][0]) {
- execl(paths[i], "mdmon",
+ execl(paths[i], paths[i],
devnm, NULL);
}
exit(1);
lim.rlim_cur = fds;
setrlimit(RLIMIT_NOFILE, &lim);
}
+
+int in_initrd(void)
+{
+ /* This is based on similar function in systemd. */
+ struct statfs s;
+ /* statfs.f_type is signed long on s390x and MIPS, causing all
+ sorts of sign extension problems with RAMFS_MAGIC being
+ defined as 0x858458f6 */
+ return statfs("/", &s) >= 0 &&
+ ((unsigned long)s.f_type == TMPFS_MAGIC ||
+ ((unsigned long)s.f_type & 0xFFFFFFFFUL) ==
+ ((unsigned long)RAMFS_MAGIC & 0xFFFFFFFFUL));
+}
+
+void reopen_mddev(int mdfd)
+{
+ /* Re-open without any O_EXCL, but keep
+ * the same fd
+ */
+ char *devnm;
+ int fd;
+ devnm = fd2devnm(mdfd);
+ close(mdfd);
+ fd = open_dev(devnm);
+ if (fd >= 0 && fd != mdfd)
+ dup2(fd, mdfd);
+}