Commit 3ae31f6a authored by Chandra Seetharaman's avatar Chandra Seetharaman Committed by James Bottomley

[SCSI] scsi_dh: Change the scsidh_activate interface to be asynchronous

Make scsi_dh_activate() function asynchronous, by taking in two additional
parameters, one is the callback function and the other is the data to call
the callback function with.
Signed-off-by: default avatarChandra Seetharaman <sekharan@us.ibm.com>
Signed-off-by: default avatarJames Bottomley <James.Bottomley@suse.de>
parent 42e62a74
...@@ -1116,8 +1116,9 @@ static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath) ...@@ -1116,8 +1116,9 @@ static int pg_init_limit_reached(struct multipath *m, struct pgpath *pgpath)
return limit_reached; return limit_reached;
} }
static void pg_init_done(struct dm_path *path, int errors) static void pg_init_done(void *data, int errors)
{ {
struct dm_path *path = data;
struct pgpath *pgpath = path_to_pgpath(path); struct pgpath *pgpath = path_to_pgpath(path);
struct priority_group *pg = pgpath->pg; struct priority_group *pg = pgpath->pg;
struct multipath *m = pg->m; struct multipath *m = pg->m;
...@@ -1183,12 +1184,11 @@ static void pg_init_done(struct dm_path *path, int errors) ...@@ -1183,12 +1184,11 @@ static void pg_init_done(struct dm_path *path, int errors)
static void activate_path(struct work_struct *work) static void activate_path(struct work_struct *work)
{ {
int ret;
struct pgpath *pgpath = struct pgpath *pgpath =
container_of(work, struct pgpath, activate_path); container_of(work, struct pgpath, activate_path);
ret = scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev)); scsi_dh_activate(bdev_get_queue(pgpath->path.dev->bdev),
pg_init_done(&pgpath->path, ret); pg_init_done, &pgpath->path);
} }
/* /*
......
...@@ -226,7 +226,7 @@ store_dh_state(struct device *dev, struct device_attribute *attr, ...@@ -226,7 +226,7 @@ store_dh_state(struct device *dev, struct device_attribute *attr,
* Activate a device handler * Activate a device handler
*/ */
if (scsi_dh->activate) if (scsi_dh->activate)
err = scsi_dh->activate(sdev); err = scsi_dh->activate(sdev, NULL, NULL);
else else
err = 0; err = 0;
} }
...@@ -423,10 +423,17 @@ EXPORT_SYMBOL_GPL(scsi_unregister_device_handler); ...@@ -423,10 +423,17 @@ EXPORT_SYMBOL_GPL(scsi_unregister_device_handler);
/* /*
* scsi_dh_activate - activate the path associated with the scsi_device * scsi_dh_activate - activate the path associated with the scsi_device
* corresponding to the given request queue. * corresponding to the given request queue.
* @q - Request queue that is associated with the scsi_device to be * Returns immediately without waiting for activation to be completed.
* activated. * @q - Request queue that is associated with the scsi_device to be
* activated.
* @fn - Function to be called upon completion of the activation.
* Function fn is called with data (below) and the error code.
* Function fn may be called from the same calling context. So,
* do not hold the lock in the caller which may be needed in fn.
* @data - data passed to the function fn upon completion.
*
*/ */
int scsi_dh_activate(struct request_queue *q) int scsi_dh_activate(struct request_queue *q, activate_complete fn, void *data)
{ {
int err = 0; int err = 0;
unsigned long flags; unsigned long flags;
...@@ -445,7 +452,7 @@ int scsi_dh_activate(struct request_queue *q) ...@@ -445,7 +452,7 @@ int scsi_dh_activate(struct request_queue *q)
return err; return err;
if (scsi_dh->activate) if (scsi_dh->activate)
err = scsi_dh->activate(sdev); err = scsi_dh->activate(sdev, fn, data);
put_device(&sdev->sdev_gendev); put_device(&sdev->sdev_gendev);
return err; return err;
} }
......
...@@ -652,7 +652,8 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h) ...@@ -652,7 +652,8 @@ static int alua_initialize(struct scsi_device *sdev, struct alua_dh_data *h)
* based on a certain policy. But until we actually encounter them it * based on a certain policy. But until we actually encounter them it
* should be okay. * should be okay.
*/ */
static int alua_activate(struct scsi_device *sdev) static int alua_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
{ {
struct alua_dh_data *h = get_alua_data(sdev); struct alua_dh_data *h = get_alua_data(sdev);
int err = SCSI_DH_OK; int err = SCSI_DH_OK;
...@@ -667,7 +668,9 @@ static int alua_activate(struct scsi_device *sdev) ...@@ -667,7 +668,9 @@ static int alua_activate(struct scsi_device *sdev)
err = alua_stpg(sdev, TPGS_STATE_OPTIMIZED, h); err = alua_stpg(sdev, TPGS_STATE_OPTIMIZED, h);
out: out:
return err; if (fn)
fn(data, err);
return 0;
} }
/* /*
......
...@@ -528,7 +528,8 @@ static int clariion_send_inquiry(struct scsi_device *sdev, ...@@ -528,7 +528,8 @@ static int clariion_send_inquiry(struct scsi_device *sdev,
return err; return err;
} }
static int clariion_activate(struct scsi_device *sdev) static int clariion_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
{ {
struct clariion_dh_data *csdev = get_clariion_data(sdev); struct clariion_dh_data *csdev = get_clariion_data(sdev);
int result; int result;
...@@ -559,7 +560,9 @@ static int clariion_activate(struct scsi_device *sdev) ...@@ -559,7 +560,9 @@ static int clariion_activate(struct scsi_device *sdev)
csdev->port, lun_state[csdev->lun_state], csdev->port, lun_state[csdev->lun_state],
csdev->default_sp + 'A'); csdev->default_sp + 'A');
return result; if (fn)
fn(data, result);
return 0;
} }
/* /*
* params - parameters in the following format * params - parameters in the following format
......
...@@ -268,7 +268,8 @@ static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req) ...@@ -268,7 +268,8 @@ static int hp_sw_prep_fn(struct scsi_device *sdev, struct request *req)
* activate the passive path (and deactivate the * activate the passive path (and deactivate the
* previously active one). * previously active one).
*/ */
static int hp_sw_activate(struct scsi_device *sdev) static int hp_sw_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
{ {
int ret = SCSI_DH_OK; int ret = SCSI_DH_OK;
struct hp_sw_dh_data *h = get_hp_sw_data(sdev); struct hp_sw_dh_data *h = get_hp_sw_data(sdev);
...@@ -283,7 +284,9 @@ static int hp_sw_activate(struct scsi_device *sdev) ...@@ -283,7 +284,9 @@ static int hp_sw_activate(struct scsi_device *sdev)
HP_SW_NAME); HP_SW_NAME);
} }
return ret; if (fn)
fn(data, ret);
return 0;
} }
static const struct scsi_dh_devlist hp_sw_dh_data_list[] = { static const struct scsi_dh_devlist hp_sw_dh_data_list[] = {
......
...@@ -568,7 +568,8 @@ static int send_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h) ...@@ -568,7 +568,8 @@ static int send_mode_select(struct scsi_device *sdev, struct rdac_dh_data *h)
return err; return err;
} }
static int rdac_activate(struct scsi_device *sdev) static int rdac_activate(struct scsi_device *sdev,
activate_complete fn, void *data)
{ {
struct rdac_dh_data *h = get_rdac_data(sdev); struct rdac_dh_data *h = get_rdac_data(sdev);
int err = SCSI_DH_OK; int err = SCSI_DH_OK;
...@@ -580,7 +581,9 @@ static int rdac_activate(struct scsi_device *sdev) ...@@ -580,7 +581,9 @@ static int rdac_activate(struct scsi_device *sdev)
if (h->lun_state == RDAC_LUN_UNOWNED) if (h->lun_state == RDAC_LUN_UNOWNED)
err = send_mode_select(sdev, h); err = send_mode_select(sdev, h);
done: done:
return err; if (fn)
fn(data, err);
return 0;
} }
static int rdac_prep_fn(struct scsi_device *sdev, struct request *req) static int rdac_prep_fn(struct scsi_device *sdev, struct request *req)
......
...@@ -177,6 +177,7 @@ struct scsi_dh_devlist { ...@@ -177,6 +177,7 @@ struct scsi_dh_devlist {
char *model; char *model;
}; };
typedef void (*activate_complete)(void *, int);
struct scsi_device_handler { struct scsi_device_handler {
/* Used by the infrastructure */ /* Used by the infrastructure */
struct list_head list; /* list of scsi_device_handlers */ struct list_head list; /* list of scsi_device_handlers */
...@@ -188,7 +189,7 @@ struct scsi_device_handler { ...@@ -188,7 +189,7 @@ struct scsi_device_handler {
int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *); int (*check_sense)(struct scsi_device *, struct scsi_sense_hdr *);
int (*attach)(struct scsi_device *); int (*attach)(struct scsi_device *);
void (*detach)(struct scsi_device *); void (*detach)(struct scsi_device *);
int (*activate)(struct scsi_device *); int (*activate)(struct scsi_device *, activate_complete, void *);
int (*prep_fn)(struct scsi_device *, struct request *); int (*prep_fn)(struct scsi_device *, struct request *);
int (*set_params)(struct scsi_device *, const char *); int (*set_params)(struct scsi_device *, const char *);
}; };
......
...@@ -56,14 +56,16 @@ enum { ...@@ -56,14 +56,16 @@ enum {
SCSI_DH_DRIVER_MAX, SCSI_DH_DRIVER_MAX,
}; };
#if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE) #if defined(CONFIG_SCSI_DH) || defined(CONFIG_SCSI_DH_MODULE)
extern int scsi_dh_activate(struct request_queue *); extern int scsi_dh_activate(struct request_queue *, activate_complete, void *);
extern int scsi_dh_handler_exist(const char *); extern int scsi_dh_handler_exist(const char *);
extern int scsi_dh_attach(struct request_queue *, const char *); extern int scsi_dh_attach(struct request_queue *, const char *);
extern void scsi_dh_detach(struct request_queue *); extern void scsi_dh_detach(struct request_queue *);
extern int scsi_dh_set_params(struct request_queue *, const char *); extern int scsi_dh_set_params(struct request_queue *, const char *);
#else #else
static inline int scsi_dh_activate(struct request_queue *req) static inline int scsi_dh_activate(struct request_queue *req,
activate_complete fn, void *data)
{ {
fn(data, 0);
return 0; return 0;
} }
static inline int scsi_dh_handler_exist(const char *name) static inline int scsi_dh_handler_exist(const char *name)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment