diff options
author | NeilBrown <neilb@suse.de> | 2008-08-19 17:55:15 +1000 |
---|---|---|
committer | NeilBrown <neilb@suse.de> | 2008-08-19 17:55:15 +1000 |
commit | e9dd159873cfa0da1ec3e4f173c24f330ea526f8 (patch) | |
tree | f95abf6b0736b9f7a0bd3743d037bc8f3f7b793d | |
parent | 3c558363a1991430e8a9e10c93ee9ee3f8996940 (diff) | |
download | mdadm-e9dd159873cfa0da1ec3e4f173c24f330ea526f8.tar.gz mdadm-e9dd159873cfa0da1ec3e4f173c24f330ea526f8.tar.xz mdadm-e9dd159873cfa0da1ec3e4f173c24f330ea526f8.zip |
Allow an externally managed array to be marked readonly
If the metadata_version is
-mdXXX/whatever
rather than
/mdXXX/whatever
then the array is readonly and should be left alone by mdmon.
Signed-off-by: NeilBrown <neilb@suse.de>
-rw-r--r-- | Manage.c | 43 | ||||
-rw-r--r-- | managemon.c | 1 | ||||
-rw-r--r-- | mdadm.h | 9 | ||||
-rw-r--r-- | mdmon.h | 1 | ||||
-rw-r--r-- | monitor.c | 22 |
5 files changed, 67 insertions, 9 deletions
@@ -45,11 +45,54 @@ int Manage_ro(char *devname, int fd, int readonly) * */ mdu_array_info_t array; + struct mdinfo *mdi; if (md_get_version(fd) < 9000) { fprintf(stderr, Name ": need md driver version 0.90.0 or later\n"); return 1; } + /* If this is an externally-manage array, we need to modify the + * metadata_version so that mdmon doesn't undo our change. + */ + mdi = sysfs_read(fd, -1, GET_LEVEL|GET_VERSION); + if (mdi && + mdi->array.major_version == -1 && + mdi->array.level > 0 && + is_subarray(mdi->text_version)) { + char vers[64]; + strcpy(vers, "external:"); + strcat(vers, mdi->text_version); + if (readonly > 0) { + int rv; + /* We set readonly ourselves. */ + vers[9] = '-'; + sysfs_set_str(mdi, NULL, "metadata_version", vers); + + close(fd); + rv = sysfs_set_str(mdi, NULL, "array_state", "readonly"); + + if (rv < 0) { + fprintf(stderr, Name ": failed to set readonly for %s: %s\n", + devname, strerror(errno)); + + vers[9] = mdi->text_version[0]; + sysfs_set_str(mdi, NULL, "metadata_version", vers); + return 1; + } + } else { + char *cp; + /* We cannot set read/write - must signal mdmon */ + vers[9] = '/'; + sysfs_set_str(mdi, NULL, "metadata_version", vers); + + cp = strchr(vers+10, '/'); + if (*cp) + *cp = 0; + ping_monitor(vers+10); + } + return 0; + } + if (ioctl(fd, GET_ARRAY_INFO, &array)) { fprintf(stderr, Name ": %s does not appear to be active.\n", devname); diff --git a/managemon.c b/managemon.c index 1c329c5..15e431f 100644 --- a/managemon.c +++ b/managemon.c @@ -460,6 +460,7 @@ static void manage_new(struct mdstat_ent *mdstat, new->action_fd = sysfs_open(new->devnum, NULL, "sync_action"); new->info.state_fd = sysfs_open(new->devnum, NULL, "array_state"); new->resync_start_fd = sysfs_open(new->devnum, NULL, "resync_start"); + new->metadata_fd = sysfs_open(new->devnum, NULL, "metadata_version"); get_resync_start(new); dprintf("%s: inst: %d action: %d state: %d\n", __func__, atoi(inst), new->action_fd, new->info.state_fd); @@ -807,7 +807,14 @@ static inline int ROUND_UP(int a, int base) static inline int is_subarray(char *vers) { - return (*vers == '/'); + /* The version string for a 'subarray' (an array in a container) + * is + * /containername/componentname for normal read-write arrays + * -containername/componentname for read-only arrays. + * containername is e.g. md0, md_d1 + * componentname is dependant on the metadata. e.g. '1' 'S1' ... + */ + return (*vers == '/' || *vers == '-'); } #define LEVEL_MULTIPATH (-4) @@ -19,6 +19,7 @@ struct active_array { int action_fd; int resync_start_fd; + int metadata_fd; /* for monitoring rw/ro status */ enum array_state prev_state, curr_state, next_state; enum sync_action prev_action, curr_action, next_action; @@ -238,15 +238,21 @@ static int read_and_act(struct active_array *a) } if (a->curr_state == readonly) { - /* Well, I'm ready to handle things, so - * read-auto is OK. FIXME what if we really want - * readonly ??? + /* Well, I'm ready to handle things. If readonly + * wasn't requested, transition to read-auto. */ - get_resync_start(a); - if (a->container->ss->set_array_state(a, 2)) - a->next_state = read_auto; /* array is clean */ - else - a->next_state = active; /* Now active for recovery etc */ + char buf[64]; + read_attr(buf, sizeof(buf), a->metadata_fd); + if (strncmp(buf, "external:-", 10) == 0) { + /* explicit request for readonly array. Leave it alone */ + ; + } else { + get_resync_start(a); + if (a->container->ss->set_array_state(a, 2)) + a->next_state = read_auto; /* array is clean */ + else + a->next_state = active; /* Now active for recovery etc */ + } } if (!deactivate && |