diff options
Diffstat (limited to 'drivers/scsi/scsi_transport_iscsi.c')
| -rw-r--r-- | drivers/scsi/scsi_transport_iscsi.c | 395 | 
1 files changed, 319 insertions, 76 deletions
diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 65d1737eb66..3af7cbcc5c5 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -30,10 +30,11 @@  #include <scsi/scsi_transport_iscsi.h>  #include <scsi/iscsi_if.h> -#define ISCSI_SESSION_ATTRS 19 +#define ISCSI_SESSION_ATTRS 21  #define ISCSI_CONN_ATTRS 13  #define ISCSI_HOST_ATTRS 4 -#define ISCSI_TRANSPORT_VERSION "2.0-869" + +#define ISCSI_TRANSPORT_VERSION "2.0-870"  struct iscsi_internal {  	int daemon_pid; @@ -101,16 +102,10 @@ show_transport_##name(struct device *dev, 				\  static DEVICE_ATTR(name, S_IRUGO, show_transport_##name, NULL);  show_transport_attr(caps, "0x%x"); -show_transport_attr(max_lun, "%d"); -show_transport_attr(max_conn, "%d"); -show_transport_attr(max_cmd_len, "%d");  static struct attribute *iscsi_transport_attrs[] = {  	&dev_attr_handle.attr,  	&dev_attr_caps.attr, -	&dev_attr_max_lun.attr, -	&dev_attr_max_conn.attr, -	&dev_attr_max_cmd_len.attr,  	NULL,  }; @@ -118,18 +113,139 @@ static struct attribute_group iscsi_transport_group = {  	.attrs = iscsi_transport_attrs,  }; +/* + * iSCSI endpoint attrs + */ +#define iscsi_dev_to_endpoint(_dev) \ +	container_of(_dev, struct iscsi_endpoint, dev) + +#define ISCSI_ATTR(_prefix,_name,_mode,_show,_store)	\ +struct device_attribute dev_attr_##_prefix##_##_name =	\ +        __ATTR(_name,_mode,_show,_store) + +static void iscsi_endpoint_release(struct device *dev) +{ +	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); +	kfree(ep); +} + +static struct class iscsi_endpoint_class = { +	.name = "iscsi_endpoint", +	.dev_release = iscsi_endpoint_release, +}; + +static ssize_t +show_ep_handle(struct device *dev, struct device_attribute *attr, char *buf) +{ +	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); +	return sprintf(buf, "%u\n", ep->id); +} +static ISCSI_ATTR(ep, handle, S_IRUGO, show_ep_handle, NULL); + +static struct attribute *iscsi_endpoint_attrs[] = { +	&dev_attr_ep_handle.attr, +	NULL, +}; + +static struct attribute_group iscsi_endpoint_group = { +	.attrs = iscsi_endpoint_attrs, +}; +#define ISCSI_MAX_EPID -1 + +static int iscsi_match_epid(struct device *dev, void *data) +{ +	struct iscsi_endpoint *ep = iscsi_dev_to_endpoint(dev); +	unsigned int *epid = (unsigned int *) data; + +	return *epid == ep->id; +} + +struct iscsi_endpoint * +iscsi_create_endpoint(int dd_size) +{ +	struct device *dev; +	struct iscsi_endpoint *ep; +	unsigned int id; +	int err; + +	for (id = 1; id < ISCSI_MAX_EPID; id++) { +		dev = class_find_device(&iscsi_endpoint_class, &id, +					iscsi_match_epid); +		if (!dev) +			break; +	} +	if (id == ISCSI_MAX_EPID) { +		printk(KERN_ERR "Too many connections. Max supported %u\n", +		       ISCSI_MAX_EPID - 1); +		return NULL; +	} + +	ep = kzalloc(sizeof(*ep) + dd_size, GFP_KERNEL); +	if (!ep) +		return NULL; + +	ep->id = id; +	ep->dev.class = &iscsi_endpoint_class; +	snprintf(ep->dev.bus_id, BUS_ID_SIZE, "ep-%u", id); +	err = device_register(&ep->dev); +        if (err) +                goto free_ep; + +	err = sysfs_create_group(&ep->dev.kobj, &iscsi_endpoint_group); +	if (err) +		goto unregister_dev; + +	if (dd_size) +		ep->dd_data = &ep[1]; +	return ep; + +unregister_dev: +	device_unregister(&ep->dev); +	return NULL; + +free_ep: +	kfree(ep); +	return NULL; +} +EXPORT_SYMBOL_GPL(iscsi_create_endpoint); + +void iscsi_destroy_endpoint(struct iscsi_endpoint *ep) +{ +	sysfs_remove_group(&ep->dev.kobj, &iscsi_endpoint_group); +	device_unregister(&ep->dev); +} +EXPORT_SYMBOL_GPL(iscsi_destroy_endpoint); + +struct iscsi_endpoint *iscsi_lookup_endpoint(u64 handle) +{ +	struct iscsi_endpoint *ep; +	struct device *dev; + +	dev = class_find_device(&iscsi_endpoint_class, &handle, +				iscsi_match_epid); +	if (!dev) +		return NULL; + +	ep = iscsi_dev_to_endpoint(dev); +	/* +	 * we can drop this now because the interface will prevent +	 * removals and lookups from racing. +	 */ +	put_device(dev); +	return ep; +} +EXPORT_SYMBOL_GPL(iscsi_lookup_endpoint);  static int iscsi_setup_host(struct transport_container *tc, struct device *dev,  			    struct device *cdev)  {  	struct Scsi_Host *shost = dev_to_shost(dev); -	struct iscsi_host *ihost = shost->shost_data; +	struct iscsi_cls_host *ihost = shost->shost_data;  	memset(ihost, 0, sizeof(*ihost)); -	INIT_LIST_HEAD(&ihost->sessions); -	mutex_init(&ihost->mutex);  	atomic_set(&ihost->nr_scans, 0); +	mutex_init(&ihost->mutex);  	snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",  		shost->host_no); @@ -144,7 +260,7 @@ static int iscsi_remove_host(struct transport_container *tc, struct device *dev,  			     struct device *cdev)  {  	struct Scsi_Host *shost = dev_to_shost(dev); -	struct iscsi_host *ihost = shost->shost_data; +	struct iscsi_cls_host *ihost = shost->shost_data;  	destroy_workqueue(ihost->scan_workq);  	return 0; @@ -287,6 +403,24 @@ static int iscsi_is_session_dev(const struct device *dev)  	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   * @shost: scsi host @@ -297,7 +431,7 @@ static int iscsi_is_session_dev(const struct device *dev)   */  int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)  { -	struct iscsi_host *ihost = shost->shost_data; +	struct iscsi_cls_host *ihost = shost->shost_data;  	/*  	 * qla4xxx will have kicked off some session unblocks before calling  	 * scsi_scan_host, so just wait for them to complete. @@ -306,42 +440,76 @@ int iscsi_scan_finished(struct Scsi_Host *shost, unsigned long time)  }  EXPORT_SYMBOL_GPL(iscsi_scan_finished); -static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, -			   uint id, uint lun) +struct iscsi_scan_data { +	unsigned int channel; +	unsigned int id; +	unsigned int lun; +}; + +static int iscsi_user_scan_session(struct device *dev, void *data)  { -	struct iscsi_host *ihost = shost->shost_data; +	struct iscsi_scan_data *scan_data = data;  	struct iscsi_cls_session *session; +	struct Scsi_Host *shost; +	struct iscsi_cls_host *ihost; +	unsigned long flags; +	unsigned int id; + +	if (!iscsi_is_session_dev(dev)) +		return 0; + +	session = iscsi_dev_to_session(dev); +	shost = iscsi_session_to_shost(session); +	ihost = shost->shost_data;  	mutex_lock(&ihost->mutex); -	list_for_each_entry(session, &ihost->sessions, host_list) { -		if ((channel == SCAN_WILD_CARD || channel == 0) && -		    (id == SCAN_WILD_CARD || id == session->target_id)) -			scsi_scan_target(&session->dev, 0, -					 session->target_id, lun, 1); +	spin_lock_irqsave(&session->lock, flags); +	if (session->state != ISCSI_SESSION_LOGGED_IN) { +		spin_unlock_irqrestore(&session->lock, flags); +		mutex_unlock(&ihost->mutex); +		return 0;  	} -	mutex_unlock(&ihost->mutex); +	id = session->target_id; +	spin_unlock_irqrestore(&session->lock, flags); +	if (id != ISCSI_MAX_TARGET) { +		if ((scan_data->channel == SCAN_WILD_CARD || +		     scan_data->channel == 0) && +		    (scan_data->id == SCAN_WILD_CARD || +		     scan_data->id == id)) +			scsi_scan_target(&session->dev, 0, id, +					 scan_data->lun, 1); +	} +	mutex_unlock(&ihost->mutex);  	return 0;  } +static int iscsi_user_scan(struct Scsi_Host *shost, uint channel, +			   uint id, uint lun) +{ +	struct iscsi_scan_data scan_data; + +	scan_data.channel = channel; +	scan_data.id = id; +	scan_data.lun = lun; + +	return device_for_each_child(&shost->shost_gendev, &scan_data, +				     iscsi_user_scan_session); +} +  static void iscsi_scan_session(struct work_struct *work)  {  	struct iscsi_cls_session *session =  			container_of(work, struct iscsi_cls_session, scan_work);  	struct Scsi_Host *shost = iscsi_session_to_shost(session); -	struct iscsi_host *ihost = shost->shost_data; -	unsigned long flags; +	struct iscsi_cls_host *ihost = shost->shost_data; +	struct iscsi_scan_data scan_data; -	spin_lock_irqsave(&session->lock, flags); -	if (session->state != ISCSI_SESSION_LOGGED_IN) { -		spin_unlock_irqrestore(&session->lock, flags); -		goto done; -	} -	spin_unlock_irqrestore(&session->lock, flags); +	scan_data.channel = 0; +	scan_data.id = SCAN_WILD_CARD; +	scan_data.lun = SCAN_WILD_CARD; -	scsi_scan_target(&session->dev, 0, session->target_id, -			 SCAN_WILD_CARD, 1); -done: +	iscsi_user_scan_session(&session->dev, &scan_data);  	atomic_dec(&ihost->nr_scans);  } @@ -381,7 +549,7 @@ static void __iscsi_unblock_session(struct work_struct *work)  			container_of(work, struct iscsi_cls_session,  				     unblock_work);  	struct Scsi_Host *shost = iscsi_session_to_shost(session); -	struct iscsi_host *ihost = shost->shost_data; +	struct iscsi_cls_host *ihost = shost->shost_data;  	unsigned long flags;  	/* @@ -449,15 +617,19 @@ static void __iscsi_unbind_session(struct work_struct *work)  			container_of(work, struct iscsi_cls_session,  				     unbind_work);  	struct Scsi_Host *shost = iscsi_session_to_shost(session); -	struct iscsi_host *ihost = shost->shost_data; +	struct iscsi_cls_host *ihost = shost->shost_data; +	unsigned long flags;  	/* Prevent new scans and make sure scanning is not in progress */  	mutex_lock(&ihost->mutex); -	if (list_empty(&session->host_list)) { +	spin_lock_irqsave(&session->lock, flags); +	if (session->target_id == ISCSI_MAX_TARGET) { +		spin_unlock_irqrestore(&session->lock, flags);  		mutex_unlock(&ihost->mutex);  		return;  	} -	list_del_init(&session->host_list); +	session->target_id = ISCSI_MAX_TARGET; +	spin_unlock_irqrestore(&session->lock, flags);  	mutex_unlock(&ihost->mutex);  	scsi_remove_target(&session->dev); @@ -467,18 +639,18 @@ static void __iscsi_unbind_session(struct work_struct *work)  static int iscsi_unbind_session(struct iscsi_cls_session *session)  {  	struct Scsi_Host *shost = iscsi_session_to_shost(session); -	struct iscsi_host *ihost = shost->shost_data; +	struct iscsi_cls_host *ihost = shost->shost_data;  	return queue_work(ihost->scan_workq, &session->unbind_work);  }  struct iscsi_cls_session * -iscsi_alloc_session(struct Scsi_Host *shost, -		    struct iscsi_transport *transport) +iscsi_alloc_session(struct Scsi_Host *shost, struct iscsi_transport *transport, +		    int dd_size)  {  	struct iscsi_cls_session *session; -	session = kzalloc(sizeof(*session) + transport->sessiondata_size, +	session = kzalloc(sizeof(*session) + dd_size,  			  GFP_KERNEL);  	if (!session)  		return NULL; @@ -487,7 +659,6 @@ iscsi_alloc_session(struct Scsi_Host *shost,  	session->recovery_tmo = 120;  	session->state = ISCSI_SESSION_FREE;  	INIT_DELAYED_WORK(&session->recovery_work, session_recovery_timedout); -	INIT_LIST_HEAD(&session->host_list);  	INIT_LIST_HEAD(&session->sess_list);  	INIT_WORK(&session->unblock_work, __iscsi_unblock_session);  	INIT_WORK(&session->block_work, __iscsi_block_session); @@ -500,22 +671,57 @@ iscsi_alloc_session(struct Scsi_Host *shost,  	session->dev.parent = &shost->shost_gendev;  	session->dev.release = iscsi_session_release;  	device_initialize(&session->dev); -	if (transport->sessiondata_size) +	if (dd_size)  		session->dd_data = &session[1];  	return session;  }  EXPORT_SYMBOL_GPL(iscsi_alloc_session); +static int iscsi_get_next_target_id(struct device *dev, void *data) +{ +	struct iscsi_cls_session *session; +	unsigned long flags; +	int err = 0; + +	if (!iscsi_is_session_dev(dev)) +		return 0; + +	session = iscsi_dev_to_session(dev); +	spin_lock_irqsave(&session->lock, flags); +	if (*((unsigned int *) data) == session->target_id) +		err = -EEXIST; +	spin_unlock_irqrestore(&session->lock, flags); +	return err; +} +  int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)  {  	struct Scsi_Host *shost = iscsi_session_to_shost(session); -	struct iscsi_host *ihost; +	struct iscsi_cls_host *ihost;  	unsigned long flags; +	unsigned int id = target_id;  	int err;  	ihost = shost->shost_data;  	session->sid = atomic_add_return(1, &iscsi_session_nr); -	session->target_id = target_id; + +	if (id == ISCSI_MAX_TARGET) { +		for (id = 0; id < ISCSI_MAX_TARGET; id++) { +			err = device_for_each_child(&shost->shost_gendev, &id, +						    iscsi_get_next_target_id); +			if (!err) +				break; +		} + +		if (id == ISCSI_MAX_TARGET) { +			iscsi_cls_session_printk(KERN_ERR, session, +						 "Too many iscsi targets. Max " +						 "number of targets is %d.\n", +						 ISCSI_MAX_TARGET - 1); +			goto release_host; +		} +	} +	session->target_id = id;  	snprintf(session->dev.bus_id, BUS_ID_SIZE, "session%u",  		 session->sid); @@ -531,10 +737,6 @@ int iscsi_add_session(struct iscsi_cls_session *session, unsigned int target_id)  	list_add(&session->sess_list, &sesslist);  	spin_unlock_irqrestore(&sesslock, flags); -	mutex_lock(&ihost->mutex); -	list_add(&session->host_list, &ihost->sessions); -	mutex_unlock(&ihost->mutex); -  	iscsi_session_event(session, ISCSI_KEVENT_CREATE_SESSION);  	return 0; @@ -548,18 +750,18 @@ EXPORT_SYMBOL_GPL(iscsi_add_session);   * iscsi_create_session - create iscsi class session   * @shost: scsi host   * @transport: iscsi transport + * @dd_size: private driver data size   * @target_id: which target   *   * This can be called from a LLD or iscsi_transport.   */  struct iscsi_cls_session * -iscsi_create_session(struct Scsi_Host *shost, -		     struct iscsi_transport *transport, -		     unsigned int target_id) +iscsi_create_session(struct Scsi_Host *shost, struct iscsi_transport *transport, +		     int dd_size, unsigned int target_id)  {  	struct iscsi_cls_session *session; -	session = iscsi_alloc_session(shost, transport); +	session = iscsi_alloc_session(shost, transport, dd_size);  	if (!session)  		return NULL; @@ -595,7 +797,7 @@ static int iscsi_iter_destroy_conn_fn(struct device *dev, void *data)  void iscsi_remove_session(struct iscsi_cls_session *session)  {  	struct Scsi_Host *shost = iscsi_session_to_shost(session); -	struct iscsi_host *ihost = shost->shost_data; +	struct iscsi_cls_host *ihost = shost->shost_data;  	unsigned long flags;  	int err; @@ -661,6 +863,7 @@ EXPORT_SYMBOL_GPL(iscsi_destroy_session);  /**   * iscsi_create_conn - create iscsi class connection   * @session: iscsi cls session + * @dd_size: private driver data size   * @cid: connection id   *   * This can be called from a LLD or iscsi_transport. The connection @@ -673,18 +876,17 @@ EXPORT_SYMBOL_GPL(iscsi_destroy_session);   * non-zero.   */  struct iscsi_cls_conn * -iscsi_create_conn(struct iscsi_cls_session *session, uint32_t cid) +iscsi_create_conn(struct iscsi_cls_session *session, int dd_size, uint32_t cid)  {  	struct iscsi_transport *transport = session->transport;  	struct iscsi_cls_conn *conn;  	unsigned long flags;  	int err; -	conn = kzalloc(sizeof(*conn) + transport->conndata_size, GFP_KERNEL); +	conn = kzalloc(sizeof(*conn) + dd_size, GFP_KERNEL);  	if (!conn)  		return NULL; - -	if (transport->conndata_size) +	if (dd_size)  		conn->dd_data = &conn[1];  	INIT_LIST_HEAD(&conn->conn_list); @@ -1017,21 +1219,20 @@ int iscsi_session_event(struct iscsi_cls_session *session,  EXPORT_SYMBOL_GPL(iscsi_session_event);  static int -iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_uevent *ev) +iscsi_if_create_session(struct iscsi_internal *priv, struct iscsi_endpoint *ep, +			struct iscsi_uevent *ev, uint32_t initial_cmdsn, +			uint16_t cmds_max, uint16_t queue_depth)  {  	struct iscsi_transport *transport = priv->iscsi_transport;  	struct iscsi_cls_session *session; -	uint32_t hostno; +	uint32_t host_no; -	session = transport->create_session(transport, &priv->t, -					    ev->u.c_session.cmds_max, -					    ev->u.c_session.queue_depth, -					    ev->u.c_session.initial_cmdsn, -					    &hostno); +	session = transport->create_session(ep, cmds_max, queue_depth, +					    initial_cmdsn, &host_no);  	if (!session)  		return -ENOMEM; -	ev->r.c_session_ret.host_no = hostno; +	ev->r.c_session_ret.host_no = host_no;  	ev->r.c_session_ret.sid = session->sid;  	return 0;  } @@ -1106,6 +1307,7 @@ static int  iscsi_if_transport_ep(struct iscsi_transport *transport,  		      struct iscsi_uevent *ev, int msg_type)  { +	struct iscsi_endpoint *ep;  	struct sockaddr *dst_addr;  	int rc = 0; @@ -1115,22 +1317,33 @@ iscsi_if_transport_ep(struct iscsi_transport *transport,  			return -EINVAL;  		dst_addr = (struct sockaddr *)((char*)ev + sizeof(*ev)); -		rc = transport->ep_connect(dst_addr, -					   ev->u.ep_connect.non_blocking, -					   &ev->r.ep_connect_ret.handle); +		ep = transport->ep_connect(dst_addr, +					   ev->u.ep_connect.non_blocking); +		if (IS_ERR(ep)) +			return PTR_ERR(ep); + +		ev->r.ep_connect_ret.handle = ep->id;  		break;  	case ISCSI_UEVENT_TRANSPORT_EP_POLL:  		if (!transport->ep_poll)  			return -EINVAL; -		ev->r.retcode = transport->ep_poll(ev->u.ep_poll.ep_handle, +		ep = iscsi_lookup_endpoint(ev->u.ep_poll.ep_handle); +		if (!ep) +			return -EINVAL; + +		ev->r.retcode = transport->ep_poll(ep,  						   ev->u.ep_poll.timeout_ms);  		break;  	case ISCSI_UEVENT_TRANSPORT_EP_DISCONNECT:  		if (!transport->ep_disconnect)  			return -EINVAL; -		transport->ep_disconnect(ev->u.ep_disconnect.ep_handle); +		ep = iscsi_lookup_endpoint(ev->u.ep_disconnect.ep_handle); +		if (!ep) +			return -EINVAL; + +		transport->ep_disconnect(ep);  		break;  	}  	return rc; @@ -1195,6 +1408,7 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  	struct iscsi_internal *priv;  	struct iscsi_cls_session *session;  	struct iscsi_cls_conn *conn; +	struct iscsi_endpoint *ep = NULL;  	priv = iscsi_if_transport_lookup(iscsi_ptr(ev->transport_handle));  	if (!priv) @@ -1208,7 +1422,22 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)  	switch (nlh->nlmsg_type) {  	case ISCSI_UEVENT_CREATE_SESSION: -		err = iscsi_if_create_session(priv, ev); +		err = iscsi_if_create_session(priv, ep, ev, +					      ev->u.c_session.initial_cmdsn, +					      ev->u.c_session.cmds_max, +					      ev->u.c_session.queue_depth); +		break; +	case ISCSI_UEVENT_CREATE_BOUND_SESSION: +		ep = iscsi_lookup_endpoint(ev->u.c_bound_session.ep_handle); +		if (!ep) { +			err = -EINVAL; +			break; +		} + +		err = iscsi_if_create_session(priv, ep, ev, +					ev->u.c_bound_session.initial_cmdsn, +					ev->u.c_bound_session.cmds_max, +					ev->u.c_bound_session.queue_depth);  		break;  	case ISCSI_UEVENT_DESTROY_SESSION:  		session = iscsi_session_lookup(ev->u.d_session.sid); @@ -1414,6 +1643,8 @@ iscsi_session_attr(password_in, ISCSI_PARAM_PASSWORD_IN, 1);  iscsi_session_attr(fast_abort, ISCSI_PARAM_FAST_ABORT, 0);  iscsi_session_attr(abort_tmo, ISCSI_PARAM_ABORT_TMO, 0);  iscsi_session_attr(lu_reset_tmo, ISCSI_PARAM_LU_RESET_TMO, 0); +iscsi_session_attr(ifacename, ISCSI_PARAM_IFACE_NAME, 0); +iscsi_session_attr(initiatorname, ISCSI_PARAM_INITIATOR_NAME, 0)  static ssize_t  show_priv_session_state(struct device *dev, struct device_attribute *attr, @@ -1580,6 +1811,8 @@ iscsi_register_transport(struct iscsi_transport *tt)  	priv->daemon_pid = -1;  	priv->iscsi_transport = tt;  	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;  	snprintf(priv->dev.bus_id, BUS_ID_SIZE, "%s", tt->name); @@ -1595,7 +1828,7 @@ iscsi_register_transport(struct iscsi_transport *tt)  	priv->t.host_attrs.ac.attrs = &priv->host_attrs[0];  	priv->t.host_attrs.ac.class = &iscsi_host_class.class;  	priv->t.host_attrs.ac.match = iscsi_host_match; -	priv->t.host_size = sizeof(struct iscsi_host); +	priv->t.host_size = sizeof(struct iscsi_cls_host);  	transport_container_register(&priv->t.host_attrs);  	SETUP_HOST_RD_ATTR(netdev, ISCSI_HOST_NETDEV_NAME); @@ -1653,6 +1886,8 @@ iscsi_register_transport(struct iscsi_transport *tt)  	SETUP_SESSION_RD_ATTR(fast_abort, ISCSI_FAST_ABORT);  	SETUP_SESSION_RD_ATTR(abort_tmo, ISCSI_ABORT_TMO);  	SETUP_SESSION_RD_ATTR(lu_reset_tmo,ISCSI_LU_RESET_TMO); +	SETUP_SESSION_RD_ATTR(ifacename, ISCSI_IFACE_NAME); +	SETUP_SESSION_RD_ATTR(initiatorname, ISCSI_INITIATOR_NAME);  	SETUP_PRIV_SESSION_RD_ATTR(recovery_tmo);  	SETUP_PRIV_SESSION_RD_ATTR(state); @@ -1668,6 +1903,7 @@ iscsi_register_transport(struct iscsi_transport *tt)  unregister_dev:  	device_unregister(&priv->dev); +	return NULL;  free_priv:  	kfree(priv);  	return NULL; @@ -1715,10 +1951,14 @@ static __init int iscsi_transport_init(void)  	if (err)  		return err; -	err = transport_class_register(&iscsi_host_class); +	err = class_register(&iscsi_endpoint_class);  	if (err)  		goto unregister_transport_class; +	err = transport_class_register(&iscsi_host_class); +	if (err) +		goto unregister_endpoint_class; +  	err = transport_class_register(&iscsi_connection_class);  	if (err)  		goto unregister_host_class; @@ -1727,8 +1967,8 @@ static __init int iscsi_transport_init(void)  	if (err)  		goto unregister_conn_class; -	nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, NULL, -			THIS_MODULE); +	nls = netlink_kernel_create(&init_net, NETLINK_ISCSI, 1, iscsi_if_rx, +				    NULL, THIS_MODULE);  	if (!nls) {  		err = -ENOBUFS;  		goto unregister_session_class; @@ -1748,6 +1988,8 @@ unregister_conn_class:  	transport_class_unregister(&iscsi_connection_class);  unregister_host_class:  	transport_class_unregister(&iscsi_host_class); +unregister_endpoint_class: +	class_unregister(&iscsi_endpoint_class);  unregister_transport_class:  	class_unregister(&iscsi_transport_class);  	return err; @@ -1760,6 +2002,7 @@ static void __exit iscsi_transport_exit(void)  	transport_class_unregister(&iscsi_connection_class);  	transport_class_unregister(&iscsi_session_class);  	transport_class_unregister(&iscsi_host_class); +	class_unregister(&iscsi_endpoint_class);  	class_unregister(&iscsi_transport_class);  }  |