@@ -19,6 +19,7 @@
#include <linux/time.h>
#include <linux/workqueue.h>
#include <scsi/scsi_dh.h>
+#include <scsi/scsi_eh.h>
#include <asm/atomic.h>
#define DM_MSG_PREFIX "multipath"
@@ -101,6 +102,7 @@ struct multipath {
struct dm_mpath_io {
struct pgpath *pgpath;
size_t nr_bytes;
+ char sense[SCSI_SENSE_BUFFERSIZE];
};
typedef int (*action_fn) (struct pgpath *pgpath);
@@ -913,6 +915,9 @@ static int multipath_map(struct dm_target *ti, struct request *clone,
map_context->ptr = mpio;
clone->cmd_flags |= REQ_FAILFAST_TRANSPORT;
+ /* Always attach a sense buffer */
+ if (!clone->sense)
+ clone->sense = mpio->sense;
r = map_io(m, clone, mpio, 0);
if (r < 0 || r == DM_MAPIO_REQUEUE)
mempool_free(mpio, m->mpio_pool);
@@ -1192,6 +1197,42 @@ static void activate_path(struct work_struct *work)
}
/*
+ * Evaluate scsi return code
+ */
+static int eval_scsi_error(int result, char *sense, int sense_len)
+{
+ struct scsi_sense_hdr sshdr;
+ int r = DM_ENDIO_REQUEUE;
+
+ if (host_byte(result) != DID_OK)
+ return r;
+
+ if (msg_byte(result) != COMMAND_COMPLETE)
+ return r;
+
+ if (status_byte(result) == RESERVATION_CONFLICT)
+ /* Do not retry here, possible data corruption */
+ return -EIO;
+
+ if (status_byte(result) == CHECK_CONDITION &&
+ !scsi_normalize_sense(sense, sense_len, &sshdr)) {
+
+ switch (sshdr.sense_key) {
+ case MEDIUM_ERROR:
+ case DATA_PROTECT:
+ case BLANK_CHECK:
+ case COPY_ABORTED:
+ case VOLUME_OVERFLOW:
+ case MISCOMPARE:
+ r = -EIO;
+ break;
+ }
The above sense key list does not cover all the cases(at least for my case). For example, I have these requirements for my storage.
1. For certain check conditions I should be reporting I/O error immediately without retrying on other paths. You have covered some cases here but we a have bigger list.
2. For few other check condtions I should be calling activate_path instead of failing the path.
So, I am thinking it may be better to handle this with scsi device handlers(may be providing a new scsi_dh interface and fallback to default handling if the device handler does not handle the sense). I am not sure if this is feasible but something to think about.
+ }
+
+ return r;