aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDave Wysochanski <dwysocha@redhat.com>2007-10-19 17:47:55 -0400
committerAlasdair G Kergon <agk@redhat.com>2007-10-19 21:01:20 -0400
commitfe97e2aa0502922488ad62303a19a20c8044ae18 (patch)
tree481f977d08248b64c4e9b3c48c74b95fbe90e1be
parent16ebbf358477b762115fec2f85d9b9496a5cae76 (diff)
dm mpath: hp retry if not ready
This patch adds retries to the hp hardware handler, and utilizes the MP_RETRY flag of dm-multipath. For now in the hp handler, if we get a pg_init completed with a check condition we just assume we can retry the pg_init command. We make this assumption because of incomplete data on specific check condition code of the HP hardware, and because testing has shown the HP path initialization command to be idempotent. The number of times we retry is settable via the "pg_init_retries" multipath map feature. Signed-off-by: Dave Wysochanski <dwysocha@redhat.com> Acked-by: Chandra Seetharaman <sekharan@us.ibm.com> Signed-off-by: Alasdair G Kergon <agk@redhat.com>
-rw-r--r--drivers/md/dm-mpath-hp-sw.c64
1 files changed, 53 insertions, 11 deletions
diff --git a/drivers/md/dm-mpath-hp-sw.c b/drivers/md/dm-mpath-hp-sw.c
index 575317037ce2..204bf42c9449 100644
--- a/drivers/md/dm-mpath-hp-sw.c
+++ b/drivers/md/dm-mpath-hp-sw.c
@@ -18,19 +18,54 @@
18#include <linux/types.h> 18#include <linux/types.h>
19#include <scsi/scsi.h> 19#include <scsi/scsi.h>
20#include <scsi/scsi_cmnd.h> 20#include <scsi/scsi_cmnd.h>
21#include <scsi/scsi_dbg.h>
21 22
22#include "dm.h" 23#include "dm.h"
23#include "dm-hw-handler.h" 24#include "dm-hw-handler.h"
24 25
25#define DM_MSG_PREFIX "multipath hp-sw" 26#define DM_MSG_PREFIX "multipath hp-sw"
26#define DM_HP_HWH_NAME "hp-sw" 27#define DM_HP_HWH_NAME "hp-sw"
27#define DM_HP_HWH_VER "0.0.3" 28#define DM_HP_HWH_VER "1.0.0"
28 29
29struct hp_sw_context { 30struct hp_sw_context {
30 unsigned char sense[SCSI_SENSE_BUFFERSIZE]; 31 unsigned char sense[SCSI_SENSE_BUFFERSIZE];
31}; 32};
32 33
33/* 34/*
35 * hp_sw_error_is_retryable - Is an HP-specific check condition retryable?
36 * @req: path activation request
37 *
38 * Examine error codes of request and determine whether the error is retryable.
39 * Some error codes are already retried by scsi-ml (see
40 * scsi_decide_disposition), but some HP specific codes are not.
41 * The intent of this routine is to supply the logic for the HP specific
42 * check conditions.
43 *
44 * Returns:
45 * 1 - command completed with retryable error
46 * 0 - command completed with non-retryable error
47 *
48 * Possible optimizations
49 * 1. More hardware-specific error codes
50 */
51static int hp_sw_error_is_retryable(struct request *req)
52{
53 /*
54 * NOT_READY is known to be retryable
55 * For now we just dump out the sense data and call it retryable
56 */
57 if (status_byte(req->errors) == CHECK_CONDITION)
58 __scsi_print_sense(DM_HP_HWH_NAME, req->sense, req->sense_len);
59
60 /*
61 * At this point we don't have complete information about all the error
62 * codes from this hardware, so we are just conservative and retry
63 * when in doubt.
64 */
65 return 1;
66}
67
68/*
34 * hp_sw_end_io - Completion handler for HP path activation. 69 * hp_sw_end_io - Completion handler for HP path activation.
35 * @req: path activation request 70 * @req: path activation request
36 * @error: scsi-ml error 71 * @error: scsi-ml error
@@ -40,23 +75,30 @@ struct hp_sw_context {
40 * 75 *
41 * Context: scsi-ml softirq 76 * Context: scsi-ml softirq
42 * 77 *
43 * Possible optimizations
44 * 1. Actually check sense data for retryable error (e.g. NOT_READY)
45 */ 78 */
46static void hp_sw_end_io(struct request *req, int error) 79static void hp_sw_end_io(struct request *req, int error)
47{ 80{
48 struct dm_path *path = req->end_io_data; 81 struct dm_path *path = req->end_io_data;
49 unsigned err_flags = 0; 82 unsigned err_flags = 0;
50 83
51 if (!error) 84 if (!error) {
52 DMDEBUG("%s path activation command - success", 85 DMDEBUG("%s path activation command - success",
53 path->dev->name); 86 path->dev->name);
54 else { 87 goto out;
55 DMWARN("%s path activation command - error=0x%x",
56 path->dev->name, error);
57 err_flags = MP_FAIL_PATH;
58 } 88 }
59 89
90 if (hp_sw_error_is_retryable(req)) {
91 DMDEBUG("%s path activation command - retry",
92 path->dev->name);
93 err_flags = MP_RETRY;
94 goto out;
95 }
96
97 DMWARN("%s path activation fail - error=0x%x",
98 path->dev->name, error);
99 err_flags = MP_FAIL_PATH;
100
101out:
60 req->end_io_data = NULL; 102 req->end_io_data = NULL;
61 __blk_put_request(req->q, req); 103 __blk_put_request(req->q, req);
62 dm_pg_init_complete(path, err_flags); 104 dm_pg_init_complete(path, err_flags);
@@ -135,7 +177,7 @@ static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
135 if (!req) { 177 if (!req) {
136 DMERR("%s path activation command - allocation fail", 178 DMERR("%s path activation command - allocation fail",
137 path->dev->name); 179 path->dev->name);
138 goto fail; 180 goto retry;
139 } 181 }
140 182
141 DMDEBUG("%s path activation command - sent", path->dev->name); 183 DMDEBUG("%s path activation command - sent", path->dev->name);
@@ -143,8 +185,8 @@ static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed,
143 blk_execute_rq_nowait(req->q, NULL, req, 1, hp_sw_end_io); 185 blk_execute_rq_nowait(req->q, NULL, req, 1, hp_sw_end_io);
144 return; 186 return;
145 187
146fail: 188retry:
147 dm_pg_init_complete(path, MP_FAIL_PATH); 189 dm_pg_init_complete(path, MP_RETRY);
148} 190}
149 191
150static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv) 192static int hp_sw_create(struct hw_handler *hwh, unsigned argc, char **argv)