Strip out path testing, we'll do this from userland instead. --- diff/drivers/md/dm-mpath.c 2004-02-18 09:17:18.000000000 +0000 +++ source/drivers/md/dm-mpath.c 2004-02-18 09:17:31.000000000 +0000 @@ -18,6 +18,7 @@ #include #include +/* FIXME: get rid of these */ #define MPATH_FAIL_COUNT 1 #define MPATH_MIN_IO 1000 @@ -26,19 +27,11 @@ struct list_head list; struct dm_dev *dev; - struct priority_group *pg; spinlock_t failed_lock; - /* FIXME: put the next 2 fields in a bitset */ - int tested; int has_failed; unsigned fail_count; - unsigned fail_total; - - struct semaphore test_lock; - struct bio *test_bio; - struct page *test_page; /* FIXME: share this between all paths ? */ }; struct priority_group { @@ -63,16 +56,11 @@ spinlock_t lock; unsigned nr_valid_paths; - unsigned nr_tested_paths; struct path *current_path; unsigned current_count; - unsigned min_io; struct bio_list failed_ios; - struct bio_list test_ios; - - unsigned test_interval; unsigned trigger_event; }; @@ -84,20 +72,6 @@ memset(path, 0, sizeof(*path)); path->failed_lock = SPIN_LOCK_UNLOCKED; path->fail_count = MPATH_FAIL_COUNT; - init_MUTEX_LOCKED(&path->test_lock); /* resume will unlock */ - - path->test_bio = bio_alloc(GFP_KERNEL, 1); - if (!path->test_bio) { - kfree(path); - return NULL; - } - - path->test_page = alloc_page(GFP_KERNEL); - if (!path->test_page) { - bio_put(path->test_bio); - kfree(path); - return NULL; - } } return path; @@ -105,9 +79,6 @@ static inline void free_path(struct path *p) { - ClearPageLocked(p->test_page); - __free_page(p->test_page); - bio_put(p->test_bio); kfree(p); } @@ -168,7 +139,6 @@ memset(m, 0, sizeof(*m)); INIT_LIST_HEAD(&m->priority_groups); m->lock = SPIN_LOCK_UNLOCKED; - m->min_io = MPATH_MIN_IO; } return m; @@ -187,119 +157,6 @@ } /*----------------------------------------------------------------- - * All paths should be tested periodically. - *---------------------------------------------------------------*/ -static void iterate_paths(struct multipath *m, void (*fn)(struct path *p)) -{ - struct priority_group *pg; - struct path *p; - - list_for_each_entry (pg, &m->priority_groups, list) { - list_for_each_entry (p, &pg->paths, list) - fn(p); - } -} - -static void clear_tested(struct path *p) -{ - p->tested = 0; -} - -static void fail_path(struct path *path) -{ - unsigned long flags; - struct multipath *m; - - spin_lock_irqsave(&path->failed_lock, flags); - - /* FIXME: path->fail_count is brain dead */ - if (!path->has_failed && !--path->fail_count) { - path->has_failed = 1; - path->fail_total++; - path->pg->ps->type->set_path_state(path->pg->ps, path, 0); - path->pg->m->trigger_event = 1; - - m = path->pg->m; - spin_lock(&m->lock); - m->nr_valid_paths--; - if (!m->nr_valid_paths) { - iterate_paths(m, clear_tested); - m->nr_tested_paths = 0; - } - - if (path == m->current_path) - m->current_path = NULL; - - spin_unlock(&m->lock); - } - - if (!path->tested) { - path->tested = 1; - - m = path->pg->m; - spin_lock(&m->lock); - m->nr_tested_paths++; - spin_unlock(&m->lock); - } - - spin_unlock_irqrestore(&path->failed_lock, flags); -} - -static void recover_path(struct path *path) -{ - unsigned long flags; - struct multipath *m = path->pg->m; - - spin_lock_irqsave(&path->failed_lock, flags); - - if (path->has_failed) { - path->has_failed = 0; - path->fail_count = MPATH_FAIL_COUNT; - path->pg->ps->type->set_path_state(path->pg->ps, path, 1); - m->trigger_event = 1; - - spin_lock(&m->lock); - m->nr_valid_paths++; - spin_unlock(&m->lock); - } - - spin_unlock_irqrestore(&path->failed_lock, flags); -} - -static int test_endio(struct bio *bio, unsigned int done, int error) -{ - struct path *path = (struct path *) bio->bi_private; - - if (bio->bi_size) - return 1; - - if (error) - fail_path(path); - else - recover_path(path); - - up(&path->test_lock); - return 0; -} - -static void test_path(struct path *p) -{ - /* - * If we get this lock we're allowed to issue a test io - * for this path. - */ - if (down_trylock(&p->test_lock)) - return; - - p->test_bio->bi_sector = 0; - p->test_bio->bi_bdev = p->dev->bdev; - p->test_bio->bi_size = bdev_hardsect_size(p->dev->bdev); - p->test_bio->bi_idx = 0; - - bio_list_add(&p->pg->m->test_ios, p->test_bio); -} - -/*----------------------------------------------------------------- * The multipath daemon is responsible for resubmitting failed ios. *---------------------------------------------------------------*/ static struct dm_daemon _kmpathd; @@ -307,18 +164,6 @@ static LIST_HEAD(_mpaths); static DECLARE_MUTEX(_mpath_lock); -static void submit_ios(struct bio *bio) -{ - struct bio *next; - - while (bio) { - next = bio->bi_next; - bio->bi_next = NULL; - generic_make_request(bio); - bio = next; - } -} - static int __choose_path(struct multipath *m) { struct priority_group *pg; @@ -334,7 +179,8 @@ } m->current_path = path; - m->current_count = m->min_io; + m->current_count = MPATH_MIN_IO; +; return 0; } @@ -375,11 +221,9 @@ struct bio *bio = NULL, *next; spin_lock_irqsave(&m->lock, flags); - if (m->nr_valid_paths || (m->nr_tested_paths == m->nr_paths)) - bio = bio_list_get(&m->failed_ios); + bio = bio_list_get(&m->failed_ios); spin_unlock_irqrestore(&m->lock, flags); - while (bio) { next = bio->bi_next; bio->bi_next = NULL; @@ -389,10 +233,9 @@ /* * This wont loop forever because the * end_io function will fail the ios if - * we've tested all the paths. + * we've no valid paths left. */ bio_io_error(bio, bio->bi_size); - else generic_make_request(bio); @@ -408,33 +251,21 @@ { unsigned long flags; struct multipath *m; - unsigned interval = 0; - int event; down(&_mpath_lock); list_for_each_entry (m, &_mpaths, list) { dispatch_failed_ios(m); - iterate_paths(m, test_path); - submit_ios(bio_list_get(&m->test_ios)); - spin_lock_irqsave(&m->lock, flags); - event = 0; + /* No locking is needed around this */ if (m->trigger_event) { - event = 1; m->trigger_event = 0; - } - spin_unlock_irqrestore(&m->lock, flags); - - if (event) dm_table_event(m->ti->table); - - interval = min_not_zero(interval, m->test_interval); + } } up(&_mpath_lock); blk_run_queues(); - - return ((jiffy_t) interval) * HZ; + return 0; } /*----------------------------------------------------------------- @@ -489,18 +320,6 @@ as->argv += n; } -static void init_test_bio(struct path *p) -{ - struct bio *bio = p->test_bio; - - bio->bi_sector = 0; - bio->bi_rw |= (1 << BIO_RW_FAILFAST); - bio->bi_bdev = p->dev->bdev; - bio->bi_end_io = test_endio; - bio->bi_private = p; - bio_add_page(bio, p->test_page, bdev_hardsect_size(p->dev->bdev), 0); -} - static struct path *parse_path(struct arg_set *as, struct path_selector *ps, struct dm_target *ti) { @@ -523,7 +342,6 @@ ti->error = ESTR("error getting device"); goto bad; } - init_test_bio(p); r = ps->type->add_path(ps, p, as->argc, as->argv, &ti->error); if (r) { @@ -621,20 +439,6 @@ return NULL; } -/* - * Debug only. - */ -static void __check_ordered(struct list_head *head) -{ - struct priority_group *pg; - unsigned last = 0; - - list_for_each_entry (pg, head, list) { - BUG_ON (pg->priority < last); - last = pg->priority; - } -} - static void __insert_priority_group(struct multipath *m, struct priority_group *pg) { @@ -646,9 +450,6 @@ list_add_tail(&pg->list, &tmp->list); pg->m = m; - - /* FIXME: remove debug later */ - __check_ordered(&m->priority_groups); } static int multipath_ctr(struct dm_target *ti, unsigned int argc, @@ -656,7 +457,6 @@ { /* target parameters */ static struct param _params[] = { - {1, 60 * 60, ESTR("invalid path test interval")}, {1, 1024, ESTR("invalid number of priority groups")}, }; @@ -673,11 +473,7 @@ return -EINVAL; } - r = read_param(_params, shift(&as), &m->test_interval, &ti->error); - if (r) - goto bad; - - r = read_param(_params + 1, shift(&as), &m->nr_priority_groups, &ti->error); + r = read_param(_params, shift(&as), &m->nr_priority_groups, &ti->error); if (r) goto bad; @@ -747,6 +543,32 @@ return NULL; } +static void fail_path(struct path *path) +{ + unsigned long flags; + struct multipath *m; + + spin_lock_irqsave(&path->failed_lock, flags); + + /* FIXME: path->fail_count is brain dead */ + if (!path->has_failed && !--path->fail_count) { + path->has_failed = 1; + path->pg->ps->type->fail_path(path->pg->ps, path); + path->pg->m->trigger_event = 1; + + m = path->pg->m; + spin_lock(&m->lock); + m->nr_valid_paths--; + + if (path == m->current_path) + m->current_path = NULL; + + spin_unlock(&m->lock); + } + + spin_unlock_irqrestore(&path->failed_lock, flags); +} + static int multipath_end_io(struct dm_target *ti, struct bio *bio, int error, union map_info *map_context) { @@ -755,7 +577,7 @@ if (error) { spin_lock(&m->lock); - if (!m->nr_valid_paths && (m->nr_tested_paths == m->nr_paths)) { + if (!m->nr_valid_paths) { spin_unlock(&m->lock); return -EIO; } @@ -776,27 +598,12 @@ return 0; } -static void lock_path(struct path *p) {down(&p->test_lock);} -static void unlock_path(struct path *p) {up(&p->test_lock);} - -static void multipath_suspend(struct dm_target *ti) -{ - struct multipath *m = (struct multipath *) ti->private; - iterate_paths(m, lock_path); -} - -static void multipath_resume(struct dm_target *ti) -{ - struct multipath *m = (struct multipath *) ti->private; - iterate_paths(m, unlock_path); -} - /* * Info string has the following format: - * num_groups [num_paths num_selector_args [path_dev A|F fail_count fail_total [selector_args]* ]+ ]+ + * num_groups [num_paths num_selector_args [path_dev A|F fail_count [selector_args]* ]+ ]+ * * Table string has the following format (identical to the constructor string): - * test_interval num_groups [priority selector-name num_paths num_selector_args [path_dev [selector_args]* ]+ ]+ + * num_groups [priority selector-name num_paths num_selector_args [path_dev [selector_args]* ]+ ]+ */ static int multipath_status(struct dm_target *ti, status_type_t type, char *result, unsigned int maxlen) @@ -821,9 +628,9 @@ format_dev_t(buffer, p->dev->bdev->bd_dev); spin_lock_irqsave(&p->failed_lock, flags); sz += snprintf(result + sz, maxlen - sz, - "%s %s %u %u ", buffer, + "%s %s %u ", buffer, p->has_failed ? "F" : "A", - p->fail_count, p->fail_total); + p->fail_count); pg->ps->type->status(pg->ps, p, type, result + sz, maxlen - sz); spin_unlock_irqrestore(&p->failed_lock, flags); @@ -837,8 +644,7 @@ break; case STATUSTYPE_TABLE: - sz += snprintf(result + sz, maxlen - sz, "%u %u ", - m->test_interval, m->nr_priority_groups); + sz += snprintf(result + sz, maxlen - sz, "%u ", m->nr_priority_groups); list_for_each_entry(pg, &m->priority_groups, list) { sz += snprintf(result + sz, maxlen - sz, "%u %s %u %u ", @@ -875,8 +681,6 @@ .dtr = multipath_dtr, .map = multipath_map, .end_io = multipath_end_io, - .suspend = multipath_suspend, - .resume = multipath_resume, .status = multipath_status, }; @@ -926,4 +730,3 @@ MODULE_DESCRIPTION(DM_NAME " multipath target"); MODULE_AUTHOR("Sistina software "); MODULE_LICENSE("GPL"); - --- diff/drivers/md/dm-path-selector.c 2004-02-18 09:14:48.000000000 +0000 +++ source/drivers/md/dm-path-selector.c 2004-02-18 09:17:31.000000000 +0000 @@ -237,8 +237,7 @@ return 0; } -static void rr_set_path_state(struct path_selector *ps, - struct path *p, int valid) +static void rr_fail_path(struct path_selector *ps, struct path *p) { unsigned long flags; struct selector *s = (struct selector *) ps->context; @@ -257,8 +256,7 @@ DMWARN("asked to change the state of an unknown path"); else - list_move(&pi->list, - valid ? &s->valid_paths : &s->invalid_paths); + list_move(&pi->list, &s->invalid_paths); spin_unlock_irqrestore(&s->lock, flags); } @@ -294,7 +292,7 @@ .ctr = rr_ctr, .dtr = rr_dtr, .add_path = rr_add_path, - .set_path_state = rr_set_path_state, + .fail_path = rr_fail_path, .select_path = rr_select_path, .status = rr_status, }; --- diff/drivers/md/dm-path-selector.h 2004-02-18 09:14:48.000000000 +0000 +++ source/drivers/md/dm-path-selector.h 2004-02-18 09:17:31.000000000 +0000 @@ -54,8 +54,8 @@ /* * Notify the selector that a path has failed. */ -typedef void (*ps_set_path_state_fn) (struct path_selector *ps, - struct path *p, int valid); +typedef void (*ps_fail_path_fn) (struct path_selector *ps, + struct path *p); /* * Table content based on parameters added in ps_add_path_fn @@ -75,7 +75,7 @@ ps_dtr_fn dtr; ps_add_path_fn add_path; - ps_set_path_state_fn set_path_state; + ps_fail_path_fn fail_path; ps_select_path_fn select_path; ps_status_fn status; };