From 9d21169f8c5d54b969031b12211a285bbb5aa18c Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Fri, 19 May 2017 02:37:49 +0000 Subject: [PATCH 1/2] scst: implement BLOCKIO devices "active" attribute MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intended to be able to load on passive side as described in https://sourceforge.net/p/scst/mailman/message/35549446/ Suggested-by: Кирилл Тюшев git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7187 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- scst/README | 13 +++-- scst/README_in-tree | 13 +++-- scst/src/dev_handlers/scst_vdisk.c | 94 ++++++++++++++++++++++-------- 3 files changed, 89 insertions(+), 31 deletions(-) diff --git a/scst/README b/scst/README index fe90af02e..752fe3856 100644 --- a/scst/README +++ b/scst/README @@ -1696,10 +1696,15 @@ DRBD as well as other replication/failover SW does not allow to open its device on the secondary as well as does not allow to perform primary to secondary transition, if this device is open. -SCST BLOCKIO handler has all the necessary support for such behavior. If -you write new ALUA state in the "state" attribute, SCST BLOCKIO handler -before transition closes the open devices' handles and after transition -reopens them, if the new state is active or nonoptimized. +SCST BLOCKIO handler has necessary support for such behavior: + +1. If you need to prevent an SCST BLOCKIO device from opening its block +device, you need to create it with parameter "active=0" + +2. If you write new ALUA state in the "state" attribute, SCST BLOCKIO +handler before transition closes open handles on all affected SCST +devices and after transition reopens them, if the new state is active or +nonoptimized. Thus, the recommended implicit ALUA state change procedure for primary to secondary transition is: diff --git a/scst/README_in-tree b/scst/README_in-tree index 494c5a8b0..5b7ec94a0 100644 --- a/scst/README_in-tree +++ b/scst/README_in-tree @@ -1549,10 +1549,15 @@ DRBD as well as other replication/failover SW does not allow to open its device on the secondary as well as does not allow to perform primary to secondary transition, if this device is open. -SCST BLOCKIO handler has all the necessary support for such behavior. If -you write new ALUA state in the "state" attribute, SCST BLOCKIO handler -before transition closes the open devices' handles and after transition -reopens them, if the new state is active or nonoptimized. +SCST BLOCKIO handler has necessary support for such behavior: + +1. If you need to prevent an SCST BLOCKIO device from opening its block +device, you need to create it with parameter "active=0" + +2. If you write new ALUA state in the "state" attribute, SCST BLOCKIO +handler before transition closes open handles on all affected SCST +devices and after transition reopens them, if the new state is active or +nonoptimized. Thus, the recommended implicit ALUA state change procedure for primary to secondary transition is: diff --git a/scst/src/dev_handlers/scst_vdisk.c b/scst/src/dev_handlers/scst_vdisk.c index bf0a8fc5e..1c2340882 100644 --- a/scst/src/dev_handlers/scst_vdisk.c +++ b/scst/src/dev_handlers/scst_vdisk.c @@ -120,6 +120,7 @@ static struct scst_trace_log vdisk_local_trace_tbl[] = { #define DEF_ROTATIONAL 1 #define DEF_THIN_PROVISIONED 0 #define DEF_EXPL_ALUA 0 +#define DEF_DEV_ACTIVE 1 #define VDISK_NULLIO_SIZE (5LL*1024*1024*1024*1024/2) @@ -168,6 +169,7 @@ struct scst_vdisk_dev { * Below flags are protected by flags_lock or suspended activity * with scst_vdisk_mutex. */ + unsigned int dev_active:1; unsigned int rd_only:1; unsigned int wt_flag:1; unsigned int nv_cache:1; @@ -418,6 +420,8 @@ static ssize_t vdisk_sysfs_nv_cache_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf); static ssize_t vdisk_sysfs_o_direct_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf); +static ssize_t vdev_sysfs_active_show(struct kobject *kobj, + struct kobj_attribute *attr, char *buf); static ssize_t vdev_sysfs_dummy_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf); static ssize_t vdev_sysfs_rz_show(struct kobject *kobj, @@ -484,6 +488,8 @@ static ssize_t vdev_dif_filename_show(struct kobject *kobj, static ssize_t vcdrom_sysfs_filename_store(struct kobject *kobj, struct kobj_attribute *attr, const char *buf, size_t count); +static struct kobj_attribute vdev_active_attr = + __ATTR(active, S_IRUGO, vdev_sysfs_active_show, NULL); static struct kobj_attribute vdev_size_ro_attr = __ATTR(size, S_IRUGO, vdev_sysfs_size_show, NULL); static struct kobj_attribute vdev_size_rw_attr = @@ -604,6 +610,7 @@ static const struct attribute *vdisk_fileio_attrs[] = { }; static const struct attribute *vdisk_blockio_attrs[] = { + &vdev_active_attr.attr, &vdev_size_rw_attr.attr, &vdev_size_mb_rw_attr.attr, &vdisk_blocksize_attr.attr, @@ -939,6 +946,12 @@ static struct file *vdev_open_fd(const struct scst_vdisk_dev *virt_dev, sBUG_ON(!name); + if (!virt_dev->dev_active) { + TRACE_MGMT_DBG("Skip openning for not active dev %s", virt_dev->dev->virt_name); + fd = ERR_PTR(-EMEDIUMTYPE); + goto out; + } + if (read_only) open_flags |= O_RDONLY; else @@ -958,6 +971,7 @@ static struct file *vdev_open_fd(const struct scst_vdisk_dev *virt_dev, PRINT_ERROR("filp_open(%s) failed: %d", name, (int)PTR_ERR(fd)); } +out: TRACE_EXIT(); return fd; } @@ -969,7 +983,7 @@ static void vdisk_blockio_check_flush_support(struct scst_vdisk_dev *virt_dev) TRACE_ENTRY(); - if (!virt_dev->blockio || virt_dev->rd_only || virt_dev->nv_cache || virt_dev->wt_flag) + if (!virt_dev->blockio || virt_dev->rd_only || virt_dev->nv_cache || virt_dev->wt_flag || !virt_dev->dev_active) goto out; fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600); @@ -1014,7 +1028,7 @@ static void vdisk_check_tp_support(struct scst_vdisk_dev *virt_dev) virt_dev->dev_thin_provisioned = 0; - if (virt_dev->rd_only || (virt_dev->filename == NULL)) + if (virt_dev->rd_only || (virt_dev->filename == NULL) || !virt_dev->dev_active) goto check; fd = filp_open(virt_dev->filename, O_LARGEFILE, 0600); @@ -1126,7 +1140,7 @@ check: } /* Returns 0 on success and file size in *file_size, error code otherwise */ -static int vdisk_get_file_size(const char *filename, bool blockio, +static int vdisk_get_file_size(const struct scst_vdisk_dev *virt_dev, loff_t *file_size) { struct inode *inode; @@ -1135,25 +1149,31 @@ static int vdisk_get_file_size(const char *filename, bool blockio, TRACE_ENTRY(); - sBUG_ON(!filename); + sBUG_ON(!virt_dev->filename); + + if (!virt_dev->dev_active) { + TRACE_DBG("Not active dev %s, skip reexaming", virt_dev->dev->virt_name); + res = -EMEDIUMTYPE; + goto out; + } *file_size = 0; - fd = filp_open(filename, O_LARGEFILE | O_RDONLY, 0600); + fd = filp_open(virt_dev->filename, O_LARGEFILE | O_RDONLY, 0600); if (IS_ERR(fd)) { res = PTR_ERR(fd); - if ((res == -EMEDIUMTYPE) && blockio) + if ((res == -EMEDIUMTYPE) && virt_dev->blockio) TRACE(TRACE_MINOR, "Unable to open %s with EMEDIUMTYPE, " - "DRBD passive?", filename); + "DRBD passive?", virt_dev->filename); else - PRINT_ERROR("filp_open(%s) failed: %d", filename, res); + PRINT_ERROR("filp_open(%s) failed: %d", virt_dev->filename, res); goto out; } inode = file_inode(fd); - if (blockio && !S_ISBLK(inode->i_mode)) { - PRINT_ERROR("File %s is NOT a block device", filename); + if (virt_dev->blockio && !S_ISBLK(inode->i_mode)) { + PRINT_ERROR("File %s is NOT a block device", virt_dev->filename); res = -EINVAL; goto out_close; } @@ -1164,7 +1184,7 @@ static int vdisk_get_file_size(const char *filename, bool blockio, inode = inode->i_bdev->bd_inode; } else { PRINT_ERROR("File %s unsupported mode: mode=0%o\n", - filename, inode->i_mode); + virt_dev->filename, inode->i_mode); res = -EINVAL; goto out_close; } @@ -1571,8 +1591,7 @@ static int vdisk_reexamine(struct scst_vdisk_dev *virt_dev) if (!virt_dev->nullio && !virt_dev->cdrom_empty) { loff_t file_size; - res = vdisk_get_file_size(virt_dev->filename, virt_dev->blockio, - &file_size); + res = vdisk_get_file_size(virt_dev, &file_size); if (res < 0) { if ((res == -EMEDIUMTYPE) && virt_dev->blockio) { TRACE_DBG("Reexam pending (dev %s)", virt_dev->name); @@ -7427,9 +7446,11 @@ static void blockio_on_alua_state_change_start(struct scst_device *dev, * no parallel fd activities could be here. */ - TRACE_MGMT_DBG("ALUA state change from %s to %s started, closing FD (dev %s)", + TRACE_MGMT_DBG("ALUA state change from %s to %s started, closing FD (dev %s, active %d)", scst_alua_state_name(old_state), scst_alua_state_name(new_state), - dev->virt_name); + dev->virt_name, virt_dev->dev_active); + + virt_dev->dev_active = 0; /* Just in case always close */ vdisk_close_fd(virt_dev); @@ -7455,9 +7476,11 @@ static void blockio_on_alua_state_change_finish(struct scst_device *dev, /* Try non-optimized as well, it might be new redirection device */ int rc = 0; - TRACE_MGMT_DBG("ALUA state change from %s to %s finished (dev %s), " + TRACE_MGMT_DBG("ALUA state change from %s to %s finished (dev %s, active %d), " "reopening FD", scst_alua_state_name(old_state), - scst_alua_state_name(new_state), dev->virt_name); + scst_alua_state_name(new_state), dev->virt_name, virt_dev->dev_active); + + virt_dev->dev_active = 1; /* * only reopen fd if tgt_dev_cnt is not zero, otherwise we will @@ -7640,6 +7663,10 @@ static void vdisk_report_registering(const struct scst_vdisk_dev *virt_dev) i += snprintf(&buf[i], buf_size - i, "%sREMOVABLE", (j == i) ? "(" : ", "); + if (!virt_dev->dev_active) + i += snprintf(&buf[i], buf_size - i, "%sINACTIVE", + (j == i) ? "(" : ", "); + if (virt_dev->tst != DEF_TST) i += snprintf(&buf[i], buf_size - i, "%sTST %d", (j == i) ? "(" : ", ", virt_dev->tst); @@ -7687,13 +7714,12 @@ static int vdisk_resync_size(struct scst_vdisk_dev *virt_dev) sBUG_ON(virt_dev->nullio); sBUG_ON(!virt_dev->filename); - if (virt_dev->fd == NULL) { + if ((virt_dev->fd == NULL) || !virt_dev->dev_active) { res = -EMEDIUMTYPE; goto out; } - res = vdisk_get_file_size(virt_dev->filename, - virt_dev->blockio, &file_size); + res = vdisk_get_file_size(virt_dev, &file_size); if (res != 0) goto out; @@ -7829,6 +7855,7 @@ static int vdev_create_node(struct scst_dev_type *devt, virt_dev->blk_shift = DEF_DISK_BLOCK_SHIFT; virt_dev->numa_node_id = NUMA_NO_NODE; + virt_dev->dev_active = DEF_DEV_ACTIVE; if (strlen(name) >= sizeof(virt_dev->name)) { PRINT_ERROR("Name %s is too long (max allowed %zd)", name, @@ -8103,6 +8130,9 @@ static int vdev_parse_add_dev_params(struct scst_vdisk_dev *virt_dev, } else if (!strcasecmp("removable", p)) { virt_dev->removable = val; TRACE_DBG("REMOVABLE %d", virt_dev->removable); + } else if (!strcasecmp("active", p)) { + virt_dev->dev_active = val; + TRACE_DBG("ACTIVE %d", virt_dev->dev_active); } else if (!strcasecmp("rotational", p)) { virt_dev->rotational = val; TRACE_DBG("ROTATIONAL %d", virt_dev->rotational); @@ -8243,7 +8273,7 @@ static int vdev_blockio_add_device(const char *device_name, char *params) const char *const allowed_params[] = { "filename", "read_only", "write_through", "removable", "blocksize", "nv_cache", "rotational", "cluster_mode", - "thin_provisioned", "tst", + "thin_provisioned", "tst", "active", "numa_node_id", "dif_mode", "dif_type", "dif_static_app_tag", "dif_filename", NULL }; @@ -8649,8 +8679,7 @@ static int vcdrom_change(struct scst_vdisk_dev *virt_dev, virt_dev->filename = fn; - res = vdisk_get_file_size(virt_dev->filename, - virt_dev->blockio, &err); + res = vdisk_get_file_size(virt_dev, &err); if (res != 0) goto out_free_fn; if (virt_dev->fd == NULL) { @@ -10153,6 +10182,25 @@ static ssize_t vdev_sysfs_inq_vend_specific_show(struct kobject *kobj, return pos; } +static ssize_t vdev_sysfs_active_show(struct kobject *kobj, + struct kobj_attribute *attr, + char *buf) +{ + int pos; + struct scst_device *dev; + struct scst_vdisk_dev *virt_dev; + + dev = container_of(kobj, struct scst_device, dev_kobj); + virt_dev = dev->dh_priv; + + pos = snprintf(buf, PAGE_SIZE, "%d\n%s", + virt_dev->dev_active, + virt_dev->dev_active != DEF_DEV_ACTIVE ? + SCST_SYSFS_KEY_MARK "\n" : ""); + + return pos; +} + static ssize_t vdev_zero_copy_show(struct kobject *kobj, struct kobj_attribute *attr, char *buf) { From 8d3a9f440ad906b396f4ae72f270d5f987e1a480 Mon Sep 17 00:00:00 2001 From: Vladislav Bolkhovitin Date: Fri, 19 May 2017 02:58:23 +0000 Subject: [PATCH 2/2] qla2x00t: Disable Out-of-order processing by default MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From: Quinn Tran Out of order(OOO) processing requires initiator, switch and target to support OOO. In today¹s environment, none of the switches support OOO. OOO requires extra buffer space which affect performance. By turning ON this feature in QLogic's FW, it delays error recovery because droped frame is treated as out of order frame. We¹re turning OFF this option of speed up error recovery. Reviewed-by: Christoph Hellwig Signed-off-by: Quinn Tran Signed-off-by: Himanshu Madhani Merge of mainline commit 300af14bdb28157090f0c6f89d244fda940082da EXPERIMENTAL! git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7188 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla2x00t/qla_init.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/qla2x00t/qla_init.c b/qla2x00t/qla_init.c index 76c946f7b..69bdaa297 100644 --- a/qla2x00t/qla_init.c +++ b/qla2x00t/qla_init.c @@ -2440,8 +2440,10 @@ qla2x00_nvram_config(scsi_qla_host_t *vha) nv->add_firmware_options[1] |= BIT_5 | BIT_4; #ifdef CONFIG_SCSI_QLA2XXX_TARGET +#if 0 /* out-of-order frames rassembly */ nv->special_options[0] |= BIT_6; +#endif #endif /* CONFIG_SCSI_QLA2XXX_TARGET */ if (IS_QLA2300(ha)) { @@ -4543,8 +4545,10 @@ qla24xx_nvram_config(scsi_qla_host_t *vha) nv->firmware_options_3 = ha->saved_firmware_options_3; } } +#if 0 /* out-of-order frames reassembly */ nv->firmware_options_3 |= cpu_to_le32(BIT_6|BIT_9); +#endif #endif /* CONFIG_SCSI_QLA2XXX_TARGET */ @@ -5500,8 +5504,10 @@ qla81xx_nvram_config(scsi_qla_host_t *vha) nv->firmware_options_3 = ha->saved_firmware_options_3; } } +#if 0 /* out-of-order frames reassembly */ nv->firmware_options_3 |= cpu_to_le32(BIT_6|BIT_9); +#endif #endif /* CONFIG_SCSI_QLA2XXX_TARGET */