return n;
}
-static int get_sync_pos(struct active_array *a)
-{
- char buf[30];
- int n;
-
- n = read_attr(buf, 30, a->sync_pos_fd);
- if (n <= 0)
- return n;
-
- if (strncmp(buf, "max", 3) == 0) {
- a->sync_pos = ~(unsigned long long)0;
- return 1;
- }
- a->sync_pos = strtoull(buf, NULL, 10);
- return 1;
-}
static int get_resync_start(struct active_array *a)
{
* sync_action was 'resync' and becomes 'idle' and resync_start becomes
* MaxSector
* Notify metadata that sync is complete.
- * "Deal with Degraded"
*
* recovery completes
* sync_action changes from 'recover' to 'idle'
* Check each device state and mark metadata if 'faulty' or 'in_sync'.
- * "Deal with Degraded"
- *
- * deal with degraded array
- * We only do this when first noticing the array is degraded.
- * This can be when we first see the array, when sync completes or
- * when recovery completes.
- *
- * Check if number of failed devices suggests recovery is needed, and
- * skip if not.
- * Ask metadata for a spare device
- * Add device as not in_sync and give a role
- * Update metadata.
- * Start recovery.
*
* deal with resync
* This only happens on finding a new array... mdadm will have set
static int read_and_act(struct active_array *a)
{
- int check_degraded;
+ int check_degraded = 0;
int deactivate = 0;
struct mdinfo *mdi;
a->curr_action = read_action(a->action_fd);
for (mdi = a->info.devs; mdi ; mdi = mdi->next) {
mdi->next_state = 0;
- if (mdi->state_fd > 0)
+ if (mdi->state_fd >= 0)
mdi->curr_state = read_dev_state(mdi->state_fd);
}
if (a->curr_state <= inactive &&
a->prev_state > inactive) {
/* array has been stopped */
- get_sync_pos(a);
- a->container->ss->mark_clean(a, a->sync_pos);
+ a->container->ss->set_array_state(a, 1);
a->next_state = clear;
deactivate = 1;
}
if (a->curr_state == write_pending) {
- a->container->ss->mark_clean(a, 0);
+ get_resync_start(a);
+ a->container->ss->set_array_state(a, 0);
a->next_state = active;
}
if (a->curr_state == active_idle) {
* readonly ???
*/
get_resync_start(a);
+ printf("Found a readonly array at %llu\n", a->resync_start);
if (a->resync_start == ~0ULL)
a->next_state = read_auto; /* array is clean */
else {
- a->container->ss->mark_clean(a, 0);
+ a->container->ss->set_array_state(a, 0);
a->next_state = active;
}
}
* until the array goes inactive or readonly though.
* Just check if we need to fiddle spares.
*/
+ get_resync_start(a);
+ a->container->ss->set_array_state(a, 0);
check_degraded = 1;
}
}
}
-
for (mdi = a->info.devs ; mdi ; mdi = mdi->next) {
if (mdi->curr_state & DS_FAULTY) {
a->container->ss->set_disk(a, mdi->disk.raid_disk,
}
}
- if (check_degraded) {
- // FIXME;
- }
-
- a->container->ss->sync_metadata(a);
+ a->container->ss->sync_metadata(a->container);
/* Effect state changes in the array */
if (a->next_state != bad_word)
if (a->next_action != bad_action)
write_attr(sync_actions[a->next_action], a->action_fd);
for (mdi = a->info.devs; mdi ; mdi = mdi->next) {
- if (mdi->next_state == DS_REMOVE && mdi->state_fd > 0) {
- int remove_err;
+ if (mdi->next_state == DS_REMOVE && mdi->state_fd >= 0) {
+ int remove_result;
write_attr("-blocked", mdi->state_fd);
/* the kernel may not be able to immediately remove the
* disk, we can simply wait until the next event to try
* again.
*/
- remove_err = write_attr("remove", mdi->state_fd);
- if (!remove_err) {
+ remove_result = write_attr("remove", mdi->state_fd);
+ if (remove_result > 0) {
close(mdi->state_fd);
mdi->state_fd = -1;
}
mdi->next_state = 0;
}
+ if (check_degraded) {
+ /* manager will do the actual check */
+ a->check_degraded = 1;
+ signal_manager();
+ }
+
if (deactivate)
a->container = NULL;
return -1;
}
-static int wait_and_act(struct active_array **aap, int pfd,
+static int wait_and_act(struct supertype *container, int pfd,
int monfd, int nowait)
{
fd_set rfds;
int maxfd = 0;
+ struct active_array **aap = &container->arrays;
struct active_array *a, **ap;
int rv;
struct mdinfo *mdi;
ap = &(*ap)->next;
}
+ if (manager_ready && *aap == NULL) {
+ /* No interesting arrays. Lets see about exiting.
+ * Note that blocking at this point is not a problem
+ * as there are no active arrays, there is nothing that
+ * we need to be ready to do.
+ */
+ int fd = open(container->device_name, O_RDONLY|O_EXCL);
+ if (fd >= 0 || errno != EBUSY) {
+ /* OK, we are safe to leave */
+ exit_now = 1;
+ signal_manager();
+ remove_pidfile(container->devname);
+ exit(0);
+ }
+ }
+
if (!nowait) {
rv = select(maxfd+1, &rfds, NULL, NULL, NULL);
}
}
+ if (update_queue) {
+ struct metadata_update *this;
+
+ for (this = update_queue; this ; this = this->next)
+ container->ss->process_update(container, this);
+
+ update_queue_handled = update_queue;
+ update_queue = NULL;
+ signal_manager();
+ container->ss->sync_metadata(container);
+ }
+
for (a = *aap; a ; a = a->next) {
if (a->replaces && !discard_this) {
struct active_array **ap;
*ap = (*ap)->next;
discard_this = a->replaces;
a->replaces = NULL;
+ /* FIXME check if device->state_fd need to be cleared?*/
signal_manager();
}
if (a->container)
int rv;
int first = 1;
do {
- rv = wait_and_act(&container->arrays, container->mgr_pipe[0],
+ rv = wait_and_act(container, container->mgr_pipe[0],
container->mon_pipe[1], first);
first = 0;
} while (rv >= 0);