DM multipath error messages were beyond useless. From: Lars Marowsky-Bree Index: linux-2.6.16-rc1/drivers/md/dm-emc.c =================================================================== --- linux-2.6.16-rc1.orig/drivers/md/dm-emc.c +++ linux-2.6.16-rc1/drivers/md/dm-emc.c @@ -39,6 +39,8 @@ static inline void free_bio(struct bio * static int emc_endio(struct bio *bio, unsigned int bytes_done, int error) { struct path *path = bio->bi_private; + int sense; + int err_flags = 0; if (bio->bi_size) return 1; @@ -48,10 +50,22 @@ static int emc_endio(struct bio *bio, un * * For now simple logic: either it works or it doesn't. */ - if (error) - dm_pg_init_complete(path, MP_FAIL_PATH); - else - dm_pg_init_complete(path, 0); + if (error) { + DMWARN("dm-emc: emc_endio: pg_init error %d", error); + if (bio_sense_valid(bio)) { + sense = bio_sense_value(bio); /* sense key/asc/ascq */ + DMWARN("dm-emc: emc_endio: " + "found valid sense data %06x", sense); + if (sense == 0x050400) { + DMWARN("dm-emc: emc_endio: " + "array-based copy in progress"); + err_flags = MP_BYPASS_PG; + } else + err_flags = MP_FAIL_PATH; + } + } + + dm_pg_init_complete(path, err_flags); /* request is freed in block layer */ free_bio(bio); @@ -271,7 +285,7 @@ static int emc_create(struct hw_handler if ((h->hr = hr)) DMWARN("dm-emc: honor reservation bit will be set"); else - DMWARN("dm-emc: honor reservation bit will not be set (default)"); + DMWARN("dm-emc: honor reservation bit will not be set"); return 0; } @@ -290,6 +304,8 @@ static unsigned emc_error(struct hw_hand if (bio_sense_valid(bio)) { sense = bio_sense_value(bio); /* sense key / asc / ascq */ + DMWARN("dm-emc: emc_err: Found valid sense data %06x " + "for sector %llu", sense, bio->bi_sector); if (sense == 0x020403) { /* LUN Not Ready - Manual Intervention Required @@ -300,6 +316,8 @@ static unsigned emc_error(struct hw_hand * progress, we should set FAIL_PATH too. * This indicates we might have to do a SCSI * inquiry in the end_io path. Ugh. */ + DMWARN("dm-emc: emc_err: Forcing bypassing of PG " + "in response to LU Not Ready"); return MP_BYPASS_PG; } else if (sense == 0x052501) { /* An array based copy is in progress. Do not Index: linux-2.6.16-rc1/drivers/md/dm-hw-handler.c =================================================================== --- linux-2.6.16-rc1.orig/drivers/md/dm-hw-handler.c +++ linux-2.6.16-rc1/drivers/md/dm-hw-handler.c @@ -160,6 +160,9 @@ unsigned dm_scsi_err_handler(struct hw_h asc = (bio_sense_value(bio) >> 8) & 0xff; ascq = bio_sense_value(bio) & 0xff; + DMWARN("dm_scsi_err_handler: Parsing sense %02x/%02x/%02x for sector %llu", + sense_key, asc, ascq, bio->bi_sector); + switch (sense_key) { /* This block as a whole comes from the device. * So no point retrying on another path. */ Index: linux-2.6.16-rc1/drivers/md/dm-mpath.c =================================================================== --- linux-2.6.16-rc1.orig/drivers/md/dm-mpath.c +++ linux-2.6.16-rc1/drivers/md/dm-mpath.c @@ -535,8 +535,10 @@ static struct pgpath *parse_path(struct } p = alloc_pgpath(); - if (!p) + if (!p) { + ti->error = ESTR("failed to allocate pgpath structure"); return NULL; + } r = dm_get_device(ti, shift(as), ti->begin, ti->len, dm_table_get_mode(ti->table), &p->path.dev); @@ -545,6 +547,7 @@ static struct pgpath *parse_path(struct goto bad; } + ti->error = ESTR("path selector add_path failed"); r = ps->type->add_path(ps, &p->path, as->argc, as->argv, &ti->error); if (r) { dm_put_device(ti, p->path.dev); @@ -584,6 +587,7 @@ static struct priority_group *parse_prio } pg->m = m; + ti->error = ESTR("failure parsing PG path selector"); r = parse_path_selector(as, pg, ti); if (r) goto bad; @@ -600,16 +604,20 @@ static struct priority_group *parse_prio goto bad; nr_params = 1 + nr_selector_args; + for (i = 0; i < pg->nr_pgpaths; i++) { struct pgpath *pgpath; struct arg_set path_args; - if (as->argc < nr_params) + if (as->argc < nr_params) { + ti->error = ESTR("path selector argument count mismatch"); goto bad; + } path_args.argc = nr_params; path_args.argv = as->argv; + ti->error = ESTR("failure parsing PG path"); pgpath = parse_path(&path_args, &pg->ps, ti); if (!pgpath) goto bad; @@ -732,6 +740,7 @@ static int multipath_ctr(struct dm_targe while (as.argc) { struct priority_group *pg; + ti->error = ESTR("failure parsing priority group"); pg = parse_priority_group(&as, m, ti); if (!pg) { r = -EINVAL; @@ -808,7 +817,7 @@ static int fail_path(struct pgpath *pgpa if (!pgpath->path.is_active) goto out; - DMWARN("dm-multipath: Failing path %s.", pgpath->path.dev->name); + DMWARN("dm-multipath: Failing path %s", pgpath->path.dev->name); pgpath->pg->ps.type->fail_path(&pgpath->pg->ps, &pgpath->path); pgpath->path.is_active = 0; @@ -896,6 +905,7 @@ static void bypass_pg(struct multipath * spin_lock_irqsave(&m->lock, flags); + DMWARN("dm-multipath: bypassing PG %u", pg->pg_num); pg->bypassed = bypassed; m->current_pgpath = NULL; m->current_pg = NULL; @@ -974,11 +984,18 @@ void dm_pg_init_complete(struct path *pa if (err_flags && pg->bypassed) err_flags |= MP_FAIL_PATH; - if (err_flags & MP_FAIL_PATH) + if (err_flags & MP_FAIL_PATH) { + DMWARN("dm-multipath: Error initialising %sPG: failing path %s", + pg->bypassed ? "bypassed " : "", + pgpath->path.dev->name); fail_path(pgpath); + } - if (err_flags & MP_BYPASS_PG) + if ((err_flags & MP_BYPASS_PG) && !pg->bypassed) { + DMWARN("dm-multipath: Error initialising PG on %s: ", + pgpath->path.dev->name); bypass_pg(m, pg, 1); + } spin_lock_irqsave(&m->lock, flags); if (err_flags) { @@ -1011,8 +1028,14 @@ static int do_end_io(struct multipath *m if (error == -EOPNOTSUPP) return error; + DMWARN("dm-multipath: IO error on path %s, sector %llu", + mpio->pgpath ? mpio->pgpath->path.dev->name : "NULL", + bio->bi_sector); + spin_lock_irqsave(&m->lock, flags); if (!m->nr_valid_paths) { + DMWARN("dm-multipath: no valid paths left"); + if (!m->queue_if_no_path) { spin_unlock_irqrestore(&m->lock, flags); return -EIO; @@ -1046,6 +1069,8 @@ static int do_end_io(struct multipath *m spin_lock_irqsave(&m->lock, flags); bio_list_add(&m->queued_ios, bio); m->queue_size++; + DMINFO("multipath_end_io: Requeued sector %llu as #%u", bio->bi_sector, + m->queue_size); if (!m->queue_io) queue_work(kmultipathd, &m->process_queued_ios); spin_unlock_irqrestore(&m->lock, flags);