mirror of
https://github.com/SCST-project/scst.git
synced 2026-05-16 10:11:28 +00:00
scst: implement BLOCKIO devices "active" attribute
Intended to be able to load on passive side as described in https://sourceforge.net/p/scst/mailman/message/35549446/ Suggested-by: Кирилл Тюшев <kirill.tyushev8@gmail.com> git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@7187 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
13
scst/README
13
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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user