- if (error == -EOPNOTSUPP)
- goto out;
-
- if ((error == -EWOULDBLOCK) && bio_rw_ahead(bio))
- goto out;
-
- if (unlikely(error)) {
- DMERR("A read failure occurred on a mirror device.");
- if (!map_context->ptr) {
- /*
- * There wasn't enough memory to record necessary
- * information for a retry or there was no other
- * mirror in-sync.
- */
- DMERR("Unable to retry read.");
- return -EIO;
- }
- m = ((struct bio_map_info *)map_context->ptr)->bmi_m;
- fail_mirror(m); /* Flag error on mirror. */
-
- /*
- * A failed read needs to get queued
- * to the daemon for another shot to
- * one (if any) intact mirrors.
- */
- if (default_ok(m) || mirror_available(ms, bio)) {
- bd = &(((struct bio_map_info *)map_context->ptr)->bmi_bd
- );
-
- DMWARN("Trying different device.");
- dm_bio_restore(bd, bio);
- mempool_free(map_context->ptr, bio_map_info_pool);
- map_context->ptr = NULL;
- queue_bio(ms, bio, rw);
- return 1; /* We want another shot on the bio. */
- }
- DMERR("All replicated volumes dead, failing I/O");
- }
-
-out:
- if (map_context->ptr)
- mempool_free(map_context->ptr, bio_map_info_pool);
-
- return error;
-}
-
-static void mirror_presuspend(struct dm_target *ti)
-{
- struct mirror_set *ms = (struct mirror_set *) ti->private;
- struct dirty_log *log = ms->rh.log;
-
- if (log->type->presuspend && log->type->presuspend(log))
- /* FIXME: need better error handling */
- DMWARN("log presuspend failed");