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:
Vladislav Bolkhovitin
2014-03-26 02:31:52 +00:00
parent 2986fbafd9
commit ff2b53ff9b
6 changed files with 279 additions and 5 deletions
+24 -2
View File
@@ -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
View File
@@ -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
+30
View File
@@ -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;
+4
View File
@@ -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);
+160
View File
@@ -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
View File
@@ -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:
{