[dm-devel] [RFC PATCH 3/4] convert dm-multipath to blkerr error values
Mike Christie
michaelc at cs.wisc.edu
Wed Aug 24 09:04:27 UTC 2005
Ok here is a first pass at converting dm-multipath.
I have tested with some software iSCSI drivers.
The next step is to move the sense code in dm-emc
to scsi. One possible problem is coming up with
a BLKERR value that will give dm-multipath the same
info as MP_BYPASS_PG.
Signed-off-by: Mike Christie <michaelc at cs.wisc.edu>
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -94,8 +94,11 @@ struct multipath {
struct mpath_io {
struct pgpath *pgpath;
struct dm_bio_details details;
+ int retries;
};
+#define MPIO_MAX_RETRIES 5
+
typedef int (*action_fn) (struct pgpath *pgpath);
#define MIN_IOS 256 /* Mempool size */
@@ -370,7 +373,7 @@ static void dispatch_queued_ios(struct m
r = map_io(m, bio, mpio, 1);
if (r < 0)
- bio_endio(bio, bio->bi_size, r);
+ bio_endio(bio, bio->bi_size, BLKERR_IO);
else if (r == 1)
generic_make_request(bio);
@@ -781,6 +784,7 @@ static int multipath_map(struct dm_targe
mpio = mempool_alloc(m->mpio_pool, GFP_NOIO);
dm_bio_record(&mpio->details, bio);
+ mpio->retries = 0;
map_context->ptr = mpio;
bio->bi_rw |= (1 << BIO_RW_FAILFAST);
@@ -988,6 +992,20 @@ void dm_pg_init_complete(struct path *pa
spin_unlock_irqrestore(&m->lock, flags);
}
+/* queue for the daemon to resubmit or fail */
+static void requeue_io(struct multipath *m, struct bio *bio,
+ struct mpath_io *mpio)
+{
+ dm_bio_restore(&mpio->details, bio);
+
+ spin_lock(&m->lock);
+ bio_list_add(&m->queued_ios, bio);
+ m->queue_size++;
+ if (!m->queue_io)
+ queue_work(kmultipathd, &m->process_queued_ios);
+ spin_unlock(&m->lock);
+}
+
/*
* end_io handling
*/
@@ -997,20 +1015,11 @@ static int do_end_io(struct multipath *m
struct hw_handler *hwh = &m->hw_handler;
unsigned err_flags = MP_FAIL_PATH; /* Default behavior */
- if (!error)
- return 0; /* I/O complete */
-
- if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
- return error;
-
- if (error == -EOPNOTSUPP)
- return error;
-
spin_lock(&m->lock);
if (!m->nr_valid_paths) {
if (!m->queue_if_no_path) {
spin_unlock(&m->lock);
- return -EIO;
+ return BLKERR_FATAL_DEV;
} else {
spin_unlock(&m->lock);
goto requeue;
@@ -1030,20 +1039,11 @@ static int do_end_io(struct multipath *m
}
if (err_flags & MP_ERROR_IO)
- return -EIO;
+ return BLKERR_FATAL_DEV;
- requeue:
- dm_bio_restore(&mpio->details, bio);
-
- /* queue for the daemon to resubmit or fail */
- spin_lock(&m->lock);
- bio_list_add(&m->queued_ios, bio);
- m->queue_size++;
- if (!m->queue_io)
- queue_work(kmultipathd, &m->process_queued_ios);
- spin_unlock(&m->lock);
-
- return 1; /* io not complete */
+requeue:
+ requeue_io(m, bio, mpio);
+ return -1; /* io not complete */
}
static int multipath_end_io(struct dm_target *ti, struct bio *bio,
@@ -1053,15 +1053,40 @@ static int multipath_end_io(struct dm_ta
struct mpath_io *mpio = (struct mpath_io *) map_context->ptr;
struct pgpath *pgpath = mpio->pgpath;
struct path_selector *ps;
- int r;
+ int r = error;
+
+ switch (error) {
+ case BLK_SUCCESS:
+ break;
+ case BLKERR_NOTSUPP:
+ break;
+ case BLKERR_WOULDBLOCK:
+ if (bio_rw_ahead(bio))
+ break;
+ case BLKERR_RETRY_DRV:
+ case BLKERR_RETRY_DEV:
+ case BLKERR_RETRY_XPT:
+ /*
+ * this should be modifiable, we should also add some
+ * counters to indicate how many error we have on this
+ * path.
+ */
+ if (mpio->retries++ < MPIO_MAX_RETRIES) {
+ requeue_io(m, bio, mpio);
+ r = -1;
+ break;
+ } else
+ r = BLKERR_FATAL_DEV;
+ default:
+ r = do_end_io(m, bio, error, mpio);
+ }
- r = do_end_io(m, bio, error, mpio);
if (pgpath) {
ps = &pgpath->pg->ps;
if (ps->type->end_io)
ps->type->end_io(ps, &pgpath->path);
}
- if (r <= 0)
+ if (r != -1)
mempool_free(mpio, m->mpio_pool);
return r;
More information about the dm-devel
mailing list