Remove the failure target. --- diff/drivers/md/Kconfig 2004-01-02 13:23:53.000000000 +0000 +++ source/drivers/md/Kconfig 2004-01-03 12:26:44.000000000 +0000 @@ -162,14 +162,6 @@ ---help--- Allow volume managers to support multipath hardware. -config DM_FAILURE - tristate "Failure target (EXPERIMENTAL)" - depends on BLK_DEV_DM && EXPERIMENTAL - ---help--- - A debug only target that attempts to change the - characteristics of a block device. Most notably its - reliability. - config DM_FLAKEY tristate "Flakey target (EXPERIMENTAL)" depends on BLK_DEV_DM && EXPERIMENTAL --- diff/drivers/md/Makefile 2004-01-02 13:24:56.000000000 +0000 +++ source/drivers/md/Makefile 2004-01-03 12:26:56.000000000 +0000 @@ -26,6 +26,5 @@ obj-$(CONFIG_DM_SNAPSHOT) += dm-snapshot.o obj-$(CONFIG_DM_MIRROR) += dm-mirror.o obj-$(CONFIG_DM_MULTIPATH) += dm-multipath.o -obj-$(CONFIG_DM_FAILURE) += dm-failure.o obj-$(CONFIG_DM_FLAKEY) += dm-flakey.o obj-$(CONFIG_DM_CRYPT) += dm-crypt.o --- diff/drivers/md/dm-failure.c 2003-12-29 10:16:45.000000000 +0000 +++ source/drivers/md/dm-failure.c 1970-01-01 01:00:00.000000000 +0100 @@ -1,682 +0,0 @@ -/* - * Copyright (C) 2003 Sistina Software Limited. - * - * This file is released under the GPL. - * - */ - -#include "dm.h" -#include "dm-daemon.h" - -#include -#include -#include -#include -#include -#include - -#define ARG_FORMAT "%ld" - -#define FAILURED_RTPRIO 20 - -/* slab for the io jobs */ -static kmem_cache_t *_failure_cache; -mempool_t *_failure_pool; - -static int ios = 0; -#define DEFAULT_IOS 256 -#define MIN_IOS 16 -#define MAX_IOS 32768 /* maximum on 32 bit hw with mempool_create() */ - -/* context of every delayed io */ -struct failure_io { - struct list_head list; - - struct dm_target *ti; - unsigned long flags; - jiffy_t delay; - - struct bio *bio; -}; - -/* processing categories */ -enum { - DELAY, - ERROR, - CATEGORY_SIZE, /* MUST BE LAST */ -}; - -/* category properties */ -enum { - IOS_MIN, - IOS_MAX, - IOS_DELTA, - DELAY_MIN, - DELAY_MAX, - MIN, - MAX, - DELTA, - W_IOS_MIN, - W_IOS_MAX, - W_IOS_RAND_MAX, - W_DELAY_MIN, - W_DELAY_MAX, - W_MIN, - W_MAX, - W_IOS, - W_RAND, - W_DELAYS_C, - W_ERRORS_C, - W_REAL_ERRORS_C, - PARAM_SIZE, /* MUST BE LAST */ -}; - -/* global flags */ -static int f[] = { 1, 2}; - -/* failure context */ -struct failure_c { - struct dm_dev *dev; - unsigned long flags; - long ios[CATEGORY_SIZE][PARAM_SIZE]; -}; - -static spinlock_t _job_lock = SPIN_LOCK_UNLOCKED; -static spinlock_t _io_lock = SPIN_LOCK_UNLOCKED; -static LIST_HEAD(_delay_jobs); -static LIST_HEAD(_request_jobs); - -/* io job allocation/deallocation */ -static inline struct failure_io *alloc_io(void) -{ - return mempool_alloc(_failure_pool, GFP_NOIO); -} - -static inline void free_io(struct failure_io *io) -{ - mempool_free(io, _failure_pool); -} - -/* push a job onto the daemon job list */ -static inline void push(struct failure_io *io) -{ - unsigned long flags; - - spin_lock_irqsave(&_job_lock, flags); - list_add_tail(&io->list, &_delay_jobs); - spin_unlock_irqrestore(&_job_lock, flags); -} - -static inline long _timeout(struct failure_io *io) -{ - return io->delay - jiffies; -} - -static inline int _delay_reached(struct failure_io *io) -{ - return jiffies >= io->delay; -} - -/* - * Daemon - */ -static unsigned long _failured_flags = 0; -enum { - RUN = 1, - RERUN, -}; -#define _RUN test_bit(RUN, &_failured_flags) - -static inline void _do_ios(void) -{ - struct list_head *jobs = &_request_jobs; - - if (list_empty(jobs)) - return; - - while (!list_empty(jobs)) { - struct failure_io *io = - list_entry(jobs->next, struct failure_io, list); - generic_make_request(io->bio); - list_del(&io->list); - } - - blk_run_queues(); -} - -/* failured does this every time it runs */ -static jiffy_t _do_work(void) -{ - unsigned long flags; - long timeout = MAX_SCHEDULE_TIMEOUT; - struct failure_io *io; - struct list_head *job, *tmp; - - spin_lock_irqsave(&_job_lock, flags); - - if (!list_empty(&_delay_jobs)) { - list_for_each_safe(job, tmp, &_delay_jobs) { - io = list_entry(job, struct failure_io, list); - - if (_delay_reached(io) || !_RUN) - list_move_tail(&io->list, &_request_jobs); - else { - long t = _timeout(io); - - if (t > 0 && t < timeout) - timeout = t; - } - } - } - - spin_unlock_irqrestore(&_job_lock, flags); - - _do_ios(); - - if (test_bit(RERUN, &_failured_flags)) { - timeout = 0; - clear_bit(RERUN, &_failured_flags); - } - - return timeout; -} - - -/*----------------------------------------------------------------- - * Daemon - *---------------------------------------------------------------*/ -struct dm_daemon _failured; -static DECLARE_WAIT_QUEUE_HEAD(_failured_queue); - -static inline long _to_jiffies(long v) -{ - long r = v * HZ / 1000; - - /* < 1 jiffy make it 1 */ - return v && !r ? 1 : r; -} - -/* - * Parse a single - * - * - * - * - * - * - * - * - * - * - * - * parameter set - * - */ -#define xx(a, s, v) \ - ti->error = "dm-failure: " s; \ - if (sscanf(argv[a], ARG_FORMAT, & v) != 1) \ - return -EINVAL; - -#define yy(s, v, min, max) \ - ti->error = "dm-failure: minimum or maximum " s " < 0"; \ - if (fc->ios[v][max] < 0 || fc->ios[v][min] < 0) \ - return -EINVAL; \ -\ - ti->error = "dm-failure: maximum " s " != 0 and <= minimum"; \ - if (fc->ios[v][max] && fc->ios[v][max] <= fc->ios[v][min]) \ - return -EINVAL; - -#define zz(c) \ - fc->ios[c][W_IOS_MIN] = fc->ios[c][IOS_MIN]; \ - fc->ios[c][W_IOS_MAX] = fc->ios[c][IOS_MAX]; \ - fc->ios[c][W_DELAY_MIN] = _to_jiffies(fc->ios[c][DELAY_MIN]); \ - fc->ios[c][W_DELAY_MAX] = _to_jiffies(fc->ios[c][DELAY_MAX]); \ - fc->ios[c][W_MIN] = fc->ios[c][MIN]; \ - fc->ios[c][W_MAX] = fc->ios[c][MAX]; - -#define PATH_ARGS 17 /* _get_path() must check for this amount */ - -static int _get_path(struct dm_target *ti, struct failure_c *fc, char **argv) -{ - /* delay parameters */ - xx(1, "minimum ios before delay", fc->ios[DELAY][IOS_MIN]) - xx(2, "maximum ios before delay", fc->ios[DELAY][IOS_MAX]) - yy("ios before delay", DELAY, IOS_MIN, IOS_MAX) - - xx(3, "ios delay delta", fc->ios[DELAY][IOS_DELTA]) - - ti->error = "dm-failure: ios delay delta too high"; - if (fc->ios[DELAY][IOS_DELTA] < 0 && - abs(fc->ios[DELAY][IOS_DELTA]) >= fc->ios[DELAY][IOS_MIN]) - return -EINVAL; - - xx(4, "delay time minimum", fc->ios[DELAY][DELAY_MIN]) - xx(5, "delay time maximum", fc->ios[DELAY][DELAY_MAX]) - yy("delay", DELAY, DELAY_MIN, DELAY_MAX) - - ti->error = "dm-failure: ios before delay without delay"; - if (!fc->ios[DELAY][IOS_MIN] && fc->ios[DELAY][DELAY_MIN]) - return -EINVAL; - - xx(6, "minimum delays", fc->ios[DELAY][MIN]) - xx(7, "maximum delays", fc->ios[DELAY][MAX]) - yy("delays", DELAY, MIN, MAX) - - xx(8, "delays delta", fc->ios[DELAY][DELTA]) - - ti->error = "dm-failure: delay delta without delay"; - /* FIXME: allow 0 delay in case maximum dleay given ? */ - if (!fc->ios[DELAY][MIN] && - fc->ios[DELAY][DELTA]) - return -EINVAL; - - ti->error = "dm-failure: delay delta too high"; - if (fc->ios[DELAY][DELTA] < 0 && - abs(fc->ios[DELAY][DELTA]) >= fc->ios[DELAY][MIN]) - return -EINVAL; - - /* error parameters */ - xx(9, "minimum ios before error", fc->ios[ERROR][IOS_MIN]) - xx(10, "maximum ios before error", fc->ios[ERROR][IOS_MAX]) - yy("ios before error", ERROR, IOS_MIN, IOS_MAX) - - xx(11, "ios error delta", fc->ios[ERROR][IOS_DELTA]); - - ti->error = "dm-failure: ios error delta too high"; - if (fc->ios[ERROR][IOS_DELTA] < 0 && - abs(fc->ios[ERROR][IOS_DELTA]) >= fc->ios[ERROR][IOS_MIN]) - return -EINVAL; - - xx(12, "error time minimum", fc->ios[ERROR][DELAY_MIN]) - xx(13, "error time maximum", fc->ios[ERROR][DELAY_MAX]) - yy("error", ERROR, DELAY_MIN, DELAY_MAX) - - ti->error = "dm-failure: ios before error without error"; - /* FIXME: allow 0 delay in case maximum dleay given ? */ - if (!fc->ios[ERROR][IOS_MIN] && - fc->ios[ERROR][DELAY_MIN]) - return -EINVAL; - - xx(14, "minimum errors", fc->ios[ERROR][MIN]) - xx(15, "maximum errors", fc->ios[ERROR][MAX]) - yy("errors", ERROR, MIN, MAX) - - xx(16, "errors delta", fc->ios[ERROR][DELTA]) - - ti->error = "dm-failure: error delta without error"; - if (!fc->ios[ERROR][MIN] && fc->ios[ERROR][DELTA]) - return -EINVAL; - - ti->error = "dm-failure: error delta too high"; - if (fc->ios[ERROR][DELTA] < 0 && - abs(fc->ios[ERROR][DELTA]) >= fc->ios[ERROR][MIN]) - return -EINVAL; - - ti->error = "dm-failure: device lookup failure"; - if (dm_get_device(ti, argv[0], ti->begin, ti->len, - dm_table_get_mode(ti->table), - &fc->dev)) - return -ENXIO; - - ti->error = NULL; - - zz(DELAY) - zz(ERROR) - - if (fc->ios[DELAY][IOS_MIN] && fc->ios[DELAY][DELAY_MIN]) - set_bit(f[DELAY], &fc->flags); - - if (fc->ios[ERROR][IOS_MIN]) - set_bit(f[ERROR], &fc->flags); - - return 0; -} -#undef zz -#undef yy -#undef xx - -/* Construct a failure mapping */ -static int failure_ctr(struct dm_target *ti, unsigned int argc, char **argv) -{ - int r; - struct failure_c *fc; - - ti->error = "dm-failure: Wrong argument count"; - if (argc != PATH_ARGS) - return -EINVAL; - - ti->error = "dm-failure: Cannot allocate failure context"; - fc = kmalloc(sizeof(*fc), GFP_NOIO); - if (!fc) - return -ENOMEM; - - memset(fc, 0, sizeof(*fc)); - - r = _get_path(ti, fc, argv); - if (r) { - kfree(fc); - return r; - } - - ti->private = fc; - - return 0; - -} - -/* Destruct a failure mapping */ -static void failure_dtr(struct dm_target *ti) -{ - struct failure_c *fc = ti->private; - - dm_put_device(ti, fc->dev); - kfree(fc); -} - -static inline int _is_delay_io(struct failure_io *io) { - return test_bit(f[DELAY], &io->flags); -} - -static inline int _is_error_io(struct failure_io *io) { - return test_bit(f[ERROR], &io->flags); -} - -static int failure_end_io(struct dm_target *ti, struct bio *bio, - int error, union map_info *map_context) -{ - int r = 0; - unsigned long flags; - struct failure_io *io = (struct failure_io *) map_context->ptr; - struct failure_c *fc = (struct failure_c *) io->ti->private; - int cat = _is_delay_io(io) ? 0 : 1; - - if (error || _is_error_io(io)) { - /* FIXME: failures on non delayed/errored io count here too */ - spin_lock_irqsave(&_io_lock, flags); - fc->ios[cat][W_REAL_ERRORS_C]++; - spin_unlock_irqrestore(&_io_lock, flags); - r = -1; - dm_table_event(io->ti->table); - } else if (_is_delay_io(io)) { - spin_lock_irqsave(&_io_lock, flags); - fc->ios[cat][W_DELAYS_C]++; - spin_unlock_irqrestore(&_io_lock, flags); - dm_table_event(io->ti->table); - } - - free_io(io); - - return r; -} - -/* return min if max <= min or a random number between min and max */ -static inline long _random(long min, long max) -{ - if (min >= abs(max)) - return min; - else { - unsigned short rand; - - get_random_bytes(&rand, sizeof(rand)); - if (!rand) - rand = 1; - - return min + ((max - min) * rand / ((typeof(rand)) -1)); - } -} - -static inline long _get_delta(long min, long max, long delta) -{ - long t = _random(0, delta); - - if (t) { - long iosmin, iosmax; - - iosmin = min + t; - iosmax = max + t; - if (iosmin > 0 && - iosmin < LONG_MAX && - iosmax < LONG_MAX) - return t; - } - - return 0; -} - -#define _i fc->ios[cat] -static inline void _delta(struct failure_c *fc, int cat, - int min, int max, int delta) -{ - if (_i[delta]) { - long d = _get_delta(_i[min], _i[max], _i[delta]); - - if (d) { - _i[min] += d; - if (_i[max]) - _i[max] += d; - } - } -} - -static inline int _prepare_io(struct failure_io *io, int cat) -{ - unsigned long flags; - struct failure_c *fc = io->ti->private; - - io->bio->bi_bdev = fc->dev->bdev; - - if (!test_bit(f[cat], &fc->flags)) - return 0; - - spin_lock_irqsave(&_io_lock, flags); - - if (!_i[W_IOS_RAND_MAX]) { - _i[W_RAND] = _random(_i[W_MIN], _i[W_MAX]); - _i[W_IOS_RAND_MAX] = _random(_i[W_IOS_MIN], _i[W_IOS_MAX]); - } - - if (++_i[W_IOS] < _i[W_IOS_RAND_MAX]) - goto out; - - if (!_i[W_RAND]) { - _i[W_IOS] = 0; - _i[W_IOS_RAND_MAX] = 0; - _delta(fc, cat, W_MIN, W_MAX, DELTA); - _delta(fc, cat, W_IOS_MIN, W_IOS_MAX, IOS_DELTA); - goto out; - } else - _i[W_RAND]--; - - spin_unlock_irqrestore(&_io_lock, flags); - - set_bit(f[cat], &io->flags); - io->delay = jiffies + _random(_i[W_DELAY_MIN], _i[W_DELAY_MAX]); - push(io); - return 1; - - out: - spin_unlock_irqrestore(&_io_lock, flags); - - return 0; -} -#undef _i - -/* failure mapping */ -static int failure_map(struct dm_target *ti, struct bio *bio, - union map_info *map_context) -{ - struct failure_io *io = alloc_io(); - - io->ti = ti; - io->bio = bio; - io->flags = 0; - - /* pointer to be handed over to end_io function */ - map_context->ptr = (void *) io; - - if (_prepare_io(io, DELAY) || - _prepare_io(io, ERROR)) { - dm_daemon_wake(&_failured); - return 0; /* handle later */ - } - - return 1; /* regular map */ -} - -/* failure status */ -static int failure_status(struct dm_target *ti, status_type_t type, - char *result, unsigned int maxlen) -{ - int sz = 0; - struct failure_c *fc = (struct failure_c *) ti->private; - char buffer[32]; - - format_dev_t(buffer, fc->dev->bdev->bd_dev); - - switch (type) { - case STATUSTYPE_INFO: - sz += snprintf(result + sz, maxlen - sz, - "%s " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT " " ARG_FORMAT, - buffer, - fc->ios[DELAY][W_IOS_MIN], - fc->ios[DELAY][W_IOS_MAX], - fc->ios[DELAY][W_MIN], - fc->ios[DELAY][W_MAX], - fc->ios[DELAY][W_DELAYS_C], - fc->ios[DELAY][W_ERRORS_C], - fc->ios[DELAY][W_REAL_ERRORS_C], - fc->ios[ERROR][W_IOS_MIN], - fc->ios[ERROR][W_IOS_MAX], - fc->ios[ERROR][W_MIN], - fc->ios[ERROR][W_MAX], - fc->ios[ERROR][W_DELAYS_C], - fc->ios[ERROR][W_ERRORS_C], - fc->ios[ERROR][W_REAL_ERRORS_C]); - - break; - - case STATUSTYPE_TABLE: - sz += snprintf(result + sz, maxlen - sz, - "%s " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT " " ARG_FORMAT " " ARG_FORMAT " " - ARG_FORMAT, - buffer, - fc->ios[DELAY][IOS_MIN], - fc->ios[DELAY][IOS_MAX], - fc->ios[DELAY][IOS_DELTA], - fc->ios[DELAY][DELAY_MIN], - fc->ios[DELAY][DELAY_MAX], - fc->ios[DELAY][MIN], - fc->ios[DELAY][MAX], - fc->ios[DELAY][DELTA], - fc->ios[ERROR][IOS_MIN], - fc->ios[ERROR][IOS_MAX], - fc->ios[ERROR][IOS_DELTA], - fc->ios[ERROR][DELAY_MIN], - fc->ios[ERROR][DELAY_MAX], - fc->ios[ERROR][MIN], - fc->ios[ERROR][MAX], - fc->ios[ERROR][DELTA]); - break; - } - - return 0; -} - -static struct target_type failure_target = { - .name = "failure", - .version = {1, 0, 1}, - .module = THIS_MODULE, - .ctr = failure_ctr, - .dtr = failure_dtr, - .map = failure_map, - .end_io = failure_end_io, - .status = failure_status, -}; - -int __init dm_failure_init(void) -{ - int r = -EINVAL; - INIT_LIST_HEAD(&_delay_jobs); - INIT_LIST_HEAD(&_request_jobs); - - if (!ios) - ios = DEFAULT_IOS; - else if (ios < MIN_IOS || - ios > MAX_IOS) - goto bad; - - /* allocate a slab for the failure ios */ - r = -ENOMEM; - _failure_cache = kmem_cache_create("dm failure io", - sizeof(struct failure_io), - 0, 0, NULL, NULL); - - if (!_failure_cache) - goto bad; - - /* Create failure io mempool */ - _failure_pool = mempool_create(ios, mempool_alloc_slab, - mempool_free_slab, _failure_cache); - - if (!_failure_pool) - goto bad1; - - r = dm_register_target(&failure_target); - if (r < 0) { - DMERR("%s: register failed %d", failure_target.name, r); - goto bad2; - } - - r = dm_daemon_start(&_failured, "failured", _do_work); - if (!r) { - DMINFO("dm_failure v0.1.2 (%d io contexts preallocated)", ios); - return 0; - } - - dm_unregister_target(&failure_target); - - bad2: - mempool_destroy(_failure_pool); - - bad1: - kmem_cache_destroy(_failure_cache); - - bad: - return r; -} - -void __exit dm_failure_exit(void) -{ - int r; - - dm_daemon_stop(&_failured); - - r = dm_unregister_target(&failure_target); - if (r < 0) - DMERR("%s: unregister failed %d", failure_target.name, r); - - mempool_destroy(_failure_pool); - kmem_cache_destroy(_failure_cache); -} - -/* - * module hooks - */ -module_init(dm_failure_init); -module_exit(dm_failure_exit); - -MODULE_DESCRIPTION(DM_NAME " failure target"); -MODULE_AUTHOR("Heinz Mauelshagen "); -MODULE_LICENSE("GPL"); -MODULE_PARM(ios, "i"); -MODULE_PARM_DESC(min_ios, "number of preallocated io contexts");