Restore the on_alua_state_change_*() callback functions

Apparently the bind_alua_state functionality is being used. Hence restore
the on_alua_state_change_*() callback functions. The changes compared to
the previous implementation are:
* Only invoke the on_alua_state_change_*() callback functions if the state
  of a local target port group is being modified.
* Report information about ALUA callback activity with PRINT_INFO() instead
  of TRACE_MGMT_DBG().

This patch reverts commit 29548a4ad7 ("scst: Remove the
on_alua_state_change_*() callback functions").


git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@9120 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
Bart Van Assche
2020-08-10 00:31:42 +00:00
parent e0c63c52e7
commit d333ce8232
3 changed files with 134 additions and 7 deletions

View File

@@ -1401,6 +1401,34 @@ struct scst_dev_type {
void (*ext_copy_remap)(struct scst_cmd *cmd,
struct scst_ext_copy_seg_descr *descr);
/*
* Called to notify dev handler that a ALUA state change is about to
* be started. Can be used to close open file handlers, which might
* prevent the state switch.
*
* Called under scst_dg_mutex and no activities on the dev handler level
* (for implicit ALUA case supposed to be done by the user space via
* "block" sysfs attribute as described in the README).
*
* OPTIONAL
*/
void (*on_alua_state_change_start)(struct scst_device *dev,
enum scst_tg_state old_state, enum scst_tg_state new_state);
/*
* Called to notify dev handler that a ALUA state change is about to
* be finished. Can be used to (re)open file handlers closed in
* on_alua_state_change_start().
*
* Called under scst_dg_mutex and no activities on the dev handler level
* (for implicit ALUA case supposed to be done by the user space via
* "block" sysfs attribute as described in the README).
*
* OPTIONAL
*/
void (*on_alua_state_change_finish)(struct scst_device *dev,
enum scst_tg_state old_state, enum scst_tg_state new_state);
/*
* Called to notify dev handler that a task management command received
*

View File

@@ -6441,6 +6441,86 @@ static enum compl_status_e nullio_exec_verify(struct vdisk_cmd_params *p)
return CMD_SUCCEEDED;
}
static void blockio_on_alua_state_change_start(struct scst_device *dev,
enum scst_tg_state old_state, enum scst_tg_state new_state)
{
struct scst_vdisk_dev *virt_dev = dev->dh_priv;
const bool close = virt_dev->dev_active &&
new_state != SCST_TG_STATE_OPTIMIZED &&
new_state != SCST_TG_STATE_NONOPTIMIZED;
TRACE_ENTRY();
/* No other fd activity may happen concurrently with this function. */
lockdep_assert_alua_lock_held();
if (!virt_dev->bind_alua_state)
return;
PRINT_INFO("dev %s: ALUA state change from %s to %s started,%s closing FD",
dev->virt_name, scst_alua_state_name(old_state),
scst_alua_state_name(new_state), close ? "" : " not");
if (!close)
return;
virt_dev->dev_active = 0;
vdisk_close_fd(virt_dev);
TRACE_EXIT();
return;
}
static void blockio_on_alua_state_change_finish(struct scst_device *dev,
enum scst_tg_state old_state, enum scst_tg_state new_state)
{
struct scst_vdisk_dev *virt_dev = dev->dh_priv;
const bool open = !virt_dev->dev_active &&
(new_state == SCST_TG_STATE_OPTIMIZED ||
new_state == SCST_TG_STATE_NONOPTIMIZED);
int rc = 0;
TRACE_ENTRY();
/* No other fd activity may happen concurrently with this function. */
lockdep_assert_alua_lock_held();
if (!virt_dev->bind_alua_state)
return;
PRINT_INFO("dev %s: ALUA state change from %s to %s finished,%s reopening FD",
dev->virt_name, scst_alua_state_name(old_state),
scst_alua_state_name(new_state), open ? "" : " not");
if (!open)
return;
virt_dev->dev_active = 1;
/*
* only reopen fd if tgt_dev_cnt is not zero, otherwise we will
* leak reference.
*/
if (virt_dev->tgt_dev_cnt)
rc = vdisk_open_fd(virt_dev, dev->dev_rd_only);
if (rc == 0) {
if (virt_dev->reexam_pending) {
rc = vdisk_reexamine(virt_dev);
WARN_ON(rc != 0);
virt_dev->reexam_pending = 0;
}
} else {
PRINT_ERROR("dev %s: opening after ALUA state change to %s failed",
dev->virt_name,
scst_alua_state_name(new_state));
}
TRACE_EXIT();
return;
}
static void vdisk_task_mgmt_fn_done(struct scst_mgmt_cmd *mcmd,
struct scst_tgt_dev *tgt_dev)
{
@@ -9316,7 +9396,10 @@ static int vdev_sysfs_process_active_store(
res = mutex_lock_interruptible(&scst_mutex);
if (res)
goto resume;
/* To do: verify whether this call is still necessary. */
/*
* This is used to serialize against the *_on_alua_state_change_*()
* calls in scst_tg.c
*/
scst_alua_lock();
/*
@@ -9798,6 +9881,8 @@ static struct scst_dev_type vdisk_blk_devtype = {
.detach_tgt = vdisk_detach_tgt,
.parse = non_fileio_parse,
.exec = blockio_exec,
.on_alua_state_change_start = blockio_on_alua_state_change_start,
.on_alua_state_change_finish = blockio_on_alua_state_change_finish,
.task_mgmt_fn_done = vdisk_task_mgmt_fn_done,
.get_supported_opcodes = vdisk_get_supported_opcodes,
.devt_priv = (void *)blockio_ops,

View File

@@ -964,18 +964,26 @@ out_fail:
}
/*
* __scst_tgt_set_state - Update the ALUA filter of a LUN
* __scst_tgt_set_state - Update the ALUA filter of a LUN and invoke callbacks
* @tg: ALUA target group of which the state is changing.
* @tgt_dev: LUN to be updated.
* @state: new ALUA state.
* @invoke_callbacks: Whether or not to invoke the on_alua_state_changed_*
* callback functions.
*/
static void __scst_tgt_set_state(struct scst_target_group *tg,
struct scst_tgt_dev *tgt_dev, enum scst_tg_state state)
struct scst_tgt_dev *tgt_dev, enum scst_tg_state state,
bool invoke_callbacks)
{
bool gen_ua = state != SCST_TG_STATE_TRANSITIONING;
struct scst_tgt *tgt = tgt_dev->sess->tgt;
enum scst_tg_state old_state = tg->state;
struct scst_device *dev = tgt_dev->dev;
struct scst_dev_group *dg = tg->dg;
if (invoke_callbacks && dev->handler->on_alua_state_change_start)
dev->handler->on_alua_state_change_start(dev, old_state,
state);
/*
* If the ALUA state transition is caused by an STPG command and if
* the STPG command has been received through the target port of which
@@ -985,6 +993,9 @@ static void __scst_tgt_set_state(struct scst_target_group *tg,
tid_equal(dg->stpg_transport_id, tgt_dev->sess->transport_id))
gen_ua = false;
scst_tg_change_tgt_dev_state(tgt_dev, state, gen_ua);
if (invoke_callbacks && dev->handler->on_alua_state_change_finish)
dev->handler->on_alua_state_change_finish(dev, old_state,
state);
}
/*
@@ -1000,6 +1011,7 @@ static void __scst_tg_set_state(struct scst_target_group *tg,
struct scst_tgt_dev *tgt_dev;
struct scst_tg_tgt *tg_tgt;
struct scst_tgt *tgt;
bool invoke_callbacks;
sBUG_ON(state >= ARRAY_SIZE(scst_alua_filter));
lockdep_assert_held(&scst_dg_mutex);
@@ -1007,23 +1019,25 @@ static void __scst_tg_set_state(struct scst_target_group *tg,
if (tg->state == state)
return;
tg->state = state;
list_for_each_entry(dg_dev, &tg->dg->dev_list, entry) {
invoke_callbacks = true;
dev = dg_dev->dev;
list_for_each_entry(tgt_dev, &dev->dev_tgt_dev_list,
dev_tgt_dev_list_entry) {
tgt = tgt_dev->sess->tgt;
list_for_each_entry(tg_tgt, &tg->tgt_list, entry) {
if (tg_tgt->tgt == tgt) {
__scst_tgt_set_state(tg, tgt_dev,
state);
__scst_tgt_set_state(tg, tgt_dev, state,
invoke_callbacks);
invoke_callbacks = false;
break;
}
}
}
}
tg->state = state;
scst_check_alua_invariant();
PRINT_INFO("Changed ALUA state of %s/%s into %s", tg->dg->name,