|
@@ -113,7 +113,7 @@ struct alua_queue_data {
|
|
#define ALUA_POLICY_SWITCH_ALL 1
|
|
#define ALUA_POLICY_SWITCH_ALL 1
|
|
|
|
|
|
static void alua_rtpg_work(struct work_struct *work);
|
|
static void alua_rtpg_work(struct work_struct *work);
|
|
-static void alua_rtpg_queue(struct alua_port_group *pg,
|
|
|
|
|
|
+static bool alua_rtpg_queue(struct alua_port_group *pg,
|
|
struct scsi_device *sdev,
|
|
struct scsi_device *sdev,
|
|
struct alua_queue_data *qdata, bool force);
|
|
struct alua_queue_data *qdata, bool force);
|
|
static void alua_check(struct scsi_device *sdev, bool force);
|
|
static void alua_check(struct scsi_device *sdev, bool force);
|
|
@@ -862,7 +862,13 @@ static void alua_rtpg_work(struct work_struct *work)
|
|
kref_put(&pg->kref, release_port_group);
|
|
kref_put(&pg->kref, release_port_group);
|
|
}
|
|
}
|
|
|
|
|
|
-static void alua_rtpg_queue(struct alua_port_group *pg,
|
|
|
|
|
|
+/**
|
|
|
|
+ * alua_rtpg_queue() - cause RTPG to be submitted asynchronously
|
|
|
|
+ *
|
|
|
|
+ * Returns true if and only if alua_rtpg_work() will be called asynchronously.
|
|
|
|
+ * That function is responsible for calling @qdata->fn().
|
|
|
|
+ */
|
|
|
|
+static bool alua_rtpg_queue(struct alua_port_group *pg,
|
|
struct scsi_device *sdev,
|
|
struct scsi_device *sdev,
|
|
struct alua_queue_data *qdata, bool force)
|
|
struct alua_queue_data *qdata, bool force)
|
|
{
|
|
{
|
|
@@ -870,8 +876,8 @@ static void alua_rtpg_queue(struct alua_port_group *pg,
|
|
unsigned long flags;
|
|
unsigned long flags;
|
|
struct workqueue_struct *alua_wq = kaluad_wq;
|
|
struct workqueue_struct *alua_wq = kaluad_wq;
|
|
|
|
|
|
- if (!pg)
|
|
|
|
- return;
|
|
|
|
|
|
+ if (WARN_ON_ONCE(!pg) || scsi_device_get(sdev))
|
|
|
|
+ return false;
|
|
|
|
|
|
spin_lock_irqsave(&pg->lock, flags);
|
|
spin_lock_irqsave(&pg->lock, flags);
|
|
if (qdata) {
|
|
if (qdata) {
|
|
@@ -884,14 +890,12 @@ static void alua_rtpg_queue(struct alua_port_group *pg,
|
|
pg->flags |= ALUA_PG_RUN_RTPG;
|
|
pg->flags |= ALUA_PG_RUN_RTPG;
|
|
kref_get(&pg->kref);
|
|
kref_get(&pg->kref);
|
|
pg->rtpg_sdev = sdev;
|
|
pg->rtpg_sdev = sdev;
|
|
- scsi_device_get(sdev);
|
|
|
|
start_queue = 1;
|
|
start_queue = 1;
|
|
} else if (!(pg->flags & ALUA_PG_RUN_RTPG) && force) {
|
|
} else if (!(pg->flags & ALUA_PG_RUN_RTPG) && force) {
|
|
pg->flags |= ALUA_PG_RUN_RTPG;
|
|
pg->flags |= ALUA_PG_RUN_RTPG;
|
|
/* Do not queue if the worker is already running */
|
|
/* Do not queue if the worker is already running */
|
|
if (!(pg->flags & ALUA_PG_RUNNING)) {
|
|
if (!(pg->flags & ALUA_PG_RUNNING)) {
|
|
kref_get(&pg->kref);
|
|
kref_get(&pg->kref);
|
|
- sdev = NULL;
|
|
|
|
start_queue = 1;
|
|
start_queue = 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
@@ -900,13 +904,17 @@ static void alua_rtpg_queue(struct alua_port_group *pg,
|
|
alua_wq = kaluad_sync_wq;
|
|
alua_wq = kaluad_sync_wq;
|
|
spin_unlock_irqrestore(&pg->lock, flags);
|
|
spin_unlock_irqrestore(&pg->lock, flags);
|
|
|
|
|
|
- if (start_queue &&
|
|
|
|
- !queue_delayed_work(alua_wq, &pg->rtpg_work,
|
|
|
|
- msecs_to_jiffies(ALUA_RTPG_DELAY_MSECS))) {
|
|
|
|
- if (sdev)
|
|
|
|
- scsi_device_put(sdev);
|
|
|
|
- kref_put(&pg->kref, release_port_group);
|
|
|
|
|
|
+ if (start_queue) {
|
|
|
|
+ if (queue_delayed_work(alua_wq, &pg->rtpg_work,
|
|
|
|
+ msecs_to_jiffies(ALUA_RTPG_DELAY_MSECS)))
|
|
|
|
+ sdev = NULL;
|
|
|
|
+ else
|
|
|
|
+ kref_put(&pg->kref, release_port_group);
|
|
}
|
|
}
|
|
|
|
+ if (sdev)
|
|
|
|
+ scsi_device_put(sdev);
|
|
|
|
+
|
|
|
|
+ return true;
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -1007,11 +1015,13 @@ static int alua_activate(struct scsi_device *sdev,
|
|
mutex_unlock(&h->init_mutex);
|
|
mutex_unlock(&h->init_mutex);
|
|
goto out;
|
|
goto out;
|
|
}
|
|
}
|
|
- fn = NULL;
|
|
|
|
rcu_read_unlock();
|
|
rcu_read_unlock();
|
|
mutex_unlock(&h->init_mutex);
|
|
mutex_unlock(&h->init_mutex);
|
|
|
|
|
|
- alua_rtpg_queue(pg, sdev, qdata, true);
|
|
|
|
|
|
+ if (alua_rtpg_queue(pg, sdev, qdata, true))
|
|
|
|
+ fn = NULL;
|
|
|
|
+ else
|
|
|
|
+ err = SCSI_DH_DEV_OFFLINED;
|
|
kref_put(&pg->kref, release_port_group);
|
|
kref_put(&pg->kref, release_port_group);
|
|
out:
|
|
out:
|
|
if (fn)
|
|
if (fn)
|