[SCSI] iscsi: add iscsi host helpers
This finishes the host/session unbinding, by adding some helpers to add and remove hosts and the session they manage. Signed-off-by: Mike Christie <michaelc@cs.wisc.edu> Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
This commit is contained in:
parent
756135215e
commit
a4804cd6eb
|
@ -371,10 +371,8 @@ static void iscsi_iser_session_destroy(struct iscsi_cls_session *cls_session)
|
||||||
{
|
{
|
||||||
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
||||||
|
|
||||||
iscsi_session_teardown(cls_session);
|
iscsi_host_remove(shost);
|
||||||
scsi_remove_host(shost);
|
iscsi_host_free(shost);
|
||||||
iscsi_host_teardown(shost);
|
|
||||||
scsi_host_put(shost);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static struct iscsi_cls_session *
|
static struct iscsi_cls_session *
|
||||||
|
@ -396,7 +394,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
shost = scsi_host_alloc(&iscsi_iser_sht, 0);
|
shost = iscsi_host_alloc(&iscsi_iser_sht, 0, ISCSI_MAX_CMD_PER_LUN);
|
||||||
if (!shost)
|
if (!shost)
|
||||||
return NULL;
|
return NULL;
|
||||||
shost->transportt = iscsi_iser_scsi_transport;
|
shost->transportt = iscsi_iser_scsi_transport;
|
||||||
|
@ -405,9 +403,7 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
|
||||||
shost->max_channel = 0;
|
shost->max_channel = 0;
|
||||||
shost->max_cmd_len = 16;
|
shost->max_cmd_len = 16;
|
||||||
|
|
||||||
iscsi_host_setup(shost, qdepth);
|
if (iscsi_host_add(shost, NULL))
|
||||||
|
|
||||||
if (scsi_add_host(shost, NULL))
|
|
||||||
goto free_host;
|
goto free_host;
|
||||||
*hostno = shost->host_no;
|
*hostno = shost->host_no;
|
||||||
|
|
||||||
|
@ -443,10 +439,9 @@ iscsi_iser_session_create(struct Scsi_Host *shost,
|
||||||
return cls_session;
|
return cls_session;
|
||||||
|
|
||||||
remove_host:
|
remove_host:
|
||||||
scsi_remove_host(shost);
|
iscsi_host_remove(shost);
|
||||||
free_host:
|
free_host:
|
||||||
iscsi_host_teardown(shost);
|
iscsi_host_free(shost);
|
||||||
scsi_host_put(shost);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1866,7 +1866,7 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
shost = scsi_host_alloc(&iscsi_sht, sizeof(struct iscsi_host));
|
shost = iscsi_host_alloc(&iscsi_sht, 0, qdepth);
|
||||||
if (!shost)
|
if (!shost)
|
||||||
return NULL;
|
return NULL;
|
||||||
shost->transportt = iscsi_tcp_scsi_transport;
|
shost->transportt = iscsi_tcp_scsi_transport;
|
||||||
|
@ -1874,10 +1874,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
|
||||||
shost->max_id = 0;
|
shost->max_id = 0;
|
||||||
shost->max_channel = 0;
|
shost->max_channel = 0;
|
||||||
shost->max_cmd_len = 16;
|
shost->max_cmd_len = 16;
|
||||||
|
shost->can_queue = cmds_max;
|
||||||
|
|
||||||
iscsi_host_setup(shost, qdepth);
|
if (iscsi_host_add(shost, NULL))
|
||||||
|
|
||||||
if (scsi_add_host(shost, NULL))
|
|
||||||
goto free_host;
|
goto free_host;
|
||||||
*hostno = shost->host_no;
|
*hostno = shost->host_no;
|
||||||
|
|
||||||
|
@ -1912,10 +1911,9 @@ iscsi_tcp_session_create(struct Scsi_Host *shost, uint16_t cmds_max,
|
||||||
remove_session:
|
remove_session:
|
||||||
iscsi_session_teardown(cls_session);
|
iscsi_session_teardown(cls_session);
|
||||||
remove_host:
|
remove_host:
|
||||||
scsi_remove_host(shost);
|
iscsi_host_remove(shost);
|
||||||
free_host:
|
free_host:
|
||||||
iscsi_host_teardown(shost);
|
iscsi_host_free(shost);
|
||||||
scsi_host_put(shost);
|
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1924,11 +1922,9 @@ static void iscsi_tcp_session_destroy(struct iscsi_cls_session *cls_session)
|
||||||
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
struct Scsi_Host *shost = iscsi_session_to_shost(cls_session);
|
||||||
|
|
||||||
iscsi_r2tpool_free(cls_session->dd_data);
|
iscsi_r2tpool_free(cls_session->dd_data);
|
||||||
iscsi_session_teardown(cls_session);
|
|
||||||
|
|
||||||
scsi_remove_host(shost);
|
iscsi_host_remove(shost);
|
||||||
iscsi_host_teardown(shost);
|
iscsi_host_free(shost);
|
||||||
scsi_host_put(shost);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
|
static int iscsi_tcp_slave_configure(struct scsi_device *sdev)
|
||||||
|
|
|
@ -1764,8 +1764,39 @@ void iscsi_pool_free(struct iscsi_pool *q)
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_pool_free);
|
EXPORT_SYMBOL_GPL(iscsi_pool_free);
|
||||||
|
|
||||||
void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth)
|
/**
|
||||||
|
* iscsi_host_add - add host to system
|
||||||
|
* @shost: scsi host
|
||||||
|
* @pdev: parent device
|
||||||
|
*
|
||||||
|
* This should be called by partial offload and software iscsi drivers
|
||||||
|
* to add a host to the system.
|
||||||
|
*/
|
||||||
|
int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev)
|
||||||
{
|
{
|
||||||
|
return scsi_add_host(shost, pdev);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(iscsi_host_add);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* iscsi_host_alloc - allocate a host and driver data
|
||||||
|
* @sht: scsi host template
|
||||||
|
* @dd_data_size: driver host data size
|
||||||
|
* @qdepth: default device queue depth
|
||||||
|
*
|
||||||
|
* This should be called by partial offload and software iscsi drivers.
|
||||||
|
* To access the driver specific memory use the iscsi_host_priv() macro.
|
||||||
|
*/
|
||||||
|
struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
|
||||||
|
int dd_data_size, uint16_t qdepth)
|
||||||
|
{
|
||||||
|
struct Scsi_Host *shost;
|
||||||
|
|
||||||
|
shost = scsi_host_alloc(sht, sizeof(struct iscsi_host) + dd_data_size);
|
||||||
|
if (!shost)
|
||||||
|
return NULL;
|
||||||
|
shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
|
||||||
|
|
||||||
if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
|
if (qdepth > ISCSI_MAX_CMD_PER_LUN || qdepth < 1) {
|
||||||
if (qdepth != 0)
|
if (qdepth != 0)
|
||||||
printk(KERN_ERR "iscsi: invalid queue depth of %d. "
|
printk(KERN_ERR "iscsi: invalid queue depth of %d. "
|
||||||
|
@ -1773,22 +1804,37 @@ void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth)
|
||||||
qdepth, ISCSI_MAX_CMD_PER_LUN);
|
qdepth, ISCSI_MAX_CMD_PER_LUN);
|
||||||
qdepth = ISCSI_DEF_CMD_PER_LUN;
|
qdepth = ISCSI_DEF_CMD_PER_LUN;
|
||||||
}
|
}
|
||||||
|
|
||||||
shost->transportt->create_work_queue = 1;
|
|
||||||
shost->transportt->eh_timed_out = iscsi_eh_cmd_timed_out;
|
|
||||||
shost->cmd_per_lun = qdepth;
|
shost->cmd_per_lun = qdepth;
|
||||||
|
return shost;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_host_setup);
|
EXPORT_SYMBOL_GPL(iscsi_host_alloc);
|
||||||
|
|
||||||
void iscsi_host_teardown(struct Scsi_Host *shost)
|
/**
|
||||||
|
* iscsi_host_remove - remove host and sessions
|
||||||
|
* @shost: scsi host
|
||||||
|
*
|
||||||
|
* This will also remove any sessions attached to the host, but if userspace
|
||||||
|
* is managing the session at the same time this will break. TODO: add
|
||||||
|
* refcounting to the netlink iscsi interface so a rmmod or host hot unplug
|
||||||
|
* does not remove the memory from under us.
|
||||||
|
*/
|
||||||
|
void iscsi_host_remove(struct Scsi_Host *shost)
|
||||||
|
{
|
||||||
|
iscsi_host_for_each_session(shost, iscsi_session_teardown);
|
||||||
|
scsi_remove_host(shost);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(iscsi_host_remove);
|
||||||
|
|
||||||
|
void iscsi_host_free(struct Scsi_Host *shost)
|
||||||
{
|
{
|
||||||
struct iscsi_host *ihost = shost_priv(shost);
|
struct iscsi_host *ihost = shost_priv(shost);
|
||||||
|
|
||||||
kfree(ihost->netdev);
|
kfree(ihost->netdev);
|
||||||
kfree(ihost->hwaddress);
|
kfree(ihost->hwaddress);
|
||||||
kfree(ihost->initiatorname);
|
kfree(ihost->initiatorname);
|
||||||
|
scsi_host_put(shost);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(iscsi_host_teardown);
|
EXPORT_SYMBOL_GPL(iscsi_host_free);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iscsi_session_setup - create iscsi cls session and host and session
|
* iscsi_session_setup - create iscsi cls session and host and session
|
||||||
|
|
|
@ -279,6 +279,24 @@ static int iscsi_is_session_dev(const struct device *dev)
|
||||||
return dev->release == iscsi_session_release;
|
return dev->release == iscsi_session_release;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int iscsi_iter_session_fn(struct device *dev, void *data)
|
||||||
|
{
|
||||||
|
void (* fn) (struct iscsi_cls_session *) = data;
|
||||||
|
|
||||||
|
if (!iscsi_is_session_dev(dev))
|
||||||
|
return 0;
|
||||||
|
fn(iscsi_dev_to_session(dev));
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void iscsi_host_for_each_session(struct Scsi_Host *shost,
|
||||||
|
void (*fn)(struct iscsi_cls_session *))
|
||||||
|
{
|
||||||
|
device_for_each_child(&shost->shost_gendev, fn,
|
||||||
|
iscsi_iter_session_fn);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL_GPL(iscsi_host_for_each_session);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* iscsi_scan_finished - helper to report when running scans are done
|
* iscsi_scan_finished - helper to report when running scans are done
|
||||||
* @shost: scsi host
|
* @shost: scsi host
|
||||||
|
@ -1599,6 +1617,8 @@ iscsi_register_transport(struct iscsi_transport *tt)
|
||||||
priv->daemon_pid = -1;
|
priv->daemon_pid = -1;
|
||||||
priv->iscsi_transport = tt;
|
priv->iscsi_transport = tt;
|
||||||
priv->t.user_scan = iscsi_user_scan;
|
priv->t.user_scan = iscsi_user_scan;
|
||||||
|
if (!(tt->caps & CAP_DATA_PATH_OFFLOAD))
|
||||||
|
priv->t.create_work_queue = 1;
|
||||||
|
|
||||||
priv->dev.class = &iscsi_transport_class;
|
priv->dev.class = &iscsi_transport_class;
|
||||||
snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name);
|
snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name);
|
||||||
|
|
|
@ -32,6 +32,7 @@
|
||||||
#include <scsi/iscsi_if.h>
|
#include <scsi/iscsi_if.h>
|
||||||
|
|
||||||
struct scsi_transport_template;
|
struct scsi_transport_template;
|
||||||
|
struct scsi_host_template;
|
||||||
struct scsi_device;
|
struct scsi_device;
|
||||||
struct Scsi_Host;
|
struct Scsi_Host;
|
||||||
struct scsi_cmnd;
|
struct scsi_cmnd;
|
||||||
|
@ -41,6 +42,7 @@ struct iscsi_cls_session;
|
||||||
struct iscsi_cls_conn;
|
struct iscsi_cls_conn;
|
||||||
struct iscsi_session;
|
struct iscsi_session;
|
||||||
struct iscsi_nopin;
|
struct iscsi_nopin;
|
||||||
|
struct device;
|
||||||
|
|
||||||
/* #define DEBUG_SCSI */
|
/* #define DEBUG_SCSI */
|
||||||
#ifdef DEBUG_SCSI
|
#ifdef DEBUG_SCSI
|
||||||
|
@ -311,6 +313,8 @@ struct iscsi_host {
|
||||||
char local_address[ISCSI_ADDRESS_BUF_LEN];
|
char local_address[ISCSI_ADDRESS_BUF_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define iscsi_host_priv(_shost) \
|
||||||
|
(shost_priv(_shost) + sizeof(struct iscsi_host))
|
||||||
/*
|
/*
|
||||||
* scsi host template
|
* scsi host template
|
||||||
*/
|
*/
|
||||||
|
@ -330,8 +334,11 @@ extern int iscsi_host_set_param(struct Scsi_Host *shost,
|
||||||
int buflen);
|
int buflen);
|
||||||
extern int iscsi_host_get_param(struct Scsi_Host *shost,
|
extern int iscsi_host_get_param(struct Scsi_Host *shost,
|
||||||
enum iscsi_host_param param, char *buf);
|
enum iscsi_host_param param, char *buf);
|
||||||
extern void iscsi_host_setup(struct Scsi_Host *shost, uint16_t qdepth);
|
extern int iscsi_host_add(struct Scsi_Host *shost, struct device *pdev);
|
||||||
extern void iscsi_host_teardown(struct Scsi_Host *shost);
|
extern struct Scsi_Host *iscsi_host_alloc(struct scsi_host_template *sht,
|
||||||
|
int dd_data_size, uint16_t qdepth);
|
||||||
|
extern void iscsi_host_remove(struct Scsi_Host *shost);
|
||||||
|
extern void iscsi_host_free(struct Scsi_Host *shost);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* session management
|
* session management
|
||||||
|
|
|
@ -207,6 +207,10 @@ struct iscsi_cls_host {
|
||||||
char scan_workq_name[KOBJ_NAME_LEN];
|
char scan_workq_name[KOBJ_NAME_LEN];
|
||||||
};
|
};
|
||||||
|
|
||||||
|
extern void iscsi_host_for_each_session(struct Scsi_Host *shost,
|
||||||
|
void (*fn)(struct iscsi_cls_session *));
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* session and connection functions that can be used by HW iSCSI LLDs
|
* session and connection functions that can be used by HW iSCSI LLDs
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Reference in New Issue