Allow default creation info to to be stored in mdadm.conf
Default owner, group, mode and 'auto' flag can be given in a 'CREATE' line. Signed-off-by: Neil Brown <neilb@suse.de>
This commit is contained in:
parent
1bfdbe01ff
commit
5bbb48424b
|
@ -8,6 +8,8 @@ Changes Prior to this release
|
||||||
- When creating a bitmap file, choose a chunksize to limit number
|
- When creating a bitmap file, choose a chunksize to limit number
|
||||||
of bitmap chunks to 2 million. More than this can cause kmalloc
|
of bitmap chunks to 2 million. More than this can cause kmalloc
|
||||||
failure.
|
failure.
|
||||||
|
- New 'CREATE' line in mdadm.conf for defaults such as owner, group,
|
||||||
|
mode and auto-flag
|
||||||
|
|
||||||
Changes Prior to 2.4.1 release
|
Changes Prior to 2.4.1 release
|
||||||
- Honour --write-mostly when adding to an array without persistent
|
- Honour --write-mostly when adding to an array without persistent
|
||||||
|
|
20
Makefile
20
Makefile
|
@ -40,10 +40,17 @@ KLIBC_GCC = gcc -nostdinc -iwithprefix include -I$(KLIBC)/klibc/include -I$(KLIB
|
||||||
CC = $(CROSS_COMPILE)gcc
|
CC = $(CROSS_COMPILE)gcc
|
||||||
CXFLAGS = -ggdb
|
CXFLAGS = -ggdb
|
||||||
CWFLAGS = -Wall -Werror -Wstrict-prototypes
|
CWFLAGS = -Wall -Werror -Wstrict-prototypes
|
||||||
|
|
||||||
|
ifdef DEBIAN
|
||||||
|
CPPFLAGS= -DDEBIAN
|
||||||
|
else
|
||||||
|
CPPFLAGS=
|
||||||
|
endif
|
||||||
|
|
||||||
SYSCONFDIR = /etc
|
SYSCONFDIR = /etc
|
||||||
CONFFILE = $(SYSCONFDIR)/mdadm.conf
|
CONFFILE = $(SYSCONFDIR)/mdadm.conf
|
||||||
MAILCMD =/usr/sbin/sendmail -t
|
MAILCMD =/usr/sbin/sendmail -t
|
||||||
CFLAGS = $(CWFLAGS) -DCONFFILE=\"$(CONFFILE)\" $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\"
|
CFLAGS = $(CWFLAGS) $(STATIC) $(CPPFLAGS) -DCONFFILE=\"$(CONFFILE)\" $(CXFLAGS) -DSendmail=\""$(MAILCMD)"\"
|
||||||
|
|
||||||
# If you want a static binary, you might uncomment these
|
# If you want a static binary, you might uncomment these
|
||||||
# LDFLAGS = -static
|
# LDFLAGS = -static
|
||||||
|
@ -76,11 +83,14 @@ all : mdadm mdadm.man md.man mdadm.conf.man
|
||||||
everything: all mdadm.static mdadm.uclibc swap_super test_stripe mdassemble mdassemble.uclibc mdassemble.static mdassemble.man
|
everything: all mdadm.static mdadm.uclibc swap_super test_stripe mdassemble mdassemble.uclibc mdassemble.static mdassemble.man
|
||||||
# mdadm.tcc doesn't work..
|
# mdadm.tcc doesn't work..
|
||||||
|
|
||||||
mdadm : $(OBJS)
|
mdadm : rmconf $(OBJS)
|
||||||
$(CC) $(LDFLAGS) -o mdadm $^
|
$(CC) $(LDFLAGS) -o mdadm $(OBJS)
|
||||||
|
|
||||||
mdadm.static : $(OBJS)
|
mdadm.static : STATIC=-DSTATIC
|
||||||
$(CC) $(LDFLAGS) -static -o mdadm.static $^
|
mdadm.static : rmconf $(OBJS)
|
||||||
|
$(CC) $(LDFLAGS) -DSTATIC -static -o mdadm.static $(OBJS)
|
||||||
|
rmconf:
|
||||||
|
rm -f config.o
|
||||||
|
|
||||||
mdadm.tcc : $(SRCS) mdadm.h
|
mdadm.tcc : $(SRCS) mdadm.h
|
||||||
$(TCC) -o mdadm.tcc $(SRCS)
|
$(TCC) -o mdadm.tcc $(SRCS)
|
||||||
|
|
148
config.c
148
config.c
|
@ -33,6 +33,8 @@
|
||||||
#include <glob.h>
|
#include <glob.h>
|
||||||
#include <fnmatch.h>
|
#include <fnmatch.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
#include <pwd.h>
|
||||||
|
#include <grp.h>
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Read the config file
|
* Read the config file
|
||||||
|
@ -77,7 +79,10 @@
|
||||||
char DefaultConfFile[] = CONFFILE;
|
char DefaultConfFile[] = CONFFILE;
|
||||||
char DefaultAltConfFile[] = CONFFILE2;
|
char DefaultAltConfFile[] = CONFFILE2;
|
||||||
|
|
||||||
char *keywords[] = { "device", "array", "mailaddr", "program", "mailfrom", NULL };
|
char *keywords[] = { "devices", "array",
|
||||||
|
"mailaddr", "program", "mailfrom",
|
||||||
|
"create",
|
||||||
|
NULL };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* match_keyword returns an index into the keywords array, or -1 for no match
|
* match_keyword returns an index into the keywords array, or -1 for no match
|
||||||
|
@ -240,6 +245,112 @@ mddev_dev_t load_partitions(void)
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct createinfo createinfo = {
|
||||||
|
#ifdef DEBIAN
|
||||||
|
.gid = 6, /* disk */
|
||||||
|
.mode = 0660,
|
||||||
|
#else
|
||||||
|
.mode = 0600,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
int parse_auto(char *str, char *msg)
|
||||||
|
{
|
||||||
|
int autof;
|
||||||
|
if (str == NULL || *str == 0)
|
||||||
|
autof = -2;
|
||||||
|
else if (strcasecmp(str,"no")==0)
|
||||||
|
autof = -3;
|
||||||
|
else if (strcasecmp(str,"yes")==0)
|
||||||
|
autof = -2;
|
||||||
|
else if (strcasecmp(str,"md")==0)
|
||||||
|
autof = -1;
|
||||||
|
else {
|
||||||
|
/* There might be digits, and maybe a hypen, at the end */
|
||||||
|
char *e = str + strlen(str);
|
||||||
|
int num = 4;
|
||||||
|
int len;
|
||||||
|
while (e > str && isdigit(e[-1]))
|
||||||
|
e--;
|
||||||
|
if (*e) {
|
||||||
|
num = atoi(e);
|
||||||
|
if (num <= 0) num = 1;
|
||||||
|
}
|
||||||
|
if (e > str && e[-1] == '-')
|
||||||
|
e--;
|
||||||
|
len = e - str;
|
||||||
|
if ((len == 3 && strncasecmp(str,"mdp",3)==0) ||
|
||||||
|
(len == 1 && strncasecmp(str,"p",1)==0) ||
|
||||||
|
(len >= 4 && strncasecmp(str,"part",4)==0))
|
||||||
|
autof = num;
|
||||||
|
else {
|
||||||
|
fprintf(stderr, Name ": %s arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n"
|
||||||
|
" optionally followed by a number.\n",
|
||||||
|
msg, str);
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return autof;
|
||||||
|
}
|
||||||
|
static void createline(char *line)
|
||||||
|
{
|
||||||
|
char *w;
|
||||||
|
char *ep;
|
||||||
|
|
||||||
|
for (w=dl_next(line); w!=line; w=dl_next(w)) {
|
||||||
|
if (strncasecmp(w, "auto=", 5) == 0)
|
||||||
|
createinfo.autof = parse_auto(w+5, "auto=");
|
||||||
|
else if (strncasecmp(w, "owner=", 6) == 0) {
|
||||||
|
if (w[6] == 0) {
|
||||||
|
fprintf(stderr, Name ": missing owner name\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
createinfo.uid = strtoul(w+6, &ep, 10);
|
||||||
|
if (*ep != 0) {
|
||||||
|
#ifndef STATIC
|
||||||
|
struct passwd *pw;
|
||||||
|
/* must be a name */
|
||||||
|
pw = getpwnam(w+6);
|
||||||
|
if (pw)
|
||||||
|
createinfo.uid = pw->pw_uid;
|
||||||
|
else
|
||||||
|
#endif /* STATIC */
|
||||||
|
fprintf(stderr, Name ": CREATE user %s not found\n", w+6);
|
||||||
|
}
|
||||||
|
} else if (strncasecmp(w, "group=", 6) == 0) {
|
||||||
|
if (w[6] == 0) {
|
||||||
|
fprintf(stderr, Name ": missing group name\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
createinfo.gid = strtoul(w+6, &ep, 10);
|
||||||
|
if (*ep != 0) {
|
||||||
|
#ifndef STATIC
|
||||||
|
struct group *gr;
|
||||||
|
/* must be a name */
|
||||||
|
gr = getgrnam(w+6);
|
||||||
|
if (gr)
|
||||||
|
createinfo.gid = gr->gr_gid;
|
||||||
|
else
|
||||||
|
#endif /* STATIC */
|
||||||
|
fprintf(stderr, Name ": CREATE group %s not found\n", w+6);
|
||||||
|
}
|
||||||
|
} else if (strncasecmp(w, "mode=", 5) == 0) {
|
||||||
|
if (w[5] == 0) {
|
||||||
|
fprintf(stderr, Name ": missing CREATE mode\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
createinfo.mode = strtoul(w+5, &ep, 8);
|
||||||
|
if (*ep != 0) {
|
||||||
|
createinfo.mode = 0600;
|
||||||
|
fprintf(stderr, Name ": unrecognised CREATE mode %s\n",
|
||||||
|
w+5);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fprintf(stderr, Name ": unrecognised word on CREATE line: %s\n",
|
||||||
|
w);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void devline(char *line)
|
void devline(char *line)
|
||||||
{
|
{
|
||||||
|
@ -364,32 +475,7 @@ void arrayline(char *line)
|
||||||
fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
|
fprintf(stderr, Name ": metadata format %s unknown, ignored.\n", w+9);
|
||||||
} else if (strncasecmp(w, "auto=", 5) == 0 ) {
|
} else if (strncasecmp(w, "auto=", 5) == 0 ) {
|
||||||
/* whether to create device special files as needed */
|
/* whether to create device special files as needed */
|
||||||
if (strcasecmp(w+5, "no")==0)
|
mis.autof = parse_auto(w+5, "auto type");
|
||||||
mis.autof = 0;
|
|
||||||
else if (strcasecmp(w+5,"yes")==0 || strcasecmp(w+5,"md")==0)
|
|
||||||
mis.autof = -1;
|
|
||||||
else {
|
|
||||||
/* There might be digits, and maybe a hyphen, at the end */
|
|
||||||
char *e = w+5 + strlen(w+5);
|
|
||||||
int num = 4;
|
|
||||||
int len;
|
|
||||||
while (e > w+5 && isdigit(e[-1]))
|
|
||||||
e--;
|
|
||||||
if (*e) {
|
|
||||||
num = atoi(e);
|
|
||||||
if (num <= 0) num = 1;
|
|
||||||
}
|
|
||||||
if (e > w+5 && e[-1] == '-')
|
|
||||||
e--;
|
|
||||||
len = e - (w+5);
|
|
||||||
if ((len == 3 && strncasecmp(w+5,"mdp",3)==0) ||
|
|
||||||
(len == 1 && strncasecmp(w+5,"p",1)==0) ||
|
|
||||||
(len >= 4 && strncasecmp(w+5,"part",4)==0))
|
|
||||||
mis.autof = num;
|
|
||||||
else
|
|
||||||
fprintf(stderr, Name ": auto type of \"%s\" ignored for %s\n",
|
|
||||||
w+5, mis.devname?mis.devname:"unlabeled-array");
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
|
fprintf(stderr, Name ": unrecognised word on ARRAY line: %s\n",
|
||||||
w);
|
w);
|
||||||
|
@ -513,6 +599,9 @@ void load_conffile(char *conffile)
|
||||||
case 4: /* MAILFROM */
|
case 4: /* MAILFROM */
|
||||||
mailfromline(line);
|
mailfromline(line);
|
||||||
break;
|
break;
|
||||||
|
case 5: /* CREATE */
|
||||||
|
createline(line);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, Name ": Unknown keyword %s\n", line);
|
fprintf(stderr, Name ": Unknown keyword %s\n", line);
|
||||||
}
|
}
|
||||||
|
@ -542,6 +631,11 @@ char *conf_get_program(char *conffile)
|
||||||
return alert_program;
|
return alert_program;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct createinfo *conf_get_create_info(char *conffile)
|
||||||
|
{
|
||||||
|
load_conffile(conffile);
|
||||||
|
return &createinfo;
|
||||||
|
}
|
||||||
|
|
||||||
mddev_ident_t conf_get_ident(char *conffile, char *dev)
|
mddev_ident_t conf_get_ident(char *conffile, char *dev)
|
||||||
{
|
{
|
||||||
|
|
37
mdadm.c
37
mdadm.c
|
@ -75,7 +75,8 @@ int main(int argc, char *argv[])
|
||||||
int force = 0;
|
int force = 0;
|
||||||
int test = 0;
|
int test = 0;
|
||||||
int assume_clean = 0;
|
int assume_clean = 0;
|
||||||
int autof = 0; /* -2 means create device based on name:
|
int autof = 0; /* -3 means don't create anything,
|
||||||
|
* -2 means create device based on name:
|
||||||
* if it ends mdN, then non-partitioned array N
|
* if it ends mdN, then non-partitioned array N
|
||||||
* if it ends dN, then partitions array N
|
* if it ends dN, then partitions array N
|
||||||
* -1 means create non-partitioned, choose N
|
* -1 means create non-partitioned, choose N
|
||||||
|
@ -482,39 +483,7 @@ int main(int argc, char *argv[])
|
||||||
case O(CREATE,'a'):
|
case O(CREATE,'a'):
|
||||||
case O(BUILD,'a'):
|
case O(BUILD,'a'):
|
||||||
case O(ASSEMBLE,'a'): /* auto-creation of device node */
|
case O(ASSEMBLE,'a'): /* auto-creation of device node */
|
||||||
if (optarg == NULL)
|
autof = parse_auto(optarg, "--auto flag");
|
||||||
autof = -2;
|
|
||||||
else if (strcasecmp(optarg,"no")==0)
|
|
||||||
autof = 0;
|
|
||||||
else if (strcasecmp(optarg,"yes")==0)
|
|
||||||
autof = -2;
|
|
||||||
else if (strcasecmp(optarg,"md")==0)
|
|
||||||
autof = -1;
|
|
||||||
else {
|
|
||||||
/* There might be digits, and maybe a hypen, at the end */
|
|
||||||
char *e = optarg + strlen(optarg);
|
|
||||||
int num = 4;
|
|
||||||
int len;
|
|
||||||
while (e > optarg && isdigit(e[-1]))
|
|
||||||
e--;
|
|
||||||
if (*e) {
|
|
||||||
num = atoi(e);
|
|
||||||
if (num <= 0) num = 1;
|
|
||||||
}
|
|
||||||
if (e > optarg && e[-1] == '-')
|
|
||||||
e--;
|
|
||||||
len = e - optarg;
|
|
||||||
if ((len == 3 && strncasecmp(optarg,"mdp",3)==0) ||
|
|
||||||
(len == 1 && strncasecmp(optarg,"p",1)==0) ||
|
|
||||||
(len >= 4 && strncasecmp(optarg,"part",4)==0))
|
|
||||||
autof = num;
|
|
||||||
else {
|
|
||||||
fprintf(stderr, Name ": --auto flag arg of \"%s\" unrecognised: use no,yes,md,mdp,part\n"
|
|
||||||
" optionally followed by a number.\n",
|
|
||||||
optarg);
|
|
||||||
exit(2);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case O(BUILD,'f'): /* force honouring '-n 1' */
|
case O(BUILD,'f'): /* force honouring '-n 1' */
|
||||||
|
|
38
mdadm.conf.5
38
mdadm.conf.5
|
@ -212,6 +212,41 @@ There should only be one
|
||||||
.B program
|
.B program
|
||||||
line and it should be give only one program.
|
line and it should be give only one program.
|
||||||
|
|
||||||
|
|
||||||
|
.TP
|
||||||
|
.B CREATE
|
||||||
|
The
|
||||||
|
.B create
|
||||||
|
line gives default values to be used when creating device entries for
|
||||||
|
arrays.
|
||||||
|
These include:
|
||||||
|
|
||||||
|
.RS 4
|
||||||
|
.TP
|
||||||
|
.B owner=
|
||||||
|
.TP
|
||||||
|
.B group=
|
||||||
|
These can give user/group ids or names to use instead of system
|
||||||
|
defaults (root/wheel or root/disk).
|
||||||
|
.TP
|
||||||
|
.B mode=
|
||||||
|
An octal file mode such as 0660 can be given to override the default
|
||||||
|
of 0600.
|
||||||
|
.TP
|
||||||
|
.B auto=
|
||||||
|
This corresponds to the
|
||||||
|
.B --auto
|
||||||
|
flag to mdadm. Give
|
||||||
|
.BR yes ,
|
||||||
|
.BR md ,
|
||||||
|
.BR mdp ,
|
||||||
|
.B part
|
||||||
|
- possibly followed by a number of partitions - to indicate how
|
||||||
|
missing device entries should be created.
|
||||||
|
|
||||||
|
.RE
|
||||||
|
|
||||||
|
|
||||||
.SH EXAMPLE
|
.SH EXAMPLE
|
||||||
DEVICE /dev/sd[bcdjkl]1
|
DEVICE /dev/sd[bcdjkl]1
|
||||||
.br
|
.br
|
||||||
|
@ -254,7 +289,8 @@ ARRAY /dev/md/home UUID=9187a482:5dde19d9:eea3cc4a:d646ab8b
|
||||||
MAILADDR root@mydomain.tld
|
MAILADDR root@mydomain.tld
|
||||||
.br
|
.br
|
||||||
PROGRAM /usr/sbin/handle-mdadm-events
|
PROGRAM /usr/sbin/handle-mdadm-events
|
||||||
|
.br
|
||||||
|
CREATE group=system mode=0640 auto=part-8
|
||||||
|
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.BR mdadm (8),
|
.BR mdadm (8),
|
||||||
|
|
10
mdadm.h
10
mdadm.h
|
@ -99,6 +99,13 @@ struct mdinfo {
|
||||||
int new_level, delta_disks, new_layout, new_chunk;
|
int new_level, delta_disks, new_layout, new_chunk;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct createinfo {
|
||||||
|
int uid;
|
||||||
|
int gid;
|
||||||
|
int autof;
|
||||||
|
int mode;
|
||||||
|
};
|
||||||
|
|
||||||
#define Name "mdadm"
|
#define Name "mdadm"
|
||||||
|
|
||||||
enum mode {
|
enum mode {
|
||||||
|
@ -366,9 +373,10 @@ extern int get_mdp_major(void);
|
||||||
extern int dev_open(char *dev, int flags);
|
extern int dev_open(char *dev, int flags);
|
||||||
extern int is_standard(char *dev, int *nump);
|
extern int is_standard(char *dev, int *nump);
|
||||||
|
|
||||||
|
extern int parse_auto(char *str, char *msg);
|
||||||
extern mddev_ident_t conf_get_ident(char *conffile, char *dev);
|
extern mddev_ident_t conf_get_ident(char *conffile, char *dev);
|
||||||
extern mddev_dev_t conf_get_devs(char *conffile);
|
extern mddev_dev_t conf_get_devs(char *conffile);
|
||||||
|
extern struct createinfo *conf_get_create_info(char *conffile);
|
||||||
extern char *conf_get_mailaddr(char *conffile);
|
extern char *conf_get_mailaddr(char *conffile);
|
||||||
extern char *conf_get_mailfrom(char *conffile);
|
extern char *conf_get_mailfrom(char *conffile);
|
||||||
extern char *conf_get_program(char *conffile);
|
extern char *conf_get_program(char *conffile);
|
||||||
|
|
13
mdopen.c
13
mdopen.c
|
@ -82,7 +82,7 @@ void make_parts(char *dev, int cnt)
|
||||||
* If it exists and is not an md device, is not the right type (partitioned or not),
|
* If it exists and is not an md device, is not the right type (partitioned or not),
|
||||||
* or is currently in-use, we remove the device, but remember the owner and mode.
|
* or is currently in-use, we remove the device, but remember the owner and mode.
|
||||||
* If it now doesn't exist, we find a new md array and create the device.
|
* If it now doesn't exist, we find a new md array and create the device.
|
||||||
* Default ownership is user=0, group=0 perm=0600
|
* Default ownership/mode comes from config file.
|
||||||
*/
|
*/
|
||||||
int open_mddev(char *dev, int autof)
|
int open_mddev(char *dev, int autof)
|
||||||
{
|
{
|
||||||
|
@ -93,8 +93,12 @@ int open_mddev(char *dev, int autof)
|
||||||
int must_remove = 0;
|
int must_remove = 0;
|
||||||
struct mdstat_ent *mdlist;
|
struct mdstat_ent *mdlist;
|
||||||
int num;
|
int num;
|
||||||
|
struct createinfo *ci = conf_get_create_info(NULL);
|
||||||
|
|
||||||
if (autof) {
|
if (autof == 0)
|
||||||
|
autof = ci->autof;
|
||||||
|
|
||||||
|
if (autof && autof != -3) {
|
||||||
/* autof is set, so we need to check that the name is ok,
|
/* autof is set, so we need to check that the name is ok,
|
||||||
* and possibly create one if not
|
* and possibly create one if not
|
||||||
*/
|
*/
|
||||||
|
@ -212,6 +216,11 @@ int open_mddev(char *dev, int autof)
|
||||||
perror("chown");
|
perror("chown");
|
||||||
if (chmod(dev, stb.st_mode & 07777))
|
if (chmod(dev, stb.st_mode & 07777))
|
||||||
perror("chmod");
|
perror("chmod");
|
||||||
|
} else {
|
||||||
|
if (chown(dev, ci->uid, ci->gid))
|
||||||
|
perror("chown");
|
||||||
|
if (chmod(dev, ci->mode))
|
||||||
|
perror("chmod");
|
||||||
}
|
}
|
||||||
stat(dev, &stb);
|
stat(dev, &stb);
|
||||||
add_dev(dev, &stb, 0, NULL);
|
add_dev(dev, &stb, 0, NULL);
|
||||||
|
|
Loading…
Reference in New Issue