summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile6
-rw-r--r--config.c78
-rw-r--r--lib.c322
-rw-r--r--util.c211
4 files changed, 325 insertions, 292 deletions
diff --git a/Makefile b/Makefile
index eca11c2b..6bdaed95 100644
--- a/Makefile
+++ b/Makefile
@@ -98,7 +98,7 @@ MAN4DIR = $(MANDIR)/man4
MAN5DIR = $(MANDIR)/man5
MAN8DIR = $(MANDIR)/man8
-OBJS = mdadm.o config.o policy.o mdstat.o ReadMe.o util.o maps.o \
+OBJS = mdadm.o config.o policy.o mdstat.o ReadMe.o util.o maps.o lib.o \
Manage.o Assemble.o Build.o \
Create.o Detail.o Examine.o Grow.o Monitor.o dlink.o Kill.o Query.o \
Incremental.o \
@@ -114,7 +114,7 @@ SRCS = $(patsubst %.o,%.c,$(OBJS))
INCL = mdadm.h part.h bitmap.h
MON_OBJS = mdmon.o monitor.o managemon.o util.o maps.o mdstat.o sysfs.o \
- config.o policy.o \
+ config.o policy.o lib.o \
Kill.o sg_io.o dlink.o ReadMe.o super0.o super1.o super-intel.o \
super-mbr.o super-gpt.o \
super-ddf.o sha1.o crc32.o msg.o bitmap.o \
@@ -126,7 +126,7 @@ STATICSRC = pwgr.c
STATICOBJS = pwgr.o
ASSEMBLE_SRCS := mdassemble.c Assemble.c Manage.c config.c policy.c dlink.c util.c \
- maps.c \
+ maps.c lib.c \
super0.c super1.c super-ddf.c super-intel.c sha1.c crc32.c sg_io.c mdstat.c \
platform-intel.c probe_roms.c sysfs.c super-mbr.c super-gpt.c
ASSEMBLE_AUTO_SRCS := mdopen.c
diff --git a/config.c b/config.c
index 1f78c689..0dbe61ed 100644
--- a/config.c
+++ b/config.c
@@ -108,84 +108,6 @@ int match_keyword(char *word)
return -1;
}
-/* conf_word gets one word from the conf file.
- * if "allow_key", then accept words at the start of a line,
- * otherwise stop when such a word is found.
- * We assume that the file pointer is at the end of a word, so the
- * next character is a space, or a newline. If not, it is the start of a line.
- */
-
-char *conf_word(FILE *file, int allow_key)
-{
- int wsize = 100;
- int len = 0;
- int c;
- int quote;
- int wordfound = 0;
- char *word = malloc(wsize);
-
- if (!word) abort();
-
- while (wordfound==0) {
- /* at the end of a word.. */
- c = getc(file);
- if (c == '#')
- while (c != EOF && c != '\n')
- c = getc(file);
- if (c == EOF) break;
- if (c == '\n') continue;
-
- if (c != ' ' && c != '\t' && ! allow_key) {
- ungetc(c, file);
- break;
- }
- /* looks like it is safe to get a word here, if there is one */
- quote = 0;
- /* first, skip any spaces */
- while (c == ' ' || c == '\t')
- c = getc(file);
- if (c != EOF && c != '\n' && c != '#') {
- /* we really have a character of a word, so start saving it */
- while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) {
- wordfound = 1;
- if (quote && c == quote) quote = 0;
- else if (quote == 0 && (c == '\'' || c == '"'))
- quote = c;
- else {
- if (len == wsize-1) {
- wsize += 100;
- word = realloc(word, wsize);
- if (!word) abort();
- }
- word[len++] = c;
- }
- c = getc(file);
- /* Hack for broken kernels (2.6.14-.24) that put
- * "active(auto-read-only)"
- * in /proc/mdstat instead of
- * "active (auto-read-only)"
- */
- if (c == '(' && len >= 6
- && strncmp(word+len-6, "active", 6) == 0)
- c = ' ';
- }
- }
- if (c != EOF) ungetc(c, file);
- }
- word[len] = 0;
-
- /* Further HACK for broken kernels.. 2.6.14-2.6.24 */
- if (strcmp(word, "auto-read-only)") == 0)
- strcpy(word, "(auto-read-only)");
-
-/* printf("word is <%s>\n", word); */
- if (!wordfound) {
- free(word);
- word = NULL;
- }
- return word;
-}
-
/*
* conf_line reads one logical line from the conffile.
* It skips comments and continues until it finds a line that starts
diff --git a/lib.c b/lib.c
new file mode 100644
index 00000000..2739b3d3
--- /dev/null
+++ b/lib.c
@@ -0,0 +1,322 @@
+/*
+ * mdadm - manage Linux "md" devices aka RAID arrays.
+ *
+ * Copyright (C) 2011 Neil Brown <neilb@suse.de>
+ *
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ *
+ * Author: Neil Brown
+ * Email: <neilb@suse.de>
+ */
+
+#include "mdadm.h"
+#include <ctype.h>
+
+/* This fill contains various 'library' style function. They
+ * have no dependency on anything outside this file.
+ */
+
+int get_mdp_major(void)
+{
+static int mdp_major = -1;
+ FILE *fl;
+ char *w;
+ int have_block = 0;
+ int have_devices = 0;
+ int last_num = -1;
+
+ if (mdp_major != -1)
+ return mdp_major;
+ fl = fopen("/proc/devices", "r");
+ if (!fl)
+ return -1;
+ while ((w = conf_word(fl, 1))) {
+ if (have_block && strcmp(w, "devices:")==0)
+ have_devices = 1;
+ have_block = (strcmp(w, "Block")==0);
+ if (isdigit(w[0]))
+ last_num = atoi(w);
+ if (have_devices && strcmp(w, "mdp")==0)
+ mdp_major = last_num;
+ free(w);
+ }
+ fclose(fl);
+ return mdp_major;
+}
+
+
+void fmt_devname(char *name, int num)
+{
+ if (num >= 0)
+ sprintf(name, "md%d", num);
+ else
+ sprintf(name, "md_d%d", -1-num);
+}
+
+char *devnum2devname(int num)
+{
+ char name[100];
+ fmt_devname(name,num);
+ return strdup(name);
+}
+
+int devname2devnum(char *name)
+{
+ char *ep;
+ int num;
+ if (strncmp(name, "md_d", 4)==0)
+ num = -1-strtoul(name+4, &ep, 10);
+ else
+ num = strtoul(name+2, &ep, 10);
+ return num;
+}
+
+int stat2devnum(struct stat *st)
+{
+ char path[30];
+ char link[200];
+ char *cp;
+ int n;
+
+ if ((S_IFMT & st->st_mode) == S_IFBLK) {
+ if (major(st->st_rdev) == MD_MAJOR)
+ return minor(st->st_rdev);
+ else if (major(st->st_rdev) == (unsigned)get_mdp_major())
+ return -1- (minor(st->st_rdev)>>MdpMinorShift);
+
+ /* must be an extended-minor partition. Look at the
+ * /sys/dev/block/%d:%d link which must look like
+ * ../../block/mdXXX/mdXXXpYY
+ */
+ sprintf(path, "/sys/dev/block/%d:%d", major(st->st_rdev),
+ minor(st->st_rdev));
+ n = readlink(path, link, sizeof(link)-1);
+ if (n <= 0)
+ return NoMdDev;
+ link[n] = 0;
+ cp = strrchr(link, '/');
+ if (cp) *cp = 0;
+ cp = strrchr(link, '/');
+ if (cp && strncmp(cp, "/md", 3) == 0)
+ return devname2devnum(cp+1);
+ }
+ return NoMdDev;
+
+}
+
+int fd2devnum(int fd)
+{
+ struct stat stb;
+ if (fstat(fd, &stb) == 0)
+ return stat2devnum(&stb);
+ return NoMdDev;
+}
+
+
+
+/*
+ * convert a major/minor pair for a block device into a name in /dev, if possible.
+ * On the first call, walk /dev collecting name.
+ * Put them in a simple linked listfor now.
+ */
+struct devmap {
+ int major, minor;
+ char *name;
+ struct devmap *next;
+} *devlist = NULL;
+int devlist_ready = 0;
+
+int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
+{
+ struct stat st;
+
+ if (S_ISLNK(stb->st_mode)) {
+ if (stat(name, &st) != 0)
+ return 0;
+ stb = &st;
+ }
+
+ if ((stb->st_mode&S_IFMT)== S_IFBLK) {
+ char *n = strdup(name);
+ struct devmap *dm = malloc(sizeof(*dm));
+ if (strncmp(n, "/dev/./", 7)==0)
+ strcpy(n+4, name+6);
+ if (dm) {
+ dm->major = major(stb->st_rdev);
+ dm->minor = minor(stb->st_rdev);
+ dm->name = n;
+ dm->next = devlist;
+ devlist = dm;
+ }
+ }
+ return 0;
+}
+
+#ifndef HAVE_NFTW
+#ifdef HAVE_FTW
+int add_dev_1(const char *name, const struct stat *stb, int flag)
+{
+ return add_dev(name, stb, flag, NULL);
+}
+int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
+{
+ return ftw(path, add_dev_1, nopenfd);
+}
+#else
+int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
+{
+ return 0;
+}
+#endif /* HAVE_FTW */
+#endif /* HAVE_NFTW */
+
+/*
+ * Find a block device with the right major/minor number.
+ * If we find multiple names, choose the shortest.
+ * If we find a name in /dev/md/, we prefer that.
+ * This applies only to names for MD devices.
+ */
+char *map_dev(int major, int minor, int create)
+{
+ struct devmap *p;
+ char *regular = NULL, *preferred=NULL;
+ int did_check = 0;
+
+ if (major == 0 && minor == 0)
+ return NULL;
+
+ retry:
+ if (!devlist_ready) {
+ char *dev = "/dev";
+ struct stat stb;
+ while(devlist) {
+ struct devmap *d = devlist;
+ devlist = d->next;
+ free(d->name);
+ free(d);
+ }
+ if (lstat(dev, &stb)==0 &&
+ S_ISLNK(stb.st_mode))
+ dev = "/dev/.";
+ nftw(dev, add_dev, 10, FTW_PHYS);
+ devlist_ready=1;
+ did_check = 1;
+ }
+
+ for (p=devlist; p; p=p->next)
+ if (p->major == major &&
+ p->minor == minor) {
+ if (strncmp(p->name, "/dev/md/",8) == 0) {
+ if (preferred == NULL ||
+ strlen(p->name) < strlen(preferred))
+ preferred = p->name;
+ } else {
+ if (regular == NULL ||
+ strlen(p->name) < strlen(regular))
+ regular = p->name;
+ }
+ }
+ if (!regular && !preferred && !did_check) {
+ devlist_ready = 0;
+ goto retry;
+ }
+ if (create && !regular && !preferred) {
+ static char buf[30];
+ snprintf(buf, sizeof(buf), "%d:%d", major, minor);
+ regular = buf;
+ }
+
+ return preferred ? preferred : regular;
+}
+
+
+/* conf_word gets one word from the conf file.
+ * if "allow_key", then accept words at the start of a line,
+ * otherwise stop when such a word is found.
+ * We assume that the file pointer is at the end of a word, so the
+ * next character is a space, or a newline. If not, it is the start of a line.
+ */
+
+char *conf_word(FILE *file, int allow_key)
+{
+ int wsize = 100;
+ int len = 0;
+ int c;
+ int quote;
+ int wordfound = 0;
+ char *word = malloc(wsize);
+
+ if (!word) abort();
+
+ while (wordfound==0) {
+ /* at the end of a word.. */
+ c = getc(file);
+ if (c == '#')
+ while (c != EOF && c != '\n')
+ c = getc(file);
+ if (c == EOF) break;
+ if (c == '\n') continue;
+
+ if (c != ' ' && c != '\t' && ! allow_key) {
+ ungetc(c, file);
+ break;
+ }
+ /* looks like it is safe to get a word here, if there is one */
+ quote = 0;
+ /* first, skip any spaces */
+ while (c == ' ' || c == '\t')
+ c = getc(file);
+ if (c != EOF && c != '\n' && c != '#') {
+ /* we really have a character of a word, so start saving it */
+ while (c != EOF && c != '\n' && (quote || (c!=' ' && c != '\t'))) {
+ wordfound = 1;
+ if (quote && c == quote) quote = 0;
+ else if (quote == 0 && (c == '\'' || c == '"'))
+ quote = c;
+ else {
+ if (len == wsize-1) {
+ wsize += 100;
+ word = realloc(word, wsize);
+ if (!word) abort();
+ }
+ word[len++] = c;
+ }
+ c = getc(file);
+ /* Hack for broken kernels (2.6.14-.24) that put
+ * "active(auto-read-only)"
+ * in /proc/mdstat instead of
+ * "active (auto-read-only)"
+ */
+ if (c == '(' && len >= 6
+ && strncmp(word+len-6, "active", 6) == 0)
+ c = ' ';
+ }
+ }
+ if (c != EOF) ungetc(c, file);
+ }
+ word[len] = 0;
+
+ /* Further HACK for broken kernels.. 2.6.14-2.6.24 */
+ if (strcmp(word, "auto-read-only)") == 0)
+ strcpy(word, "(auto-read-only)");
+
+/* printf("word is <%s>\n", word); */
+ if (!wordfound) {
+ free(word);
+ word = NULL;
+ }
+ return word;
+}
diff --git a/util.c b/util.c
index 45e68739..1056ae4a 100644
--- a/util.c
+++ b/util.c
@@ -602,122 +602,6 @@ int is_standard(char *dev, int *nump)
return type;
}
-
-/*
- * convert a major/minor pair for a block device into a name in /dev, if possible.
- * On the first call, walk /dev collecting name.
- * Put them in a simple linked listfor now.
- */
-struct devmap {
- int major, minor;
- char *name;
- struct devmap *next;
-} *devlist = NULL;
-int devlist_ready = 0;
-
-int add_dev(const char *name, const struct stat *stb, int flag, struct FTW *s)
-{
- struct stat st;
-
- if (S_ISLNK(stb->st_mode)) {
- if (stat(name, &st) != 0)
- return 0;
- stb = &st;
- }
-
- if ((stb->st_mode&S_IFMT)== S_IFBLK) {
- char *n = strdup(name);
- struct devmap *dm = malloc(sizeof(*dm));
- if (strncmp(n, "/dev/./", 7)==0)
- strcpy(n+4, name+6);
- if (dm) {
- dm->major = major(stb->st_rdev);
- dm->minor = minor(stb->st_rdev);
- dm->name = n;
- dm->next = devlist;
- devlist = dm;
- }
- }
- return 0;
-}
-
-#ifndef HAVE_NFTW
-#ifdef HAVE_FTW
-int add_dev_1(const char *name, const struct stat *stb, int flag)
-{
- return add_dev(name, stb, flag, NULL);
-}
-int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
-{
- return ftw(path, add_dev_1, nopenfd);
-}
-#else
-int nftw(const char *path, int (*han)(const char *name, const struct stat *stb, int flag, struct FTW *s), int nopenfd, int flags)
-{
- return 0;
-}
-#endif /* HAVE_FTW */
-#endif /* HAVE_NFTW */
-
-/*
- * Find a block device with the right major/minor number.
- * If we find multiple names, choose the shortest.
- * If we find a name in /dev/md/, we prefer that.
- * This applies only to names for MD devices.
- */
-char *map_dev(int major, int minor, int create)
-{
- struct devmap *p;
- char *regular = NULL, *preferred=NULL;
- int did_check = 0;
-
- if (major == 0 && minor == 0)
- return NULL;
-
- retry:
- if (!devlist_ready) {
- char *dev = "/dev";
- struct stat stb;
- while(devlist) {
- struct devmap *d = devlist;
- devlist = d->next;
- free(d->name);
- free(d);
- }
- if (lstat(dev, &stb)==0 &&
- S_ISLNK(stb.st_mode))
- dev = "/dev/.";
- nftw(dev, add_dev, 10, FTW_PHYS);
- devlist_ready=1;
- did_check = 1;
- }
-
- for (p=devlist; p; p=p->next)
- if (p->major == major &&
- p->minor == minor) {
- if (strncmp(p->name, "/dev/md/",8) == 0) {
- if (preferred == NULL ||
- strlen(p->name) < strlen(preferred))
- preferred = p->name;
- } else {
- if (regular == NULL ||
- strlen(p->name) < strlen(regular))
- regular = p->name;
- }
- }
- if (!regular && !preferred && !did_check) {
- devlist_ready = 0;
- goto retry;
- }
- if (create && !regular && !preferred) {
- static char buf[30];
- snprintf(buf, sizeof(buf), "%d:%d", major, minor);
- regular = buf;
- }
-
- return preferred ? preferred : regular;
-}
-
unsigned long calc_csum(void *super, int bytes)
{
unsigned long long newcsum = 0;
@@ -828,34 +712,6 @@ unsigned long long calc_array_size(int level, int raid_disks, int layout,
return data_disks * devsize;
}
-int get_mdp_major(void)
-{
-static int mdp_major = -1;
- FILE *fl;
- char *w;
- int have_block = 0;
- int have_devices = 0;
- int last_num = -1;
-
- if (mdp_major != -1)
- return mdp_major;
- fl = fopen("/proc/devices", "r");
- if (!fl)
- return -1;
- while ((w = conf_word(fl, 1))) {
- if (have_block && strcmp(w, "devices:")==0)
- have_devices = 1;
- have_block = (strcmp(w, "Block")==0);
- if (isdigit(w[0]))
- last_num = atoi(w);
- if (have_devices && strcmp(w, "mdp")==0)
- mdp_major = last_num;
- free(w);
- }
- fclose(fl);
- return mdp_major;
-}
-
#if !defined(MDASSEMBLE) || defined(MDASSEMBLE) && defined(MDASSEMBLE_AUTO)
char *get_md_name(int dev)
{
@@ -1684,73 +1540,6 @@ unsigned long long min_recovery_start(struct mdinfo *array)
return recovery_start;
}
-void fmt_devname(char *name, int num)
-{
- if (num >= 0)
- sprintf(name, "md%d", num);
- else
- sprintf(name, "md_d%d", -1-num);
-}
-
-char *devnum2devname(int num)
-{
- char name[100];
- fmt_devname(name,num);
- return strdup(name);
-}
-
-int devname2devnum(char *name)
-{
- char *ep;
- int num;
- if (strncmp(name, "md_d", 4)==0)
- num = -1-strtoul(name+4, &ep, 10);
- else
- num = strtoul(name+2, &ep, 10);
- return num;
-}
-
-int stat2devnum(struct stat *st)
-{
- char path[30];
- char link[200];
- char *cp;
- int n;
-
- if ((S_IFMT & st->st_mode) == S_IFBLK) {
- if (major(st->st_rdev) == MD_MAJOR)
- return minor(st->st_rdev);
- else if (major(st->st_rdev) == (unsigned)get_mdp_major())
- return -1- (minor(st->st_rdev)>>MdpMinorShift);
-
- /* must be an extended-minor partition. Look at the
- * /sys/dev/block/%d:%d link which must look like
- * ../../block/mdXXX/mdXXXpYY
- */
- sprintf(path, "/sys/dev/block/%d:%d", major(st->st_rdev),
- minor(st->st_rdev));
- n = readlink(path, link, sizeof(link)-1);
- if (n <= 0)
- return NoMdDev;
- link[n] = 0;
- cp = strrchr(link, '/');
- if (cp) *cp = 0;
- cp = strrchr(link, '/');
- if (cp && strncmp(cp, "/md", 3) == 0)
- return devname2devnum(cp+1);
- }
- return NoMdDev;
-
-}
-
-int fd2devnum(int fd)
-{
- struct stat stb;
- if (fstat(fd, &stb) == 0)
- return stat2devnum(&stb);
- return NoMdDev;
-}
-
int mdmon_pid(int devnum)
{
char path[100];