diff --git a/Assemble.c b/Assemble.c index c0ed917..d765001 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 44d5c7c..009d88c 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 b6aac0b..35ffeaa 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 1a7cba7..33919bd 100644 --- a/mdadm.8.in +++ b/mdadm.8.in @@ -831,6 +831,13 @@ initial resync work faster). With .I mdadm 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 diff --git a/mdadm.c b/mdadm.c index d346240..e10fc38 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 3071c45..f96ac7b 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,