-__ATTR(chunk_size, S_IRUGO|S_IWUSR, chunk_size_show, chunk_size_store);
-
-static ssize_t
-resync_start_show(mddev_t *mddev, char *page)
-{
- return sprintf(page, "%llu\n", (unsigned long long)mddev->recovery_cp);
-}
-
-static ssize_t
-resync_start_store(mddev_t *mddev, const char *buf, size_t len)
-{
- /* can only set chunk_size if array is not yet active */
- char *e;
- unsigned long long n = simple_strtoull(buf, &e, 10);
-
- if (mddev->pers)
- return -EBUSY;
- if (!*buf || (*e && *e != '\n'))
- return -EINVAL;
-
- mddev->recovery_cp = n;
- return len;
-}
-static struct md_sysfs_entry md_resync_start =
-__ATTR(resync_start, S_IRUGO|S_IWUSR, resync_start_show, resync_start_store);
-
-/*
- * The array state can be:
- *
- * clear
- * No devices, no size, no level
- * Equivalent to STOP_ARRAY ioctl
- * inactive
- * May have some settings, but array is not active
- * all IO results in error
- * When written, doesn't tear down array, but just stops it
- * suspended (not supported yet)
- * All IO requests will block. The array can be reconfigured.
- * Writing this, if accepted, will block until array is quiessent
- * readonly
- * no resync can happen. no superblocks get written.
- * write requests fail
- * read-auto
- * like readonly, but behaves like 'clean' on a write request.
- *
- * clean - no pending writes, but otherwise active.
- * When written to inactive array, starts without resync
- * If a write request arrives then
- * if metadata is known, mark 'dirty' and switch to 'active'.
- * if not known, block and switch to write-pending
- * If written to an active array that has pending writes, then fails.
- * active
- * fully active: IO and resync can be happening.
- * When written to inactive array, starts with resync
- *
- * write-pending
- * clean, but writes are blocked waiting for 'active' to be written.
- *
- * active-idle
- * like active, but no writes have been seen for a while (100msec).
- *
- */
-enum array_state { clear, inactive, suspended, readonly, read_auto, clean, active,
- write_pending, active_idle, bad_word};
-static char *array_states[] = {
- "clear", "inactive", "suspended", "readonly", "read-auto", "clean", "active",
- "write-pending", "active-idle", NULL };
-
-static int match_word(const char *word, char **list)
-{
- int n;
- for (n=0; list[n]; n++)
- if (cmd_match(word, list[n]))
- break;
- return n;
-}
-
-static ssize_t
-array_state_show(mddev_t *mddev, char *page)
-{
- enum array_state st = inactive;
-
- if (mddev->pers)
- switch(mddev->ro) {
- case 1:
- st = readonly;
- break;
- case 2:
- st = read_auto;
- break;
- case 0:
- if (mddev->in_sync)
- st = clean;
- else if (mddev->safemode)
- st = active_idle;
- else
- st = active;
- }
- else {
- if (list_empty(&mddev->disks) &&
- mddev->raid_disks == 0 &&
- mddev->size == 0)
- st = clear;
- else
- st = inactive;
- }
- return sprintf(page, "%s\n", array_states[st]);
-}
-
-static int do_md_stop(mddev_t * mddev, int ro);
-static int do_md_run(mddev_t * mddev);
-static int restart_array(mddev_t *mddev);
-
-static ssize_t
-array_state_store(mddev_t *mddev, const char *buf, size_t len)
-{
- int err = -EINVAL;
- enum array_state st = match_word(buf, array_states);
- switch(st) {
- case bad_word:
- break;
- case clear:
- /* stopping an active array */
- if (mddev->pers) {
- if (atomic_read(&mddev->active) > 1)
- return -EBUSY;
- err = do_md_stop(mddev, 0);
- }
- break;
- case inactive:
- /* stopping an active array */
- if (mddev->pers) {
- if (atomic_read(&mddev->active) > 1)
- return -EBUSY;
- err = do_md_stop(mddev, 2);
- }
- break;
- case suspended:
- break; /* not supported yet */
- case readonly:
- if (mddev->pers)
- err = do_md_stop(mddev, 1);
- else {
- mddev->ro = 1;
- err = do_md_run(mddev);
- }
- break;
- case read_auto:
- /* stopping an active array */
- if (mddev->pers) {
- err = do_md_stop(mddev, 1);
- if (err == 0)
- mddev->ro = 2; /* FIXME mark devices writable */
- } else {
- mddev->ro = 2;
- err = do_md_run(mddev);
- }
- break;
- case clean:
- if (mddev->pers) {
- restart_array(mddev);
- spin_lock_irq(&mddev->write_lock);
- if (atomic_read(&mddev->writes_pending) == 0) {
- mddev->in_sync = 1;
- mddev->sb_dirty = 1;
- }
- spin_unlock_irq(&mddev->write_lock);
- } else {
- mddev->ro = 0;
- mddev->recovery_cp = MaxSector;
- err = do_md_run(mddev);
- }
- break;
- case active:
- if (mddev->pers) {
- restart_array(mddev);
- mddev->sb_dirty = 0;
- wake_up(&mddev->sb_wait);
- err = 0;
- } else {
- mddev->ro = 0;
- err = do_md_run(mddev);
- }
- break;
- case write_pending:
- case active_idle:
- /* these cannot be set */
- break;
- }
- if (err)
- return err;
- else
- return len;
-}
-static struct md_sysfs_entry md_array_state =
-__ATTR(array_state, S_IRUGO|S_IWUSR, array_state_show, array_state_store);