/* * hp_sw_end_io - Completion handler for HP path activation. * @req: path activation request * @error: scsi-ml error * * Check sense data, free request structure, and notify dm that * pg initialization has completed. * * Context: scsi-ml softirq * */ static void hp_sw_end_io(struct request *req, int error) { struct dm_path *path = req->end_io_data; unsigned err_flags = 0; if (!error) { DMDEBUG("%s path activation command - success", path->dev->name); goto out; } if (hp_sw_error_is_retryable(req)) { DMDEBUG("%s path activation command - retry", path->dev->name); err_flags = MP_RETRY; goto out; } DMWARN("%s path activation fail - error=0x%x", path->dev->name, error); err_flags = MP_FAIL_PATH; out: req->end_io_data = NULL; __blk_put_request(req->q, req); dm_pg_init_complete(path, err_flags); }
static void emc_pg_init(struct hw_handler *hwh, unsigned bypassed, struct path *path) { struct request *rq; struct request_queue *q = bdev_get_queue(path->dev->bdev); /* * We can either blindly init the pg (then look at the sense), * or we can send some commands to get the state here (then * possibly send the fo cmnd), or we can also have the * initial state passed into us and then get an update here. */ if (!q) { DMINFO("dm-emc: emc_pg_init: no queue"); goto fail_path; } /* FIXME: The request should be pre-allocated. */ rq = emc_trespass_get(hwh->context, path); if (!rq) { DMERR("dm-emc: emc_pg_init: no rq"); goto fail_path; } DMINFO("dm-emc: emc_pg_init: sending switch-over command"); elv_add_request(q, rq, ELEVATOR_INSERT_FRONT, 1); return; fail_path: dm_pg_init_complete(path, MP_FAIL_PATH); }
static void emc_endio(struct bio *bio, int error) { struct dm_path *path = bio->bi_private; /* We also need to look at the sense keys here whether or not to * switch to the next PG etc. * * 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); /* request is freed in block layer */ free_bio(bio); }
/* * hp_sw_pg_init - HP path activation implementation. * @hwh: hardware handler specific data * @bypassed: unused; is the path group bypassed? (see dm-mpath.c) * @path: path to send initialization command * * Send an HP-specific path activation command on 'path'. * Do not try to optimize in any way, just send the activation command. * More than one path activation command may be sent to the same controller. * This seems to work fine for basic failover support. * * Possible optimizations * 1. Detect an in-progress activation request and avoid submitting another one * 2. Model the controller and only send a single activation request at a time * 3. Determine the state of a path before sending an activation request * * Context: kmpathd (see process_queued_ios() in dm-mpath.c) */ static void hp_sw_pg_init(struct hw_handler *hwh, unsigned bypassed, struct path *path) { struct request *req; struct hp_sw_context *h; path->hwhcontext = hwh->context; h = hwh->context; req = hp_sw_get_request(path); if (!req) { DMERR("%s path activation command - allocation fail", path->dev->name); goto retry; } blk_execute_rq_nowait(req->q, NULL, req, 1, hp_sw_end_io); return; retry: dm_pg_init_complete(path, MP_RETRY); }