*
*/
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);
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);
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)
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;
}
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 &&