Add queue/fail_if_no_paths messages & functionality. --- diff/drivers/md/dm-mpath.c 2004-10-29 21:04:24.000000000 +0100 +++ source/drivers/md/dm-mpath.c 2004-10-29 21:06:44.000000000 +0100 @@ -55,6 +55,7 @@ struct list_head priority_groups; unsigned pg_init_required; /* pg_init needs calling? */ unsigned queue_io; /* Must we queue all I/O? */ + unsigned queue_if_no_paths; /* Queue I/O if last path fails? */ spinlock_t lock; unsigned nr_valid_paths; @@ -242,7 +243,7 @@ { unsigned long flags; struct path *path; - unsigned must_queue; + unsigned must_queue = 0; spin_lock_irqsave(&m->lock, flags); @@ -251,28 +252,30 @@ (!m->queue_io && (m->current_count && --m->current_count == 0))) __choose_path(m); - must_queue = m->queue_io; path = m->current_path; + if ((path && m->queue_io) || (!path && m->queue_if_no_paths)) + must_queue = 1; + spin_unlock_irqrestore(&m->lock, flags); - if (!path) - return -EIO; + if (must_queue) { + /* queue for the daemon to resubmit */ + spin_lock_irqsave(&m->lock, flags); + bio_list_add(&m->queued_ios, bio); + if (m->pg_init_required || !m->queue_io) + schedule_work(&m->process_queued_ios); + spin_unlock_irqrestore(&m->lock, flags); - if (!must_queue) { - mpio->path = path; - bio->bi_bdev = mpio->path->dev->bdev; - return 1; /* Mapped successfully */ + return 0; /* Queued */ } - /* queue for the daemon to resubmit */ - spin_lock_irqsave(&m->lock, flags); - bio_list_add(&m->queued_ios, bio); - if (m->pg_init_required || !m->queue_io) - schedule_work(&m->process_queued_ios); - spin_unlock_irqrestore(&m->lock, flags); + if (!path) + return -EIO; - return 0; /* Queued */ + mpio->path = path; + bio->bi_bdev = mpio->path->dev->bdev; + return 1; /* Mapped successfully */ } /*----------------------------------------------------------------- @@ -313,7 +316,7 @@ struct multipath *m = (struct multipath *) data; struct hw_handler *hwh = &m->hw_handler; struct path *path; - unsigned init_required, must_queue; + unsigned init_required, must_queue = 0; unsigned long flags; spin_lock_irqsave(&m->lock, flags); @@ -322,7 +325,9 @@ __choose_path(m); path = m->current_path; - must_queue = m->queue_io; + + if ((path && m->queue_io) || (!path && m->queue_if_no_paths)) + must_queue = 1; init_required = m->pg_init_required; if (init_required) @@ -334,10 +339,8 @@ hwh->type->pg_init(hwh, path->pg->bypassed, path, path->dev->bdev); - if (path && must_queue) - return; - - dispatch_queued_ios(m); + if (!must_queue) + dispatch_queued_ios(m); } /* @@ -692,8 +695,9 @@ m = path->pg->m; spin_lock(&m->lock); - m->nr_valid_paths++; m->current_path = NULL; + if (!m->nr_valid_paths++) + schedule_work(&m->process_queued_ios); spin_unlock(&m->lock); schedule_work(&m->trigger_event); @@ -925,6 +929,19 @@ return 0; } +static int queue_if_no_paths(struct multipath *m, unsigned queue_if_no_paths) +{ + unsigned long flags; + + spin_lock_irqsave(&m->lock, flags); + m->queue_if_no_paths = queue_if_no_paths; + if (!m->queue_if_no_paths) + schedule_work(&m->process_queued_ios); + spin_unlock_irqrestore(&m->lock, flags); + + return 0; +} + #define MESG_STR(x) x, sizeof(x) static int multipath_message(struct dm_target *ti, unsigned argc, char **argv) @@ -934,6 +951,13 @@ struct multipath *m = (struct multipath *) ti->private; action_fn action; + if (argc == 1) { + if (!strnicmp(argv[0], MESG_STR("queue_if_no_paths"))) + return queue_if_no_paths(m, 1); + else if (!strnicmp(argv[0], MESG_STR("fail_if_no_paths"))) + return queue_if_no_paths(m, 0); + } + if (argc != 2) goto error;