summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Assemble.c17
-rw-r--r--Incremental.c13
-rw-r--r--ReadMe.c1
-rw-r--r--mdadm.8.in7
-rw-r--r--mdadm.c6
-rw-r--r--mdadm.h1
6 files changed, 38 insertions, 7 deletions
diff --git a/Assemble.c b/Assemble.c
index c0ed917d..d7650010 100644
--- a/Assemble.c
+++ b/Assemble.c
@@ -719,6 +719,7 @@ int Assemble(struct supertype *st, char *mddev,
/* This is a member of a container. Try starting the array. */
int err;
err = assemble_container_content(st, mdfd, content, runstop,
+ readonly,
chosen_name, verbose,
backup_file, freeze_reshape);
close(mdfd);
@@ -1378,6 +1379,11 @@ int Assemble(struct supertype *st, char *mddev,
rv = Grow_continue(mdfd, st, content,
backup_file,
freeze_reshape);
+ } else if (readonly &&
+ sysfs_attribute_available(
+ content, NULL, "array_state")) {
+ rv = sysfs_set_str(content, NULL,
+ "array_state", "readonly");
} else
#endif
rv = ioctl(mdfd, RUN_ARRAY, NULL);
@@ -1543,6 +1549,7 @@ int Assemble(struct supertype *st, char *mddev,
#ifndef MDASSEMBLE
int assemble_container_content(struct supertype *st, int mdfd,
struct mdinfo *content, int runstop,
+ int readonly,
char *chosen_name, int verbose,
char *backup_file, int freeze_reshape)
{
@@ -1556,12 +1563,18 @@ int assemble_container_content(struct supertype *st, int mdfd,
sysfs_init(content, mdfd, 0);
sra = sysfs_read(mdfd, 0, GET_VERSION);
- if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0)
+ if (sra == NULL || strcmp(sra->text_version, content->text_version) != 0) {
+ if (content->array.major_version == -1 &&
+ content->array.minor_version == -2 &&
+ readonly &&
+ content->text_version[0] == '/')
+ content->text_version[0] = '-';
if (sysfs_set_array(content, md_get_version(mdfd)) != 0) {
if (sra)
sysfs_free(sra);
return 1;
}
+ }
/* There are two types of reshape: container wide or sub-array specific
* Check if metadata requests blocking container wide reshapes
@@ -1628,7 +1641,7 @@ int assemble_container_content(struct supertype *st, int mdfd,
case LEVEL_MULTIPATH:
case 0:
err = sysfs_set_str(content, NULL, "array_state",
- "active");
+ readonly ? "readonly" : "active");
break;
default:
err = sysfs_set_str(content, NULL, "array_state",
diff --git a/Incremental.c b/Incremental.c
index 44d5c7c2..009d88c1 100644
--- a/Incremental.c
+++ b/Incremental.c
@@ -44,7 +44,8 @@ static int try_spare(char *devname, int *dfdp, struct dev_policy *pol,
static int Incremental_container(struct supertype *st, char *devname,
char *homehost,
- int verbose, int runstop, int autof,
+ int verbose, int runstop,
+ int readonly, int autof,
int freeze_reshape);
int Incremental(char *devname, int verbose, int runstop,
@@ -139,7 +140,8 @@ int Incremental(char *devname, int verbose, int runstop,
pr_err("failed to get "
"exclusive lock on mapfile\n");
rv = Incremental_container(st, devname, homehost,
- verbose, runstop, autof,
+ verbose, runstop,
+ 0, autof,
freeze_reshape);
map_unlock(&map);
return rv;
@@ -451,7 +453,7 @@ int Incremental(char *devname, int verbose, int runstop,
sysfs_free(sra);
if (!rv)
rv = Incremental_container(st, chosen_name, homehost,
- verbose, runstop, autof,
+ verbose, runstop, 0, autof,
freeze_reshape);
map_unlock(&map);
if (rv == 1)
@@ -1335,7 +1337,8 @@ static char *container2devname(char *devname)
static int Incremental_container(struct supertype *st, char *devname,
char *homehost, int verbose,
- int runstop, int autof, int freeze_reshape)
+ int runstop, int readonly,
+ int autof, int freeze_reshape)
{
/* Collect the contents of this container and for each
* array, choose a device name and assemble the array.
@@ -1470,7 +1473,7 @@ static int Incremental_container(struct supertype *st, char *devname,
return 2;
}
- assemble_container_content(st, mdfd, ra, runstop,
+ assemble_container_content(st, mdfd, ra, runstop, readonly,
chosen_name, verbose, NULL,
freeze_reshape);
close(mdfd);
diff --git a/ReadMe.c b/ReadMe.c
index b6aac0b3..35ffeaac 100644
--- a/ReadMe.c
+++ b/ReadMe.c
@@ -440,6 +440,7 @@ char Help_assemble[] =
" : out-of-date. This involves modifying the superblocks.\n"
" --update= -U : Update superblock: try '-A --update=?' for option list.\n"
" --no-degraded : Assemble but do not start degraded arrays.\n"
+" --readonly -o : Mark the array as read-only. No resync will start.\n"
;
char Help_manage[] =
diff --git a/mdadm.8.in b/mdadm.8.in
index 1a7cba7e..33919bd2 100644
--- a/mdadm.8.in
+++ b/mdadm.8.in
@@ -832,6 +832,13 @@ initial resync work faster). With
will not try to be so clever.
.TP
+.BR \-o ", " \-\-readonly
+Start the array
+.B read only
+rather than read-write as normal. No writes will be allowed to the
+array, and no resync, recovery, or reshape will be started.
+
+.TP
.BR \-a ", " "\-\-auto{=yes,md,mdp,part,p}{NN}"
Instruct mdadm how to create the device file if needed, possibly allocating
an unused minor number. "md" causes a non-partitionable array
diff --git a/mdadm.c b/mdadm.c
index d346240e..e10fc38d 100644
--- a/mdadm.c
+++ b/mdadm.c
@@ -707,6 +707,12 @@ int main(int argc, char *argv[])
}
continue;
+ case O(ASSEMBLE,'o'):
+ case O(MANAGE,'o'):
+ case O(CREATE,'o'):
+ readonly = 1;
+ continue;
+
case O(ASSEMBLE,'U'): /* update the superblock */
case O(MISC,'U'):
if (update) {
diff --git a/mdadm.h b/mdadm.h
index 3071c45b..f96ac7b1 100644
--- a/mdadm.h
+++ b/mdadm.h
@@ -1193,6 +1193,7 @@ extern int flush_metadata_updates(struct supertype *st);
extern void append_metadata_update(struct supertype *st, void *buf, int len);
extern int assemble_container_content(struct supertype *st, int mdfd,
struct mdinfo *content, int runstop,
+ int readonly,
char *chosen_name, int verbose,
char *backup_file, int freeze_reshape);
extern struct mdinfo *container_choose_spares(struct supertype *st,