mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-27 18:42:54 +00:00
Merge t10-pi branch back
git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@6192 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -50,6 +50,7 @@ SRP_DIR=srpt
|
|||||||
SCST_LOCAL_DIR=scst_local
|
SCST_LOCAL_DIR=scst_local
|
||||||
MVSAS_DIR=mvsas_tgt
|
MVSAS_DIR=mvsas_tgt
|
||||||
FCST_DIR=fcst
|
FCST_DIR=fcst
|
||||||
|
EMULEX_DIR=emulex
|
||||||
|
|
||||||
ISCSI_DIR=iscsi-scst
|
ISCSI_DIR=iscsi-scst
|
||||||
|
|
||||||
@@ -94,6 +95,12 @@ help:
|
|||||||
@echo " iscsi_install : ISCSI target: install"
|
@echo " iscsi_install : ISCSI target: install"
|
||||||
@echo " iscsi_uninstall : ISCSI target: uninstall"
|
@echo " iscsi_uninstall : ISCSI target: uninstall"
|
||||||
@echo ""
|
@echo ""
|
||||||
|
@echo " emulex : make Emulex target"
|
||||||
|
@echo " emulex_clean : Emulex target: clean "
|
||||||
|
@echo " emulex_extraclean : Emulex target: clean + clean dependencies"
|
||||||
|
@echo " emulex_install : Emulex target: install"
|
||||||
|
@echo " emulex_uninstall : Emulex target: uninstall"
|
||||||
|
@echo ""
|
||||||
@echo " lsi : make LSI MPT target"
|
@echo " lsi : make LSI MPT target"
|
||||||
@echo " lsi_clean : lsi target: clean "
|
@echo " lsi_clean : lsi target: clean "
|
||||||
@echo " lsi_extraclean : lsi target: clean + clean dependencies"
|
@echo " lsi_extraclean : lsi target: clean + clean dependencies"
|
||||||
@@ -148,6 +155,7 @@ all:
|
|||||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
||||||
|
@if [ -d $(EMULEX_DIR) ]; then cd $(EMULEX_DIR) && $(MAKE) $@; fi
|
||||||
|
|
||||||
install:
|
install:
|
||||||
cd $(SCST_DIR) && $(MAKE) $@
|
cd $(SCST_DIR) && $(MAKE) $@
|
||||||
@@ -159,6 +167,7 @@ install:
|
|||||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
||||||
|
@if [ -d $(EMULEX_DIR) ]; then cd $(EMULEX_DIR) && $(MAKE) $@; fi
|
||||||
|
|
||||||
uninstall:
|
uninstall:
|
||||||
cd $(SCST_DIR) && $(MAKE) $@
|
cd $(SCST_DIR) && $(MAKE) $@
|
||||||
@@ -170,6 +179,7 @@ uninstall:
|
|||||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
||||||
|
@if [ -d $(EMULEX_DIR) ]; then cd $(EMULEX_DIR) && $(MAKE) $@; fi
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
cd $(SCST_DIR) && $(MAKE) $@
|
cd $(SCST_DIR) && $(MAKE) $@
|
||||||
@@ -183,6 +193,7 @@ clean:
|
|||||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
||||||
|
@if [ -d $(EMULEX_DIR) ]; then cd $(EMULEX_DIR) && $(MAKE) $@; fi
|
||||||
|
|
||||||
extraclean:
|
extraclean:
|
||||||
-rm -f TAGS
|
-rm -f TAGS
|
||||||
@@ -197,6 +208,7 @@ extraclean:
|
|||||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
@if [ -d $(USR_DIR) ]; then cd $(USR_DIR) && $(MAKE) $@; fi
|
||||||
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
@if [ -d $(SCST_LOCAL_DIR) ]; then cd $(SCST_LOCAL_DIR) && $(MAKE) $@; fi
|
||||||
|
@if [ -d $(EMULEX_DIR) ]; then cd $(EMULEX_DIR) && $(MAKE) $@; fi
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
find . -type f -name "*.[ch]" | ctags --c-kinds=+p --fields=+iaS --extra=+q -e -L-
|
find . -type f -name "*.[ch]" | ctags --c-kinds=+p --fields=+iaS --extra=+q -e -L-
|
||||||
@@ -290,6 +302,21 @@ iscsi_clean:
|
|||||||
iscsi_extraclean:
|
iscsi_extraclean:
|
||||||
cd $(ISCSI_DIR) && $(MAKE) extraclean
|
cd $(ISCSI_DIR) && $(MAKE) extraclean
|
||||||
|
|
||||||
|
emulex:
|
||||||
|
cd $(EMULEX_DIR) && $(MAKE) all
|
||||||
|
|
||||||
|
emulex_install:
|
||||||
|
cd $(EMULEX_DIR) && $(MAKE) install
|
||||||
|
|
||||||
|
emulex_uninstall:
|
||||||
|
cd $(EMULEX_DIR) && $(MAKE) uninstall
|
||||||
|
|
||||||
|
emulex_clean:
|
||||||
|
cd $(EMULEX_DIR) && $(MAKE) clean
|
||||||
|
|
||||||
|
emulex_extraclean:
|
||||||
|
cd $(EMULEX_DIR) && $(MAKE) extraclean
|
||||||
|
|
||||||
lsi:
|
lsi:
|
||||||
cd $(LSI_DIR) && $(MAKE) all
|
cd $(LSI_DIR) && $(MAKE) all
|
||||||
|
|
||||||
@@ -506,6 +533,7 @@ disable_proc: extraclean
|
|||||||
qla_old qla_old_install qla_old_uninstall qla_old_clean qla_old_extraclean \
|
qla_old qla_old_install qla_old_uninstall qla_old_clean qla_old_extraclean \
|
||||||
lsi lsi_install lsi_uninstall lsi_clean lsi_extraclean \
|
lsi lsi_install lsi_uninstall lsi_clean lsi_extraclean \
|
||||||
iscsi iscsi_install iscsi_uninstall iscsi_clean iscsi_extraclean \
|
iscsi iscsi_install iscsi_uninstall iscsi_clean iscsi_extraclean \
|
||||||
|
emulex emulex_install emulex_uninstall emulex_clean emulex_extraclean \
|
||||||
scst scst_install scst_uninstall scst_clean scst_extraclean \
|
scst scst_install scst_uninstall scst_clean scst_extraclean \
|
||||||
docs docs_clean docs_extraclean \
|
docs docs_clean docs_extraclean \
|
||||||
scstadm scstadm_install scstadm_uninstall scstadm_clean scstadm_extraclean \
|
scstadm scstadm_install scstadm_uninstall scstadm_clean scstadm_extraclean \
|
||||||
|
|||||||
+2
-1
@@ -57,7 +57,8 @@ void ft_cmd_dump(struct scst_cmd *cmd, const char *caller)
|
|||||||
prefix, cmd, fcmd->write_data_len, fcmd->read_data_len);
|
prefix, cmd, fcmd->write_data_len, fcmd->read_data_len);
|
||||||
pr_info("%s exp_dir %x exp_xfer_len %d exp_in_len %d\n",
|
pr_info("%s exp_dir %x exp_xfer_len %d exp_in_len %d\n",
|
||||||
prefix, cmd->expected_data_direction,
|
prefix, cmd->expected_data_direction,
|
||||||
cmd->expected_transfer_len, cmd->expected_out_transfer_len);
|
cmd->expected_transfer_len_full,
|
||||||
|
cmd->expected_out_transfer_len);
|
||||||
pr_info("%s dir %x data_len %lld bufflen %d out_bufflen %d\n",
|
pr_info("%s dir %x data_len %lld bufflen %d out_bufflen %d\n",
|
||||||
prefix, cmd->data_direction, cmd->data_len,
|
prefix, cmd->data_direction, cmd->data_len,
|
||||||
cmd->bufflen, cmd->out_bufflen);
|
cmd->bufflen, cmd->out_bufflen);
|
||||||
|
|||||||
@@ -1270,18 +1270,18 @@ void iscsi_dump_pdu(struct iscsi_pdu *pdu)
|
|||||||
int i;
|
int i;
|
||||||
|
|
||||||
buf = (void *)&pdu->bhs;
|
buf = (void *)&pdu->bhs;
|
||||||
printk(KERN_DEBUG "BHS: (%p,%zd)\n", buf, sizeof(pdu->bhs));
|
pr_debug("BHS: (%p,%zd)\n", buf, sizeof(pdu->bhs));
|
||||||
for (i = 0; i < (int)sizeof(pdu->bhs); i++)
|
for (i = 0; i < (int)sizeof(pdu->bhs); i++)
|
||||||
iscsi_dump_char(*buf++, text, &pos);
|
iscsi_dump_char(*buf++, text, &pos);
|
||||||
iscsi_dump_char(-1, text, &pos);
|
iscsi_dump_char(-1, text, &pos);
|
||||||
|
|
||||||
buf = (void *)pdu->ahs;
|
buf = (void *)pdu->ahs;
|
||||||
printk(KERN_DEBUG "AHS: (%p,%d)\n", buf, pdu->ahssize);
|
pr_debug("AHS: (%p,%d)\n", buf, pdu->ahssize);
|
||||||
for (i = 0; i < pdu->ahssize; i++)
|
for (i = 0; i < pdu->ahssize; i++)
|
||||||
iscsi_dump_char(*buf++, text, &pos);
|
iscsi_dump_char(*buf++, text, &pos);
|
||||||
iscsi_dump_char(-1, text, &pos);
|
iscsi_dump_char(-1, text, &pos);
|
||||||
|
|
||||||
printk(KERN_DEBUG "Data: (%d)\n", pdu->datasize);
|
pr_debug("Data: (%d)\n", pdu->datasize);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+72
-4
@@ -331,6 +331,11 @@ in/out in Makefile and scst.h:
|
|||||||
can clear already measured results by writing 0 in each file. Note,
|
can clear already measured results by writing 0 in each file. Note,
|
||||||
you need a non-preemptible kernel to have correct results.
|
you need a non-preemptible kernel to have correct results.
|
||||||
|
|
||||||
|
- CONFIG_SCST_DIF_INJECT_CORRUPTED_TAGS - if defined, allows injection
|
||||||
|
of corrupted DIF tags according to the Oracle specification. This
|
||||||
|
functionality is working only if dif_mode doesn't contain dev_store
|
||||||
|
and dif_type is 1.
|
||||||
|
|
||||||
HIGHMEM kernel configurations are fully supported, but not recommended
|
HIGHMEM kernel configurations are fully supported, but not recommended
|
||||||
for performance reasons, except for scst_user, where they are not
|
for performance reasons, except for scst_user, where they are not
|
||||||
supported, because this module deals with user supplied memory on a
|
supported, because this module deals with user supplied memory on a
|
||||||
@@ -613,6 +618,17 @@ Every target should have at least the following entries:
|
|||||||
particular target driver or not, you can find out by checking traces
|
particular target driver or not, you can find out by checking traces
|
||||||
or the target driver's source code.
|
or the target driver's source code.
|
||||||
|
|
||||||
|
- dif_capabilities - if this target supports T10-PI, returns which
|
||||||
|
exact DIF capabilities this target supports.
|
||||||
|
|
||||||
|
- dif_checks_failed - if this target supports T10-PI, returns
|
||||||
|
statistics how many DIF errors have been detected on the
|
||||||
|
corresponding processing stages on this target. It returns 3 rows of
|
||||||
|
numbers with 3 numbers in each row: for target driver stage, for SCST
|
||||||
|
stage and for dev handler stage. Numbers in each row: how many errors
|
||||||
|
detected checking application, reference and guard tags
|
||||||
|
correspondingly. Writing to this attribute resets the numbers.
|
||||||
|
|
||||||
- cpu_mask - defines CPU affinity mask for threads serving this target.
|
- cpu_mask - defines CPU affinity mask for threads serving this target.
|
||||||
For threads serving LUNs it is used only for devices with
|
For threads serving LUNs it is used only for devices with
|
||||||
threads_pool_type "per_initiator".
|
threads_pool_type "per_initiator".
|
||||||
@@ -671,6 +687,17 @@ following entries:
|
|||||||
|
|
||||||
- commands - contains overall number of SCSI commands in this session.
|
- commands - contains overall number of SCSI commands in this session.
|
||||||
|
|
||||||
|
- dif_checks_failed - if target of this session supports T10-PI, returns
|
||||||
|
statistics how many DIF errors have been detected on the
|
||||||
|
corresponding processing stages on all DIF-enabled LUNs in this
|
||||||
|
session. It returns 3 rows of numbers with 3 numbers in each row: for
|
||||||
|
target driver stage, for SCST stage and for dev handler stage.
|
||||||
|
Numbers in each row: how many errors detected checking application,
|
||||||
|
reference and guard tags correspondingly. Writing to this attribute
|
||||||
|
resets the numbers. Similar statistics returned in attribute with the
|
||||||
|
same name for each LUN in this session in this LUN's subdirectory, if
|
||||||
|
its device configured with dif_type > 0.
|
||||||
|
|
||||||
- read_cmd_count - number of READ SCSI commands received since beginning
|
- read_cmd_count - number of READ SCSI commands received since beginning
|
||||||
or last reset (writing 0 in this attribute)
|
or last reset (writing 0 in this attribute)
|
||||||
|
|
||||||
@@ -993,6 +1020,47 @@ cache. The following parameters possible for vdisk_fileio:
|
|||||||
- zero_copy - if set, then this device uses zero copy access to the
|
- zero_copy - if set, then this device uses zero copy access to the
|
||||||
page cache. At the moment, only read side zero copy is implemented.
|
page cache. At the moment, only read side zero copy is implemented.
|
||||||
|
|
||||||
|
- dif_mode - specifies which T10-PI, or DIF, mode this device will use.
|
||||||
|
See SCSI standards from more info about T10-PI. Available DIF modes
|
||||||
|
(can be combined using '|'):
|
||||||
|
|
||||||
|
* tgt - DIF tags are checked on the target hardware, if supported
|
||||||
|
|
||||||
|
* scst - DIF tags are checked inside SCST core
|
||||||
|
|
||||||
|
* dev_check - DIF tags are checked inside backend device
|
||||||
|
|
||||||
|
* dev_store - DIF tags are stored inside backend device on the WRITE
|
||||||
|
path and read from it on the READ path
|
||||||
|
|
||||||
|
For instance, if only tgt DIF mode specified, then target driver,
|
||||||
|
serving this device, will inside hardware check, then STRIP DIF tags
|
||||||
|
from SCSI commands on the WRITE path and generate, then INSERT DIF
|
||||||
|
tags into SCSI commands on the READ path, so neither SCST core, nor
|
||||||
|
dev handler will see them.
|
||||||
|
|
||||||
|
Similarly, if only scst DIF mode specified, then target driver will
|
||||||
|
PASS DIF tags into SCST core, which then check/STRIP/generate/INSERT
|
||||||
|
them, so dev handler will not see them.
|
||||||
|
|
||||||
|
If only dev_check DIF mode specified, then both target driver and
|
||||||
|
SCST core will PASS DIF tags into the dev handler, which is then
|
||||||
|
responsible to check them in the backend hardware. If only dev_store
|
||||||
|
specified, then DIF tags will only be stored by the dev handler in
|
||||||
|
the backend hardware without checking at any level.
|
||||||
|
|
||||||
|
If all "tgt|scst|dev_check|dev_store" DIF mode specified, then all
|
||||||
|
target driver, SCST core and dev handler will check DIF tags, then
|
||||||
|
dev handler will store them in the backend hardware.
|
||||||
|
|
||||||
|
- dif_type - specifies which DIF SCSI type this device will use.
|
||||||
|
|
||||||
|
- dif_static_app_tag - specifies fixed (static) DIF application tag for
|
||||||
|
this device.
|
||||||
|
|
||||||
|
- dif_filename - specifies full path to filename, where DIF tags will
|
||||||
|
be stored.
|
||||||
|
|
||||||
Handler vdisk_blockio provides BLOCKIO mode to create virtual devices.
|
Handler vdisk_blockio provides BLOCKIO mode to create virtual devices.
|
||||||
This mode performs direct block I/O with a block device, bypassing the
|
This mode performs direct block I/O with a block device, bypassing the
|
||||||
page cache for all operations. This mode works ideally with high-end
|
page cache for all operations. This mode works ideally with high-end
|
||||||
@@ -1000,10 +1068,10 @@ storage HBAs and for applications that either do not need caching
|
|||||||
between application and disk or need the large block throughput. See
|
between application and disk or need the large block throughput. See
|
||||||
below for more info.
|
below for more info.
|
||||||
|
|
||||||
The following common with vdisk_fileio parameters are possible for
|
The following parameters possible for vdisk_blockio: filename,
|
||||||
vdisk_blockio: filename, blocksize, nv_cache, write_through, read_only,
|
blocksize, nv_cache, read_only, removable, rotational, thin_provisioned,
|
||||||
removable, rotational, thin_provisioned, tst. See vdisk_fileio above for
|
tst, dif_mode, dif_type, dif_static_app_tag, dif_filename. See
|
||||||
description of those parameters.
|
vdisk_fileio above for description of those parameters.
|
||||||
|
|
||||||
Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
|
Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
|
||||||
this mode no real I/O is done, but success returned to initiators.
|
this mode no real I/O is done, but success returned to initiators.
|
||||||
|
|||||||
+72
-4
@@ -233,6 +233,11 @@ your favorite kernel configuration Makefile target, e.g. "make xconfig":
|
|||||||
can clear already measured results by writing 0 in each file. Note,
|
can clear already measured results by writing 0 in each file. Note,
|
||||||
you need a non-preemptible kernel to have correct results.
|
you need a non-preemptible kernel to have correct results.
|
||||||
|
|
||||||
|
- CONFIG_SCST_DIF_INJECT_CORRUPTED_TAGS - if defined, allows injection
|
||||||
|
of corrupted DIF tags according to the Oracle specification. This
|
||||||
|
functionality is working only if dif_mode doesn't contain dev_store
|
||||||
|
and dif_type is 1.
|
||||||
|
|
||||||
HIGHMEM kernel configurations are fully supported, but not recommended
|
HIGHMEM kernel configurations are fully supported, but not recommended
|
||||||
for performance reasons.
|
for performance reasons.
|
||||||
|
|
||||||
@@ -489,6 +494,17 @@ Every target should have at least the following entries:
|
|||||||
particular target driver or not, you can find out by checking traces
|
particular target driver or not, you can find out by checking traces
|
||||||
or the target driver's source code.
|
or the target driver's source code.
|
||||||
|
|
||||||
|
- dif_capabilities - if this target supports T10-PI, returns which
|
||||||
|
exact DIF capabilities this target supports.
|
||||||
|
|
||||||
|
- dif_checks_failed - if this target supports T10-PI, returns
|
||||||
|
statistics how many DIF errors have been detected on the
|
||||||
|
corresponding processing stages on this target. It returns 3 rows of
|
||||||
|
numbers with 3 numbers in each row: for target driver stage, for SCST
|
||||||
|
stage and for dev handler stage. Numbers in each row: how many errors
|
||||||
|
detected checking application, reference and guard tags
|
||||||
|
correspondingly. Writing to this attribute resets the numbers.
|
||||||
|
|
||||||
- cpu_mask - defines CPU affinity mask for threads serving this target.
|
- cpu_mask - defines CPU affinity mask for threads serving this target.
|
||||||
For threads serving LUNs it is used only for devices with
|
For threads serving LUNs it is used only for devices with
|
||||||
threads_pool_type "per_initiator".
|
threads_pool_type "per_initiator".
|
||||||
@@ -547,6 +563,17 @@ following entries:
|
|||||||
|
|
||||||
- commands - contains overall number of SCSI commands in this session.
|
- commands - contains overall number of SCSI commands in this session.
|
||||||
|
|
||||||
|
- dif_checks_failed - if target of this session supports T10-PI, returns
|
||||||
|
statistics how many DIF errors have been detected on the
|
||||||
|
corresponding processing stages on all DIF-enabled LUNs in this
|
||||||
|
session. It returns 3 rows of numbers with 3 numbers in each row: for
|
||||||
|
target driver stage, for SCST stage and for dev handler stage.
|
||||||
|
Numbers in each row: how many errors detected checking application,
|
||||||
|
reference and guard tags correspondingly. Writing to this attribute
|
||||||
|
resets the numbers. Similar statistics returned in attribute with the
|
||||||
|
same name for each LUN in this session in this LUN's subdirectory, if
|
||||||
|
its device configured with dif_type > 0.
|
||||||
|
|
||||||
- read_cmd_count - number of READ SCSI commands received since beginning
|
- read_cmd_count - number of READ SCSI commands received since beginning
|
||||||
or last reset (writing 0 in this attribute)
|
or last reset (writing 0 in this attribute)
|
||||||
|
|
||||||
@@ -865,6 +892,47 @@ cache. The following parameters possible for vdisk_fileio:
|
|||||||
- zero_copy - if set, then this device uses zero copy access to the
|
- zero_copy - if set, then this device uses zero copy access to the
|
||||||
page cache. At the moment, only read side zero copy is implemented.
|
page cache. At the moment, only read side zero copy is implemented.
|
||||||
|
|
||||||
|
- dif_mode - specifies which T10-PI, or DIF, mode this device will use.
|
||||||
|
See SCSI standards from more info about T10-PI. Available DIF modes
|
||||||
|
(can be combined using '|'):
|
||||||
|
|
||||||
|
* tgt - DIF tags are checked on the target hardware, if supported
|
||||||
|
|
||||||
|
* scst - DIF tags are checked inside SCST core
|
||||||
|
|
||||||
|
* dev_check - DIF tags are checked inside backend device
|
||||||
|
|
||||||
|
* dev_store - DIF tags are stored inside backend device on the WRITE
|
||||||
|
path and read from it on the READ path
|
||||||
|
|
||||||
|
For instance, if only tgt DIF mode specified, then target driver,
|
||||||
|
serving this device, will inside hardware check, then STRIP DIF tags
|
||||||
|
from SCSI commands on the WRITE path and generate, then INSERT DIF
|
||||||
|
tags into SCSI commands on the READ path, so neither SCST core, nor
|
||||||
|
dev handler will see them.
|
||||||
|
|
||||||
|
Similarly, if only scst DIF mode specified, then target driver will
|
||||||
|
PASS DIF tags into SCST core, which then check/STRIP/generate/INSERT
|
||||||
|
them, so dev handler will not see them.
|
||||||
|
|
||||||
|
If only dev_check DIF mode specified, then both target driver and
|
||||||
|
SCST core will PASS DIF tags into the dev handler, which is then
|
||||||
|
responsible to check them in the backend hardware. If only dev_store
|
||||||
|
specified, then DIF tags will only be stored by the dev handler in
|
||||||
|
the backend hardware without checking at any level.
|
||||||
|
|
||||||
|
If all "tgt|scst|dev_check|dev_store" DIF mode specified, then all
|
||||||
|
target driver, SCST core and dev handler will check DIF tags, then
|
||||||
|
dev handler will store them in the backend hardware.
|
||||||
|
|
||||||
|
- dif_type - specifies which DIF SCSI type this device will use.
|
||||||
|
|
||||||
|
- dif_static_app_tag - specifies fixed (static) DIF application tag for
|
||||||
|
this device.
|
||||||
|
|
||||||
|
- dif_filename - specifies full path to filename, where DIF tags will
|
||||||
|
be stored.
|
||||||
|
|
||||||
Handler vdisk_blockio provides BLOCKIO mode to create virtual devices.
|
Handler vdisk_blockio provides BLOCKIO mode to create virtual devices.
|
||||||
This mode performs direct block I/O with a block device, bypassing the
|
This mode performs direct block I/O with a block device, bypassing the
|
||||||
page cache for all operations. This mode works ideally with high-end
|
page cache for all operations. This mode works ideally with high-end
|
||||||
@@ -872,10 +940,10 @@ storage HBAs and for applications that either do not need caching
|
|||||||
between application and disk or need the large block throughput. See
|
between application and disk or need the large block throughput. See
|
||||||
below for more info.
|
below for more info.
|
||||||
|
|
||||||
The following common with vdisk_fileio parameters are possible for
|
The following parameters possible for vdisk_blockio: filename,
|
||||||
vdisk_blockio: filename, blocksize, nv_cache, write_through, read_only,
|
blocksize, nv_cache, read_only, removable, rotational, thin_provisioned,
|
||||||
removable, rotational, thin_provisioned, tst. See vdisk_fileio above for
|
tst, dif_mode, dif_type, dif_static_app_tag, dif_filename. See
|
||||||
description of those parameters.
|
vdisk_fileio above for description of those parameters.
|
||||||
|
|
||||||
Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
|
Handler vdisk_nullio provides NULLIO mode to create virtual devices. In
|
||||||
this mode no real I/O is done, but success returned to initiators.
|
this mode no real I/O is done, but success returned to initiators.
|
||||||
|
|||||||
+845
-18
File diff suppressed because it is too large
Load Diff
@@ -334,6 +334,9 @@ static inline int scst_sense_response_code(const uint8_t *sense)
|
|||||||
|
|
||||||
/* ABORTED_COMMAND is 0xb */
|
/* ABORTED_COMMAND is 0xb */
|
||||||
#define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0
|
#define scst_sense_aborted_command ABORTED_COMMAND, 0x00, 0
|
||||||
|
#define scst_logical_block_guard_check_failed ABORTED_COMMAND, 0x10, 1
|
||||||
|
#define scst_logical_block_app_tag_check_failed ABORTED_COMMAND, 0x10, 2
|
||||||
|
#define scst_logical_block_ref_tag_check_failed ABORTED_COMMAND, 0x10, 3
|
||||||
#define scst_sense_internal_failure ABORTED_COMMAND, 0x44, 0 /* retriable */
|
#define scst_sense_internal_failure ABORTED_COMMAND, 0x44, 0 /* retriable */
|
||||||
|
|
||||||
/* MISCOMPARE is 0xe */
|
/* MISCOMPARE is 0xe */
|
||||||
@@ -427,6 +430,13 @@ static inline int scst_sense_response_code(const uint8_t *sense)
|
|||||||
#define UNMAP 0x42
|
#define UNMAP 0x42
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/* Subcodes of VARIABLE_LENGTH_CMD (0x7F) */
|
||||||
|
#define SUBCODE_READ_32 0x09
|
||||||
|
#define SUBCODE_VERIFY_32 0x0a
|
||||||
|
#define SUBCODE_WRITE_32 0x0b
|
||||||
|
#define SUBCODE_WRITE_VERIFY_32 0x0c
|
||||||
|
#define SUBCODE_WRITE_SAME_32 0x0d
|
||||||
|
|
||||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
|
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 12, 0)
|
||||||
/*
|
/*
|
||||||
* From <scsi/scsi.h>. See also commit
|
* From <scsi/scsi.h>. See also commit
|
||||||
@@ -445,7 +455,6 @@ static inline int scst_sense_response_code(const uint8_t *sense)
|
|||||||
#define BLKDISCARD _IO(0x12,119)
|
#define BLKDISCARD _IO(0x12,119)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
** SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
|
** SCSI Architecture Model (SAM) Status codes. Taken from SAM-3 draft
|
||||||
** T10/1561-D Revision 4 Draft dated 7th November 2002.
|
** T10/1561-D Revision 4 Draft dated 7th November 2002.
|
||||||
@@ -520,6 +529,44 @@ enum {
|
|||||||
#define SCST_QERR_2_RESERVED 2
|
#define SCST_QERR_2_RESERVED 2
|
||||||
#define SCST_QERR_3_ABORT_THIS_NEXUS_ONLY 3
|
#define SCST_QERR_3_ABORT_THIS_NEXUS_ONLY 3
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
** Values for the control mode page ATO field
|
||||||
|
*************************************************************/
|
||||||
|
|
||||||
|
/* I.e., app tags owned by storage */
|
||||||
|
#define SCST_ATO_0_MODIFIED_BY_STORAGE 0
|
||||||
|
|
||||||
|
/* I.e., app tags owned by application */
|
||||||
|
#define SCST_ATO_1_NOT_MODIFIED_BY_STORAGE 1
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
** Values for the control mode page DPICZ field
|
||||||
|
*************************************************************/
|
||||||
|
#define SCST_DPICZ_CHECK_ON_xPROT_0 0
|
||||||
|
#define SCST_DPICZ_NO_CHECK_ON_xPROT_0 1
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
** APP/REF TAG DIF constants
|
||||||
|
*************************************************************/
|
||||||
|
|
||||||
|
/* Skip all guards checks for this block */
|
||||||
|
#define SCST_DIF_NO_CHECK_ALL_APP_TAG cpu_to_be16(0xFFFF)
|
||||||
|
#define SCST_DIF_NO_CHECK_ALL_REF_TAG cpu_to_be32(0xFFFFFFFF)
|
||||||
|
|
||||||
|
/* Don't check app tag for this block */
|
||||||
|
#define SCST_DIF_NO_CHECK_APP_TAG 0
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
** Shift of size of DIF tag (8 bytes)
|
||||||
|
*************************************************************/
|
||||||
|
#define SCST_DIF_TAG_SHIFT 3
|
||||||
|
|
||||||
|
/*************************************************************
|
||||||
|
** Formats of DIF guard tags
|
||||||
|
*************************************************************/
|
||||||
|
#define SCST_DIF_GUARD_FORMAT_CRC 0
|
||||||
|
#define SCST_DIF_GUARD_FORMAT_IP 1
|
||||||
|
|
||||||
/*************************************************************
|
/*************************************************************
|
||||||
** TransportID protocol identifiers
|
** TransportID protocol identifiers
|
||||||
*************************************************************/
|
*************************************************************/
|
||||||
|
|||||||
@@ -121,6 +121,7 @@ install: all
|
|||||||
install -m 644 $(MODULE_SYMVERS) $(INSTALL_DIR_H)
|
install -m 644 $(MODULE_SYMVERS) $(INSTALL_DIR_H)
|
||||||
-/sbin/depmod -b $(INSTALL_MOD_PATH)/ -a $(KVER)
|
-/sbin/depmod -b $(INSTALL_MOD_PATH)/ -a $(KVER)
|
||||||
mkdir -p $(DESTDIR)/var/lib/scst/pr
|
mkdir -p $(DESTDIR)/var/lib/scst/pr
|
||||||
|
mkdir -p $(DESTDIR)/var/lib/scst/dif_tags
|
||||||
mkdir -p $(DESTDIR)/var/lib/scst/vdev_mode_pages
|
mkdir -p $(DESTDIR)/var/lib/scst/vdev_mode_pages
|
||||||
@echo "****************************************************************"
|
@echo "****************************************************************"
|
||||||
@echo "*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*"
|
@echo "*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*"
|
||||||
|
|||||||
@@ -814,7 +814,7 @@ static int dev_user_parse(struct scst_cmd *cmd)
|
|||||||
ucmd->user_cmd.parse_cmd.expected_data_direction =
|
ucmd->user_cmd.parse_cmd.expected_data_direction =
|
||||||
cmd->expected_data_direction;
|
cmd->expected_data_direction;
|
||||||
ucmd->user_cmd.parse_cmd.expected_transfer_len =
|
ucmd->user_cmd.parse_cmd.expected_transfer_len =
|
||||||
cmd->expected_transfer_len;
|
cmd->expected_transfer_len_full;
|
||||||
ucmd->user_cmd.parse_cmd.expected_out_transfer_len =
|
ucmd->user_cmd.parse_cmd.expected_out_transfer_len =
|
||||||
cmd->expected_out_transfer_len;
|
cmd->expected_out_transfer_len;
|
||||||
ucmd->user_cmd.parse_cmd.sn = cmd->tgt_sn;
|
ucmd->user_cmd.parse_cmd.sn = cmd->tgt_sn;
|
||||||
|
|||||||
+1341
-95
File diff suppressed because it is too large
Load Diff
+2717
-82
File diff suppressed because it is too large
Load Diff
@@ -520,6 +520,11 @@ static inline void scst_devt_dev_sysfs_del(struct scst_device *dev) { }
|
|||||||
|
|
||||||
static inline void scst_dev_sysfs_del(struct scst_device *dev) { }
|
static inline void scst_dev_sysfs_del(struct scst_device *dev) { }
|
||||||
|
|
||||||
|
static inline int scst_dev_sysfs_dif_create(struct scst_device *dev)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static inline int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
|
static inline int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@@ -568,6 +573,7 @@ int scst_devt_sysfs_create(struct scst_dev_type *devt);
|
|||||||
void scst_devt_sysfs_del(struct scst_dev_type *devt);
|
void scst_devt_sysfs_del(struct scst_dev_type *devt);
|
||||||
int scst_dev_sysfs_create(struct scst_device *dev);
|
int scst_dev_sysfs_create(struct scst_device *dev);
|
||||||
void scst_dev_sysfs_del(struct scst_device *dev);
|
void scst_dev_sysfs_del(struct scst_device *dev);
|
||||||
|
int scst_dev_sysfs_dif_create(struct scst_device *dev);
|
||||||
int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev);
|
int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev);
|
||||||
void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev);
|
void scst_tgt_dev_sysfs_del(struct scst_tgt_dev *tgt_dev);
|
||||||
int scst_devt_dev_sysfs_create(struct scst_device *dev);
|
int scst_devt_dev_sysfs_create(struct scst_device *dev);
|
||||||
|
|||||||
@@ -1033,6 +1033,63 @@ static struct kobj_attribute scst_tgtt_mgmt =
|
|||||||
__ATTR(mgmt, S_IRUGO | S_IWUSR, scst_tgtt_mgmt_show,
|
__ATTR(mgmt, S_IRUGO | S_IWUSR, scst_tgtt_mgmt_show,
|
||||||
scst_tgtt_mgmt_store);
|
scst_tgtt_mgmt_store);
|
||||||
|
|
||||||
|
static ssize_t scst_tgtt_dif_capable_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
struct scst_tgt_template *tgtt;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
tgtt = container_of(kobj, struct scst_tgt_template, tgtt_kobj);
|
||||||
|
|
||||||
|
EXTRACHECKS_BUG_ON(!tgtt->dif_supported);
|
||||||
|
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"dif_supported");
|
||||||
|
|
||||||
|
if (tgtt->hw_dif_type1_supported)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_type1_supported");
|
||||||
|
|
||||||
|
if (tgtt->hw_dif_type2_supported)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_type2_supported");
|
||||||
|
|
||||||
|
if (tgtt->hw_dif_type3_supported)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_type3_supported");
|
||||||
|
|
||||||
|
if (tgtt->hw_dif_ip_supported)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_ip_supported");
|
||||||
|
|
||||||
|
if (tgtt->hw_dif_same_sg_layout_required)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_same_sg_layout_required");
|
||||||
|
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos, "\n");
|
||||||
|
|
||||||
|
if (tgtt->supported_dif_block_sizes) {
|
||||||
|
const int *p = tgtt->supported_dif_block_sizes;
|
||||||
|
int j;
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"Supported blocks: ");
|
||||||
|
j = pos;
|
||||||
|
while (*p != 0) {
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"%s%d", (j == pos) ? "" : ", ", *p);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_EXIT_RES(pos);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute scst_tgtt_dif_capable_attr =
|
||||||
|
__ATTR(dif_capabilities, S_IRUGO, scst_tgtt_dif_capable_show, NULL);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Creates an attribute entry for target driver.
|
* Creates an attribute entry for target driver.
|
||||||
*/
|
*/
|
||||||
@@ -1085,6 +1142,16 @@ int scst_tgtt_sysfs_create(struct scst_tgt_template *tgtt)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tgtt->dif_supported) {
|
||||||
|
res = sysfs_create_file(&tgtt->tgtt_kobj,
|
||||||
|
&scst_tgtt_dif_capable_attr.attr);
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("Can't add attribute %s for target driver %s",
|
||||||
|
scst_tgtt_dif_capable_attr.attr.name, tgtt->name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
#if defined(CONFIG_SCST_DEBUG) || defined(CONFIG_SCST_TRACING)
|
||||||
if (tgtt->trace_flags != NULL) {
|
if (tgtt->trace_flags != NULL) {
|
||||||
res = sysfs_create_file(&tgtt->tgtt_kobj,
|
res = sysfs_create_file(&tgtt->tgtt_kobj,
|
||||||
@@ -2524,6 +2591,114 @@ out:
|
|||||||
}
|
}
|
||||||
EXPORT_SYMBOL(scst_create_tgt_attr);
|
EXPORT_SYMBOL(scst_create_tgt_attr);
|
||||||
|
|
||||||
|
static ssize_t scst_tgt_dif_capable_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
struct scst_tgt *tgt;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||||
|
|
||||||
|
EXTRACHECKS_BUG_ON(!tgt->tgt_dif_supported);
|
||||||
|
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"dif_supported");
|
||||||
|
|
||||||
|
if (tgt->tgt_hw_dif_type1_supported)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_type1_supported");
|
||||||
|
|
||||||
|
if (tgt->tgt_hw_dif_type2_supported)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_type2_supported");
|
||||||
|
|
||||||
|
if (tgt->tgt_hw_dif_type3_supported)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_type3_supported");
|
||||||
|
|
||||||
|
if (tgt->tgt_hw_dif_ip_supported)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_ip_supported");
|
||||||
|
|
||||||
|
if (tgt->tgt_hw_dif_same_sg_layout_required)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
", hw_dif_same_sg_layout_required");
|
||||||
|
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos, "\n");
|
||||||
|
|
||||||
|
if (tgt->tgt_supported_dif_block_sizes) {
|
||||||
|
const int *p = tgt->tgt_supported_dif_block_sizes;
|
||||||
|
int j;
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"Supported blocks: ");
|
||||||
|
j = pos;
|
||||||
|
while (*p != 0) {
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"%s%d", (j == pos) ? "" : ", ", *p);
|
||||||
|
p++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_EXIT_RES(pos);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute scst_tgt_dif_capable_attr =
|
||||||
|
__ATTR(dif_capabilities, S_IRUGO, scst_tgt_dif_capable_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t scst_tgt_dif_checks_failed_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
struct scst_tgt *tgt;
|
||||||
|
|
||||||
|
tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||||
|
|
||||||
|
pos = scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "\tapp\tref\tguard\n"
|
||||||
|
"tgt\t%d\t%d\t%d\nscst\t%d\t%d\t%d\ndev\t%d\t%d\t%d\n",
|
||||||
|
atomic_read(&tgt->tgt_dif_app_failed_tgt),
|
||||||
|
atomic_read(&tgt->tgt_dif_ref_failed_tgt),
|
||||||
|
atomic_read(&tgt->tgt_dif_guard_failed_tgt),
|
||||||
|
atomic_read(&tgt->tgt_dif_app_failed_scst),
|
||||||
|
atomic_read(&tgt->tgt_dif_ref_failed_scst),
|
||||||
|
atomic_read(&tgt->tgt_dif_guard_failed_scst),
|
||||||
|
atomic_read(&tgt->tgt_dif_app_failed_dev),
|
||||||
|
atomic_read(&tgt->tgt_dif_ref_failed_dev),
|
||||||
|
atomic_read(&tgt->tgt_dif_guard_failed_dev));
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t scst_tgt_dif_checks_failed_store(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct scst_tgt *tgt;
|
||||||
|
|
||||||
|
tgt = container_of(kobj, struct scst_tgt, tgt_kobj);
|
||||||
|
|
||||||
|
PRINT_INFO("Zeroing DIF failures statistics for target %s",
|
||||||
|
tgt->tgt_name);
|
||||||
|
|
||||||
|
atomic_set(&tgt->tgt_dif_app_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt->tgt_dif_ref_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt->tgt_dif_guard_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt->tgt_dif_app_failed_scst, 0);
|
||||||
|
atomic_set(&tgt->tgt_dif_ref_failed_scst, 0);
|
||||||
|
atomic_set(&tgt->tgt_dif_guard_failed_scst, 0);
|
||||||
|
atomic_set(&tgt->tgt_dif_app_failed_dev, 0);
|
||||||
|
atomic_set(&tgt->tgt_dif_ref_failed_dev, 0);
|
||||||
|
atomic_set(&tgt->tgt_dif_guard_failed_dev, 0);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute scst_tgt_dif_checks_failed_attr =
|
||||||
|
__ATTR(dif_checks_failed, S_IRUGO | S_IWUSR,
|
||||||
|
scst_tgt_dif_checks_failed_show,
|
||||||
|
scst_tgt_dif_checks_failed_store);
|
||||||
|
|
||||||
#define SCST_TGT_SYSFS_STAT_ATTR(member_name, attr, dir, result_op) \
|
#define SCST_TGT_SYSFS_STAT_ATTR(member_name, attr, dir, result_op) \
|
||||||
static int scst_tgt_sysfs_##attr##_show_work_fn( \
|
static int scst_tgt_sysfs_##attr##_show_work_fn( \
|
||||||
struct scst_sysfs_work_item *work) \
|
struct scst_sysfs_work_item *work) \
|
||||||
@@ -2679,6 +2854,26 @@ int scst_tgt_sysfs_create(struct scst_tgt *tgt)
|
|||||||
goto out_err;
|
goto out_err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tgt->tgt_dif_supported) {
|
||||||
|
res = sysfs_create_file(&tgt->tgt_kobj,
|
||||||
|
&scst_tgt_dif_capable_attr.attr);
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||||
|
scst_tgt_dif_capable_attr.attr.name,
|
||||||
|
tgt->tgt_name);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = sysfs_create_file(&tgt->tgt_kobj,
|
||||||
|
&scst_tgt_dif_checks_failed_attr.attr);
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("Can't add attribute %s for tgt %s",
|
||||||
|
scst_tgt_dif_checks_failed_attr.attr.name,
|
||||||
|
tgt->tgt_name);
|
||||||
|
goto out_err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (tgt->tgtt->tgt_attrs) {
|
if (tgt->tgtt->tgt_attrs) {
|
||||||
res = sysfs_create_files(&tgt->tgt_kobj, tgt->tgtt->tgt_attrs);
|
res = sysfs_create_files(&tgt->tgt_kobj, tgt->tgtt->tgt_attrs);
|
||||||
if (res != 0) {
|
if (res != 0) {
|
||||||
@@ -3397,6 +3592,164 @@ void scst_dev_sysfs_del(struct scst_device *dev)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ssize_t scst_dev_dif_mode_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
struct scst_device *dev;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||||
|
|
||||||
|
if (dev->dev_dif_mode == SCST_DIF_MODE_NONE)
|
||||||
|
pos = sprintf(buf, "None\n");
|
||||||
|
else {
|
||||||
|
int j = pos;
|
||||||
|
|
||||||
|
if (dev->dev_dif_mode & SCST_DIF_MODE_TGT)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"%s%s", (j == pos) ? "" : "|", SCST_DIF_MODE_TGT_STR);
|
||||||
|
|
||||||
|
if (dev->dev_dif_mode & SCST_DIF_MODE_SCST)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"%s%s", (j == pos) ? "" : "|", SCST_DIF_MODE_SCST_STR);
|
||||||
|
|
||||||
|
if (dev->dev_dif_mode & SCST_DIF_MODE_DEV_CHECK)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"%s%s", (j == pos) ? "" : "|", SCST_DIF_MODE_DEV_CHECK_STR);
|
||||||
|
|
||||||
|
if (dev->dev_dif_mode & SCST_DIF_MODE_DEV_STORE)
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"%s%s", (j == pos) ? "" : "|", SCST_DIF_MODE_DEV_STORE_STR);
|
||||||
|
|
||||||
|
pos += scnprintf(&buf[pos], SCST_SYSFS_BLOCK_SIZE - pos,
|
||||||
|
"\n%s", SCST_SYSFS_KEY_MARK "\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
TRACE_EXIT_RES(pos);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute scst_dev_dif_mode_attr =
|
||||||
|
__ATTR(dif_mode, S_IRUGO, scst_dev_dif_mode_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t scst_dev_dif_type_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
struct scst_device *dev;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||||
|
|
||||||
|
pos = sprintf(buf, "%d\n%s", dev->dev_dif_type,
|
||||||
|
(dev->dev_dif_type != 0) ? SCST_SYSFS_KEY_MARK "\n" : "");
|
||||||
|
|
||||||
|
TRACE_EXIT_RES(pos);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute scst_dev_dif_type_attr =
|
||||||
|
__ATTR(dif_type, S_IRUGO, scst_dev_dif_type_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t scst_dev_sysfs_dif_static_app_tag_store(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
struct scst_device *dev;
|
||||||
|
unsigned long long val;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||||
|
|
||||||
|
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
|
||||||
|
res = kstrtoull(buf, 0, &val);
|
||||||
|
#else
|
||||||
|
res = strict_strtoull(buf, 0, &val);
|
||||||
|
#endif
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("strtoul() for %s failed: %d (device %s)",
|
||||||
|
buf, res, dev->virt_name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
scst_dev_set_dif_static_app_tag_combined(dev, cpu_to_be64(val));
|
||||||
|
|
||||||
|
res = count;
|
||||||
|
|
||||||
|
PRINT_INFO("APP TAG for device %s changed to %llx", dev->virt_name,
|
||||||
|
(long long)be64_to_cpu(scst_dev_get_dif_static_app_tag_combined(dev)));
|
||||||
|
|
||||||
|
out:
|
||||||
|
TRACE_EXIT_RES(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t scst_dev_sysfs_dif_static_app_tag_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
struct scst_device *dev;
|
||||||
|
__be64 a;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||||
|
|
||||||
|
a = scst_dev_get_dif_static_app_tag_combined(dev);
|
||||||
|
|
||||||
|
pos = sprintf(buf, "0x%llx\n%s", (unsigned long long)be64_to_cpu(a),
|
||||||
|
(a != SCST_DIF_NO_CHECK_APP_TAG) ? SCST_SYSFS_KEY_MARK "\n" : "");
|
||||||
|
|
||||||
|
TRACE_EXIT_RES(pos);
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute scst_dev_dif_static_app_tag_attr =
|
||||||
|
__ATTR(dif_static_app_tag, S_IWUSR|S_IRUGO,
|
||||||
|
scst_dev_sysfs_dif_static_app_tag_show,
|
||||||
|
scst_dev_sysfs_dif_static_app_tag_store);
|
||||||
|
|
||||||
|
int scst_dev_sysfs_dif_create(struct scst_device *dev)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
/*
|
||||||
|
* On errors the caller supposed to unregister this device, hence,
|
||||||
|
* perform the cleanup.
|
||||||
|
*/
|
||||||
|
|
||||||
|
res = sysfs_create_file(&dev->dev_kobj, &scst_dev_dif_mode_attr.attr);
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("Can't create attr %s for dev %s",
|
||||||
|
scst_dev_dif_mode_attr.attr.name, dev->virt_name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = sysfs_create_file(&dev->dev_kobj, &scst_dev_dif_type_attr.attr);
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("Can't create attr %s for dev %s",
|
||||||
|
scst_dev_dif_type_attr.attr.name, dev->virt_name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
res = sysfs_create_file(&dev->dev_kobj, &scst_dev_dif_static_app_tag_attr.attr);
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("Can't create attr %s for dev %s",
|
||||||
|
scst_dev_dif_static_app_tag_attr.attr.name, dev->virt_name);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
|
||||||
|
out:
|
||||||
|
TRACE_EXIT_RES(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
** Tgt_dev implementation
|
** Tgt_dev implementation
|
||||||
**/
|
**/
|
||||||
@@ -3554,6 +3907,58 @@ static struct kobj_attribute tgt_dev_active_commands_attr =
|
|||||||
__ATTR(active_commands, S_IRUGO,
|
__ATTR(active_commands, S_IRUGO,
|
||||||
scst_tgt_dev_active_commands_show, NULL);
|
scst_tgt_dev_active_commands_show, NULL);
|
||||||
|
|
||||||
|
static ssize_t scst_tgt_dev_dif_checks_failed_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
struct scst_tgt_dev *tgt_dev;
|
||||||
|
|
||||||
|
tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
|
||||||
|
|
||||||
|
pos = scnprintf(buf, SCST_SYSFS_BLOCK_SIZE, "\tapp\tref\tguard\n"
|
||||||
|
"tgt\t%d\t%d\t%d\nscst\t%d\t%d\t%d\ndev\t%d\t%d\t%d\n",
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_app_failed_tgt),
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_ref_failed_tgt),
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_guard_failed_tgt),
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_app_failed_scst),
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_ref_failed_scst),
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_guard_failed_scst),
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_app_failed_dev),
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_ref_failed_dev),
|
||||||
|
atomic_read(&tgt_dev->tgt_dev_dif_guard_failed_dev));
|
||||||
|
|
||||||
|
return pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t scst_tgt_dev_dif_checks_failed_store(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
struct scst_tgt_dev *tgt_dev;
|
||||||
|
|
||||||
|
tgt_dev = container_of(kobj, struct scst_tgt_dev, tgt_dev_kobj);
|
||||||
|
|
||||||
|
PRINT_INFO("Zeroing DIF failures statistics for initiator "
|
||||||
|
"%s, target %s, LUN %lld", tgt_dev->sess->initiator_name,
|
||||||
|
tgt_dev->sess->tgt->tgt_name, (unsigned long long)tgt_dev->lun);
|
||||||
|
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_app_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_ref_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_guard_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_app_failed_scst, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_ref_failed_scst, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_guard_failed_scst, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_app_failed_dev, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_ref_failed_dev, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_guard_failed_dev, 0);
|
||||||
|
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute tgt_dev_dif_checks_failed_attr =
|
||||||
|
__ATTR(dif_checks_failed, S_IRUGO | S_IWUSR,
|
||||||
|
scst_tgt_dev_dif_checks_failed_show,
|
||||||
|
scst_tgt_dev_dif_checks_failed_store);
|
||||||
|
|
||||||
static struct attribute *scst_tgt_dev_attrs[] = {
|
static struct attribute *scst_tgt_dev_attrs[] = {
|
||||||
&tgt_dev_thread_pid_attr.attr,
|
&tgt_dev_thread_pid_attr.attr,
|
||||||
&tgt_dev_active_commands_attr.attr,
|
&tgt_dev_active_commands_attr.attr,
|
||||||
@@ -3598,9 +4003,25 @@ int scst_tgt_dev_sysfs_create(struct scst_tgt_dev *tgt_dev)
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (tgt_dev->sess->tgt->tgt_dif_supported && (tgt_dev->dev->dev_dif_type != 0)) {
|
||||||
|
res = sysfs_create_file(&tgt_dev->tgt_dev_kobj,
|
||||||
|
&tgt_dev_dif_checks_failed_attr.attr);
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("Adding %s sysfs attribute to tgt_dev %lld "
|
||||||
|
"failed (%d)", tgt_dev_dif_checks_failed_attr.attr.name,
|
||||||
|
(unsigned long long)tgt_dev->lun, res);
|
||||||
|
goto out_del;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
out:
|
out:
|
||||||
TRACE_EXIT_RES(res);
|
TRACE_EXIT_RES(res);
|
||||||
return res;
|
return res;
|
||||||
|
|
||||||
|
out_del:
|
||||||
|
kobject_del(&tgt_dev->tgt_dev_kobj);
|
||||||
|
kobject_put(&tgt_dev->tgt_dev_kobj);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -3944,6 +4365,161 @@ static struct kobj_attribute session_active_commands_attr =
|
|||||||
__ATTR(active_commands, S_IRUGO, scst_sess_sysfs_active_commands_show,
|
__ATTR(active_commands, S_IRUGO, scst_sess_sysfs_active_commands_show,
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
static int scst_sysfs_sess_get_dif_checks_failed_work_fn(struct scst_sysfs_work_item *work)
|
||||||
|
{
|
||||||
|
int res, t;
|
||||||
|
struct scst_session *sess = work->sess;
|
||||||
|
int app_failed_tgt = 0, ref_failed_tgt = 0, guard_failed_tgt = 0;
|
||||||
|
int app_failed_scst = 0, ref_failed_scst = 0, guard_failed_scst = 0;
|
||||||
|
int app_failed_dev = 0, ref_failed_dev = 0, guard_failed_dev = 0;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
res = mutex_lock_interruptible(&scst_mutex);
|
||||||
|
if (res != 0)
|
||||||
|
goto out_put;
|
||||||
|
|
||||||
|
for (t = SESS_TGT_DEV_LIST_HASH_SIZE-1; t >= 0; t--) {
|
||||||
|
struct list_head *head = &sess->sess_tgt_dev_list[t];
|
||||||
|
struct scst_tgt_dev *tgt_dev;
|
||||||
|
list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) {
|
||||||
|
app_failed_tgt += atomic_read(&tgt_dev->tgt_dev_dif_app_failed_tgt);
|
||||||
|
ref_failed_tgt += atomic_read(&tgt_dev->tgt_dev_dif_ref_failed_tgt);
|
||||||
|
guard_failed_tgt += atomic_read(&tgt_dev->tgt_dev_dif_guard_failed_tgt);
|
||||||
|
app_failed_scst += atomic_read(&tgt_dev->tgt_dev_dif_app_failed_scst);
|
||||||
|
ref_failed_scst += atomic_read(&tgt_dev->tgt_dev_dif_ref_failed_scst);
|
||||||
|
guard_failed_scst += atomic_read(&tgt_dev->tgt_dev_dif_guard_failed_scst);
|
||||||
|
app_failed_dev += atomic_read(&tgt_dev->tgt_dev_dif_app_failed_dev);
|
||||||
|
ref_failed_dev += atomic_read(&tgt_dev->tgt_dev_dif_ref_failed_dev);
|
||||||
|
guard_failed_dev += atomic_read(&tgt_dev->tgt_dev_dif_guard_failed_dev);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&scst_mutex);
|
||||||
|
|
||||||
|
work->res_buf = kasprintf(GFP_KERNEL, "\tapp\tref\tguard\n"
|
||||||
|
"tgt\t%d\t%d\t%d\nscst\t%d\t%d\t%d\ndev\t%d\t%d\t%d\n",
|
||||||
|
app_failed_tgt, ref_failed_tgt, guard_failed_tgt,
|
||||||
|
app_failed_scst, ref_failed_scst, guard_failed_scst,
|
||||||
|
app_failed_dev, ref_failed_dev, guard_failed_dev);
|
||||||
|
res = work->res_buf ? 0 : -ENOMEM;
|
||||||
|
|
||||||
|
out_put:
|
||||||
|
kobject_put(&sess->sess_kobj);
|
||||||
|
|
||||||
|
TRACE_EXIT_RES(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t scst_sess_sysfs_dif_checks_failed_show(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, char *buf)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
struct scst_session *sess;
|
||||||
|
struct scst_sysfs_work_item *work;
|
||||||
|
|
||||||
|
sess = container_of(kobj, struct scst_session, sess_kobj);
|
||||||
|
|
||||||
|
res = scst_alloc_sysfs_work(scst_sysfs_sess_get_dif_checks_failed_work_fn,
|
||||||
|
true, &work);
|
||||||
|
if (res != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
work->sess = sess;
|
||||||
|
|
||||||
|
SCST_SET_DEP_MAP(work, &scst_sess_dep_map);
|
||||||
|
kobject_get(&sess->sess_kobj);
|
||||||
|
|
||||||
|
scst_sysfs_work_get(work);
|
||||||
|
|
||||||
|
res = scst_sysfs_queue_wait_work(work);
|
||||||
|
if (res != 0)
|
||||||
|
goto out_put;
|
||||||
|
|
||||||
|
res = snprintf(buf, SCST_SYSFS_BLOCK_SIZE, "%s", work->res_buf);
|
||||||
|
|
||||||
|
out_put:
|
||||||
|
scst_sysfs_work_put(work);
|
||||||
|
|
||||||
|
out:
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int scst_sess_zero_dif_checks_failed(struct scst_sysfs_work_item *work)
|
||||||
|
{
|
||||||
|
int res, t;
|
||||||
|
struct scst_session *sess = work->sess;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
PRINT_INFO("Zeroing DIF failures statistics for initiator "
|
||||||
|
"%s, target %s", sess->initiator_name, sess->tgt->tgt_name);
|
||||||
|
|
||||||
|
res = mutex_lock_interruptible(&scst_mutex);
|
||||||
|
if (res != 0)
|
||||||
|
goto out_put;
|
||||||
|
|
||||||
|
for (t = SESS_TGT_DEV_LIST_HASH_SIZE-1; t >= 0; t--) {
|
||||||
|
struct list_head *head = &sess->sess_tgt_dev_list[t];
|
||||||
|
struct scst_tgt_dev *tgt_dev;
|
||||||
|
list_for_each_entry(tgt_dev, head, sess_tgt_dev_list_entry) {
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_app_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_ref_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_guard_failed_tgt, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_app_failed_scst, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_ref_failed_scst, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_guard_failed_scst, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_app_failed_dev, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_ref_failed_dev, 0);
|
||||||
|
atomic_set(&tgt_dev->tgt_dev_dif_guard_failed_dev, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_unlock(&scst_mutex);
|
||||||
|
|
||||||
|
res = 0;
|
||||||
|
|
||||||
|
out_put:
|
||||||
|
kobject_put(&sess->sess_kobj);
|
||||||
|
|
||||||
|
TRACE_EXIT_RES(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static ssize_t scst_sess_sysfs_dif_checks_failed_store(struct kobject *kobj,
|
||||||
|
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||||
|
{
|
||||||
|
int res;
|
||||||
|
struct scst_session *sess;
|
||||||
|
struct scst_sysfs_work_item *work;
|
||||||
|
|
||||||
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
sess = container_of(kobj, struct scst_session, sess_kobj);
|
||||||
|
|
||||||
|
res = scst_alloc_sysfs_work(scst_sess_zero_dif_checks_failed, false, &work);
|
||||||
|
if (res != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
work->sess = sess;
|
||||||
|
|
||||||
|
SCST_SET_DEP_MAP(work, &scst_sess_dep_map);
|
||||||
|
kobject_get(&sess->sess_kobj);
|
||||||
|
|
||||||
|
res = scst_sysfs_queue_wait_work(work);
|
||||||
|
if (res == 0)
|
||||||
|
res = count;
|
||||||
|
|
||||||
|
out:
|
||||||
|
TRACE_EXIT_RES(res);
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct kobj_attribute session_dif_checks_failed_attr =
|
||||||
|
__ATTR(dif_checks_failed, S_IRUGO | S_IWUSR,
|
||||||
|
scst_sess_sysfs_dif_checks_failed_show,
|
||||||
|
scst_sess_sysfs_dif_checks_failed_store);
|
||||||
|
|
||||||
static ssize_t scst_sess_sysfs_initiator_name_show(struct kobject *kobj,
|
static ssize_t scst_sess_sysfs_initiator_name_show(struct kobject *kobj,
|
||||||
struct kobj_attribute *attr, char *buf)
|
struct kobj_attribute *attr, char *buf)
|
||||||
{
|
{
|
||||||
@@ -4129,6 +4705,17 @@ int scst_sess_sysfs_create(struct scst_session *sess)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (sess->tgt->tgt_dif_supported) {
|
||||||
|
res = sysfs_create_file(&sess->sess_kobj,
|
||||||
|
&session_dif_checks_failed_attr.attr);
|
||||||
|
if (res != 0) {
|
||||||
|
PRINT_ERROR("Adding %s sysfs attribute to session %s "
|
||||||
|
"failed (%d)", session_dif_checks_failed_attr.attr.name,
|
||||||
|
name, res);
|
||||||
|
goto out_del;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (sess->tgt->tgtt->sess_attrs) {
|
if (sess->tgt->tgtt->sess_attrs) {
|
||||||
res = sysfs_create_files(&sess->sess_kobj,
|
res = sysfs_create_files(&sess->sess_kobj,
|
||||||
sess->tgt->tgtt->sess_attrs);
|
sess->tgt->tgtt->sess_attrs);
|
||||||
|
|||||||
+61
-32
@@ -578,12 +578,14 @@ int scst_pre_parse(struct scst_cmd *cmd)
|
|||||||
|
|
||||||
TRACE_DBG("op_name <%s> (cmd %p), direction=%d "
|
TRACE_DBG("op_name <%s> (cmd %p), direction=%d "
|
||||||
"(expected %d, set %s), lba %lld, bufflen=%d, data_len %lld, "
|
"(expected %d, set %s), lba %lld, bufflen=%d, data_len %lld, "
|
||||||
"out_bufflen=%d (expected len %d, out expected len %d), "
|
"out_bufflen=%d (expected len data %d, expected len DIF %d, "
|
||||||
"flags=0x%x, naca %d", cmd->op_name, cmd, cmd->data_direction,
|
"out expected len %d), flags=0x%x, , naca %d",
|
||||||
|
cmd->op_name, cmd, cmd->data_direction,
|
||||||
cmd->expected_data_direction,
|
cmd->expected_data_direction,
|
||||||
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
|
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
|
||||||
(long long)cmd->lba, cmd->bufflen, (long long)cmd->data_len,
|
(long long)cmd->lba, cmd->bufflen, (long long)cmd->data_len,
|
||||||
cmd->out_bufflen, cmd->expected_transfer_len,
|
cmd->out_bufflen, scst_cmd_get_expected_transfer_len_data(cmd),
|
||||||
|
scst_cmd_get_expected_transfer_len_dif(cmd),
|
||||||
cmd->expected_out_transfer_len, cmd->op_flags, cmd->cmd_naca);
|
cmd->expected_out_transfer_len, cmd->op_flags, cmd->cmd_naca);
|
||||||
|
|
||||||
res = 0;
|
res = 0;
|
||||||
@@ -617,6 +619,16 @@ static bool scst_is_allowed_to_mismatch_cmd(struct scst_cmd *cmd)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static bool scst_bufflen_eq_expecten_len(struct scst_cmd *cmd)
|
||||||
|
{
|
||||||
|
int b = cmd->bufflen;
|
||||||
|
|
||||||
|
if (cmd->tgt_dif_data_expected)
|
||||||
|
b += (b >> cmd->dev->block_shift) << SCST_DIF_TAG_SHIFT;
|
||||||
|
|
||||||
|
return b == cmd->expected_transfer_len_full;
|
||||||
|
}
|
||||||
|
|
||||||
static int scst_parse_cmd(struct scst_cmd *cmd)
|
static int scst_parse_cmd(struct scst_cmd *cmd)
|
||||||
{
|
{
|
||||||
int res = SCST_CMD_STATE_RES_CONT_SAME;
|
int res = SCST_CMD_STATE_RES_CONT_SAME;
|
||||||
@@ -679,12 +691,12 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
|||||||
#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
|
#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
|
||||||
if (scst_cmd_is_expected_set(cmd)) {
|
if (scst_cmd_is_expected_set(cmd)) {
|
||||||
TRACE(TRACE_MINOR, "Using initiator supplied values: "
|
TRACE(TRACE_MINOR, "Using initiator supplied values: "
|
||||||
"direction %d, transfer_len %d/%d",
|
"direction %d, transfer_len %d/%d/%d",
|
||||||
cmd->expected_data_direction,
|
scst_cmd_get_expected_transfer_len_data(cmd),
|
||||||
cmd->expected_transfer_len,
|
scst_cmd_get_expected_transfer_len_dif(cmd),
|
||||||
cmd->expected_out_transfer_len);
|
cmd->expected_out_transfer_len);
|
||||||
cmd->data_direction = cmd->expected_data_direction;
|
cmd->data_direction = cmd->expected_data_direction;
|
||||||
cmd->bufflen = cmd->expected_transfer_len;
|
cmd->bufflen = scst_cmd_get_expected_transfer_len_data(cmd);
|
||||||
cmd->data_len = cmd->bufflen;
|
cmd->data_len = cmd->bufflen;
|
||||||
cmd->out_bufflen = cmd->expected_out_transfer_len;
|
cmd->out_bufflen = cmd->expected_out_transfer_len;
|
||||||
} else {
|
} else {
|
||||||
@@ -722,7 +734,7 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
|||||||
* expected value, but limit it to some
|
* expected value, but limit it to some
|
||||||
* reasonable value (15MB).
|
* reasonable value (15MB).
|
||||||
*/
|
*/
|
||||||
cmd->bufflen = min(cmd->expected_transfer_len,
|
cmd->bufflen = min(scst_cmd_get_expected_transfer_len_data(cmd),
|
||||||
15*1024*1024);
|
15*1024*1024);
|
||||||
cmd->data_len = cmd->bufflen;
|
cmd->data_len = cmd->bufflen;
|
||||||
if (cmd->data_direction == SCST_DATA_BIDI)
|
if (cmd->data_direction == SCST_DATA_BIDI)
|
||||||
@@ -785,21 +797,22 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
|||||||
if (scst_cmd_is_expected_set(cmd)) {
|
if (scst_cmd_is_expected_set(cmd)) {
|
||||||
#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
|
#ifdef CONFIG_SCST_USE_EXPECTED_VALUES
|
||||||
if (unlikely((cmd->data_direction != cmd->expected_data_direction) ||
|
if (unlikely((cmd->data_direction != cmd->expected_data_direction) ||
|
||||||
(cmd->bufflen != cmd->expected_transfer_len) ||
|
!scst_bufflen_eq_expecten_len(cmd) ||
|
||||||
(cmd->out_bufflen != cmd->expected_out_transfer_len))) {
|
(cmd->out_bufflen != cmd->expected_out_transfer_len))) {
|
||||||
TRACE(TRACE_MINOR, "Expected values don't match "
|
TRACE(TRACE_MINOR, "Expected values don't match "
|
||||||
"decoded ones: data_direction %d, "
|
"decoded ones: data_direction %d, "
|
||||||
"expected_data_direction %d, "
|
"expected_data_direction %d, "
|
||||||
"bufflen %d, expected_transfer_len %d, "
|
"bufflen %d, expected len data %d, expected len "
|
||||||
"out_bufflen %d, expected_out_transfer_len %d",
|
"DIF %d, out_bufflen %d, expected_out_transfer_len %d",
|
||||||
cmd->data_direction,
|
cmd->data_direction,
|
||||||
cmd->expected_data_direction,
|
cmd->expected_data_direction,
|
||||||
cmd->bufflen, cmd->expected_transfer_len,
|
cmd->bufflen, scst_cmd_get_expected_transfer_len_data(cmd),
|
||||||
|
scst_cmd_get_expected_transfer_len_dif(cmd),
|
||||||
cmd->out_bufflen, cmd->expected_out_transfer_len);
|
cmd->out_bufflen, cmd->expected_out_transfer_len);
|
||||||
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
|
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
|
||||||
cmd->cdb, cmd->cdb_len);
|
cmd->cdb, cmd->cdb_len);
|
||||||
cmd->data_direction = cmd->expected_data_direction;
|
cmd->data_direction = cmd->expected_data_direction;
|
||||||
cmd->bufflen = cmd->expected_transfer_len;
|
cmd->bufflen = scst_cmd_get_expected_transfer_len_data(cmd);
|
||||||
cmd->data_len = cmd->bufflen;
|
cmd->data_len = cmd->bufflen;
|
||||||
cmd->out_bufflen = cmd->expected_out_transfer_len;
|
cmd->out_bufflen = cmd->expected_out_transfer_len;
|
||||||
cmd->resid_possible = 1;
|
cmd->resid_possible = 1;
|
||||||
@@ -823,13 +836,15 @@ static int scst_parse_cmd(struct scst_cmd *cmd)
|
|||||||
goto out_done;
|
goto out_done;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (unlikely(cmd->bufflen != cmd->expected_transfer_len)) {
|
if (unlikely(!scst_bufflen_eq_expecten_len(cmd))) {
|
||||||
TRACE(TRACE_MINOR, "Warning: expected "
|
TRACE(TRACE_MINOR, "Warning: expected "
|
||||||
"transfer length %d for opcode %s "
|
"transfer length %d (DIF %d) for opcode %s "
|
||||||
"(handler %s, target %s) doesn't match "
|
"(handler %s, target %s) doesn't match "
|
||||||
"decoded value %d",
|
"decoded value %d",
|
||||||
cmd->expected_transfer_len, scst_get_opcode_name(cmd),
|
scst_cmd_get_expected_transfer_len_data(cmd),
|
||||||
devt->name, cmd->tgtt->name, cmd->bufflen);
|
scst_cmd_get_expected_transfer_len_dif(cmd),
|
||||||
|
scst_get_opcode_name(cmd), devt->name,
|
||||||
|
cmd->tgtt->name, cmd->bufflen);
|
||||||
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
|
PRINT_BUFF_FLAG(TRACE_MINOR, "Suspicious CDB",
|
||||||
cmd->cdb, cmd->cdb_len);
|
cmd->cdb, cmd->cdb_len);
|
||||||
if ((cmd->expected_data_direction & SCST_DATA_READ) ||
|
if ((cmd->expected_data_direction & SCST_DATA_READ) ||
|
||||||
@@ -878,14 +893,16 @@ set_res:
|
|||||||
|
|
||||||
TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
|
TRACE(TRACE_SCSI, "op_name <%s> (cmd %p), direction=%d "
|
||||||
"(expected %d, set %s), lba=%lld, bufflen=%d, data len %lld, "
|
"(expected %d, set %s), lba=%lld, bufflen=%d, data len %lld, "
|
||||||
"out_bufflen=%d, (expected len %d, out expected len %d), "
|
"out_bufflen=%d, (expected len data %d, expected len DIF %d, "
|
||||||
"flags=0x%x, internal %d, naca %d", cmd->op_name, cmd,
|
"out expected len %d), flags=0x%x, internal %d, naca %d",
|
||||||
cmd->data_direction, cmd->expected_data_direction,
|
cmd->op_name, cmd, cmd->data_direction, cmd->expected_data_direction,
|
||||||
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
|
scst_cmd_is_expected_set(cmd) ? "yes" : "no",
|
||||||
(unsigned long long)cmd->lba,
|
(unsigned long long)cmd->lba,
|
||||||
cmd->bufflen, (long long)cmd->data_len, cmd->out_bufflen,
|
cmd->bufflen, (long long)cmd->data_len, cmd->out_bufflen,
|
||||||
cmd->expected_transfer_len, cmd->expected_out_transfer_len,
|
scst_cmd_get_expected_transfer_len_data(cmd),
|
||||||
cmd->op_flags, cmd->internal, cmd->cmd_naca);
|
scst_cmd_get_expected_transfer_len_dif(cmd),
|
||||||
|
cmd->expected_out_transfer_len, cmd->op_flags, cmd->internal,
|
||||||
|
cmd->cmd_naca);
|
||||||
|
|
||||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||||
switch (state) {
|
switch (state) {
|
||||||
@@ -1045,7 +1062,7 @@ static void scst_set_write_len(struct scst_cmd *cmd)
|
|||||||
goto out;
|
goto out;
|
||||||
} else {
|
} else {
|
||||||
cmd->write_len = min(cmd->bufflen,
|
cmd->write_len = min(cmd->bufflen,
|
||||||
cmd->expected_transfer_len);
|
scst_cmd_get_expected_transfer_len_data(cmd));
|
||||||
if (cmd->write_len == cmd->bufflen)
|
if (cmd->write_len == cmd->bufflen)
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
@@ -1163,13 +1180,18 @@ alloc:
|
|||||||
TRACE_MEM("tgt_i_data_buf_alloced set (cmd %p)", cmd);
|
TRACE_MEM("tgt_i_data_buf_alloced set (cmd %p)", cmd);
|
||||||
cmd->sg = cmd->tgt_i_sg;
|
cmd->sg = cmd->tgt_i_sg;
|
||||||
cmd->sg_cnt = cmd->tgt_i_sg_cnt;
|
cmd->sg_cnt = cmd->tgt_i_sg_cnt;
|
||||||
|
cmd->dif_sg = cmd->tgt_i_dif_sg;
|
||||||
|
cmd->dif_sg_cnt = cmd->tgt_i_dif_sg_cnt;
|
||||||
cmd->out_sg = cmd->tgt_out_sg;
|
cmd->out_sg = cmd->tgt_out_sg;
|
||||||
cmd->out_sg_cnt = cmd->tgt_out_sg_cnt;
|
cmd->out_sg_cnt = cmd->tgt_out_sg_cnt;
|
||||||
r = 0;
|
r = 0;
|
||||||
} else {
|
} else {
|
||||||
TRACE_MEM("Both *_data_buf_alloced set (cmd %p, sg %p, "
|
TRACE_MEM("Both *_data_buf_alloced set (cmd %p, sg %p, "
|
||||||
"sg_cnt %d, tgt_i_sg %p, tgt_i_sg_cnt %d)", cmd, cmd->sg,
|
"sg_cnt %d, dif_sg %p, dif_sg_cnt %d, tgt_i_sg %p, "
|
||||||
cmd->sg_cnt, cmd->tgt_i_sg, cmd->tgt_i_sg_cnt);
|
"tgt_i_sg_cnt %d, tgt_i_dif_sg %p, tgt_i_dif_sg_cnt %d)",
|
||||||
|
cmd, cmd->sg, cmd->sg_cnt, cmd->dif_sg, cmd->dif_sg_cnt,
|
||||||
|
cmd->tgt_i_sg, cmd->tgt_i_sg_cnt, cmd->tgt_i_dif_sg,
|
||||||
|
cmd->tgt_i_dif_sg_cnt);
|
||||||
r = 0;
|
r = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3537,6 +3559,7 @@ static int scst_pre_dev_done(struct scst_cmd *cmd)
|
|||||||
|
|
||||||
TRACE_ENTRY();
|
TRACE_ENTRY();
|
||||||
|
|
||||||
|
again:
|
||||||
rc = scst_check_auto_sense(cmd);
|
rc = scst_check_auto_sense(cmd);
|
||||||
if (unlikely(rc)) {
|
if (unlikely(rc)) {
|
||||||
if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))
|
if (test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags))
|
||||||
@@ -3567,16 +3590,22 @@ next:
|
|||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
rc = scsi_status_is_good(cmd->status);
|
if (likely(cmd->status == SAM_STAT_GOOD)) {
|
||||||
if (likely(rc)) {
|
if (cmd->deferred_dif_read_check) {
|
||||||
unsigned char type = cmd->dev->type;
|
int rc = scst_dif_process_read(cmd);
|
||||||
|
if (unlikely(rc != 0)) {
|
||||||
|
cmd->deferred_dif_read_check = 0;
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (unlikely((cmd->cdb[0] == MODE_SENSE ||
|
if (unlikely((cmd->cdb[0] == MODE_SENSE ||
|
||||||
cmd->cdb[0] == MODE_SENSE_10)) &&
|
cmd->cdb[0] == MODE_SENSE_10)) &&
|
||||||
(cmd->tgt_dev->tgt_dev_rd_only || cmd->dev->swp) &&
|
(cmd->tgt_dev->tgt_dev_rd_only || cmd->dev->swp) &&
|
||||||
(type == TYPE_DISK ||
|
(cmd->dev->type == TYPE_DISK ||
|
||||||
type == TYPE_WORM ||
|
cmd->dev->type == TYPE_WORM ||
|
||||||
type == TYPE_MOD ||
|
cmd->dev->type == TYPE_MOD ||
|
||||||
type == TYPE_TAPE)) {
|
cmd->dev->type == TYPE_TAPE)) {
|
||||||
int32_t length;
|
int32_t length;
|
||||||
uint8_t *address;
|
uint8_t *address;
|
||||||
bool err = false;
|
bool err = false;
|
||||||
|
|||||||
+1
-1
@@ -3433,7 +3433,7 @@ static int srpt_xfer_data(struct srpt_rdma_ch *ch,
|
|||||||
len = scst_get_buf_next(cmd, &buf);
|
len = scst_get_buf_next(cmd, &buf);
|
||||||
}
|
}
|
||||||
WARN_ON_ONCE(offset !=
|
WARN_ON_ONCE(offset !=
|
||||||
scst_cmd_get_expected_transfer_len(cmd));
|
scst_cmd_get_expected_transfer_len_full(cmd));
|
||||||
}
|
}
|
||||||
scst_rx_data(cmd, SCST_RX_STATUS_SUCCESS,
|
scst_rx_data(cmd, SCST_RX_STATUS_SUCCESS,
|
||||||
in_irq() ? SCST_CONTEXT_TASKLET :
|
in_irq() ? SCST_CONTEXT_TASKLET :
|
||||||
|
|||||||
Reference in New Issue
Block a user