mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-19 22:42:38 +00:00
Black hole functionality added
Scst_mutex intentially used directly in the sysfs handler, because comming sysfs improvements will allow that. git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@5382 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
+24
-2
@@ -580,7 +580,7 @@ Every target should have at least the following entries:
|
||||
mapping to the corresponding hardware port. It isn't anyhow used by
|
||||
SCST.
|
||||
|
||||
- enabled - using this attribute you can enable or disable this target/
|
||||
- enabled - using this attribute you can enable or disable this target.
|
||||
It allows to finish configuring it before it starts accepting new
|
||||
connections. 0 by default.
|
||||
|
||||
@@ -592,6 +592,28 @@ Every target should have at least the following entries:
|
||||
can assign the addressing method on per-initiator basis. See also the
|
||||
"Logical unit addressing (LUN)" section in SAM-5 for more information.
|
||||
|
||||
- black_hole - if set, all LUNs in the corresponding initiator group,
|
||||
default target group in this case, start "swallowing" requests from
|
||||
initiators. Possible values are:
|
||||
|
||||
* 0 - disable black hole mode
|
||||
|
||||
* 1 - immediately abort all coming commands
|
||||
|
||||
* 2 - immediately abort all coming commands and drop all coming TM
|
||||
commands
|
||||
|
||||
* 3 - immediately abort all coming data transfer commands. This is
|
||||
the most evil mode, because it is not too well handled by many
|
||||
initiator OS'es, including Linux, so they may never recover from
|
||||
it.
|
||||
|
||||
* 4 - immediately abort all coming data transfer commands and drop all
|
||||
coming TM commands
|
||||
|
||||
CAUTION! With some target drivers modes 2 and 4 can cause internal
|
||||
resources leaks, so don't abuse those options!
|
||||
|
||||
- cpu_mask - defines CPU affinity mask for threads serving this target.
|
||||
For threads serving LUNs it is used only for devices with
|
||||
threads_pool_type "per_initiator".
|
||||
@@ -750,7 +772,7 @@ commands by looking inside this file.
|
||||
|
||||
Each security group's subdirectory contains 2 subdirectories: initiators
|
||||
and luns as well as the following attributes: addr_method, cpu_mask and
|
||||
io_grouping_type. See above description of them.
|
||||
io_grouping_type, black_hole. See above description of them.
|
||||
|
||||
Each "initiators" subdirectory contains list of added to this groups
|
||||
initiator as well as as well as file "mgmt". This file has the following
|
||||
|
||||
+24
-2
@@ -442,7 +442,7 @@ Every target should have at least the following entries:
|
||||
mapping to the corresponding hardware port. It isn't anyhow used by
|
||||
SCST.
|
||||
|
||||
- enabled - using this attribute you can enable or disable this target/
|
||||
- enabled - using this attribute you can enable or disable this target.
|
||||
It allows to finish configuring it before it starts accepting new
|
||||
connections. 0 by default.
|
||||
|
||||
@@ -454,6 +454,28 @@ Every target should have at least the following entries:
|
||||
can assign the addressing method on per-initiator basis. See also the
|
||||
"Logical unit addressing (LUN)" section in SAM-5 for more information.
|
||||
|
||||
- black_hole - if set, all LUNs in the corresponding initiator group,
|
||||
default target group in this case, start "swallowing" requests from
|
||||
initiators. Possible values are:
|
||||
|
||||
* 0 - disable black hole mode
|
||||
|
||||
* 1 - immediately abort all coming commands
|
||||
|
||||
* 2 - immediately abort all coming commands and drop all coming TM
|
||||
commands
|
||||
|
||||
* 3 - immediately abort all coming data transfer commands. This is
|
||||
the most evil mode, because it is not too well handled by many
|
||||
initiator OS'es, including Linux, so they may never recover from
|
||||
it.
|
||||
|
||||
* 4 - immediately abort all coming data transfer commands and drop all
|
||||
coming TM commands
|
||||
|
||||
CAUTION! With some target drivers modes 2 and 4 can cause internal
|
||||
resources leaks, so don't abuse those options!
|
||||
|
||||
- cpu_mask - defines CPU affinity mask for threads serving this target.
|
||||
For threads serving LUNs it is used only for devices with
|
||||
threads_pool_type "per_initiator".
|
||||
@@ -612,7 +634,7 @@ commands by looking inside this file.
|
||||
|
||||
Each security group's subdirectory contains 2 subdirectories: initiators
|
||||
and luns as well as the following attributes: addr_method, cpu_mask and
|
||||
io_grouping_type. See above description of them.
|
||||
io_grouping_type, black_hole. See above description of them.
|
||||
|
||||
Each "initiators" subdirectory contains list of added to this groups
|
||||
initiator as well as as well as file "mgmt". This file has the following
|
||||
|
||||
@@ -592,6 +592,9 @@ enum scst_exec_context {
|
||||
/* Set if tgt_dev has Unit Attention sense */
|
||||
#define SCST_TGT_DEV_UA_PENDING 0
|
||||
|
||||
/* Cache of acg->acg_black_hole_type */
|
||||
#define SCST_TGT_DEV_BLACK_HOLE 1
|
||||
|
||||
/*************************************************************
|
||||
** I/O grouping types. Changing them don't forget to change
|
||||
** the corresponding *_STR values in scst_const.h!
|
||||
@@ -2727,6 +2730,33 @@ struct scst_acg {
|
||||
|
||||
unsigned int tgt_acg:1;
|
||||
|
||||
/* Not a black hole */
|
||||
#define SCST_ACG_BLACK_HOLE_NONE 0
|
||||
|
||||
/* Immediately abort all coming commands */
|
||||
#define SCST_ACG_BLACK_HOLE_CMD 1
|
||||
|
||||
/*
|
||||
* Immediately abort all coming commands and drop all coming TM commands.
|
||||
*
|
||||
* CAUTION! With some target drivers it can cause internal resources
|
||||
* leaks, so don't abuse this option!
|
||||
*/
|
||||
#define SCST_ACG_BLACK_HOLE_ALL 2
|
||||
|
||||
/* Immediately abort all coming data transfer commands */
|
||||
#define SCST_ACG_BLACK_HOLE_DATA_CMD 3
|
||||
|
||||
/*
|
||||
* Immediately abort all coming data transfer commands and drop all
|
||||
* coming TM commands.
|
||||
*
|
||||
* CAUTION! With some target drivers it can cause internal resources
|
||||
* leaks, so don't abuse this option!
|
||||
*/
|
||||
#define SCST_ACG_BLACK_HOLE_DATA_MCMD 4
|
||||
volatile int acg_black_hole_type;
|
||||
|
||||
/* sysfs release completion */
|
||||
struct completion *acg_kobj_release_cmpl;
|
||||
|
||||
|
||||
@@ -4152,6 +4152,10 @@ static int scst_alloc_add_tgt_dev(struct scst_session *sess,
|
||||
tgt_dev->tgt_dev_rd_only = acg_dev->acg_dev_rd_only || dev->dev_rd_only;
|
||||
tgt_dev->sess = sess;
|
||||
atomic_set(&tgt_dev->tgt_dev_cmd_count, 0);
|
||||
if (sess->acg->acg_black_hole_type != SCST_ACG_BLACK_HOLE_NONE)
|
||||
set_bit(SCST_TGT_DEV_BLACK_HOLE, &tgt_dev->tgt_dev_flags);
|
||||
else
|
||||
clear_bit(SCST_TGT_DEV_BLACK_HOLE, &tgt_dev->tgt_dev_flags);
|
||||
|
||||
scst_sgv_pool_use_norm(tgt_dev);
|
||||
|
||||
|
||||
@@ -1756,6 +1756,125 @@ static struct kobj_attribute scst_tgt_io_grouping_type =
|
||||
scst_tgt_io_grouping_type_show,
|
||||
scst_tgt_io_grouping_type_store);
|
||||
|
||||
static ssize_t __scst_acg_black_hole_show(struct scst_acg *acg, char *buf)
|
||||
{
|
||||
int res, t = acg->acg_black_hole_type;
|
||||
|
||||
res = sprintf(buf, "%d\n%s\n", t,
|
||||
(t != SCST_ACG_BLACK_HOLE_NONE) ? SCST_SYSFS_KEY_MARK : "");
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t __scst_acg_black_hole_store(struct scst_acg *acg,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int res = 0;
|
||||
int prev, t;
|
||||
struct scst_session *sess;
|
||||
|
||||
prev = acg->acg_black_hole_type;
|
||||
|
||||
if ((buf == NULL) || (count == 0)) {
|
||||
res = 0;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mutex_lock(&scst_mutex);
|
||||
|
||||
BUILD_BUG_ON((SCST_ACG_BLACK_HOLE_NONE != 0) ||
|
||||
(SCST_ACG_BLACK_HOLE_CMD != 1) ||
|
||||
(SCST_ACG_BLACK_HOLE_ALL != 2) ||
|
||||
(SCST_ACG_BLACK_HOLE_DATA_CMD != 3) ||
|
||||
(SCST_ACG_BLACK_HOLE_DATA_MCMD != 4));
|
||||
switch (buf[0]) {
|
||||
case '0':
|
||||
acg->acg_black_hole_type = SCST_ACG_BLACK_HOLE_NONE;
|
||||
break;
|
||||
case '1':
|
||||
acg->acg_black_hole_type = SCST_ACG_BLACK_HOLE_CMD;
|
||||
break;
|
||||
case '2':
|
||||
acg->acg_black_hole_type = SCST_ACG_BLACK_HOLE_ALL;
|
||||
break;
|
||||
case '3':
|
||||
acg->acg_black_hole_type = SCST_ACG_BLACK_HOLE_DATA_CMD;
|
||||
break;
|
||||
case '4':
|
||||
acg->acg_black_hole_type = SCST_ACG_BLACK_HOLE_DATA_MCMD;
|
||||
break;
|
||||
default:
|
||||
PRINT_ERROR("%s: Requested action not understood: %s",
|
||||
__func__, buf);
|
||||
res = -EINVAL;
|
||||
goto out_unlock;
|
||||
}
|
||||
|
||||
t = acg->acg_black_hole_type;
|
||||
|
||||
if (prev == t)
|
||||
goto out_unlock;
|
||||
|
||||
list_for_each_entry(sess, &acg->acg_sess_list, acg_sess_list_entry) {
|
||||
int i;
|
||||
for (i = 0; i < SESS_TGT_DEV_LIST_HASH_SIZE; i++) {
|
||||
struct list_head *head = &sess->sess_tgt_dev_list[i];
|
||||
struct scst_tgt_dev *tgt_dev;
|
||||
list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) {
|
||||
if (t != SCST_ACG_BLACK_HOLE_NONE)
|
||||
set_bit(SCST_TGT_DEV_BLACK_HOLE, &tgt_dev->tgt_dev_flags);
|
||||
else
|
||||
clear_bit(SCST_TGT_DEV_BLACK_HOLE, &tgt_dev->tgt_dev_flags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PRINT_INFO("Black hole set to %d for ACG %s", t, acg->acg_name);
|
||||
|
||||
out_unlock:
|
||||
mutex_unlock(&scst_mutex);
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t scst_tgt_black_hole_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct scst_acg *acg;
|
||||
struct scst_tgt *tgt;
|
||||
|
||||
tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
acg = tgt->default_acg;
|
||||
|
||||
return __scst_acg_black_hole_show(acg, buf);
|
||||
}
|
||||
|
||||
static ssize_t scst_tgt_black_hole_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int res;
|
||||
struct scst_acg *acg;
|
||||
struct scst_tgt *tgt;
|
||||
|
||||
tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||
acg = tgt->default_acg;
|
||||
|
||||
res = __scst_acg_black_hole_store(acg, buf, count);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct kobj_attribute scst_tgt_black_hole =
|
||||
__ATTR(black_hole, S_IRUGO | S_IWUSR,
|
||||
scst_tgt_black_hole_show, scst_tgt_black_hole_store);
|
||||
|
||||
static ssize_t __scst_acg_cpu_mask_show(struct scst_acg *acg, char *buf)
|
||||
{
|
||||
int res;
|
||||
@@ -2473,6 +2592,7 @@ static struct attribute *scst_tgt_attrs[] = {
|
||||
&scst_tgt_comment.attr,
|
||||
&scst_tgt_addr_method.attr,
|
||||
&scst_tgt_io_grouping_type.attr,
|
||||
&scst_tgt_black_hole.attr,
|
||||
&scst_tgt_cpu_mask.attr,
|
||||
&scst_tgt_unknown_cmd_count_attr.attr,
|
||||
&scst_tgt_write_cmd_count_attr.attr,
|
||||
@@ -4285,6 +4405,39 @@ static struct kobj_attribute scst_acg_io_grouping_type =
|
||||
scst_acg_io_grouping_type_show,
|
||||
scst_acg_io_grouping_type_store);
|
||||
|
||||
static ssize_t scst_acg_black_hole_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct scst_acg *acg;
|
||||
|
||||
acg = container_of(kobj, struct scst_acg, acg_kobj);
|
||||
|
||||
return __scst_acg_black_hole_show(acg, buf);
|
||||
}
|
||||
|
||||
static ssize_t scst_acg_black_hole_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
int res;
|
||||
struct scst_acg *acg;
|
||||
|
||||
acg = container_of(kobj, struct scst_acg, acg_kobj);
|
||||
|
||||
res = __scst_acg_black_hole_store(acg, buf, count);
|
||||
if (res != 0)
|
||||
goto out;
|
||||
|
||||
res = count;
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct kobj_attribute scst_acg_black_hole =
|
||||
__ATTR(black_hole, S_IRUGO | S_IWUSR,
|
||||
scst_acg_black_hole_show, scst_acg_black_hole_store);
|
||||
|
||||
static ssize_t scst_acg_cpu_mask_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -4408,6 +4561,13 @@ int scst_acg_sysfs_create(struct scst_tgt *tgt,
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&acg->acg_kobj, &scst_acg_black_hole.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
scst_acg_black_hole.attr.name, tgt->tgt_name);
|
||||
goto out_del;
|
||||
}
|
||||
|
||||
res = sysfs_create_file(&acg->acg_kobj, &scst_acg_cpu_mask.attr);
|
||||
if (res != 0) {
|
||||
PRINT_ERROR("Can't add tgt attr %s for tgt %s",
|
||||
|
||||
+37
-1
@@ -972,6 +972,32 @@ out:
|
||||
}
|
||||
#endif
|
||||
|
||||
if (unlikely(test_bit(SCST_TGT_DEV_BLACK_HOLE, &cmd->tgt_dev->tgt_dev_flags))) {
|
||||
struct scst_session *sess = cmd->sess;
|
||||
bool abort = false;
|
||||
switch (sess->acg->acg_black_hole_type) {
|
||||
case SCST_ACG_BLACK_HOLE_CMD:
|
||||
case SCST_ACG_BLACK_HOLE_ALL:
|
||||
abort = true;
|
||||
break;
|
||||
case SCST_ACG_BLACK_HOLE_DATA_CMD:
|
||||
case SCST_ACG_BLACK_HOLE_DATA_MCMD:
|
||||
if (cmd->data_direction != SCST_DATA_NONE)
|
||||
abort = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (abort) {
|
||||
TRACE_MGMT_DBG("Black hole: aborting cmd %p (op %x, "
|
||||
"initiator %s)", cmd, cmd->cdb[0],
|
||||
sess->initiator_name);
|
||||
spin_lock_irq(&sess->sess_list_lock);
|
||||
scst_abort_cmd(cmd, NULL, false, false);
|
||||
spin_unlock_irq(&sess->sess_list_lock);
|
||||
}
|
||||
}
|
||||
|
||||
TRACE_EXIT_HRES(res);
|
||||
return res;
|
||||
|
||||
@@ -5466,10 +5492,20 @@ static int scst_clear_task_set(struct scst_mgmt_cmd *mcmd)
|
||||
* >0, if it should be requeued, <0 otherwise */
|
||||
static int scst_mgmt_cmd_init(struct scst_mgmt_cmd *mcmd)
|
||||
{
|
||||
int res = 0, rc;
|
||||
int res = 0, rc, t;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
t = mcmd->sess->acg->acg_black_hole_type;
|
||||
|
||||
if (unlikely((t == SCST_ACG_BLACK_HOLE_ALL) ||
|
||||
(t == SCST_ACG_BLACK_HOLE_DATA_MCMD))) {
|
||||
TRACE_MGMT_DBG("Dropping mcmd %p (fn %d, initiator %s)", mcmd,
|
||||
mcmd->fn, mcmd->sess->initiator_name);
|
||||
mcmd->state = SCST_MCMD_STATE_FINISHED;
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (mcmd->fn) {
|
||||
case SCST_ABORT_TASK:
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user