Skip to content

Commit

Permalink
[SCSI] iscsi class: add session scanning
Browse files Browse the repository at this point in the history
This just adds iscsi session scanning which works like fc rport scanning.
The future patches will hook the drivers into Mathew Wilcox's async
scanning infrastructure, so userspace does not have to special case
iscsi and so userspace does not have to make a extra special case for
hardware iscsi root scanning.

Signed-off-by: Mike Christie <michaelc@cs.wisc.edu>
Signed-off-by: James Bottomley <James.Bottomley@HansenPartnership.com>
  • Loading branch information
Mike Christie authored and James Bottomley committed Feb 8, 2008
1 parent 7fb1921 commit bd976f6
Show file tree
Hide file tree
Showing 2 changed files with 34 additions and 10 deletions.
37 changes: 30 additions & 7 deletions drivers/scsi/scsi_transport_iscsi.c
Original file line number Diff line number Diff line change
Expand Up @@ -128,11 +128,11 @@ static int iscsi_setup_host(struct transport_container *tc, struct device *dev,
INIT_LIST_HEAD(&ihost->sessions);
mutex_init(&ihost->mutex);

snprintf(ihost->unbind_workq_name, KOBJ_NAME_LEN, "iscsi_unbind_%d",
snprintf(ihost->scan_workq_name, KOBJ_NAME_LEN, "iscsi_scan_%d",
shost->host_no);
ihost->unbind_workq = create_singlethread_workqueue(
ihost->unbind_workq_name);
if (!ihost->unbind_workq)
ihost->scan_workq = create_singlethread_workqueue(
ihost->scan_workq_name);
if (!ihost->scan_workq)
return -ENOMEM;
return 0;
}
Expand All @@ -143,7 +143,7 @@ static int iscsi_remove_host(struct transport_container *tc, struct device *dev,
struct Scsi_Host *shost = dev_to_shost(dev);
struct iscsi_host *ihost = shost->shost_data;

destroy_workqueue(ihost->unbind_workq);
destroy_workqueue(ihost->scan_workq);
return 0;
}

Expand Down Expand Up @@ -302,6 +302,23 @@ static int iscsi_user_scan(struct Scsi_Host *shost, uint channel,
return 0;
}

static void iscsi_scan_session(struct work_struct *work)
{
struct iscsi_cls_session *session =
container_of(work, struct iscsi_cls_session, scan_work);
unsigned long flags;

spin_lock_irqsave(&session->lock, flags);
if (session->state != ISCSI_SESSION_LOGGED_IN) {
spin_unlock_irqrestore(&session->lock, flags);
return;
}
spin_unlock_irqrestore(&session->lock, flags);

scsi_scan_target(&session->dev, 0, session->target_id,
SCAN_WILD_CARD, 1);
}

static void session_recovery_timedout(struct work_struct *work)
{
struct iscsi_cls_session *session =
Expand Down Expand Up @@ -340,13 +357,16 @@ void __iscsi_unblock_session(struct iscsi_cls_session *session)

void iscsi_unblock_session(struct iscsi_cls_session *session)
{
struct Scsi_Host *shost = iscsi_session_to_shost(session);
struct iscsi_host *ihost = shost->shost_data;
unsigned long flags;

spin_lock_irqsave(&session->lock, flags);
session->state = ISCSI_SESSION_LOGGED_IN;
spin_unlock_irqrestore(&session->lock, flags);

__iscsi_unblock_session(session);
queue_work(ihost->scan_workq, &session->scan_work);
}
EXPORT_SYMBOL_GPL(iscsi_unblock_session);

Expand Down Expand Up @@ -390,7 +410,7 @@ 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;

return queue_work(ihost->unbind_workq, &session->unbind_work);
return queue_work(ihost->scan_workq, &session->unbind_work);
}

struct iscsi_cls_session *
Expand All @@ -411,6 +431,7 @@ iscsi_alloc_session(struct Scsi_Host *shost,
INIT_LIST_HEAD(&session->host_list);
INIT_LIST_HEAD(&session->sess_list);
INIT_WORK(&session->unbind_work, __iscsi_unbind_session);
INIT_WORK(&session->scan_work, iscsi_scan_session);
spin_lock_init(&session->lock);

/* this is released in the dev's release function */
Expand Down Expand Up @@ -530,13 +551,15 @@ void iscsi_remove_session(struct iscsi_cls_session *session)
spin_unlock_irqrestore(&session->lock, flags);
__iscsi_unblock_session(session);
iscsi_unbind_session(session);

/* flush running scans */
flush_workqueue(ihost->scan_workq);
/*
* If the session dropped while removing devices then we need to make
* sure it is not blocked
*/
if (!cancel_delayed_work(&session->recovery_work))
flush_workqueue(iscsi_eh_timer_workq);
flush_workqueue(ihost->unbind_workq);

/* hw iscsi may not have removed all connections from session */
err = device_for_each_child(&session->dev, NULL,
Expand Down
7 changes: 4 additions & 3 deletions include/scsi/scsi_transport_iscsi.h
Original file line number Diff line number Diff line change
Expand Up @@ -177,11 +177,12 @@ struct iscsi_cls_session {
struct list_head host_list;
struct iscsi_transport *transport;
spinlock_t lock;
struct work_struct scan_work;
struct work_struct unbind_work;

/* recovery fields */
int recovery_tmo;
struct delayed_work recovery_work;
struct work_struct unbind_work;

int target_id;

Expand All @@ -203,8 +204,8 @@ struct iscsi_cls_session {
struct iscsi_host {
struct list_head sessions;
struct mutex mutex;
struct workqueue_struct *unbind_workq;
char unbind_workq_name[KOBJ_NAME_LEN];
struct workqueue_struct *scan_workq;
char scan_workq_name[KOBJ_NAME_LEN];
};

/*
Expand Down

0 comments on commit bd976f6

Please sign in to comment.