mirror of
https://github.com/SCST-project/scst.git
synced 2026-07-08 09:06:32 +00:00
Merged revisions 5667-5670,5672-5686,5698,5700-5722,5724-5737 via svnmerge from
svn+ssh://yanb123@svn.code.sf.net/p/scst/svn/trunk
........
r5667 | bvassche | 2014-07-08 18:11:58 +0300 (Tue, 08 Jul 2014) | 1 line
nightly build: Update kernel versions
........
r5668 | vlnb | 2014-07-10 04:00:29 +0300 (Thu, 10 Jul 2014) | 3 lines
Make SCST interface compatibility more robust
........
r5669 | bvassche | 2014-07-10 09:17:57 +0300 (Thu, 10 Jul 2014) | 1 line
scst/Makefile: Create /var/lib/scst/vdev_mode_pages while installing SCST
........
r5670 | bvassche | 2014-07-10 09:18:58 +0300 (Thu, 10 Jul 2014) | 1 line
scst.spec.in: Create /var/lib/scst/pr and /var/lib/scst/vdev_mode_pages when installing the SCST RPM
........
r5672 | bvassche | 2014-07-10 15:29:59 +0300 (Thu, 10 Jul 2014) | 2 lines
scripts/rebuild-rhel-kernel-rpm: Move code for downloading a RHEL (clone) RPM into a separate file
........
r5673 | bvassche | 2014-07-11 09:48:49 +0300 (Fri, 11 Jul 2014) | 1 line
scripts/generate-kernel-patch: Also generate scst-itf-ver.h
........
r5674 | bvassche | 2014-07-11 10:54:19 +0300 (Fri, 11 Jul 2014) | 1 line
scripts/generate-kernel-patch: Remove trailing whitespace
........
r5675 | vlnb | 2014-07-12 03:53:46 +0300 (Sat, 12 Jul 2014) | 3 lines
BLOCKIO microoptimization: use per-device biosets
........
r5676 | bvassche | 2014-07-13 10:15:05 +0300 (Sun, 13 Jul 2014) | 1 line
nightly build: Update kernel versions
........
r5677 | vlnb | 2014-07-16 06:27:20 +0300 (Wed, 16 Jul 2014) | 3 lines
Install scst_itf_ver.h as well
........
r5678 | bvassche | 2014-07-16 08:35:40 +0300 (Wed, 16 Jul 2014) | 1 line
scst-devel rpm: Include /usr/include/scst/scst_itf_ver.h
........
r5679 | bvassche | 2014-07-16 11:29:16 +0300 (Wed, 16 Jul 2014) | 6 lines
ib_srpt: Fix Mellanox OFED build
Use the proper include directory when building against Mellanox OFED.
Do not require to remove /lib/modules/$(KVER)/kernel/drivers/infiniband
before building ib_srpt.
........
r5680 | bvassche | 2014-07-18 12:27:41 +0300 (Fri, 18 Jul 2014) | 1 line
srpt/Makefile: Remove a superfluous assignment statement
........
r5681 | bvassche | 2014-07-18 12:28:22 +0300 (Fri, 18 Jul 2014) | 1 line
srpt/Makefile: SLES + Mellanox OFED build fix
........
r5682 | bvassche | 2014-07-18 12:30:25 +0300 (Fri, 18 Jul 2014) | 1 line
srpt/README: Fix SLES patch instructions
........
r5683 | vlnb | 2014-07-19 06:54:33 +0300 (Sat, 19 Jul 2014) | 11 lines
iscsi-scst: Handle data buffers with non-zero offset correctly
Start at the proper offset in the receive buffer if sg[0].offset != 0.
Return the proper data to the initiator if sg[0].offset != 0.
This patch reworks trunk r5281, "iscsi-scst: fix offset
calculation", February 13, 2014.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5684 | vlnb | 2014-07-19 07:08:30 +0300 (Sat, 19 Jul 2014) | 10 lines
scst: Clean up scst_process_active_cmd()
Since inside scst_process_active_cmd() cmd->state can only change after
cmd has been added back to the command list it is safe to perform the
cmd->state check without holding the command list lock. Hence move the
perform the cmd->state check without holding the command list lock.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5685 | vlnb | 2014-07-19 07:11:39 +0300 (Sat, 19 Jul 2014) | 7 lines
scst: Introduce scst_set_thr_cpu_mask()
This patch does not change any functionality.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5686 | vlnb | 2014-07-19 07:13:24 +0300 (Sat, 19 Jul 2014) | 8 lines
scst_vdisk: Micro-optimize the zero-copy check
Only evaluate the SCSI command type if virt_dev->zero_copy has been
set instead of always checking the SCSI command type.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5698 | bvassche | 2014-07-20 11:37:58 +0300 (Sun, 20 Jul 2014) | 1 line
nightly build: Update kernel versions
........
r5700 | vlnb | 2014-07-22 02:04:18 +0300 (Tue, 22 Jul 2014) | 3 lines
Web updates
........
r5701 | vlnb | 2014-07-22 03:22:06 +0300 (Tue, 22 Jul 2014) | 8 lines
scst: Make scst_cmd_threads.threads_list locking more fine-grained
Introduce a new synchronization object, namely scst_cmd_threads.thr_lock,
to protect scst_cmd_threads.threads_list.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5702 | vlnb | 2014-07-23 05:00:06 +0300 (Wed, 23 Jul 2014) | 7 lines
Prevent possible collisions between saved PR and mode pages backup files
From now on '.' is illegal character in SCST device names
Reported-by Ken Raeburn <raeburn@permabit.com>
........
r5703 | vlnb | 2014-07-23 05:49:50 +0300 (Wed, 23 Jul 2014) | 5 lines
Review of host_status handling (pass-through mode)
Inspired by Dave Butler <tears.the@gmail.com> and Bart Van Assche <bvanassche@acm.org>
........
r5704 | vlnb | 2014-07-26 03:04:51 +0300 (Sat, 26 Jul 2014) | 3 lines
Internal REQUEST SENSE: NO SENSE is also valid sense
........
r5705 | vlnb | 2014-07-29 02:11:14 +0300 (Tue, 29 Jul 2014) | 3 lines
Print initiator and target in the abort messages
........
r5706 | vlnb | 2014-07-30 05:27:10 +0300 (Wed, 30 Jul 2014) | 3 lines
Minor logging improvements
........
r5707 | vlnb | 2014-07-30 05:52:26 +0300 (Wed, 30 Jul 2014) | 3 lines
Follow up for r5704: NO SENSE is also valid sense
........
r5708 | vlnb | 2014-07-30 05:53:07 +0300 (Wed, 30 Jul 2014) | 3 lines
Minor fix
........
r5709 | bvassche | 2014-08-06 20:40:30 +0300 (Wed, 06 Aug 2014) | 1 line
nightly build: Update kernel versions
........
r5710 | bvassche | 2014-08-07 10:20:08 +0300 (Thu, 07 Aug 2014) | 1 line
RHEL 7: Add scst_exec_req_fifo and put_page_callback patches
........
r5711 | bvassche | 2014-08-07 11:12:22 +0300 (Thu, 07 Aug 2014) | 1 line
Rename the two RHEL 7 scst_exec_req_fifo patches
........
r5712 | bvassche | 2014-08-07 11:38:19 +0300 (Thu, 07 Aug 2014) | 1 line
scripts/rebuild-rhel-kernel-rpm: Add RHEL 7 support
........
r5713 | bvassche | 2014-08-08 13:37:17 +0300 (Fri, 08 Aug 2014) | 1 line
nightly build: Update kernel versions
........
r5714 | bvassche | 2014-08-09 14:02:19 +0300 (Sat, 09 Aug 2014) | 1 line
scripts/rebuild-rhel-kernel-rpm: Install more prerequisites
........
r5715 | bvassche | 2014-08-15 10:49:07 +0300 (Fri, 15 Aug 2014) | 1 line
nightly build: Update kernel versions
........
r5716 | vlnb | 2014-08-16 02:44:33 +0300 (Sat, 16 Aug 2014) | 3 lines
Fix blockio bioset for older kernels, which need explicit bio destructors
........
r5717 | vlnb | 2014-08-20 00:52:31 +0300 (Wed, 20 Aug 2014) | 3 lines
Update for kernels 3.16
........
r5718 | vlnb | 2014-08-20 05:24:08 +0300 (Wed, 20 Aug 2014) | 12 lines
Fix Coverity warning of q2t_ctio_to_cmd() dead code
Coverity warns that 'handle == Q2T_SKIP_HANDLE' can never occur, because
code preceding the test has masked out a handle bit that would be
required for the test to succeed.
Fix that by extending Q2T_SKIP_HANDLE to incorporate
CTIO_INTERMEDIATE_HANDLE_MARK as well.
Reported-by: Steven J. Magnani <steve@digidescorp.com>
........
r5719 | bvassche | 2014-08-20 09:55:04 +0300 (Wed, 20 Aug 2014) | 1 line
nightly build: Add kernel 3.16 nightly build infrastructure
........
r5720 | bvassche | 2014-08-20 09:57:04 +0300 (Wed, 20 Aug 2014) | 1 line
nightly build: Add kernel version 3.16.1
........
r5721 | vlnb | 2014-08-21 08:17:47 +0300 (Thu, 21 Aug 2014) | 5 lines
Fix incorrect address computation during receive PDUs preparations
Found and fix suggested by Кирилл Тюшев <kirill.tyushev8@gmail.com>
........
r5722 | vlnb | 2014-08-21 08:18:43 +0300 (Thu, 21 Aug 2014) | 3 lines
Integration of the QLogic git's qla2x00t into the SCST tree
........
r5724 | bvassche | 2014-08-22 10:19:55 +0300 (Fri, 22 Aug 2014) | 9 lines
Fix a kernel 3.16 checkpatch complaint about trailing semicolons
Avoid that the checkpatch tool included in Linux kernel v3.16 reports the
following warning:
macros should not use a trailing semicolon
This patch does not change any functionality.
........
r5725 | bvassche | 2014-08-25 14:36:33 +0300 (Mon, 25 Aug 2014) | 1 line
ib_srpt: Kernel v3.17 build fix
........
r5726 | bvassche | 2014-08-25 14:41:55 +0300 (Mon, 25 Aug 2014) | 1 line
ib_srpt: Log QPN next to session name
........
r5727 | bvassche | 2014-08-25 14:46:43 +0300 (Mon, 25 Aug 2014) | 6 lines
ib_srpt: Speed up kernel driver unloading after a cable pull
When unloading the ib_srpt kernel module, instead of waiting until
all connected queue pairs have left the TimeWait state, destroy
these queue pairs immediately.
........
r5728 | bvassche | 2014-08-25 15:50:19 +0300 (Mon, 25 Aug 2014) | 8 lines
ib_srpt: Make the completion vector configurable
Allow a set of completion vectors to be associated with each InfiniBand
HCA port and allocate the completion vector for each session in a
round-robin fashion from the per-port set. This helps to spread the
InfiniBand interrupt workload over multiple CPU's, at least if different
InfiniBand MSI-X vectors are associated with different CPU's.
........
r5729 | vlnb | 2014-08-26 06:21:07 +0300 (Tue, 26 Aug 2014) | 7 lines
scst_vdisk: Make vdisk_sup_vpd() easier to extend
This patch doesn't change any functionality.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5730 | vlnb | 2014-08-26 06:44:23 +0300 (Tue, 26 Aug 2014) | 12 lines
scst_vdisk: Make EUI-64 and NAA IDs configurable
Make the SCSI device identification page (83h) EUI-64 and NAA
IDs configurable. If neither the eui64_id nor the naa_id sysfs
attribute has been set, export the first eight bytes of the
t10_dev_id as an EUI-64 ID. If the NAA ID but not the EUI-64 ID
has been set, report the NAA ID only. If both IDs have been set,
report both.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5731 | bvassche | 2014-08-26 12:56:54 +0300 (Tue, 26 Aug 2014) | 1 line
scstadmin: Avoid that the Perl interpreter prints a warning message about using an undefined variable on Fedora systems
........
r5732 | vlnb | 2014-08-27 05:41:40 +0300 (Wed, 27 Aug 2014) | 9 lines
iscsi-scst: Build fix for IPV6=n
Ensure that iscsi-scst builds properly against a kernel with CONFIG_IPV6=n.
Reported by Igor Novgorodov <igor@novg.net> on June 7, 2014.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5733 | vlnb | 2014-08-27 05:42:35 +0300 (Wed, 27 Aug 2014) | 9 lines
scst_pres: Make a few error messages more clear
Make it possible to figure out what went wrong from inspecting the
system log only by mentioning the incorrect filename in the system
log.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5734 | vlnb | 2014-08-27 05:43:50 +0300 (Wed, 27 Aug 2014) | 8 lines
scst: Remove set_cpus_allowed() invocations
Since scst.h contains a backport of the definition of set_cpus_allowed_ptr(),
the set_cpus_allowed() invocations are superfluous. Hence remove these.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5735 | vlnb | 2014-08-27 05:55:28 +0300 (Wed, 27 Aug 2014) | 8 lines
iscsi-scst: Micro-optimize cmnd_prepare_recv_pdu()
Instead of adding sg[idx].offset to addr and immediately subtracting
sg[idx].offset again, leave out both arithmetic operations.
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5736 | vlnb | 2014-08-27 06:00:44 +0300 (Wed, 27 Aug 2014) | 5 lines
scst/include/scst.h: Document on_abort_cmd() further
Signed-off-by: Bart Van Assche <bvanassche@acm.org>
........
r5737 | bvassche | 2014-08-27 09:33:02 +0300 (Wed, 27 Aug 2014) | 1 line
scst_vdisk: Build fix for kernel 3.1.x
........
git-svn-id: http://svn.code.sf.net/p/scst/svn/branches/iser@5738 d57e44dd-8a1f-0410-8b47-8ef2f437770f
This commit is contained in:
@@ -40,9 +40,10 @@ endif
|
||||
SCST_DIR=scst
|
||||
DOC_DIR=doc
|
||||
SCSTADM_DIR=scstadmin
|
||||
QLA_INI_DIR=qla2x00t
|
||||
QLA_DIR=qla2x00t/qla2x00-target
|
||||
QLA_ISP_DIR=qla_isp
|
||||
QLA_INI_DIR=qla2x00t_git
|
||||
QLA_DIR=qla2x00t_git/qla2x00-target
|
||||
QLA_OLD_INI_DIR=qla2x00t
|
||||
QLA_OLD_DIR=qla2x00t/qla2x00-target
|
||||
LSI_DIR=mpt
|
||||
USR_DIR=usr/fileio
|
||||
SRP_DIR=srpt
|
||||
@@ -75,16 +76,17 @@ help:
|
||||
@echo " scstadm_uninstall : scstadmin: uninstall"
|
||||
@echo ""
|
||||
@echo " qla : make QLA target driver"
|
||||
@echo " qla_clean : 2.6 qla target: clean "
|
||||
@echo " qla_extraclean : 2.6 qla target: clean + clean dependencies"
|
||||
@echo " qla_install : 2.6 qla target: install"
|
||||
@echo " qla_uninstall : 2.6 qla target: uninstall"
|
||||
@echo " qla_pull : pull the latest version of the QLA target driver from the QLogic's git"
|
||||
@echo " qla_clean : qla target: clean "
|
||||
@echo " qla_extraclean : qla target: clean + clean dependencies"
|
||||
@echo " qla_install : qla target: install"
|
||||
@echo " qla_uninstall : qla target: uninstall"
|
||||
@echo ""
|
||||
@echo " qla_isp : make ISP Qlogic chipsets target driver"
|
||||
@echo " qla_isp_clean : qla ISP target: clean "
|
||||
@echo " qla_isp_extraclean: qla ISP target: clean + clean dependencies"
|
||||
@echo " qla_isp_install : qla ISP target: install"
|
||||
@echo " qla_isp_uninstall : qla ISP target: uninstall"
|
||||
@echo " qla_old : make old Qlogic chipsets target driver"
|
||||
@echo " qla_old_clean : qla old target: clean "
|
||||
@echo " qla_old_extraclean: qla old target: clean + clean dependencies"
|
||||
@echo " qla_old_install : qla old target: install"
|
||||
@echo " qla_old_uninstall : qla old target: uninstall"
|
||||
@echo ""
|
||||
@echo " iscsi : make iSCSI target"
|
||||
@echo " iscsi_clean : ISCSI target: clean "
|
||||
@@ -140,7 +142,7 @@ all:
|
||||
cd $(SCST_DIR) && $(MAKE) $@
|
||||
# @if [ -d $(DOC_DIR) ]; then cd $(DOC_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(QLA_ISP_DIR) ]; then cd $(QLA_ISP_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -151,7 +153,7 @@ install:
|
||||
cd $(SCST_DIR) && $(MAKE) $@
|
||||
# @if [ -d $(DOC_DIR) ]; then cd $(DOC_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(QLA_ISP_DIR) ]; then cd $(QLA_ISP_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -162,7 +164,7 @@ uninstall:
|
||||
cd $(SCST_DIR) && $(MAKE) $@
|
||||
# @if [ -d $(DOC_DIR) ]; then cd $(DOC_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(QLA_ISP_DIR) ]; then cd $(QLA_ISP_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -174,7 +176,8 @@ clean:
|
||||
@if [ -d $(DOC_DIR) ]; then cd $(DOC_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_INI_DIR) ]; then cd $(QLA_INI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(QLA_ISP_DIR) ]; then cd $(QLA_ISP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_OLD_INI_DIR) ]; then cd $(QLA_OLD_INI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -187,7 +190,8 @@ extraclean:
|
||||
@if [ -d $(DOC_DIR) ]; then cd $(DOC_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_INI_DIR) ]; then cd $(QLA_INI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(QLA_ISP_DIR) ]; then cd $(QLA_ISP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_OLD_INI_DIR) ]; then cd $(QLA_OLD_INI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -239,6 +243,9 @@ scstadm_extraclean:
|
||||
qla:
|
||||
cd $(QLA_DIR) && $(MAKE) all
|
||||
|
||||
qla_pull:
|
||||
cd $(QLA_INI_DIR) && git pull
|
||||
|
||||
qla_install:
|
||||
cd $(QLA_DIR) && $(MAKE) install
|
||||
|
||||
@@ -253,20 +260,20 @@ qla_extraclean:
|
||||
cd $(QLA_INI_DIR)/.. && $(MAKE) extraclean
|
||||
cd $(QLA_DIR) && $(MAKE) extraclean
|
||||
|
||||
qla_isp:
|
||||
cd $(QLA_ISP_DIR) && $(MAKE) all
|
||||
qla_old:
|
||||
cd $(QLA_OLD_DIR) && $(MAKE) all
|
||||
|
||||
qla_isp_install:
|
||||
cd $(QLA_ISP_DIR) && $(MAKE) install
|
||||
qla_old_install:
|
||||
cd $(QLA_OLD_DIR) && $(MAKE) install
|
||||
|
||||
qla_isp_uninstall:
|
||||
cd $(QLA_ISP_DIR) && $(MAKE) uninstall
|
||||
qla_old_uninstall:
|
||||
cd $(QLA_OLD_DIR) && $(MAKE) uninstall
|
||||
|
||||
qla_isp_clean:
|
||||
cd $(QLA_ISP_DIR) && $(MAKE) clean
|
||||
qla_old_clean:
|
||||
cd $(QLA_OLD_DIR) && $(MAKE) clean
|
||||
|
||||
qla_isp_extraclean:
|
||||
cd $(QLA_ISP_DIR) && $(MAKE) extraclean
|
||||
qla_old_extraclean:
|
||||
cd $(QLA_OLD_DIR) && $(MAKE) extraclean
|
||||
|
||||
iscsi:
|
||||
cd $(ISCSI_DIR) && $(MAKE) all
|
||||
@@ -411,7 +418,7 @@ rpm:
|
||||
2perf: extraclean
|
||||
cd $(SCST_DIR) && $(MAKE) $@
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# patch -p0 <qla_isp-release.patch
|
||||
@if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -422,7 +429,7 @@ rpm:
|
||||
2release: extraclean
|
||||
cd $(SCST_DIR) && $(MAKE) $@
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# patch -p0 <qla_isp-release.patch
|
||||
@if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -433,7 +440,7 @@ rpm:
|
||||
2debug: extraclean
|
||||
cd $(SCST_DIR) && $(MAKE) $@
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# patch -p0 -R <qla_isp-release.patch
|
||||
@if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -444,7 +451,7 @@ rpm:
|
||||
enable_proc: extraclean
|
||||
cd $(SCST_DIR) && $(MAKE) $@
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# patch -p0 -R <qla_isp-release.patch
|
||||
@if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -454,7 +461,7 @@ enable_proc: extraclean
|
||||
disable_proc: extraclean
|
||||
cd $(SCST_DIR) && $(MAKE) $@
|
||||
@if [ -d $(QLA_DIR) ]; then cd $(QLA_DIR) && $(MAKE) $@; fi
|
||||
# patch -p0 -R <qla_isp-release.patch
|
||||
@if [ -d $(QLA_OLD_DIR) ]; then cd $(QLA_OLD_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(LSI_DIR) ]; then cd $(LSI_DIR) && $(MAKE) $@; fi
|
||||
# @if [ -d $(SRP_DIR) ]; then cd $(SRP_DIR) && $(MAKE) $@; fi
|
||||
@if [ -d $(ISCSI_DIR) ]; then cd $(ISCSI_DIR) && $(MAKE) $@; fi
|
||||
@@ -463,7 +470,7 @@ disable_proc: extraclean
|
||||
|
||||
.PHONY: all install uninstall clean extraclean tags help \
|
||||
qla qla_install qla_uninstall qla_clean qla_extraclean \
|
||||
qla_isp qla_isp_install qla_isp_uninstall qla_isp_clean qla_isp_extraclean \
|
||||
qla_old qla_old_install qla_old_uninstall qla_old_clean qla_old_extraclean \
|
||||
lsi lsi_install lsi_uninstall lsi_clean lsi_extraclean \
|
||||
iscsi iscsi_install iscsi_uninstall iscsi_clean iscsi_extraclean \
|
||||
scst scst_install scst_uninstall scst_clean scst_extraclean \
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
Overview
|
||||
========
|
||||
|
||||
This is the SCST development repository. It contains not a single
|
||||
project SCST as one can think, but a number of them, which are divided
|
||||
as the following:
|
||||
@@ -24,4 +27,34 @@ make scst scst_install iscsi iscsi_install
|
||||
|
||||
For more information about each subproject see their README files.
|
||||
|
||||
|
||||
QLogic target driver
|
||||
====================
|
||||
|
||||
QLogic target driver in qla2x00t/ is the old one, forked from qla2xxx
|
||||
from kernel 2.6.26. It is not maintained anymore and not built by
|
||||
default by the common Makefile targets, like "all".
|
||||
|
||||
You can find the latest version of this driver in git://git.qlogic.com/scst-qla2xxx.git.
|
||||
It is now maintained by QLogic, hence located in the QLogic's git.
|
||||
|
||||
To integrate it into the SCST build tree you need:
|
||||
|
||||
1. Clone the QLogic git tree somewhere in your system.
|
||||
|
||||
2. Create in the SCST root, i.e. this directory, a subdirectory with name
|
||||
qla2x00t_git
|
||||
|
||||
3. Bind mount drivers/scsi/qla2xxx in the cloned git tree to the
|
||||
qla2x00t_git subdirectory, like:
|
||||
|
||||
# mount --bind /home/u/scst-qla2xxx/drivers/scsi/qla2xxx /home/u/trunk/qla2x00t_git
|
||||
|
||||
Thats all. Now "make all" and other common and QLA specific root
|
||||
Makefile targets "magically" start working. The bind mount is necessary
|
||||
for the driver to correctly find the SCST header files. Symlinks can't
|
||||
do it.
|
||||
|
||||
You can still build the old driver using qla_old* root Makefile targets.
|
||||
|
||||
Vladislav Bolkhovitin <vst@vlnb.net>, http://scst.sourceforge.net
|
||||
|
||||
@@ -105,6 +105,7 @@ void conn_info_show(struct seq_file *seq, struct iscsi_session *session)
|
||||
"%pI4", &inet_sk(sk)->inet_daddr);
|
||||
#endif
|
||||
break;
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
case AF_INET6:
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,29)
|
||||
snprintf(buf, sizeof(buf),
|
||||
@@ -118,6 +119,7 @@ void conn_info_show(struct seq_file *seq, struct iscsi_session *session)
|
||||
&sk->sk_v6_daddr);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
snprintf(buf, sizeof(buf), "Unknown family %d",
|
||||
sk->sk_family);
|
||||
|
||||
@@ -1585,9 +1585,8 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn,
|
||||
iscsi_extracheck_is_rd_thread(conn);
|
||||
|
||||
buff_offs = offset;
|
||||
idx = (offset + sg[0].offset) >> PAGE_SHIFT;
|
||||
if (offset + sg[0].offset >= PAGE_SIZE)
|
||||
offset += sg[0].offset;
|
||||
offset += sg[0].offset;
|
||||
idx = offset >> PAGE_SHIFT;
|
||||
offset &= ~PAGE_MASK;
|
||||
|
||||
conn->read_msg.msg_iov = conn->read_iov;
|
||||
@@ -1606,9 +1605,9 @@ static int cmnd_prepare_recv_pdu(struct iscsi_conn *conn,
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
addr = (char __force __user *)(sg_virt(&sg[idx]));
|
||||
addr = (char __force __user *)(page_address(sg_page(&sg[idx])));
|
||||
EXTRACHECKS_BUG_ON(addr == NULL);
|
||||
sg_len = sg[idx].length - offset;
|
||||
sg_len = sg[idx].offset + sg[idx].length - offset;
|
||||
|
||||
conn->read_iov[i].iov_base = addr + offset;
|
||||
|
||||
@@ -3265,6 +3264,7 @@ static ssize_t iscsi_tcp_get_initiator_ip(struct iscsi_conn *conn,
|
||||
"%pI4", &inet_sk(sk)->inet_daddr);
|
||||
#endif
|
||||
break;
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
case AF_INET6:
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
|
||||
pos = scnprintf(buf, size,
|
||||
@@ -3279,6 +3279,7 @@ static ssize_t iscsi_tcp_get_initiator_ip(struct iscsi_conn *conn,
|
||||
#endif
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
pos = scnprintf(buf, size, "Unknown family %d",
|
||||
sk->sk_family);
|
||||
|
||||
@@ -426,6 +426,7 @@ static ssize_t isert_get_initiator_ip(struct iscsi_conn *conn,
|
||||
"%pI4", &((struct sockaddr_in *)&ss)->sin_addr.s_addr);
|
||||
#endif
|
||||
break;
|
||||
#if defined(CONFIG_IPV6) || defined(CONFIG_IPV6_MODULE)
|
||||
case AF_INET6:
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 29)
|
||||
pos = scnprintf(buf, size,
|
||||
@@ -436,6 +437,7 @@ static ssize_t isert_get_initiator_ip(struct iscsi_conn *conn,
|
||||
&((struct sockaddr_in6 *)&ss)->sin6_addr);
|
||||
#endif
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
pos = scnprintf(buf, size, "Unknown family %d",
|
||||
ss.ss_family);
|
||||
|
||||
+10
-10
@@ -1077,11 +1077,7 @@ int istrd(void *arg)
|
||||
PRINT_INFO("Read thread for pool %p started, PID %d", p, current->pid);
|
||||
|
||||
current->flags |= PF_NOFREEZE;
|
||||
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 <= 5
|
||||
rc = set_cpus_allowed(current, p->cpu_mask);
|
||||
#else
|
||||
rc = set_cpus_allowed_ptr(current, &p->cpu_mask);
|
||||
#endif
|
||||
if (rc != 0)
|
||||
PRINT_ERROR("Setting CPU affinity failed: %d", rc);
|
||||
|
||||
@@ -1400,16 +1396,24 @@ retry:
|
||||
sg_size = size;
|
||||
|
||||
if (sg != write_cmnd->rsp_sg) {
|
||||
/*
|
||||
* Data scatterlist. It is assumed that only the first element
|
||||
* has a non-zero offset and that all elements except the
|
||||
* first and the last have a length that is equal to
|
||||
* PAGE_SIZE.
|
||||
*/
|
||||
offset = conn->write_offset + sg[0].offset;
|
||||
idx = offset >> PAGE_SHIFT;
|
||||
if (offset + sg[0].offset >= PAGE_SIZE)
|
||||
offset += sg[0].offset;
|
||||
offset &= ~PAGE_MASK;
|
||||
length = min(size, (int)PAGE_SIZE - offset);
|
||||
TRACE_WRITE("write_offset %d, sg_size %d, idx %d, offset %d, "
|
||||
"length %d", conn->write_offset, sg_size, idx, offset,
|
||||
length);
|
||||
} else {
|
||||
/*
|
||||
* Response scatterlist. No assumptions are made about the
|
||||
* offset nor about the length of scatterlist elements.
|
||||
*/
|
||||
idx = 0;
|
||||
offset = conn->write_offset;
|
||||
while (offset >= sg[idx].length) {
|
||||
@@ -1837,11 +1841,7 @@ int istwr(void *arg)
|
||||
PRINT_INFO("Write thread for pool %p started, PID %d", p, current->pid);
|
||||
|
||||
current->flags |= PF_NOFREEZE;
|
||||
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 <= 5
|
||||
rc = set_cpus_allowed(current, p->cpu_mask);
|
||||
#else
|
||||
rc = set_cpus_allowed_ptr(current, &p->cpu_mask);
|
||||
#endif
|
||||
if (rc != 0)
|
||||
PRINT_ERROR("Setting CPU affinity failed: %d", rc);
|
||||
|
||||
|
||||
@@ -0,0 +1,364 @@
|
||||
=== modified file 'drivers/block/drbd/drbd_receiver.c'
|
||||
--- old/drivers/block/drbd/drbd_receiver.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/drivers/block/drbd/drbd_receiver.c 2014-08-19 01:17:24 +0000
|
||||
@@ -132,7 +132,7 @@ static int page_chain_free(struct page *
|
||||
struct page *tmp;
|
||||
int i = 0;
|
||||
page_chain_for_each_safe(page, tmp) {
|
||||
- put_page(page);
|
||||
+ net_put_page(page);
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
|
||||
=== modified file 'include/linux/mm_types.h'
|
||||
--- old/include/linux/mm_types.h 2014-08-19 01:00:36 +0000
|
||||
+++ new/include/linux/mm_types.h 2014-08-19 01:17:24 +0000
|
||||
@@ -196,6 +196,17 @@ struct page {
|
||||
#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
|
||||
int _last_cpupid;
|
||||
#endif
|
||||
+
|
||||
+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
|
||||
+ /*
|
||||
+ * Used to implement support for notification on zero-copy TCP transfer
|
||||
+ * completion. It might look as not good to have this field here and
|
||||
+ * it's better to have it in struct sk_buff, but it would make the code
|
||||
+ * much more complicated and fragile, since all skb then would have to
|
||||
+ * contain only pages with the same value in this field.
|
||||
+ */
|
||||
+ void *net_priv;
|
||||
+#endif
|
||||
}
|
||||
/*
|
||||
* The struct page can be forced to be double word aligned so that atomic ops
|
||||
|
||||
=== modified file 'include/linux/net.h'
|
||||
--- old/include/linux/net.h 2014-08-19 01:00:36 +0000
|
||||
+++ new/include/linux/net.h 2014-08-19 01:17:24 +0000
|
||||
@@ -19,6 +19,7 @@
|
||||
#define _LINUX_NET_H
|
||||
|
||||
#include <linux/stringify.h>
|
||||
+#include <linux/mm.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/fcntl.h> /* For O_CLOEXEC and O_NONBLOCK */
|
||||
@@ -285,6 +286,45 @@ int kernel_sendpage(struct socket *sock,
|
||||
int kernel_sock_ioctl(struct socket *sock, int cmd, unsigned long arg);
|
||||
int kernel_sock_shutdown(struct socket *sock, enum sock_shutdown_cmd how);
|
||||
|
||||
+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
|
||||
+/* Support for notification on zero-copy TCP transfer completion */
|
||||
+typedef void (*net_get_page_callback_t)(struct page *page);
|
||||
+typedef void (*net_put_page_callback_t)(struct page *page);
|
||||
+
|
||||
+extern net_get_page_callback_t net_get_page_callback;
|
||||
+extern net_put_page_callback_t net_put_page_callback;
|
||||
+
|
||||
+extern int net_set_get_put_page_callbacks(
|
||||
+ net_get_page_callback_t get_callback,
|
||||
+ net_put_page_callback_t put_callback);
|
||||
+
|
||||
+/*
|
||||
+ * See comment for net_set_get_put_page_callbacks() why those functions
|
||||
+ * don't need any protection.
|
||||
+ */
|
||||
+static inline void net_get_page(struct page *page)
|
||||
+{
|
||||
+ if (page->net_priv != 0)
|
||||
+ net_get_page_callback(page);
|
||||
+ get_page(page);
|
||||
+}
|
||||
+static inline void net_put_page(struct page *page)
|
||||
+{
|
||||
+ if (page->net_priv != 0)
|
||||
+ net_put_page_callback(page);
|
||||
+ put_page(page);
|
||||
+}
|
||||
+#else
|
||||
+static inline void net_get_page(struct page *page)
|
||||
+{
|
||||
+ get_page(page);
|
||||
+}
|
||||
+static inline void net_put_page(struct page *page)
|
||||
+{
|
||||
+ put_page(page);
|
||||
+}
|
||||
+#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */
|
||||
+
|
||||
#define MODULE_ALIAS_NETPROTO(proto) \
|
||||
MODULE_ALIAS("net-pf-" __stringify(proto))
|
||||
|
||||
|
||||
=== modified file 'include/linux/skbuff.h'
|
||||
--- old/include/linux/skbuff.h 2014-08-19 01:00:36 +0000
|
||||
+++ new/include/linux/skbuff.h 2014-08-19 01:17:24 +0000
|
||||
@@ -2139,7 +2139,7 @@ static inline struct page *skb_frag_page
|
||||
*/
|
||||
static inline void __skb_frag_ref(skb_frag_t *frag)
|
||||
{
|
||||
- get_page(skb_frag_page(frag));
|
||||
+ net_get_page(skb_frag_page(frag));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2162,7 +2162,7 @@ static inline void skb_frag_ref(struct s
|
||||
*/
|
||||
static inline void __skb_frag_unref(skb_frag_t *frag)
|
||||
{
|
||||
- put_page(skb_frag_page(frag));
|
||||
+ net_put_page(skb_frag_page(frag));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
=== modified file 'net/Kconfig'
|
||||
--- old/net/Kconfig 2014-08-19 01:00:36 +0000
|
||||
+++ new/net/Kconfig 2014-08-19 01:17:24 +0000
|
||||
@@ -75,6 +75,18 @@ config INET
|
||||
|
||||
Short answer: say Y.
|
||||
|
||||
+config TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION
|
||||
+ bool "TCP/IP zero-copy transfer completion notification"
|
||||
+ depends on INET
|
||||
+ default SCST_ISCSI
|
||||
+ ---help---
|
||||
+ Adds support for sending a notification upon completion of a
|
||||
+ zero-copy TCP/IP transfer. This can speed up certain TCP/IP
|
||||
+ software. Currently this is only used by the iSCSI target driver
|
||||
+ iSCSI-SCST.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
if INET
|
||||
source "net/ipv4/Kconfig"
|
||||
source "net/ipv6/Kconfig"
|
||||
|
||||
=== modified file 'net/ceph/pagevec.c'
|
||||
--- old/net/ceph/pagevec.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/net/ceph/pagevec.c 2014-08-19 01:17:24 +0000
|
||||
@@ -51,7 +51,7 @@ void ceph_put_page_vector(struct page **
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
if (dirty)
|
||||
set_page_dirty_lock(pages[i]);
|
||||
- put_page(pages[i]);
|
||||
+ net_put_page(pages[i]);
|
||||
}
|
||||
if (is_vmalloc_addr(pages))
|
||||
vfree(pages);
|
||||
|
||||
=== modified file 'net/core/skbuff.c'
|
||||
--- old/net/core/skbuff.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/net/core/skbuff.c 2014-08-19 01:17:24 +0000
|
||||
@@ -425,7 +425,7 @@ struct sk_buff *__netdev_alloc_skb(struc
|
||||
if (likely(data)) {
|
||||
skb = build_skb(data, fragsz);
|
||||
if (unlikely(!skb))
|
||||
- put_page(virt_to_head_page(data));
|
||||
+ net_put_page(virt_to_head_page(data));
|
||||
}
|
||||
} else {
|
||||
skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask,
|
||||
@@ -483,7 +483,7 @@ static void skb_clone_fraglist(struct sk
|
||||
static void skb_free_head(struct sk_buff *skb)
|
||||
{
|
||||
if (skb->head_frag)
|
||||
- put_page(virt_to_head_page(skb->head));
|
||||
+ net_put_page(virt_to_head_page(skb->head));
|
||||
else
|
||||
kfree(skb->head);
|
||||
}
|
||||
@@ -807,7 +807,7 @@ int skb_copy_ubufs(struct sk_buff *skb,
|
||||
if (!page) {
|
||||
while (head) {
|
||||
struct page *next = (struct page *)page_private(head);
|
||||
- put_page(head);
|
||||
+ net_put_page(head);
|
||||
head = next;
|
||||
}
|
||||
return -ENOMEM;
|
||||
@@ -1654,7 +1654,7 @@ EXPORT_SYMBOL(skb_copy_bits);
|
||||
*/
|
||||
static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
|
||||
{
|
||||
- put_page(spd->pages[i]);
|
||||
+ net_put_page(spd->pages[i]);
|
||||
}
|
||||
|
||||
static struct page *linear_to_page(struct page *page, unsigned int *len,
|
||||
@@ -1707,7 +1707,7 @@ static bool spd_fill_page(struct splice_
|
||||
spd->partial[spd->nr_pages - 1].len += *len;
|
||||
return false;
|
||||
}
|
||||
- get_page(page);
|
||||
+ net_get_page(page);
|
||||
spd->pages[spd->nr_pages] = page;
|
||||
spd->partial[spd->nr_pages].len = *len;
|
||||
spd->partial[spd->nr_pages].offset = offset;
|
||||
@@ -2166,7 +2166,7 @@ skb_zerocopy(struct sk_buff *to, struct
|
||||
page = virt_to_head_page(from->head);
|
||||
offset = from->data - (unsigned char *)page_address(page);
|
||||
__skb_fill_page_desc(to, 0, page, offset, plen);
|
||||
- get_page(page);
|
||||
+ net_get_page(page);
|
||||
j = 1;
|
||||
len -= plen;
|
||||
}
|
||||
@@ -2820,7 +2820,7 @@ int skb_append_datato_frags(struct sock
|
||||
copy);
|
||||
frg_cnt++;
|
||||
pfrag->offset += copy;
|
||||
- get_page(pfrag->page);
|
||||
+ net_get_page(pfrag->page);
|
||||
|
||||
skb->truesize += copy;
|
||||
atomic_add(copy, &sk->sk_wmem_alloc);
|
||||
|
||||
=== modified file 'net/core/sock.c'
|
||||
--- old/net/core/sock.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/net/core/sock.c 2014-08-19 01:17:24 +0000
|
||||
@@ -1888,7 +1888,7 @@ bool skb_page_frag_refill(unsigned int s
|
||||
}
|
||||
if (pfrag->offset + sz <= pfrag->size)
|
||||
return true;
|
||||
- put_page(pfrag->page);
|
||||
+ net_put_page(pfrag->page);
|
||||
}
|
||||
|
||||
order = SKB_FRAG_PAGE_ORDER;
|
||||
@@ -2651,7 +2651,7 @@ void sk_common_release(struct sock *sk)
|
||||
sk_refcnt_debug_release(sk);
|
||||
|
||||
if (sk->sk_frag.page) {
|
||||
- put_page(sk->sk_frag.page);
|
||||
+ net_put_page(sk->sk_frag.page);
|
||||
sk->sk_frag.page = NULL;
|
||||
}
|
||||
|
||||
|
||||
=== modified file 'net/ipv4/Makefile'
|
||||
--- old/net/ipv4/Makefile 2014-08-19 01:00:36 +0000
|
||||
+++ new/net/ipv4/Makefile 2014-08-19 01:17:24 +0000
|
||||
@@ -53,6 +53,7 @@ obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.
|
||||
obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
|
||||
obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o
|
||||
obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
|
||||
+obj-$(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) += tcp_zero_copy.o
|
||||
|
||||
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
|
||||
xfrm4_output.o xfrm4_protocol.o
|
||||
|
||||
=== modified file 'net/ipv4/ip_output.c'
|
||||
--- old/net/ipv4/ip_output.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/net/ipv4/ip_output.c 2014-08-19 01:17:24 +0000
|
||||
@@ -1046,7 +1046,7 @@ alloc_new_skb:
|
||||
__skb_fill_page_desc(skb, i, pfrag->page,
|
||||
pfrag->offset, 0);
|
||||
skb_shinfo(skb)->nr_frags = ++i;
|
||||
- get_page(pfrag->page);
|
||||
+ net_get_page(pfrag->page);
|
||||
}
|
||||
copy = min_t(int, copy, pfrag->size - pfrag->offset);
|
||||
if (getfrag(from,
|
||||
@@ -1271,7 +1271,7 @@ ssize_t ip_append_page(struct sock *sk,
|
||||
if (skb_can_coalesce(skb, i, page, offset)) {
|
||||
skb_frag_size_add(&skb_shinfo(skb)->frags[i-1], len);
|
||||
} else if (i < MAX_SKB_FRAGS) {
|
||||
- get_page(page);
|
||||
+ net_get_page(page);
|
||||
skb_fill_page_desc(skb, i, page, offset, len);
|
||||
} else {
|
||||
err = -EMSGSIZE;
|
||||
|
||||
=== modified file 'net/ipv4/tcp.c'
|
||||
--- old/net/ipv4/tcp.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/net/ipv4/tcp.c 2014-08-19 01:17:24 +0000
|
||||
@@ -939,7 +939,7 @@ new_segment:
|
||||
if (can_coalesce) {
|
||||
skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
|
||||
} else {
|
||||
- get_page(page);
|
||||
+ net_get_page(page);
|
||||
skb_fill_page_desc(skb, i, page, offset, copy);
|
||||
}
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
|
||||
@@ -1238,7 +1238,7 @@ new_segment:
|
||||
} else {
|
||||
skb_fill_page_desc(skb, i, pfrag->page,
|
||||
pfrag->offset, copy);
|
||||
- get_page(pfrag->page);
|
||||
+ net_get_page(pfrag->page);
|
||||
}
|
||||
pfrag->offset += copy;
|
||||
}
|
||||
|
||||
=== added file 'net/ipv4/tcp_zero_copy.c'
|
||||
--- old/net/ipv4/tcp_zero_copy.c 1970-01-01 00:00:00 +0000
|
||||
+++ new/net/ipv4/tcp_zero_copy.c 2014-08-19 01:17:24 +0000
|
||||
@@ -0,0 +1,50 @@
|
||||
+/*
|
||||
+ * Support routines for TCP zero copy transmit
|
||||
+ *
|
||||
+ * Created by Vladislav Bolkhovitin
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * version 2 as published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/export.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+
|
||||
+net_get_page_callback_t net_get_page_callback __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(net_get_page_callback);
|
||||
+
|
||||
+net_put_page_callback_t net_put_page_callback __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(net_put_page_callback);
|
||||
+
|
||||
+/*
|
||||
+ * Caller of this function must ensure that at the moment when it's called
|
||||
+ * there are no pages in the system with net_priv field set to non-zero
|
||||
+ * value. Hence, this function, as well as net_get_page() and net_put_page(),
|
||||
+ * don't need any protection.
|
||||
+ */
|
||||
+int net_set_get_put_page_callbacks(
|
||||
+ net_get_page_callback_t get_callback,
|
||||
+ net_put_page_callback_t put_callback)
|
||||
+{
|
||||
+ int res = 0;
|
||||
+
|
||||
+ if ((net_get_page_callback != NULL) && (get_callback != NULL) &&
|
||||
+ (net_get_page_callback != get_callback)) {
|
||||
+ res = -EBUSY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((net_put_page_callback != NULL) && (put_callback != NULL) &&
|
||||
+ (net_put_page_callback != put_callback)) {
|
||||
+ res = -EBUSY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ net_get_page_callback = get_callback;
|
||||
+ net_put_page_callback = put_callback;
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(net_set_get_put_page_callbacks);
|
||||
|
||||
=== modified file 'net/ipv6/ip6_output.c'
|
||||
--- old/net/ipv6/ip6_output.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/net/ipv6/ip6_output.c 2014-08-19 01:17:24 +0000
|
||||
@@ -1475,7 +1475,7 @@ alloc_new_skb:
|
||||
__skb_fill_page_desc(skb, i, pfrag->page,
|
||||
pfrag->offset, 0);
|
||||
skb_shinfo(skb)->nr_frags = ++i;
|
||||
- get_page(pfrag->page);
|
||||
+ net_get_page(pfrag->page);
|
||||
}
|
||||
copy = min_t(int, copy, pfrag->size - pfrag->offset);
|
||||
if (getfrag(from,
|
||||
|
||||
@@ -0,0 +1,399 @@
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/block/drbd/drbd_receiver.c ./drivers/block/drbd/drbd_receiver.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/block/drbd/drbd_receiver.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./drivers/block/drbd/drbd_receiver.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -130,7 +130,7 @@ static int page_chain_free(struct page *
|
||||
struct page *tmp;
|
||||
int i = 0;
|
||||
page_chain_for_each_safe(page, tmp) {
|
||||
- put_page(page);
|
||||
+ net_put_page(page);
|
||||
++i;
|
||||
}
|
||||
return i;
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/net/macvtap.c ./drivers/net/macvtap.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/net/macvtap.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./drivers/net/macvtap.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -597,7 +597,7 @@ static int zerocopy_sg_from_iovec(struct
|
||||
int j;
|
||||
|
||||
for (j = 0; j < num_pages; j++)
|
||||
- put_page(page[i + j]);
|
||||
+ net_put_page(page[i + j]);
|
||||
return -EFAULT;
|
||||
}
|
||||
truesize = size * PAGE_SIZE;
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/net/tun.c ./drivers/net/tun.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/net/tun.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./drivers/net/tun.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -1015,7 +1015,7 @@ static int zerocopy_sg_from_iovec(struct
|
||||
int j;
|
||||
|
||||
for (j = 0; j < num_pages; j++)
|
||||
- put_page(page[i + j]);
|
||||
+ net_put_page(page[i + j]);
|
||||
return -EFAULT;
|
||||
}
|
||||
truesize = size * PAGE_SIZE;
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/net/vmxnet3/vmxnet3_drv.c ./drivers/net/vmxnet3/vmxnet3_drv.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/net/vmxnet3/vmxnet3_drv.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./drivers/net/vmxnet3/vmxnet3_drv.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -1360,7 +1360,7 @@ vmxnet3_rq_cleanup(struct vmxnet3_rx_que
|
||||
rq->buf_info[ring_idx][i].page) {
|
||||
pci_unmap_page(adapter->pdev, rxd->addr,
|
||||
rxd->len, PCI_DMA_FROMDEVICE);
|
||||
- put_page(rq->buf_info[ring_idx][i].page);
|
||||
+ net_put_page(rq->buf_info[ring_idx][i].page);
|
||||
rq->buf_info[ring_idx][i].page = NULL;
|
||||
}
|
||||
}
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/net/xen-netback/netback.c ./drivers/net/xen-netback/netback.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/drivers/net/xen-netback/netback.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./drivers/net/xen-netback/netback.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -1292,7 +1292,7 @@ static void xen_netbk_fill_frags(struct
|
||||
skb->truesize += txp->size;
|
||||
|
||||
/* Take an extra reference to offset xen_netbk_idx_release */
|
||||
- get_page(netbk->mmap_pages[pending_idx]);
|
||||
+ net_get_page(netbk->mmap_pages[pending_idx]);
|
||||
xen_netbk_idx_release(netbk, pending_idx, XEN_NETIF_RSP_OKAY);
|
||||
}
|
||||
}
|
||||
@@ -1774,7 +1774,7 @@ static void xen_netbk_idx_release(struct
|
||||
} while (!pending_tx_is_head(netbk, peek));
|
||||
|
||||
netbk->mmap_pages[pending_idx]->mapping = 0;
|
||||
- put_page(netbk->mmap_pages[pending_idx]);
|
||||
+ net_put_page(netbk->mmap_pages[pending_idx]);
|
||||
netbk->mmap_pages[pending_idx] = NULL;
|
||||
}
|
||||
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/mm_types.h ./include/linux/mm_types.h
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/mm_types.h 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./include/linux/mm_types.h 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -186,6 +186,17 @@ struct page {
|
||||
#ifdef LAST_CPUPID_NOT_IN_PAGE_FLAGS
|
||||
int _last_cpupid;
|
||||
#endif
|
||||
+
|
||||
+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
|
||||
+ /*
|
||||
+ * Used to implement support for notification on zero-copy TCP transfer
|
||||
+ * completion. It might look as not good to have this field here and
|
||||
+ * it's better to have it in struct sk_buff, but it would make the code
|
||||
+ * much more complicated and fragile, since all skb then would have to
|
||||
+ * contain only pages with the same value in this field.
|
||||
+ */
|
||||
+ void *net_priv;
|
||||
+#endif
|
||||
}
|
||||
/*
|
||||
* The struct page can be forced to be double word aligned so that atomic ops
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/net.h ./include/linux/net.h
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/net.h 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./include/linux/net.h 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -19,6 +19,7 @@
|
||||
#define _LINUX_NET_H
|
||||
|
||||
#include <linux/stringify.h>
|
||||
+#include <linux/mm.h>
|
||||
#include <linux/random.h>
|
||||
#include <linux/wait.h>
|
||||
#include <linux/fcntl.h> /* For O_CLOEXEC and O_NONBLOCK */
|
||||
@@ -278,6 +279,45 @@ extern int kernel_sock_ioctl(struct sock
|
||||
extern int kernel_sock_shutdown(struct socket *sock,
|
||||
enum sock_shutdown_cmd how);
|
||||
|
||||
+#if defined(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION)
|
||||
+/* Support for notification on zero-copy TCP transfer completion */
|
||||
+typedef void (*net_get_page_callback_t)(struct page *page);
|
||||
+typedef void (*net_put_page_callback_t)(struct page *page);
|
||||
+
|
||||
+extern net_get_page_callback_t net_get_page_callback;
|
||||
+extern net_put_page_callback_t net_put_page_callback;
|
||||
+
|
||||
+extern int net_set_get_put_page_callbacks(
|
||||
+ net_get_page_callback_t get_callback,
|
||||
+ net_put_page_callback_t put_callback);
|
||||
+
|
||||
+/*
|
||||
+ * See comment for net_set_get_put_page_callbacks() why those functions
|
||||
+ * don't need any protection.
|
||||
+ */
|
||||
+static inline void net_get_page(struct page *page)
|
||||
+{
|
||||
+ if (page->net_priv != 0)
|
||||
+ net_get_page_callback(page);
|
||||
+ get_page(page);
|
||||
+}
|
||||
+static inline void net_put_page(struct page *page)
|
||||
+{
|
||||
+ if (page->net_priv != 0)
|
||||
+ net_put_page_callback(page);
|
||||
+ put_page(page);
|
||||
+}
|
||||
+#else
|
||||
+static inline void net_get_page(struct page *page)
|
||||
+{
|
||||
+ get_page(page);
|
||||
+}
|
||||
+static inline void net_put_page(struct page *page)
|
||||
+{
|
||||
+ put_page(page);
|
||||
+}
|
||||
+#endif /* CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION */
|
||||
+
|
||||
#define MODULE_ALIAS_NETPROTO(proto) \
|
||||
MODULE_ALIAS("net-pf-" __stringify(proto))
|
||||
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/skbuff.h ./include/linux/skbuff.h
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/skbuff.h 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./include/linux/skbuff.h 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -2036,7 +2036,7 @@ static inline struct page *skb_frag_page
|
||||
*/
|
||||
static inline void __skb_frag_ref(skb_frag_t *frag)
|
||||
{
|
||||
- get_page(skb_frag_page(frag));
|
||||
+ net_get_page(skb_frag_page(frag));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2059,7 +2059,7 @@ static inline void skb_frag_ref(struct s
|
||||
*/
|
||||
static inline void __skb_frag_unref(skb_frag_t *frag)
|
||||
{
|
||||
- put_page(skb_frag_page(frag));
|
||||
+ net_put_page(skb_frag_page(frag));
|
||||
}
|
||||
|
||||
/**
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/Kconfig ./net/Kconfig
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/Kconfig 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./net/Kconfig 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -74,6 +74,18 @@ config INET
|
||||
|
||||
Short answer: say Y.
|
||||
|
||||
+config TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION
|
||||
+ bool "TCP/IP zero-copy transfer completion notification"
|
||||
+ depends on INET
|
||||
+ default SCST_ISCSI
|
||||
+ ---help---
|
||||
+ Adds support for sending a notification upon completion of a
|
||||
+ zero-copy TCP/IP transfer. This can speed up certain TCP/IP
|
||||
+ software. Currently this is only used by the iSCSI target driver
|
||||
+ iSCSI-SCST.
|
||||
+
|
||||
+ If unsure, say N.
|
||||
+
|
||||
if INET
|
||||
source "net/ipv4/Kconfig"
|
||||
source "net/ipv6/Kconfig"
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ceph/pagevec.c ./net/ceph/pagevec.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ceph/pagevec.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./net/ceph/pagevec.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -51,7 +51,7 @@ void ceph_put_page_vector(struct page **
|
||||
for (i = 0; i < num_pages; i++) {
|
||||
if (dirty)
|
||||
set_page_dirty_lock(pages[i]);
|
||||
- put_page(pages[i]);
|
||||
+ net_put_page(pages[i]);
|
||||
}
|
||||
kfree(pages);
|
||||
}
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/core/skbuff.c ./net/core/skbuff.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/core/skbuff.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./net/core/skbuff.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -453,7 +453,7 @@ struct sk_buff *__netdev_alloc_skb(struc
|
||||
if (likely(data)) {
|
||||
skb = build_skb(data, fragsz);
|
||||
if (unlikely(!skb))
|
||||
- put_page(virt_to_head_page(data));
|
||||
+ net_put_page(virt_to_head_page(data));
|
||||
}
|
||||
} else {
|
||||
skb = __alloc_skb(length + NET_SKB_PAD, gfp_mask,
|
||||
@@ -499,7 +499,7 @@ static void skb_clone_fraglist(struct sk
|
||||
static void skb_free_head(struct sk_buff *skb)
|
||||
{
|
||||
if (skb->head_frag)
|
||||
- put_page(virt_to_head_page(skb->head));
|
||||
+ net_put_page(virt_to_head_page(skb->head));
|
||||
else
|
||||
kfree(skb->head);
|
||||
}
|
||||
@@ -824,7 +824,7 @@ int skb_copy_ubufs(struct sk_buff *skb,
|
||||
if (!page) {
|
||||
while (head) {
|
||||
struct page *next = (struct page *)head->private;
|
||||
- put_page(head);
|
||||
+ net_put_page(head);
|
||||
head = next;
|
||||
}
|
||||
return -ENOMEM;
|
||||
@@ -1644,7 +1644,7 @@ EXPORT_SYMBOL(skb_copy_bits);
|
||||
*/
|
||||
static void sock_spd_release(struct splice_pipe_desc *spd, unsigned int i)
|
||||
{
|
||||
- put_page(spd->pages[i]);
|
||||
+ net_put_page(spd->pages[i]);
|
||||
}
|
||||
|
||||
static struct page *linear_to_page(struct page *page, unsigned int *len,
|
||||
@@ -1697,7 +1697,7 @@ static bool spd_fill_page(struct splice_
|
||||
spd->partial[spd->nr_pages - 1].len += *len;
|
||||
return false;
|
||||
}
|
||||
- get_page(page);
|
||||
+ net_get_page(page);
|
||||
spd->pages[spd->nr_pages] = page;
|
||||
spd->partial[spd->nr_pages].len = *len;
|
||||
spd->partial[spd->nr_pages].offset = offset;
|
||||
@@ -2794,7 +2794,7 @@ int skb_append_datato_frags(struct sock
|
||||
copy);
|
||||
frg_cnt++;
|
||||
pfrag->offset += copy;
|
||||
- get_page(pfrag->page);
|
||||
+ net_get_page(pfrag->page);
|
||||
|
||||
skb->truesize += copy;
|
||||
atomic_add(copy, &sk->sk_wmem_alloc);
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/core/sock.c ./net/core/sock.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/core/sock.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./net/core/sock.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -1829,7 +1829,7 @@ bool sk_page_frag_refill(struct sock *sk
|
||||
}
|
||||
if (pfrag->offset < pfrag->size)
|
||||
return true;
|
||||
- put_page(pfrag->page);
|
||||
+ net_put_page(pfrag->page);
|
||||
}
|
||||
|
||||
/* We restrict high order allocations to users that can afford to wait */
|
||||
@@ -2534,7 +2534,7 @@ void sk_common_release(struct sock *sk)
|
||||
sk_refcnt_debug_release(sk);
|
||||
|
||||
if (sk->sk_frag.page) {
|
||||
- put_page(sk->sk_frag.page);
|
||||
+ net_put_page(sk->sk_frag.page);
|
||||
sk->sk_frag.page = NULL;
|
||||
}
|
||||
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv4/Makefile ./net/ipv4/Makefile
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv4/Makefile 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./net/ipv4/Makefile 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -53,6 +53,7 @@ obj-$(CONFIG_TCP_CONG_YEAH) += tcp_yeah.
|
||||
obj-$(CONFIG_TCP_CONG_ILLINOIS) += tcp_illinois.o
|
||||
obj-$(CONFIG_MEMCG_KMEM) += tcp_memcontrol.o
|
||||
obj-$(CONFIG_NETLABEL) += cipso_ipv4.o
|
||||
+obj-$(CONFIG_TCP_ZERO_COPY_TRANSFER_COMPLETION_NOTIFICATION) += tcp_zero_copy.o
|
||||
|
||||
obj-$(CONFIG_XFRM) += xfrm4_policy.o xfrm4_state.o xfrm4_input.o \
|
||||
xfrm4_output.o
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv4/ip_output.c ./net/ipv4/ip_output.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv4/ip_output.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./net/ipv4/ip_output.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -1011,7 +1011,7 @@ alloc_new_skb:
|
||||
__skb_fill_page_desc(skb, i, pfrag->page,
|
||||
pfrag->offset, 0);
|
||||
skb_shinfo(skb)->nr_frags = ++i;
|
||||
- get_page(pfrag->page);
|
||||
+ net_get_page(pfrag->page);
|
||||
}
|
||||
copy = min_t(int, copy, pfrag->size - pfrag->offset);
|
||||
if (getfrag(from,
|
||||
@@ -1235,7 +1235,7 @@ ssize_t ip_append_page(struct sock *sk,
|
||||
if (skb_can_coalesce(skb, i, page, offset)) {
|
||||
skb_frag_size_add(&skb_shinfo(skb)->frags[i-1], len);
|
||||
} else if (i < MAX_SKB_FRAGS) {
|
||||
- get_page(page);
|
||||
+ net_get_page(page);
|
||||
skb_fill_page_desc(skb, i, page, offset, len);
|
||||
} else {
|
||||
err = -EMSGSIZE;
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv4/tcp.c ./net/ipv4/tcp.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv4/tcp.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./net/ipv4/tcp.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -898,7 +898,7 @@ new_segment:
|
||||
if (can_coalesce) {
|
||||
skb_frag_size_add(&skb_shinfo(skb)->frags[i - 1], copy);
|
||||
} else {
|
||||
- get_page(page);
|
||||
+ net_get_page(page);
|
||||
skb_fill_page_desc(skb, i, page, offset, copy);
|
||||
}
|
||||
skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
|
||||
@@ -1194,7 +1194,7 @@ new_segment:
|
||||
} else {
|
||||
skb_fill_page_desc(skb, i, pfrag->page,
|
||||
pfrag->offset, copy);
|
||||
- get_page(pfrag->page);
|
||||
+ net_get_page(pfrag->page);
|
||||
}
|
||||
pfrag->offset += copy;
|
||||
}
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv4/tcp_zero_copy.c ./net/ipv4/tcp_zero_copy.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv4/tcp_zero_copy.c 1970-01-01 01:00:00.000000000 +0100
|
||||
+++ ./net/ipv4/tcp_zero_copy.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -0,0 +1,50 @@
|
||||
+/*
|
||||
+ * Support routines for TCP zero copy transmit
|
||||
+ *
|
||||
+ * Created by Vladislav Bolkhovitin
|
||||
+ *
|
||||
+ * This program is free software; you can redistribute it and/or
|
||||
+ * modify it under the terms of the GNU General Public License
|
||||
+ * version 2 as published by the Free Software Foundation.
|
||||
+ */
|
||||
+
|
||||
+#include <linux/export.h>
|
||||
+#include <linux/skbuff.h>
|
||||
+
|
||||
+net_get_page_callback_t net_get_page_callback __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(net_get_page_callback);
|
||||
+
|
||||
+net_put_page_callback_t net_put_page_callback __read_mostly;
|
||||
+EXPORT_SYMBOL_GPL(net_put_page_callback);
|
||||
+
|
||||
+/*
|
||||
+ * Caller of this function must ensure that at the moment when it's called
|
||||
+ * there are no pages in the system with net_priv field set to non-zero
|
||||
+ * value. Hence, this function, as well as net_get_page() and net_put_page(),
|
||||
+ * don't need any protection.
|
||||
+ */
|
||||
+int net_set_get_put_page_callbacks(
|
||||
+ net_get_page_callback_t get_callback,
|
||||
+ net_put_page_callback_t put_callback)
|
||||
+{
|
||||
+ int res = 0;
|
||||
+
|
||||
+ if ((net_get_page_callback != NULL) && (get_callback != NULL) &&
|
||||
+ (net_get_page_callback != get_callback)) {
|
||||
+ res = -EBUSY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ if ((net_put_page_callback != NULL) && (put_callback != NULL) &&
|
||||
+ (net_put_page_callback != put_callback)) {
|
||||
+ res = -EBUSY;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ net_get_page_callback = get_callback;
|
||||
+ net_put_page_callback = put_callback;
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL_GPL(net_set_get_put_page_callbacks);
|
||||
diff -Nrup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv6/ip6_output.c ./net/ipv6/ip6_output.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/net/ipv6/ip6_output.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./net/ipv6/ip6_output.c 2014-08-07 09:14:18.606676153 +0200
|
||||
@@ -1421,7 +1421,7 @@ alloc_new_skb:
|
||||
__skb_fill_page_desc(skb, i, pfrag->page,
|
||||
pfrag->offset, 0);
|
||||
skb_shinfo(skb)->nr_frags = ++i;
|
||||
- get_page(pfrag->page);
|
||||
+ net_get_page(pfrag->page);
|
||||
}
|
||||
copy = min_t(int, copy, pfrag->size - pfrag->offset);
|
||||
if (getfrag(from,
|
||||
@@ -466,7 +466,7 @@ static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
|
||||
} \
|
||||
\
|
||||
static struct kobj_attribute iscsi_sess_attr_##name = \
|
||||
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
|
||||
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL)
|
||||
|
||||
#define ISCSI_SESS_INT_PARAM_ATTR(name, exported_name) \
|
||||
static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
|
||||
@@ -485,7 +485,7 @@ static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
|
||||
} \
|
||||
\
|
||||
static struct kobj_attribute iscsi_sess_attr_##name = \
|
||||
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
|
||||
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL)
|
||||
|
||||
#define ISCSI_SESS_DIGEST_PARAM_ATTR(name, exported_name) \
|
||||
static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
|
||||
@@ -506,7 +506,7 @@ static ssize_t iscsi_sess_show_##name(struct kobject *kobj, \
|
||||
} \
|
||||
\
|
||||
static struct kobj_attribute iscsi_sess_attr_##name = \
|
||||
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL);
|
||||
__ATTR(exported_name, S_IRUGO, iscsi_sess_show_##name, NULL)
|
||||
|
||||
ISCSI_SESS_BOOL_PARAM_ATTR(initial_r2t, InitialR2T);
|
||||
ISCSI_SESS_BOOL_PARAM_ATTR(immediate_data, ImmediateData);
|
||||
|
||||
@@ -3,20 +3,21 @@
|
||||
ABT_DETAILS="x86_64"
|
||||
ABT_JOBS=5
|
||||
ABT_KERNELS=" \
|
||||
3.15.3 \
|
||||
3.14.10-nc \
|
||||
3.16.1 \
|
||||
3.15.10-nc \
|
||||
3.14.17-nc \
|
||||
3.13.11-nc \
|
||||
3.12.21-nc \
|
||||
3.11.10-nc \
|
||||
3.10.46-nc \
|
||||
3.10.53-nc \
|
||||
3.9.11-nc \
|
||||
3.8.13-nc \
|
||||
3.7.10-nc \
|
||||
3.6.11-nc \
|
||||
3.5.7-nc \
|
||||
3.4.96-nc \
|
||||
3.4.103-nc \
|
||||
3.3.8-nc \
|
||||
3.2.59-nc \
|
||||
3.2.61-nc \
|
||||
3.1.10-nc \
|
||||
3.0.101-nc \
|
||||
2.6.39.4-nc \
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
ccflags-y += -Idrivers/scsi/qla2xxx
|
||||
|
||||
qla2x00tgt-y := qla2x00t.o
|
||||
|
||||
obj-$(CONFIG_SCST_QLA_TGT_ADDON) += qla2x00tgt.o
|
||||
@@ -78,9 +78,13 @@
|
||||
#define Q2T_STATE_PROCESSED 3 /* SCST done processing */
|
||||
#define Q2T_STATE_ABORTED 4 /* Command aborted */
|
||||
|
||||
/* Special handles */
|
||||
/*
|
||||
* Special handles.
|
||||
* !! Changing them here, make sure that mask in the beginning of
|
||||
* !! q2t_ctio_to_cmd() changed accordingly!
|
||||
*/
|
||||
#define Q2T_NULL_HANDLE 0
|
||||
#define Q2T_SKIP_HANDLE (0xFFFFFFFF & ~CTIO_COMPLETION_HANDLE_MARK)
|
||||
#define Q2T_SKIP_HANDLE (0xFFFFFFFF & ~(CTIO_COMPLETION_HANDLE_MARK|CTIO_INTERMEDIATE_HANDLE_MARK))
|
||||
|
||||
/* ATIO task_codes field */
|
||||
#define ATIO_SIMPLE_QUEUE 0
|
||||
|
||||
@@ -373,18 +373,32 @@ rm -rf "${tmpdir}"
|
||||
|
||||
for s in ${separate_patches}
|
||||
do
|
||||
fileset=$s
|
||||
for f in $(set | grep "^$s=" | sed -e "s/^$s='\(.*\)'\$/\1/" -e "s/^$s=\(.*\)\$/\1/")
|
||||
do
|
||||
if [ "${f#scst/include}" != "${f}" ]; then
|
||||
add_file "${f}" "include/scst/${f#scst/include/}"
|
||||
elif [ "${f#doc}" != "${f}" ]; then
|
||||
add_file "${f}" "Documentation/scst/${f#doc/}"
|
||||
else
|
||||
add_file "${f}" "drivers/scst/${f#scst/src/}"
|
||||
{
|
||||
fileset=$s
|
||||
for f in $(set | grep "^$s=" | sed -e "s/^$s='\(.*\)'\$/\1/" -e "s/^$s=\(.*\)\$/\1/")
|
||||
do
|
||||
if [ "${f#scst/include}" != "${f}" ]; then
|
||||
add_file "${f}" "include/scst/${f#scst/include/}"
|
||||
elif [ "${f#doc}" != "${f}" ]; then
|
||||
add_file "${f}" "Documentation/scst/${f#doc/}"
|
||||
else
|
||||
add_file "${f}" "drivers/scst/${f#scst/src/}"
|
||||
fi
|
||||
done
|
||||
if [ "$s" = "scst_03_public_headers" ]; then
|
||||
tmp_itf_ver="$(mktemp /tmp/scst-itf-ver.h.XXXXXXXXXX)"
|
||||
cat <<"EOF" >$tmp_itf_ver
|
||||
/* Autogenerated, don't edit */
|
||||
|
||||
#define SCST_INTF_VER "SCST_INTF_VER"
|
||||
#define SCST_CONST_INTF_VER "SCST_CONST_INTF_VER"
|
||||
#define DEV_USER_INTF_VER "DEV_USER_INTF_VER"
|
||||
EOF
|
||||
add_file "$tmp_itf_ver" "include/scst/scst_itf_ver.h"
|
||||
rm -f "$tmp_itf_ver"
|
||||
fi
|
||||
done \
|
||||
| process_patch "${s}.diff"
|
||||
} |
|
||||
process_patch "${s}.diff"
|
||||
done
|
||||
|
||||
{
|
||||
|
||||
@@ -36,63 +36,50 @@
|
||||
#
|
||||
############################################################################
|
||||
|
||||
scst_dir="$(dirname "$(dirname "$0")")"
|
||||
if [ ${scst_dir:0:1} != "/" ]; then
|
||||
scst_dir="$PWD/${scst_dir}"
|
||||
scriptdir="$(dirname "$0")"
|
||||
if [ "${scriptdir:0:1}" != "/" ]; then
|
||||
scriptdir="$PWD/${scriptdir}"
|
||||
fi
|
||||
source "${scriptdir}/rhel-rpm-functions"
|
||||
scst_dir="$(dirname "$scriptdir")"
|
||||
downloaddir=$HOME/software/downloads
|
||||
rpmbuild_dir=$HOME/rpmbuild
|
||||
if [ "$1" = "" ]; then
|
||||
if echo "$(uname -r)" | grep -q uek; then
|
||||
|
||||
if echo "$(uname -r)" | grep -q uek; then
|
||||
kernel="kernel-uek-$(uname -r)"
|
||||
else
|
||||
kernel="kernel-$(uname -r)"
|
||||
fi
|
||||
else
|
||||
kernel="$1"
|
||||
kernel="kernel-$(uname -r)"
|
||||
fi
|
||||
|
||||
releasever="$(sed -n -e 's/^.* release \([0-9.]*\).*$/\1/p' /etc/redhat-release)"
|
||||
distro="$(sed -n -e 's/^\(.*\) release .*$/\1/p' /etc/redhat-release)"
|
||||
|
||||
install_prerequisites=true
|
||||
|
||||
usage() {
|
||||
echo "$(basename "$0") [-d <distro>] [-h] [-i] [-k <kver>] [-r <rel>]"
|
||||
}
|
||||
|
||||
type /usr/bin/getopt >/dev/null || exit 1
|
||||
options="$(/usr/bin/getopt d:hik:r: "$@")" || { usage; exit 1; }
|
||||
set -- $options
|
||||
while [ "$1" != "${1#-}" ]; do
|
||||
case "$1" in
|
||||
'-d') distro="$2"; shift; shift;;
|
||||
'-i') install_prerequisites="false"; shift;;
|
||||
'-k') kernel="$2"; shift; shift;;
|
||||
'-r') releasever="$2"; shift; shift;;
|
||||
'--') shift; break;;
|
||||
*) usage; exit 1;;
|
||||
esac
|
||||
done
|
||||
|
||||
arch="$(uname -m)"
|
||||
kernel="${kernel%.${arch}}"
|
||||
kernel_src_rpm="${kernel}.src.rpm"
|
||||
kver="${kernel#kernel-}"
|
||||
distro="$(sed -n -e 's/^\(.*\) release .*$/\1/p' /etc/issue)"
|
||||
if [ -n "$2" ]; then
|
||||
releasever="$2"
|
||||
else
|
||||
releasever="$(sed -n -e 's/^.* release \([0-9.]*\).*$/\1/p' /etc/issue)"
|
||||
fi
|
||||
releasevermajor="$(echo $releasever | cut -f1 -d.)"
|
||||
releaseverminor="$(echo $releasever | cut -f2 -d.)"
|
||||
case "$distro" in
|
||||
"CentOS"*)
|
||||
case $releasever in
|
||||
5.*|6.[01])
|
||||
srpm_url=("http://vault.centos.org/${releasever}/os/SRPMS" "http://vault.centos.org/${releasever}/updates/SRPMS");;
|
||||
*)
|
||||
srpm_url=("http://vault.centos.org/${releasever}/os/Source/SPackages" "http://vault.centos.org/${releasever}/updates/Source/SPackages");;
|
||||
esac
|
||||
;;
|
||||
"Red Hat Enterprise Linux"*)
|
||||
srpm_url=("http://ftp.redhat.com/pub/redhat/linux/enterprise/${releasevermajor}Server/en/os/SRPMS")
|
||||
;;
|
||||
"Oracle Linux Server")
|
||||
srpm_url=("http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/${releaseverminor}/base/x86_64/getPackageSource" "http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/latest/x86_64/getPackageSource" "http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/UEK/latest/x86_64/getPackageSource")
|
||||
;;
|
||||
"Scientific Linux")
|
||||
if [ "$releasevermajor" = 6 ]; then
|
||||
srpm_url=("http://ftp.scientificlinux.org/linux/scientific/$releasever/SRPMS/vendor")
|
||||
else
|
||||
srpm_url=("http://ftp.scientificlinux.org/linux/scientific/$releasevermajor$releaseverminor/SRPMS/vendor")
|
||||
fi
|
||||
;;
|
||||
"Fedora")
|
||||
srpm_url="http://ftp.redhat.com/redhat/rhel/rc/7/Server/source/tree/Packages"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown type of distribution: $distro"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
srpm_urls="$(get_srpm_urls "$distro" "$releasever" "$arch")" || exit $?
|
||||
|
||||
function log {
|
||||
echo
|
||||
@@ -100,6 +87,25 @@ function log {
|
||||
echo
|
||||
}
|
||||
|
||||
copy_best_matching_patch() {
|
||||
local f v
|
||||
|
||||
v="${kver}"
|
||||
while [ "${v%[0-9a-z]}" != "$v" ]; do
|
||||
f="${1}-${v}.patch"
|
||||
if [ -e "$f" ]; then
|
||||
copy_patch "$f" "$2"
|
||||
return 0
|
||||
fi
|
||||
while [ "${v%[0-9a-z]}" != "$v" ]; do
|
||||
v="${v%[0-9a-z]}"
|
||||
done
|
||||
v="${v%.}"
|
||||
v="${v%-}"
|
||||
done
|
||||
return 1
|
||||
}
|
||||
|
||||
function copy_patch {
|
||||
local p="$1"
|
||||
while [ ! -e "$p" ]
|
||||
@@ -137,7 +143,33 @@ fi
|
||||
|
||||
log "Installing prerequisites"
|
||||
|
||||
sudo yum install -y -q asciidoc binutils-devel elfutils-libelf-devel hmaccalc ncurses-devel newt-devel patchutils 'perl(ExtUtils::Embed)' python-devel redhat-rpm-config rpmdevtools rng-tools rpm-build unifdef xmlto yum-utils zlib-devel
|
||||
if $install_prerequisites; then
|
||||
for p in \
|
||||
asciidoc \
|
||||
audit-libs-devel \
|
||||
binutils-devel \
|
||||
elfutils-devel \
|
||||
elfutils-libelf-devel \
|
||||
hmaccalc \
|
||||
ncurses-devel \
|
||||
newt-devel \
|
||||
patchutils \
|
||||
numactl-devel \
|
||||
pciutils-devel \
|
||||
'perl(ExtUtils::Embed)' \
|
||||
pesign \
|
||||
python-devel \
|
||||
redhat-rpm-config \
|
||||
rng-tools \
|
||||
rpm-build \
|
||||
rpmdevtools \
|
||||
unifdef \
|
||||
wget \
|
||||
xmlto \
|
||||
yum-utils \
|
||||
zlib-devel \
|
||||
; do sudo yum install -y -q "$p"; done
|
||||
fi
|
||||
|
||||
rc=$?; if [ $rc != 0 ]; then exit $rc; fi
|
||||
|
||||
@@ -150,7 +182,7 @@ log "Installing, unpacking and preparing kernel source files"
|
||||
mkdir -p ${downloaddir}
|
||||
if [ ! -e ${downloaddir}/${kernel_src_rpm} ]; then
|
||||
cd ${downloaddir}
|
||||
for dir in ${srpm_url[@]}
|
||||
for dir in ${srpm_urls}
|
||||
do
|
||||
url="$dir/${kernel_src_rpm}"
|
||||
echo "Trying $url ..."
|
||||
@@ -166,7 +198,9 @@ fi
|
||||
|
||||
log "Installing kernel build prerequisites"
|
||||
|
||||
sudo yum-builddep -q -y ${downloaddir}/${kernel_src_rpm}
|
||||
if $install_prerequisites; then
|
||||
sudo yum-builddep -q -y ${downloaddir}/${kernel_src_rpm}
|
||||
fi
|
||||
|
||||
log "Installing kernel sources in ${rpmbuild_dir}"
|
||||
|
||||
@@ -185,11 +219,16 @@ cd SPECS
|
||||
log "Copying SCST patches to the SOURCES directory"
|
||||
|
||||
cd ${rpmbuild_dir}/SOURCES
|
||||
copy_patch $scst_dir/scst/kernel/rhel/scst_exec_req_fifo-${kver}.patch scst_exec_req_fifo.patch
|
||||
f="$scst_dir/iscsi-scst/kernel/patches/rhel/put_page_callback-${kver}.patch"
|
||||
if [ -e "$f" ]; then
|
||||
copy_patch "$f" put_page_callback.patch
|
||||
fi
|
||||
copy_best_matching_patch $scst_dir/scst/kernel/rhel/scst_exec_req_fifo scst_exec_req_fifo.patch ||
|
||||
{
|
||||
echo "No matching scst_exec_req_fifo patch found for kernel version $kver";
|
||||
exit 1;
|
||||
}
|
||||
copy_best_matching_patch $scst_dir/iscsi-scst/kernel/patches/rhel/put_page_callback put_page_callback.patch ||
|
||||
{
|
||||
echo "No matching scst_exec_req_fifo patch found for kernel version $kver";
|
||||
exit 1;
|
||||
}
|
||||
|
||||
log "Adding SCST patches in kernel.spec"
|
||||
|
||||
@@ -325,7 +364,7 @@ diff -u SPECS/kernel.spec{.orig,}
|
||||
make ARCH=$Arch %{oldconfig_target} > /dev/null
|
||||
echo "# $Arch" > configs/$i
|
||||
EOF
|
||||
elif [ ${kver#3.10.0-121} != $kver ]; then
|
||||
elif [ ${kver#3.10.0-12[13]} != $kver ]; then
|
||||
# RHEL/CentOS/SL 7.0
|
||||
patch -p1 ${rpmbuild_dir}/SPECS/kernel.spec <<'EOF' || exit $?
|
||||
--- kernel.spec.orig 2014-05-23 10:09:17.707202148 +0200
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
# -*- mode: shell-script -*-
|
||||
# Shell functions for downloading and extracting a RHEL or RHEL clone RPM
|
||||
|
||||
# Arguments:
|
||||
# $1: Linux distribution name
|
||||
# $2: Linux distribution version (major.minor)
|
||||
# $3: architecture
|
||||
function get_srpm_urls() {
|
||||
local arch distro releasever releasevermajor releaseverminor
|
||||
|
||||
distro="$1"
|
||||
releasever="$2"
|
||||
arch="$3"
|
||||
IFS=.
|
||||
set -- "$2"
|
||||
unset IFS
|
||||
releasevermajor="$1"
|
||||
releaseverminor="$2"
|
||||
|
||||
case "$distro" in
|
||||
"CentOS"*)
|
||||
case $releasever in
|
||||
5.*|6.[01])
|
||||
echo "http://vault.centos.org/${releasever}/os/SRPMS http://vault.centos.org/${releasever}/updates/SRPMS";;
|
||||
[67].*)
|
||||
echo "http://vault.centos.org/${releasever}/os/Source/SPackages http://vault.centos.org/${releasever}/updates/Source/SPackages";;
|
||||
esac
|
||||
;;
|
||||
"Red Hat Enterprise Linux"*)
|
||||
case $releasever in
|
||||
[56].*)
|
||||
echo "http://ftp.redhat.com/pub/redhat/linux/enterprise/${releasevermajor}Server/en/os/SRPMS http://ftp.redhat.com/redhat/rhel/rc/7/Server/source/tree/Packages";;
|
||||
esac
|
||||
;;
|
||||
"Oracle Linux Server")
|
||||
echo "http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/${releaseverminor}/base/${arch}/getPackageSource http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/latest/${arch}/getPackageSource http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/UEK/latest/${arch}/getPackageSource"
|
||||
;;
|
||||
"Scientific Linux")
|
||||
case $releasever in
|
||||
5.*)
|
||||
echo "http://ftp.scientificlinux.org/linux/scientific/$releasevermajor$releaseverminor/SRPMS/vendor";;
|
||||
6.*)
|
||||
echo "http://ftp.scientificlinux.org/linux/scientific/$releasever/SRPMS/vendor";;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Unknown type of distribution: $distro" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
|
||||
# Arguments:
|
||||
# $1: Linux distribution name
|
||||
# $2: Linux distribution version (major.minor)
|
||||
# $3: architecture
|
||||
function get_rpm_urls() {
|
||||
local arch distro releasever releasevermajor releaseverminor
|
||||
|
||||
distro="$1"
|
||||
releasever="$2"
|
||||
arch="$3"
|
||||
IFS=.
|
||||
set -- "$2"
|
||||
unset IFS
|
||||
releasevermajor="$1"
|
||||
releaseverminor="$2"
|
||||
|
||||
case "$distro" in
|
||||
"CentOS"*)
|
||||
case $releasever in
|
||||
5.*)
|
||||
echo "http://vault.centos.org/${releasever}/os/${arch}/CentOS http://vault.centos.org/${releasever}/updates/${arch}/RPMS";;
|
||||
6.[01])
|
||||
echo "http://vault.centos.org/${releasever}/os/${arch}/Packages http://vault.centos.org/${releasever}/updates/${arch}/Packages";;
|
||||
[67].*)
|
||||
echo "http://vault.centos.org/${releasever}/os/${arch}/Packages http://vault.centos.org/${releasever}/updates/${arch}/Packages";;
|
||||
esac
|
||||
;;
|
||||
"Red Hat Enterprise Linux"*)
|
||||
echo "";;
|
||||
"Oracle Linux Server")
|
||||
echo "http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/${releaseverminor}/base/${arch}/getPackageSource http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/latest/${arch}/getPackageSource http://public-yum.oracle.com/repo/OracleLinux/OL${releasevermajor}/UEK/latest/${arch}/getPackageSource"
|
||||
;;
|
||||
"Scientific Linux")
|
||||
case $releasever in
|
||||
5.*)
|
||||
echo "http://ftp.scientificlinux.org/linux/scientific/$releasevermajor$releaseverminor/SRPMS/vendor";;
|
||||
6.*)
|
||||
echo "http://ftp.scientificlinux.org/linux/scientific/$releasever/SRPMS/vendor";;
|
||||
esac
|
||||
;;
|
||||
*)
|
||||
echo "Unknown distribution type: $distro" >&2
|
||||
return 1
|
||||
;;
|
||||
esac
|
||||
}
|
||||
+3
-1
@@ -122,7 +122,8 @@ find /lib/modules/%{kver} -name ib_srpt.ko -exec rm {} \;
|
||||
%{_mandir}/man8/iscsi-scstd.8.gz
|
||||
%{_sbindir}/iscsi-scst-adm
|
||||
%{_sbindir}/iscsi-scstd
|
||||
%dir /var/lib/scst
|
||||
%dir /var/lib/scst/pr
|
||||
%dir /var/lib/scst/vdev_mode_pages
|
||||
|
||||
%files devel
|
||||
%defattr(-,root,root)
|
||||
@@ -131,6 +132,7 @@ find /lib/modules/%{kver} -name ib_srpt.ko -exec rm {} \;
|
||||
/usr/include/scst/scst.h
|
||||
/usr/include/scst/scst_const.h
|
||||
/usr/include/scst/scst_debug.h
|
||||
/usr/include/scst/scst_itf_ver.h
|
||||
/usr/include/scst/scst_sgv.h
|
||||
/usr/include/scst/scst_user.h
|
||||
|
||||
|
||||
+27
@@ -1067,6 +1067,33 @@ Each vdisk_fileio's device has the following attributes in
|
||||
that these first eight characters are unique or VMware will consider
|
||||
these devices as identical.
|
||||
|
||||
- eui64_id - allows to set the EUI-64 based device identifier in the
|
||||
SCSI device identification VPD page (83h). This identifier must be 8,
|
||||
12 or 16 bytes long and must be specified in hexadecimal format (EUI =
|
||||
Extended Unique Identifier). A leading "0x" is allowed but is not
|
||||
required. Writing a newline into this attribute discards the EUI-64
|
||||
identifier. If neither eui64_id nor naa_id have been set the first
|
||||
eight bytes of the t10_dev_id are used as the EUI-64 ID. If naa_id has
|
||||
been set but eui64_id has not been set no EUI-64 identifier is
|
||||
reported in the SCSI device identification VPD page. If eui64_id has
|
||||
been set the value of this attribute is reported as the EUI-64 ID. The
|
||||
first three bytes of an EUI-64 ID are a so-called organizationally
|
||||
unique identifier (OUI). The remaining bytes may be choosen by the
|
||||
organization that owns the OUI. For more information about OUIs, see
|
||||
also http://standards.ieee.org/develop/regauth/oui/public.html.
|
||||
|
||||
- naa_id - allows to set the NAA ID in the SCSI INQUIRY response (NAA =
|
||||
Network Address Authority). This identifier must be 8 or 16 bytes long
|
||||
and must be specified in hex format. A leading "0x" is allowed but is
|
||||
not required. Writing a newline into this attribute discards the NAA
|
||||
ID. If this ID is set it is reported in the SCSI VPD device
|
||||
identification page (83h). More information about NAA identifiers can
|
||||
be found in the following documents:
|
||||
* ANSI T11 committee, Fibre Channel Framing and Signaling Interface - 4
|
||||
(FC-FS-4) rev 0.50, May 2014 (http://www.t11.org/).
|
||||
* IETF, RFC 3980 - T11 Network Address Authority (NAA) Naming Format for
|
||||
iSCSI Node Names, February 2005 (https://tools.ietf.org/html/rfc3980).
|
||||
|
||||
- t10_vend_id - Contents of the T10 VENDOR IDENTIFICATION field of the
|
||||
INQUIRY response. The default value for this field is "SCST_BIO" for
|
||||
vdisk_block devices and "SCST_FIO" for vdisk_fileio devices.
|
||||
|
||||
@@ -914,6 +914,33 @@ Each vdisk_fileio's device has the following attributes in
|
||||
created device at creation time based on the device name and
|
||||
scst_vdisk_ID scst_vdisk.ko module parameter (see below).
|
||||
|
||||
- eui64_id - allows to set the EUI-64 based device identifier in the
|
||||
SCSI device identification VPD page (83h). This identifier must be 8,
|
||||
12 or 16 bytes long and must be specified in hexadecimal format (EUI =
|
||||
Extended Unique Identifier). A leading "0x" is allowed but is not
|
||||
required. Writing a newline into this attribute discards the EUI-64
|
||||
identifier. If neither eui64_id nor naa_id have been set the first
|
||||
eight bytes of the t10_dev_id are used as the EUI-64 ID. If naa_id has
|
||||
been set but eui64_id has not been set no EUI-64 identifier is
|
||||
reported in the SCSI device identification VPD page. If eui64_id has
|
||||
been set the value of this attribute is reported as the EUI-64 ID. The
|
||||
first three bytes of an EUI-64 ID are a so-called organizationally
|
||||
unique identifier (OUI). The remaining bytes may be choosen by the
|
||||
organization that owns the OUI. For more information about OUIs, see
|
||||
also http://standards.ieee.org/develop/regauth/oui/public.html.
|
||||
|
||||
- naa_id - allows to set the NAA ID in the SCSI INQUIRY response (NAA =
|
||||
Network Address Authority). This identifier must be 8 or 16 bytes long
|
||||
and must be specified in hex format. A leading "0x" is allowed but is
|
||||
not required. Writing a newline into this attribute discards the NAA
|
||||
ID. If this ID is set it is reported in the SCSI VPD device
|
||||
identification page (83h). More information about NAA identifiers can
|
||||
be found in the following documents:
|
||||
* ANSI T11 committee, Fibre Channel Framing and Signaling Interface - 4
|
||||
(FC-FS-4) rev 0.50, May 2014 (http://www.t11.org/).
|
||||
* IETF, RFC 3980 - T11 Network Address Authority (NAA) Naming Format for
|
||||
iSCSI Node Names, February 2005 (https://tools.ietf.org/html/rfc3980).
|
||||
|
||||
- t10_vend_id - Contents of the T10 VENDOR IDENTIFICATION field of the
|
||||
INQUIRY response. The default value for this field is "SCST_BIO" for
|
||||
vdisk_block devices and "SCST_FIO" for vdisk_fileio devices.
|
||||
|
||||
+43
-3
@@ -66,6 +66,13 @@
|
||||
#include <scst_const.h>
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0)
|
||||
#define smp_mb__after_atomic_inc smp_mb__after_atomic
|
||||
#define smp_mb__after_clear_bit smp_mb__after_atomic
|
||||
#define smp_mb__before_atomic_dec smp_mb__before_atomic
|
||||
#define smp_mb__after_atomic_dec smp_mb__after_atomic
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 19)
|
||||
#ifndef RHEL_RELEASE_CODE
|
||||
typedef _Bool bool;
|
||||
@@ -235,6 +242,25 @@ static inline unsigned int queue_max_hw_sectors(struct request_queue *q)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
extern int hex_to_bin(char ch);
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 38)
|
||||
/*
|
||||
* See also "lib: hex2bin converts ascii hexadecimal string to binary" (commit
|
||||
* dc88e46029486ed475c71fe1bb696d39511ac8fe).
|
||||
*/
|
||||
static inline void hex2bin(u8 *dst, const char *src, size_t count)
|
||||
{
|
||||
while (count--) {
|
||||
*dst = hex_to_bin(*src++) << 4;
|
||||
*dst += hex_to_bin(*src++);
|
||||
dst++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef __list_for_each
|
||||
/* ToDo: cleanup when both are the same for all relevant kernels */
|
||||
#define __list_for_each list_for_each
|
||||
@@ -250,7 +276,7 @@ static inline bool list_entry_in_list(const struct list_head *entry)
|
||||
}
|
||||
|
||||
#define SCST_INTERFACE_VERSION \
|
||||
SCST_VERSION_STRING "$Revision$" SCST_CONST_VERSION
|
||||
SCST_VERSION_STRING SCST_INTF_VER SCST_CONST_VERSION
|
||||
|
||||
#define SCST_LOCAL_NAME "scst_local"
|
||||
|
||||
@@ -969,7 +995,17 @@ struct scst_tgt_template {
|
||||
/*
|
||||
* Called to notify target driver that the command is being aborted.
|
||||
* If target driver wants to redirect processing to some outside
|
||||
* processing, it should get it using scst_cmd_get().
|
||||
* processing, it should get it using scst_cmd_get(). Since this
|
||||
* function is invoked from the context of a task management function
|
||||
* it runs asynchronously with the regular command processing finite
|
||||
* state machine. In other words, it is only safe to invoke functions
|
||||
* like scst_tgt_cmd_done() or scst_rx_data() from this callback
|
||||
* function if the target driver owns the command and if appropriate
|
||||
* measures have been taken to avoid that the target driver would
|
||||
* invoke one of these functions from the regular command processing
|
||||
* path. Note: if scst_tgt_cmd_done() or scst_rx_data() is invoked
|
||||
* from this callback function these must be invoked with the
|
||||
* SCST_CONTEXT_THREAD argument.
|
||||
*
|
||||
* OPTIONAL
|
||||
*/
|
||||
@@ -1908,12 +1944,16 @@ struct scst_cmd_threads {
|
||||
/* io_context_mutex protects io_context and io_context_refcnt. */
|
||||
struct mutex io_context_mutex;
|
||||
|
||||
spinlock_t thr_lock; /* Protects nr_threads and threads_list */
|
||||
int nr_threads; /* number of processing threads */
|
||||
struct list_head threads_list; /* processing threads */
|
||||
|
||||
struct list_head lists_list_entry;
|
||||
};
|
||||
|
||||
int scst_set_thr_cpu_mask(struct scst_cmd_threads *cmd_threads,
|
||||
cpumask_t *cpu_mask);
|
||||
|
||||
/*
|
||||
* Used to execute cmd's in order of arrival, honoring SCSI task attributes
|
||||
*/
|
||||
@@ -4331,7 +4371,7 @@ static inline int cancel_delayed_work_sync(struct delayed_work *work)
|
||||
defined(CONFIG_DEBUG_LOCK_ALLOC)
|
||||
extern struct lockdep_map scst_suspend_dep_map;
|
||||
#define scst_assert_activity_suspended() \
|
||||
WARN_ON(debug_locks && !lock_is_held(&scst_suspend_dep_map));
|
||||
WARN_ON(debug_locks && !lock_is_held(&scst_suspend_dep_map))
|
||||
#else
|
||||
/*
|
||||
* See also patch "lockdep: Introduce lockdep_assert_held()" (commit ID
|
||||
|
||||
@@ -35,6 +35,8 @@
|
||||
#include <errno.h>
|
||||
#endif
|
||||
|
||||
#include "scst_itf_ver.h"
|
||||
|
||||
/*
|
||||
* Version numbers, the same as for the kernel.
|
||||
*
|
||||
@@ -51,7 +53,7 @@
|
||||
#define SCST_VERSION_NAME "3.1.0-pre1"
|
||||
#define SCST_VERSION_STRING SCST_VERSION_NAME SCST_VERSION_STRING_SUFFIX
|
||||
|
||||
#define SCST_CONST_VERSION "$Revision$"
|
||||
#define SCST_CONST_VERSION SCST_CONST_INTF_VER
|
||||
|
||||
/*** Shared constants between user and kernel spaces ***/
|
||||
|
||||
@@ -575,6 +577,29 @@ enum scst_tg_sup {
|
||||
#define POSITION_LEN_SHORT 20
|
||||
#define POSITION_LEN_LONG 32
|
||||
|
||||
/*************************************************************
|
||||
** Compatibility constants
|
||||
*************************************************************/
|
||||
#ifndef DID_TRANSPORT_DISRUPTED
|
||||
#define DID_TRANSPORT_DISRUPTED 0xe
|
||||
#endif
|
||||
|
||||
#ifndef DID_TRANSPORT_FAILFAST
|
||||
#define DID_TRANSPORT_FAILFAST 0xf
|
||||
#endif
|
||||
|
||||
#ifndef DID_NEXUS_FAILURE
|
||||
#define DID_NEXUS_FAILURE 0x11
|
||||
#endif
|
||||
|
||||
#ifndef DID_ALLOC_FAILURE
|
||||
#define DID_ALLOC_FAILURE 0x12
|
||||
#endif
|
||||
|
||||
#ifndef DID_MEDIUM_ERROR
|
||||
#define DID_MEDIUM_ERROR 0x13
|
||||
#endif
|
||||
|
||||
/*************************************************************
|
||||
** Various timeouts
|
||||
*************************************************************/
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
#define DEV_USER_PATH "/dev/"
|
||||
#define DEV_USER_VERSION_NAME SCST_VERSION_NAME
|
||||
#define DEV_USER_VERSION \
|
||||
DEV_USER_VERSION_NAME "$Revision$" SCST_CONST_VERSION
|
||||
DEV_USER_VERSION_NAME DEV_USER_INTF_VER SCST_CONST_VERSION
|
||||
|
||||
#define SCST_USER_PARSE_STANDARD 0
|
||||
#define SCST_USER_PARSE_CALL 1
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
diff --git a/drivers/Kconfig b/drivers/Kconfig
|
||||
index aa43b91..c96860e 100644
|
||||
--- a/drivers/Kconfig
|
||||
+++ b/drivers/Kconfig
|
||||
@@ -24,6 +24,8 @@ source "drivers/ide/Kconfig"
|
||||
|
||||
source "drivers/scsi/Kconfig"
|
||||
|
||||
+source "drivers/scst/Kconfig"
|
||||
+
|
||||
source "drivers/ata/Kconfig"
|
||||
|
||||
source "drivers/md/Kconfig"
|
||||
@@ -0,0 +1,14 @@
|
||||
ccflags-y += -Wno-unused-parameter
|
||||
|
||||
obj-m := scst_cdrom.o scst_changer.o scst_disk.o scst_modisk.o scst_tape.o \
|
||||
scst_vdisk.o scst_raid.o scst_processor.o scst_user.o
|
||||
|
||||
obj-$(CONFIG_SCST_DISK) += scst_disk.o
|
||||
obj-$(CONFIG_SCST_TAPE) += scst_tape.o
|
||||
obj-$(CONFIG_SCST_CDROM) += scst_cdrom.o
|
||||
obj-$(CONFIG_SCST_MODISK) += scst_modisk.o
|
||||
obj-$(CONFIG_SCST_CHANGER) += scst_changer.o
|
||||
obj-$(CONFIG_SCST_RAID) += scst_raid.o
|
||||
obj-$(CONFIG_SCST_PROCESSOR) += scst_processor.o
|
||||
obj-$(CONFIG_SCST_VDISK) += scst_vdisk.o
|
||||
obj-$(CONFIG_SCST_USER) += scst_user.o
|
||||
@@ -0,0 +1,12 @@
|
||||
diff --git a/drivers/Makefile b/drivers/Makefile
|
||||
index ab93de8..45077ec 100644
|
||||
--- a/drivers/Makefile
|
||||
+++ b/drivers/Makefile
|
||||
@@ -128,6 +128,7 @@ obj-$(CONFIG_SSB) += ssb/
|
||||
obj-$(CONFIG_BCMA) += bcma/
|
||||
obj-$(CONFIG_VHOST_RING) += vhost/
|
||||
obj-$(CONFIG_VLYNQ) += vlynq/
|
||||
+obj-$(CONFIG_SCST) += scst/
|
||||
obj-$(CONFIG_STAGING) += staging/
|
||||
obj-y += platform/
|
||||
#common clk code
|
||||
@@ -0,0 +1,13 @@
|
||||
ccflags-y += -Wno-unused-parameter
|
||||
|
||||
scst-y += scst_main.o
|
||||
scst-y += scst_pres.o
|
||||
scst-y += scst_targ.o
|
||||
scst-y += scst_lib.o
|
||||
scst-y += scst_sysfs.o
|
||||
scst-y += scst_mem.o
|
||||
scst-y += scst_tg.o
|
||||
scst-y += scst_debug.o
|
||||
|
||||
obj-$(CONFIG_SCST) += scst.o dev_handlers/ fcst/ iscsi-scst/ qla2xxx-target/ \
|
||||
srpt/ scst_local/
|
||||
@@ -0,0 +1,524 @@
|
||||
diff -rup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/block/blk-map.c ./block/blk-map.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/block/blk-map.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./block/blk-map.c 2014-08-07 09:09:11.751302961 +0200
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/bio.h>
|
||||
#include <linux/blkdev.h>
|
||||
+#include <linux/scatterlist.h>
|
||||
+#include <linux/slab.h>
|
||||
#include <scsi/sg.h> /* for struct sg_iovec */
|
||||
|
||||
#include "blk.h"
|
||||
@@ -275,6 +277,337 @@ int blk_rq_unmap_user(struct bio *bio)
|
||||
}
|
||||
EXPORT_SYMBOL(blk_rq_unmap_user);
|
||||
|
||||
+struct blk_kern_sg_work {
|
||||
+ atomic_t bios_inflight;
|
||||
+ struct sg_table sg_table;
|
||||
+ struct scatterlist *src_sgl;
|
||||
+};
|
||||
+
|
||||
+static void blk_free_kern_sg_work(struct blk_kern_sg_work *bw)
|
||||
+{
|
||||
+ struct sg_table *sgt = &bw->sg_table;
|
||||
+ struct scatterlist *sg;
|
||||
+ int i;
|
||||
+
|
||||
+ for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
|
||||
+ struct page *pg = sg_page(sg);
|
||||
+ if (pg == NULL)
|
||||
+ break;
|
||||
+ __free_page(pg);
|
||||
+ }
|
||||
+
|
||||
+ sg_free_table(sgt);
|
||||
+ kfree(bw);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void blk_bio_map_kern_endio(struct bio *bio, int err)
|
||||
+{
|
||||
+ struct blk_kern_sg_work *bw = bio->bi_private;
|
||||
+
|
||||
+ if (bw != NULL) {
|
||||
+ /* Decrement the bios in processing and, if zero, free */
|
||||
+ BUG_ON(atomic_read(&bw->bios_inflight) <= 0);
|
||||
+ if (atomic_dec_and_test(&bw->bios_inflight)) {
|
||||
+ if ((bio_data_dir(bio) == READ) && (err == 0)) {
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ local_irq_save(flags); /* to protect KMs */
|
||||
+ sg_copy(bw->src_sgl, bw->sg_table.sgl, 0, 0);
|
||||
+ local_irq_restore(flags);
|
||||
+ }
|
||||
+ blk_free_kern_sg_work(bw);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ bio_put(bio);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static int blk_rq_copy_kern_sg(struct request *rq, struct scatterlist *sgl,
|
||||
+ int nents, struct blk_kern_sg_work **pbw,
|
||||
+ gfp_t gfp, gfp_t page_gfp)
|
||||
+{
|
||||
+ int res = 0, i;
|
||||
+ struct scatterlist *sg;
|
||||
+ struct scatterlist *new_sgl;
|
||||
+ int new_sgl_nents;
|
||||
+ size_t len = 0, to_copy;
|
||||
+ struct blk_kern_sg_work *bw;
|
||||
+
|
||||
+ bw = kzalloc(sizeof(*bw), gfp);
|
||||
+ if (bw == NULL)
|
||||
+ goto out;
|
||||
+
|
||||
+ bw->src_sgl = sgl;
|
||||
+
|
||||
+ for_each_sg(sgl, sg, nents, i)
|
||||
+ len += sg->length;
|
||||
+ to_copy = len;
|
||||
+
|
||||
+ new_sgl_nents = PFN_UP(len);
|
||||
+
|
||||
+ res = sg_alloc_table(&bw->sg_table, new_sgl_nents, gfp);
|
||||
+ if (res != 0)
|
||||
+ goto err_free;
|
||||
+
|
||||
+ new_sgl = bw->sg_table.sgl;
|
||||
+
|
||||
+ for_each_sg(new_sgl, sg, new_sgl_nents, i) {
|
||||
+ struct page *pg;
|
||||
+
|
||||
+ pg = alloc_page(page_gfp);
|
||||
+ if (pg == NULL)
|
||||
+ goto err_free;
|
||||
+
|
||||
+ sg_assign_page(sg, pg);
|
||||
+ sg->length = min_t(size_t, PAGE_SIZE, len);
|
||||
+
|
||||
+ len -= PAGE_SIZE;
|
||||
+ }
|
||||
+
|
||||
+ if (rq_data_dir(rq) == WRITE) {
|
||||
+ /*
|
||||
+ * We need to limit amount of copied data to to_copy, because
|
||||
+ * sgl might have the last element in sgl not marked as last in
|
||||
+ * SG chaining.
|
||||
+ */
|
||||
+ sg_copy(new_sgl, sgl, 0, to_copy);
|
||||
+ }
|
||||
+
|
||||
+ *pbw = bw;
|
||||
+ /*
|
||||
+ * REQ_COPY_USER name is misleading. It should be something like
|
||||
+ * REQ_HAS_TAIL_SPACE_FOR_PADDING.
|
||||
+ */
|
||||
+ rq->cmd_flags |= REQ_COPY_USER;
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+
|
||||
+err_free:
|
||||
+ blk_free_kern_sg_work(bw);
|
||||
+ res = -ENOMEM;
|
||||
+ goto out;
|
||||
+}
|
||||
+
|
||||
+static int __blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
|
||||
+ int nents, struct blk_kern_sg_work *bw, gfp_t gfp)
|
||||
+{
|
||||
+ int res;
|
||||
+ struct request_queue *q = rq->q;
|
||||
+ int rw = rq_data_dir(rq);
|
||||
+ int max_nr_vecs, i;
|
||||
+ size_t tot_len;
|
||||
+ bool need_new_bio;
|
||||
+ struct scatterlist *sg, *prev_sg = NULL;
|
||||
+ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
|
||||
+ int bios;
|
||||
+
|
||||
+ if (unlikely((sgl == NULL) || (sgl->length == 0) || (nents <= 0))) {
|
||||
+ WARN_ON(1);
|
||||
+ res = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Let's keep each bio allocation inside a single page to decrease
|
||||
+ * probability of failure.
|
||||
+ */
|
||||
+ max_nr_vecs = min_t(size_t,
|
||||
+ ((PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec)),
|
||||
+ BIO_MAX_PAGES);
|
||||
+
|
||||
+ need_new_bio = true;
|
||||
+ tot_len = 0;
|
||||
+ bios = 0;
|
||||
+ for_each_sg(sgl, sg, nents, i) {
|
||||
+ struct page *page = sg_page(sg);
|
||||
+ void *page_addr = page_address(page);
|
||||
+ size_t len = sg->length, l;
|
||||
+ size_t offset = sg->offset;
|
||||
+
|
||||
+ tot_len += len;
|
||||
+ prev_sg = sg;
|
||||
+
|
||||
+ /*
|
||||
+ * Each segment must be aligned on DMA boundary and
|
||||
+ * not on stack. The last one may have unaligned
|
||||
+ * length as long as the total length is aligned to
|
||||
+ * DMA padding alignment.
|
||||
+ */
|
||||
+ if (i == nents - 1)
|
||||
+ l = 0;
|
||||
+ else
|
||||
+ l = len;
|
||||
+ if (((sg->offset | l) & queue_dma_alignment(q)) ||
|
||||
+ (page_addr && object_is_on_stack(page_addr + sg->offset))) {
|
||||
+ res = -EINVAL;
|
||||
+ goto out_free_bios;
|
||||
+ }
|
||||
+
|
||||
+ while (len > 0) {
|
||||
+ size_t bytes;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (need_new_bio) {
|
||||
+ bio = bio_kmalloc(gfp, max_nr_vecs);
|
||||
+ if (bio == NULL) {
|
||||
+ res = -ENOMEM;
|
||||
+ goto out_free_bios;
|
||||
+ }
|
||||
+
|
||||
+ if (rw == WRITE)
|
||||
+ bio->bi_rw |= REQ_WRITE;
|
||||
+
|
||||
+ bios++;
|
||||
+ bio->bi_private = bw;
|
||||
+ bio->bi_end_io = blk_bio_map_kern_endio;
|
||||
+
|
||||
+ if (hbio == NULL)
|
||||
+ hbio = tbio = bio;
|
||||
+ else
|
||||
+ tbio = tbio->bi_next = bio;
|
||||
+ }
|
||||
+
|
||||
+ bytes = min_t(size_t, len, PAGE_SIZE - offset);
|
||||
+
|
||||
+ rc = bio_add_pc_page(q, bio, page, bytes, offset);
|
||||
+ if (rc < bytes) {
|
||||
+ if (unlikely(need_new_bio || (rc < 0))) {
|
||||
+ if (rc < 0)
|
||||
+ res = rc;
|
||||
+ else
|
||||
+ res = -EIO;
|
||||
+ goto out_free_bios;
|
||||
+ } else {
|
||||
+ need_new_bio = true;
|
||||
+ len -= rc;
|
||||
+ offset += rc;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ need_new_bio = false;
|
||||
+ offset = 0;
|
||||
+ len -= bytes;
|
||||
+ page = nth_page(page, 1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (hbio == NULL) {
|
||||
+ res = -EINVAL;
|
||||
+ goto out_free_bios;
|
||||
+ }
|
||||
+
|
||||
+ /* Total length must be aligned on DMA padding alignment */
|
||||
+ if ((tot_len & q->dma_pad_mask) &&
|
||||
+ !(rq->cmd_flags & REQ_COPY_USER)) {
|
||||
+ res = -EINVAL;
|
||||
+ goto out_free_bios;
|
||||
+ }
|
||||
+
|
||||
+ if (bw != NULL)
|
||||
+ atomic_set(&bw->bios_inflight, bios);
|
||||
+
|
||||
+ while (hbio != NULL) {
|
||||
+ bio = hbio;
|
||||
+ hbio = hbio->bi_next;
|
||||
+ bio->bi_next = NULL;
|
||||
+
|
||||
+ blk_queue_bounce(q, &bio);
|
||||
+
|
||||
+ res = blk_rq_append_bio(q, rq, bio);
|
||||
+ if (unlikely(res != 0)) {
|
||||
+ bio->bi_next = hbio;
|
||||
+ hbio = bio;
|
||||
+ /* We can have one or more bios bounced */
|
||||
+ goto out_unmap_bios;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ res = 0;
|
||||
+
|
||||
+ rq->buffer = NULL;
|
||||
+out:
|
||||
+ return res;
|
||||
+
|
||||
+out_unmap_bios:
|
||||
+ blk_rq_unmap_kern_sg(rq, res);
|
||||
+
|
||||
+out_free_bios:
|
||||
+ while (hbio != NULL) {
|
||||
+ bio = hbio;
|
||||
+ hbio = hbio->bi_next;
|
||||
+ bio_put(bio);
|
||||
+ }
|
||||
+ goto out;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * blk_rq_map_kern_sg - map kernel data to a request, for REQ_TYPE_BLOCK_PC
|
||||
+ * @rq: request to fill
|
||||
+ * @sgl: area to map
|
||||
+ * @nents: number of elements in @sgl
|
||||
+ * @gfp: memory allocation flags
|
||||
+ *
|
||||
+ * Description:
|
||||
+ * Data will be mapped directly if possible. Otherwise a bounce
|
||||
+ * buffer will be used.
|
||||
+ */
|
||||
+int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
|
||||
+ int nents, gfp_t gfp)
|
||||
+{
|
||||
+ int res;
|
||||
+
|
||||
+ res = __blk_rq_map_kern_sg(rq, sgl, nents, NULL, gfp);
|
||||
+ if (unlikely(res != 0)) {
|
||||
+ struct blk_kern_sg_work *bw = NULL;
|
||||
+
|
||||
+ res = blk_rq_copy_kern_sg(rq, sgl, nents, &bw,
|
||||
+ gfp, rq->q->bounce_gfp | gfp);
|
||||
+ if (unlikely(res != 0))
|
||||
+ goto out;
|
||||
+
|
||||
+ res = __blk_rq_map_kern_sg(rq, bw->sg_table.sgl,
|
||||
+ bw->sg_table.nents, bw, gfp);
|
||||
+ if (res != 0) {
|
||||
+ blk_free_kern_sg_work(bw);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ rq->buffer = NULL;
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL(blk_rq_map_kern_sg);
|
||||
+
|
||||
+/**
|
||||
+ * blk_rq_unmap_kern_sg - unmap a request with kernel sg
|
||||
+ * @rq: request to unmap
|
||||
+ * @err: non-zero error code
|
||||
+ *
|
||||
+ * Description:
|
||||
+ * Unmap a rq previously mapped by blk_rq_map_kern_sg(). Must be called
|
||||
+ * only in case of an error!
|
||||
+ */
|
||||
+void blk_rq_unmap_kern_sg(struct request *rq, int err)
|
||||
+{
|
||||
+ struct bio *bio = rq->bio;
|
||||
+
|
||||
+ while (bio) {
|
||||
+ struct bio *b = bio;
|
||||
+ bio = bio->bi_next;
|
||||
+ b->bi_end_io(b, err);
|
||||
+ }
|
||||
+ rq->bio = NULL;
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+EXPORT_SYMBOL(blk_rq_unmap_kern_sg);
|
||||
+
|
||||
/**
|
||||
* blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage
|
||||
* @q: request queue where request should be inserted
|
||||
diff -rup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/blkdev.h ./include/linux/blkdev.h
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/blkdev.h 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./include/linux/blkdev.h 2014-08-07 09:09:11.751302961 +0200
|
||||
@@ -719,6 +719,8 @@ extern unsigned long blk_max_low_pfn, bl
|
||||
#define BLK_DEFAULT_SG_TIMEOUT (60 * HZ)
|
||||
#define BLK_MIN_SG_TIMEOUT (7 * HZ)
|
||||
|
||||
+#define SCSI_EXEC_REQ_FIFO_DEFINED
|
||||
+
|
||||
#ifdef CONFIG_BOUNCE
|
||||
extern int init_emergency_isa_pool(void);
|
||||
extern void blk_queue_bounce(struct request_queue *q, struct bio **bio);
|
||||
@@ -838,6 +840,9 @@ extern int blk_rq_map_kern(struct reques
|
||||
extern int blk_rq_map_user_iov(struct request_queue *, struct request *,
|
||||
struct rq_map_data *, struct sg_iovec *, int,
|
||||
unsigned int, gfp_t);
|
||||
+extern int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
|
||||
+ int nents, gfp_t gfp);
|
||||
+extern void blk_rq_unmap_kern_sg(struct request *rq, int err);
|
||||
extern int blk_execute_rq(struct request_queue *, struct gendisk *,
|
||||
struct request *, int);
|
||||
extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
|
||||
diff -rup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/scatterlist.h ./include/linux/scatterlist.h
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/include/linux/scatterlist.h 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./include/linux/scatterlist.h 2014-08-07 09:09:11.751302961 +0200
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <asm/types.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include <asm/io.h>
|
||||
+#include <asm/kmap_types.h>
|
||||
|
||||
struct sg_table {
|
||||
struct scatterlist *sgl; /* the list */
|
||||
@@ -244,6 +245,9 @@ size_t sg_copy_from_buffer(struct scatte
|
||||
size_t sg_copy_to_buffer(struct scatterlist *sgl, unsigned int nents,
|
||||
void *buf, size_t buflen);
|
||||
|
||||
+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
|
||||
+ int nents_to_copy, size_t copy_len);
|
||||
+
|
||||
/*
|
||||
* Maximum number of entries that will be allocated in one piece, if
|
||||
* a list larger than this is required then chaining will be utilized.
|
||||
diff -rup ../../centos-7-orig/linux-3.10.0-123.6.3.el7/lib/scatterlist.c ./lib/scatterlist.c
|
||||
--- ../../centos-7-orig/linux-3.10.0-123.6.3.el7/lib/scatterlist.c 2014-07-16 20:25:31.000000000 +0200
|
||||
+++ ./lib/scatterlist.c 2014-08-07 09:09:11.751302961 +0200
|
||||
@@ -628,3 +628,126 @@ size_t sg_copy_to_buffer(struct scatterl
|
||||
return sg_copy_buffer(sgl, nents, buf, buflen, 1);
|
||||
}
|
||||
EXPORT_SYMBOL(sg_copy_to_buffer);
|
||||
+
|
||||
+/*
|
||||
+ * Can switch to the next dst_sg element, so, to copy to strictly only
|
||||
+ * one dst_sg element, it must be either last in the chain, or
|
||||
+ * copy_len == dst_sg->length.
|
||||
+ */
|
||||
+static int sg_copy_elem(struct scatterlist **pdst_sg, size_t *pdst_len,
|
||||
+ size_t *pdst_offs, struct scatterlist *src_sg,
|
||||
+ size_t copy_len)
|
||||
+{
|
||||
+ int res = 0;
|
||||
+ struct scatterlist *dst_sg;
|
||||
+ size_t src_len, dst_len, src_offs, dst_offs;
|
||||
+ struct page *src_page, *dst_page;
|
||||
+
|
||||
+ dst_sg = *pdst_sg;
|
||||
+ dst_len = *pdst_len;
|
||||
+ dst_offs = *pdst_offs;
|
||||
+ dst_page = sg_page(dst_sg);
|
||||
+
|
||||
+ src_page = sg_page(src_sg);
|
||||
+ src_len = src_sg->length;
|
||||
+ src_offs = src_sg->offset;
|
||||
+
|
||||
+ do {
|
||||
+ void *saddr, *daddr;
|
||||
+ size_t n;
|
||||
+
|
||||
+ saddr = kmap_atomic(src_page + (src_offs >> PAGE_SHIFT)) +
|
||||
+ (src_offs & ~PAGE_MASK);
|
||||
+ daddr = kmap_atomic(dst_page + (dst_offs >> PAGE_SHIFT)) +
|
||||
+ (dst_offs & ~PAGE_MASK);
|
||||
+
|
||||
+ if (((src_offs & ~PAGE_MASK) == 0) &&
|
||||
+ ((dst_offs & ~PAGE_MASK) == 0) &&
|
||||
+ (src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) &&
|
||||
+ (copy_len >= PAGE_SIZE)) {
|
||||
+ copy_page(daddr, saddr);
|
||||
+ n = PAGE_SIZE;
|
||||
+ } else {
|
||||
+ n = min_t(size_t, PAGE_SIZE - (dst_offs & ~PAGE_MASK),
|
||||
+ PAGE_SIZE - (src_offs & ~PAGE_MASK));
|
||||
+ n = min(n, src_len);
|
||||
+ n = min(n, dst_len);
|
||||
+ n = min_t(size_t, n, copy_len);
|
||||
+ memcpy(daddr, saddr, n);
|
||||
+ }
|
||||
+ dst_offs += n;
|
||||
+ src_offs += n;
|
||||
+
|
||||
+ kunmap_atomic(saddr);
|
||||
+ kunmap_atomic(daddr);
|
||||
+
|
||||
+ res += n;
|
||||
+ copy_len -= n;
|
||||
+ if (copy_len == 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ src_len -= n;
|
||||
+ dst_len -= n;
|
||||
+ if (dst_len == 0) {
|
||||
+ dst_sg = sg_next(dst_sg);
|
||||
+ if (dst_sg == NULL)
|
||||
+ goto out;
|
||||
+ dst_page = sg_page(dst_sg);
|
||||
+ dst_len = dst_sg->length;
|
||||
+ dst_offs = dst_sg->offset;
|
||||
+ }
|
||||
+ } while (src_len > 0);
|
||||
+
|
||||
+out:
|
||||
+ *pdst_sg = dst_sg;
|
||||
+ *pdst_len = dst_len;
|
||||
+ *pdst_offs = dst_offs;
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * sg_copy - copy one SG vector to another
|
||||
+ * @dst_sg: destination SG
|
||||
+ * @src_sg: source SG
|
||||
+ * @nents_to_copy: maximum number of entries to copy
|
||||
+ * @copy_len: maximum amount of data to copy. If 0, then copy all.
|
||||
+ *
|
||||
+ * Description:
|
||||
+ * Data from the source SG vector will be copied to the destination SG
|
||||
+ * vector. End of the vectors will be determined by sg_next() returning
|
||||
+ * NULL. Returns number of bytes copied.
|
||||
+ */
|
||||
+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
|
||||
+ int nents_to_copy, size_t copy_len)
|
||||
+{
|
||||
+ int res = 0;
|
||||
+ size_t dst_len, dst_offs;
|
||||
+
|
||||
+ if (copy_len == 0)
|
||||
+ copy_len = 0x7FFFFFFF; /* copy all */
|
||||
+
|
||||
+ if (nents_to_copy == 0)
|
||||
+ nents_to_copy = 0x7FFFFFFF; /* copy all */
|
||||
+
|
||||
+ dst_len = dst_sg->length;
|
||||
+ dst_offs = dst_sg->offset;
|
||||
+
|
||||
+ do {
|
||||
+ int copied = sg_copy_elem(&dst_sg, &dst_len, &dst_offs,
|
||||
+ src_sg, copy_len);
|
||||
+ copy_len -= copied;
|
||||
+ res += copied;
|
||||
+ if ((copy_len == 0) || (dst_sg == NULL))
|
||||
+ goto out;
|
||||
+
|
||||
+ nents_to_copy--;
|
||||
+ if (nents_to_copy == 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ src_sg = sg_next(src_sg);
|
||||
+ } while (src_sg != NULL);
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL(sg_copy);
|
||||
|
||||
@@ -0,0 +1,524 @@
|
||||
=== modified file 'block/blk-map.c'
|
||||
--- old/block/blk-map.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/block/blk-map.c 2014-08-19 01:37:01 +0000
|
||||
@@ -5,6 +5,8 @@
|
||||
#include <linux/module.h>
|
||||
#include <linux/bio.h>
|
||||
#include <linux/blkdev.h>
|
||||
+#include <linux/scatterlist.h>
|
||||
+#include <linux/slab.h>
|
||||
#include <scsi/sg.h> /* for struct sg_iovec */
|
||||
|
||||
#include "blk.h"
|
||||
@@ -273,6 +275,333 @@ int blk_rq_unmap_user(struct bio *bio)
|
||||
}
|
||||
EXPORT_SYMBOL(blk_rq_unmap_user);
|
||||
|
||||
+struct blk_kern_sg_work {
|
||||
+ atomic_t bios_inflight;
|
||||
+ struct sg_table sg_table;
|
||||
+ struct scatterlist *src_sgl;
|
||||
+};
|
||||
+
|
||||
+static void blk_free_kern_sg_work(struct blk_kern_sg_work *bw)
|
||||
+{
|
||||
+ struct sg_table *sgt = &bw->sg_table;
|
||||
+ struct scatterlist *sg;
|
||||
+ int i;
|
||||
+
|
||||
+ for_each_sg(sgt->sgl, sg, sgt->orig_nents, i) {
|
||||
+ struct page *pg = sg_page(sg);
|
||||
+ if (pg == NULL)
|
||||
+ break;
|
||||
+ __free_page(pg);
|
||||
+ }
|
||||
+
|
||||
+ sg_free_table(sgt);
|
||||
+ kfree(bw);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static void blk_bio_map_kern_endio(struct bio *bio, int err)
|
||||
+{
|
||||
+ struct blk_kern_sg_work *bw = bio->bi_private;
|
||||
+
|
||||
+ if (bw != NULL) {
|
||||
+ /* Decrement the bios in processing and, if zero, free */
|
||||
+ BUG_ON(atomic_read(&bw->bios_inflight) <= 0);
|
||||
+ if (atomic_dec_and_test(&bw->bios_inflight)) {
|
||||
+ if ((bio_data_dir(bio) == READ) && (err == 0)) {
|
||||
+ unsigned long flags;
|
||||
+
|
||||
+ local_irq_save(flags); /* to protect KMs */
|
||||
+ sg_copy(bw->src_sgl, bw->sg_table.sgl, 0, 0);
|
||||
+ local_irq_restore(flags);
|
||||
+ }
|
||||
+ blk_free_kern_sg_work(bw);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ bio_put(bio);
|
||||
+ return;
|
||||
+}
|
||||
+
|
||||
+static int blk_rq_copy_kern_sg(struct request *rq, struct scatterlist *sgl,
|
||||
+ int nents, struct blk_kern_sg_work **pbw,
|
||||
+ gfp_t gfp, gfp_t page_gfp)
|
||||
+{
|
||||
+ int res = 0, i;
|
||||
+ struct scatterlist *sg;
|
||||
+ struct scatterlist *new_sgl;
|
||||
+ int new_sgl_nents;
|
||||
+ size_t len = 0, to_copy;
|
||||
+ struct blk_kern_sg_work *bw;
|
||||
+
|
||||
+ bw = kzalloc(sizeof(*bw), gfp);
|
||||
+ if (bw == NULL)
|
||||
+ goto out;
|
||||
+
|
||||
+ bw->src_sgl = sgl;
|
||||
+
|
||||
+ for_each_sg(sgl, sg, nents, i)
|
||||
+ len += sg->length;
|
||||
+ to_copy = len;
|
||||
+
|
||||
+ new_sgl_nents = PFN_UP(len);
|
||||
+
|
||||
+ res = sg_alloc_table(&bw->sg_table, new_sgl_nents, gfp);
|
||||
+ if (res != 0)
|
||||
+ goto err_free;
|
||||
+
|
||||
+ new_sgl = bw->sg_table.sgl;
|
||||
+
|
||||
+ for_each_sg(new_sgl, sg, new_sgl_nents, i) {
|
||||
+ struct page *pg;
|
||||
+
|
||||
+ pg = alloc_page(page_gfp);
|
||||
+ if (pg == NULL)
|
||||
+ goto err_free;
|
||||
+
|
||||
+ sg_assign_page(sg, pg);
|
||||
+ sg->length = min_t(size_t, PAGE_SIZE, len);
|
||||
+
|
||||
+ len -= PAGE_SIZE;
|
||||
+ }
|
||||
+
|
||||
+ if (rq_data_dir(rq) == WRITE) {
|
||||
+ /*
|
||||
+ * We need to limit amount of copied data to to_copy, because
|
||||
+ * sgl might have the last element in sgl not marked as last in
|
||||
+ * SG chaining.
|
||||
+ */
|
||||
+ sg_copy(new_sgl, sgl, 0, to_copy);
|
||||
+ }
|
||||
+
|
||||
+ *pbw = bw;
|
||||
+ /*
|
||||
+ * REQ_COPY_USER name is misleading. It should be something like
|
||||
+ * REQ_HAS_TAIL_SPACE_FOR_PADDING.
|
||||
+ */
|
||||
+ rq->cmd_flags |= REQ_COPY_USER;
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+
|
||||
+err_free:
|
||||
+ blk_free_kern_sg_work(bw);
|
||||
+ res = -ENOMEM;
|
||||
+ goto out;
|
||||
+}
|
||||
+
|
||||
+static int __blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
|
||||
+ int nents, struct blk_kern_sg_work *bw, gfp_t gfp)
|
||||
+{
|
||||
+ int res;
|
||||
+ struct request_queue *q = rq->q;
|
||||
+ int rw = rq_data_dir(rq);
|
||||
+ int max_nr_vecs, i;
|
||||
+ size_t tot_len;
|
||||
+ bool need_new_bio;
|
||||
+ struct scatterlist *sg, *prev_sg = NULL;
|
||||
+ struct bio *bio = NULL, *hbio = NULL, *tbio = NULL;
|
||||
+ int bios;
|
||||
+
|
||||
+ if (unlikely((sgl == NULL) || (sgl->length == 0) || (nents <= 0))) {
|
||||
+ WARN_ON(1);
|
||||
+ res = -EINVAL;
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
+ /*
|
||||
+ * Let's keep each bio allocation inside a single page to decrease
|
||||
+ * probability of failure.
|
||||
+ */
|
||||
+ max_nr_vecs = min_t(size_t,
|
||||
+ ((PAGE_SIZE - sizeof(struct bio)) / sizeof(struct bio_vec)),
|
||||
+ BIO_MAX_PAGES);
|
||||
+
|
||||
+ need_new_bio = true;
|
||||
+ tot_len = 0;
|
||||
+ bios = 0;
|
||||
+ for_each_sg(sgl, sg, nents, i) {
|
||||
+ struct page *page = sg_page(sg);
|
||||
+ void *page_addr = page_address(page);
|
||||
+ size_t len = sg->length, l;
|
||||
+ size_t offset = sg->offset;
|
||||
+
|
||||
+ tot_len += len;
|
||||
+ prev_sg = sg;
|
||||
+
|
||||
+ /*
|
||||
+ * Each segment must be aligned on DMA boundary and
|
||||
+ * not on stack. The last one may have unaligned
|
||||
+ * length as long as the total length is aligned to
|
||||
+ * DMA padding alignment.
|
||||
+ */
|
||||
+ if (i == nents - 1)
|
||||
+ l = 0;
|
||||
+ else
|
||||
+ l = len;
|
||||
+ if (((sg->offset | l) & queue_dma_alignment(q)) ||
|
||||
+ (page_addr && object_is_on_stack(page_addr + sg->offset))) {
|
||||
+ res = -EINVAL;
|
||||
+ goto out_free_bios;
|
||||
+ }
|
||||
+
|
||||
+ while (len > 0) {
|
||||
+ size_t bytes;
|
||||
+ int rc;
|
||||
+
|
||||
+ if (need_new_bio) {
|
||||
+ bio = bio_kmalloc(gfp, max_nr_vecs);
|
||||
+ if (bio == NULL) {
|
||||
+ res = -ENOMEM;
|
||||
+ goto out_free_bios;
|
||||
+ }
|
||||
+
|
||||
+ if (rw == WRITE)
|
||||
+ bio->bi_rw |= REQ_WRITE;
|
||||
+
|
||||
+ bios++;
|
||||
+ bio->bi_private = bw;
|
||||
+ bio->bi_end_io = blk_bio_map_kern_endio;
|
||||
+
|
||||
+ if (hbio == NULL)
|
||||
+ hbio = tbio = bio;
|
||||
+ else
|
||||
+ tbio = tbio->bi_next = bio;
|
||||
+ }
|
||||
+
|
||||
+ bytes = min_t(size_t, len, PAGE_SIZE - offset);
|
||||
+
|
||||
+ rc = bio_add_pc_page(q, bio, page, bytes, offset);
|
||||
+ if (rc < bytes) {
|
||||
+ if (unlikely(need_new_bio || (rc < 0))) {
|
||||
+ if (rc < 0)
|
||||
+ res = rc;
|
||||
+ else
|
||||
+ res = -EIO;
|
||||
+ goto out_free_bios;
|
||||
+ } else {
|
||||
+ need_new_bio = true;
|
||||
+ len -= rc;
|
||||
+ offset += rc;
|
||||
+ continue;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ need_new_bio = false;
|
||||
+ offset = 0;
|
||||
+ len -= bytes;
|
||||
+ page = nth_page(page, 1);
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ if (hbio == NULL) {
|
||||
+ res = -EINVAL;
|
||||
+ goto out_free_bios;
|
||||
+ }
|
||||
+
|
||||
+ /* Total length must be aligned on DMA padding alignment */
|
||||
+ if ((tot_len & q->dma_pad_mask) &&
|
||||
+ !(rq->cmd_flags & REQ_COPY_USER)) {
|
||||
+ res = -EINVAL;
|
||||
+ goto out_free_bios;
|
||||
+ }
|
||||
+
|
||||
+ if (bw != NULL)
|
||||
+ atomic_set(&bw->bios_inflight, bios);
|
||||
+
|
||||
+ while (hbio != NULL) {
|
||||
+ bio = hbio;
|
||||
+ hbio = hbio->bi_next;
|
||||
+ bio->bi_next = NULL;
|
||||
+
|
||||
+ blk_queue_bounce(q, &bio);
|
||||
+
|
||||
+ res = blk_rq_append_bio(q, rq, bio);
|
||||
+ if (unlikely(res != 0)) {
|
||||
+ bio->bi_next = hbio;
|
||||
+ hbio = bio;
|
||||
+ /* We can have one or more bios bounced */
|
||||
+ goto out_unmap_bios;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ res = 0;
|
||||
+out:
|
||||
+ return res;
|
||||
+
|
||||
+out_unmap_bios:
|
||||
+ blk_rq_unmap_kern_sg(rq, res);
|
||||
+
|
||||
+out_free_bios:
|
||||
+ while (hbio != NULL) {
|
||||
+ bio = hbio;
|
||||
+ hbio = hbio->bi_next;
|
||||
+ bio_put(bio);
|
||||
+ }
|
||||
+ goto out;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * blk_rq_map_kern_sg - map kernel data to a request, for REQ_TYPE_BLOCK_PC
|
||||
+ * @rq: request to fill
|
||||
+ * @sgl: area to map
|
||||
+ * @nents: number of elements in @sgl
|
||||
+ * @gfp: memory allocation flags
|
||||
+ *
|
||||
+ * Description:
|
||||
+ * Data will be mapped directly if possible. Otherwise a bounce
|
||||
+ * buffer will be used.
|
||||
+ */
|
||||
+int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
|
||||
+ int nents, gfp_t gfp)
|
||||
+{
|
||||
+ int res;
|
||||
+
|
||||
+ res = __blk_rq_map_kern_sg(rq, sgl, nents, NULL, gfp);
|
||||
+ if (unlikely(res != 0)) {
|
||||
+ struct blk_kern_sg_work *bw = NULL;
|
||||
+
|
||||
+ res = blk_rq_copy_kern_sg(rq, sgl, nents, &bw,
|
||||
+ gfp, rq->q->bounce_gfp | gfp);
|
||||
+ if (unlikely(res != 0))
|
||||
+ goto out;
|
||||
+
|
||||
+ res = __blk_rq_map_kern_sg(rq, bw->sg_table.sgl,
|
||||
+ bw->sg_table.nents, bw, gfp);
|
||||
+ if (res != 0) {
|
||||
+ blk_free_kern_sg_work(bw);
|
||||
+ goto out;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL(blk_rq_map_kern_sg);
|
||||
+
|
||||
+/**
|
||||
+ * blk_rq_unmap_kern_sg - unmap a request with kernel sg
|
||||
+ * @rq: request to unmap
|
||||
+ * @err: non-zero error code
|
||||
+ *
|
||||
+ * Description:
|
||||
+ * Unmap a rq previously mapped by blk_rq_map_kern_sg(). Must be called
|
||||
+ * only in case of an error!
|
||||
+ */
|
||||
+void blk_rq_unmap_kern_sg(struct request *rq, int err)
|
||||
+{
|
||||
+ struct bio *bio = rq->bio;
|
||||
+
|
||||
+ while (bio) {
|
||||
+ struct bio *b = bio;
|
||||
+ bio = bio->bi_next;
|
||||
+ b->bi_end_io(b, err);
|
||||
+ }
|
||||
+ rq->bio = NULL;
|
||||
+
|
||||
+ return;
|
||||
+}
|
||||
+EXPORT_SYMBOL(blk_rq_unmap_kern_sg);
|
||||
+
|
||||
/**
|
||||
* blk_rq_map_kern - map kernel data to a request, for REQ_TYPE_BLOCK_PC usage
|
||||
* @q: request queue where request should be inserted
|
||||
|
||||
=== modified file 'include/linux/blkdev.h'
|
||||
--- old/include/linux/blkdev.h 2014-08-19 01:00:36 +0000
|
||||
+++ new/include/linux/blkdev.h 2014-08-19 01:06:48 +0000
|
||||
@@ -735,6 +735,8 @@ extern unsigned long blk_max_low_pfn, bl
|
||||
#define BLK_DEFAULT_SG_TIMEOUT (60 * HZ)
|
||||
#define BLK_MIN_SG_TIMEOUT (7 * HZ)
|
||||
|
||||
+#define SCSI_EXEC_REQ_FIFO_DEFINED
|
||||
+
|
||||
#ifdef CONFIG_BOUNCE
|
||||
extern int init_emergency_isa_pool(void);
|
||||
extern void blk_queue_bounce(struct request_queue *q, struct bio **bio);
|
||||
@@ -856,6 +858,9 @@ extern int blk_rq_map_kern(struct reques
|
||||
extern int blk_rq_map_user_iov(struct request_queue *, struct request *,
|
||||
struct rq_map_data *, const struct sg_iovec *,
|
||||
int, unsigned int, gfp_t);
|
||||
+extern int blk_rq_map_kern_sg(struct request *rq, struct scatterlist *sgl,
|
||||
+ int nents, gfp_t gfp);
|
||||
+extern void blk_rq_unmap_kern_sg(struct request *rq, int err);
|
||||
extern int blk_execute_rq(struct request_queue *, struct gendisk *,
|
||||
struct request *, int);
|
||||
extern void blk_execute_rq_nowait(struct request_queue *, struct gendisk *,
|
||||
|
||||
=== modified file 'include/linux/scatterlist.h'
|
||||
--- old/include/linux/scatterlist.h 2014-08-19 01:00:36 +0000
|
||||
+++ new/include/linux/scatterlist.h 2014-08-19 01:06:48 +0000
|
||||
@@ -8,6 +8,7 @@
|
||||
#include <asm/types.h>
|
||||
#include <asm/scatterlist.h>
|
||||
#include <asm/io.h>
|
||||
+#include <asm/kmap_types.h>
|
||||
|
||||
struct sg_table {
|
||||
struct scatterlist *sgl; /* the list */
|
||||
@@ -249,6 +250,9 @@ size_t sg_pcopy_from_buffer(struct scatt
|
||||
size_t sg_pcopy_to_buffer(struct scatterlist *sgl, unsigned int nents,
|
||||
void *buf, size_t buflen, off_t skip);
|
||||
|
||||
+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
|
||||
+ int nents_to_copy, size_t copy_len);
|
||||
+
|
||||
/*
|
||||
* Maximum number of entries that will be allocated in one piece, if
|
||||
* a list larger than this is required then chaining will be utilized.
|
||||
|
||||
=== modified file 'lib/scatterlist.c'
|
||||
--- old/lib/scatterlist.c 2014-08-19 01:00:36 +0000
|
||||
+++ new/lib/scatterlist.c 2014-08-19 01:06:48 +0000
|
||||
@@ -718,3 +718,127 @@ size_t sg_pcopy_to_buffer(struct scatter
|
||||
return sg_copy_buffer(sgl, nents, buf, buflen, skip, true);
|
||||
}
|
||||
EXPORT_SYMBOL(sg_pcopy_to_buffer);
|
||||
+
|
||||
+
|
||||
+/*
|
||||
+ * Can switch to the next dst_sg element, so, to copy to strictly only
|
||||
+ * one dst_sg element, it must be either last in the chain, or
|
||||
+ * copy_len == dst_sg->length.
|
||||
+ */
|
||||
+static int sg_copy_elem(struct scatterlist **pdst_sg, size_t *pdst_len,
|
||||
+ size_t *pdst_offs, struct scatterlist *src_sg,
|
||||
+ size_t copy_len)
|
||||
+{
|
||||
+ int res = 0;
|
||||
+ struct scatterlist *dst_sg;
|
||||
+ size_t src_len, dst_len, src_offs, dst_offs;
|
||||
+ struct page *src_page, *dst_page;
|
||||
+
|
||||
+ dst_sg = *pdst_sg;
|
||||
+ dst_len = *pdst_len;
|
||||
+ dst_offs = *pdst_offs;
|
||||
+ dst_page = sg_page(dst_sg);
|
||||
+
|
||||
+ src_page = sg_page(src_sg);
|
||||
+ src_len = src_sg->length;
|
||||
+ src_offs = src_sg->offset;
|
||||
+
|
||||
+ do {
|
||||
+ void *saddr, *daddr;
|
||||
+ size_t n;
|
||||
+
|
||||
+ saddr = kmap_atomic(src_page + (src_offs >> PAGE_SHIFT)) +
|
||||
+ (src_offs & ~PAGE_MASK);
|
||||
+ daddr = kmap_atomic(dst_page + (dst_offs >> PAGE_SHIFT)) +
|
||||
+ (dst_offs & ~PAGE_MASK);
|
||||
+
|
||||
+ if (((src_offs & ~PAGE_MASK) == 0) &&
|
||||
+ ((dst_offs & ~PAGE_MASK) == 0) &&
|
||||
+ (src_len >= PAGE_SIZE) && (dst_len >= PAGE_SIZE) &&
|
||||
+ (copy_len >= PAGE_SIZE)) {
|
||||
+ copy_page(daddr, saddr);
|
||||
+ n = PAGE_SIZE;
|
||||
+ } else {
|
||||
+ n = min_t(size_t, PAGE_SIZE - (dst_offs & ~PAGE_MASK),
|
||||
+ PAGE_SIZE - (src_offs & ~PAGE_MASK));
|
||||
+ n = min(n, src_len);
|
||||
+ n = min(n, dst_len);
|
||||
+ n = min_t(size_t, n, copy_len);
|
||||
+ memcpy(daddr, saddr, n);
|
||||
+ }
|
||||
+ dst_offs += n;
|
||||
+ src_offs += n;
|
||||
+
|
||||
+ kunmap_atomic(saddr);
|
||||
+ kunmap_atomic(daddr);
|
||||
+
|
||||
+ res += n;
|
||||
+ copy_len -= n;
|
||||
+ if (copy_len == 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ src_len -= n;
|
||||
+ dst_len -= n;
|
||||
+ if (dst_len == 0) {
|
||||
+ dst_sg = sg_next(dst_sg);
|
||||
+ if (dst_sg == NULL)
|
||||
+ goto out;
|
||||
+ dst_page = sg_page(dst_sg);
|
||||
+ dst_len = dst_sg->length;
|
||||
+ dst_offs = dst_sg->offset;
|
||||
+ }
|
||||
+ } while (src_len > 0);
|
||||
+
|
||||
+out:
|
||||
+ *pdst_sg = dst_sg;
|
||||
+ *pdst_len = dst_len;
|
||||
+ *pdst_offs = dst_offs;
|
||||
+ return res;
|
||||
+}
|
||||
+
|
||||
+/**
|
||||
+ * sg_copy - copy one SG vector to another
|
||||
+ * @dst_sg: destination SG
|
||||
+ * @src_sg: source SG
|
||||
+ * @nents_to_copy: maximum number of entries to copy
|
||||
+ * @copy_len: maximum amount of data to copy. If 0, then copy all.
|
||||
+ *
|
||||
+ * Description:
|
||||
+ * Data from the source SG vector will be copied to the destination SG
|
||||
+ * vector. End of the vectors will be determined by sg_next() returning
|
||||
+ * NULL. Returns number of bytes copied.
|
||||
+ */
|
||||
+int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
|
||||
+ int nents_to_copy, size_t copy_len)
|
||||
+{
|
||||
+ int res = 0;
|
||||
+ size_t dst_len, dst_offs;
|
||||
+
|
||||
+ if (copy_len == 0)
|
||||
+ copy_len = 0x7FFFFFFF; /* copy all */
|
||||
+
|
||||
+ if (nents_to_copy == 0)
|
||||
+ nents_to_copy = 0x7FFFFFFF; /* copy all */
|
||||
+
|
||||
+ dst_len = dst_sg->length;
|
||||
+ dst_offs = dst_sg->offset;
|
||||
+
|
||||
+ do {
|
||||
+ int copied = sg_copy_elem(&dst_sg, &dst_len, &dst_offs,
|
||||
+ src_sg, copy_len);
|
||||
+ copy_len -= copied;
|
||||
+ res += copied;
|
||||
+ if ((copy_len == 0) || (dst_sg == NULL))
|
||||
+ goto out;
|
||||
+
|
||||
+ nents_to_copy--;
|
||||
+ if (nents_to_copy == 0)
|
||||
+ goto out;
|
||||
+
|
||||
+ src_sg = sg_next(src_sg);
|
||||
+ } while (src_sg != NULL);
|
||||
+
|
||||
+out:
|
||||
+ return res;
|
||||
+}
|
||||
+EXPORT_SYMBOL(sg_copy);
|
||||
|
||||
+20
-1
@@ -73,7 +73,23 @@ ifeq ($(INSTALL_MOD_PATH),)
|
||||
export INSTALL_MOD_PATH := $(DESTDIR)
|
||||
endif
|
||||
|
||||
all:
|
||||
ifeq ($(SCST_INC_DIR),)
|
||||
SCST_INC_DIR := ../include
|
||||
endif
|
||||
|
||||
SCST_INTF_VER_FILE := $(SCST_INC_DIR)/scst_itf_ver.h
|
||||
|
||||
$(SCST_INTF_VER_FILE): $(SCST_INC_DIR)/scst.h $(SCST_INC_DIR)/scst_const.h $(SCST_INC_DIR)/scst_user.h
|
||||
echo "/* Autogenerated, don't edit */" >$(SCST_INTF_VER_FILE)
|
||||
echo "" >>$(SCST_INTF_VER_FILE)
|
||||
echo -n "#define SCST_INTF_VER " >>$(SCST_INTF_VER_FILE)
|
||||
echo "\"`sha1sum $(SCST_INC_DIR)/scst.h|awk '{printf $$1}'`\"" >>$(SCST_INTF_VER_FILE)
|
||||
echo -n "#define SCST_CONST_INTF_VER " >>$(SCST_INTF_VER_FILE)
|
||||
echo "\"`sha1sum $(SCST_INC_DIR)/scst_const.h|awk '{printf $$1}'`\"" >>$(SCST_INTF_VER_FILE)
|
||||
echo -n "#define DEV_USER_INTF_VER " >>$(SCST_INTF_VER_FILE)
|
||||
echo "\"`sha1sum $(SCST_INC_DIR)/scst_user.h|awk '{printf $$1}'`\"" >>$(SCST_INTF_VER_FILE)
|
||||
|
||||
all: $(SCST_INTF_VER_FILE)
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd) BUILD_DEV=m
|
||||
|
||||
scst:
|
||||
@@ -99,6 +115,7 @@ install: all
|
||||
install -m 644 ../include/scst_debug.h $(INSTALL_DIR_H)
|
||||
install -m 644 ../include/scst_user.h $(INSTALL_DIR_H)
|
||||
install -m 644 ../include/scst_const.h $(INSTALL_DIR_H)
|
||||
install -m 644 ../include/scst_itf_ver.h $(INSTALL_DIR_H)
|
||||
ifneq ($(MODS_VERS),)
|
||||
rm -f $(INSTALL_DIR_H)/Module.symvers
|
||||
install -m 644 Modules.symvers $(INSTALL_DIR_H)
|
||||
@@ -109,6 +126,7 @@ ifneq ($(MOD_VERS),)
|
||||
endif
|
||||
-/sbin/depmod -b $(INSTALL_MOD_PATH)/ -a $(KVER)
|
||||
mkdir -p $(DESTDIR)/var/lib/scst/pr
|
||||
mkdir -p $(DESTDIR)/var/lib/scst/vdev_mode_pages
|
||||
@echo "****************************************************************"
|
||||
@echo "*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!*"
|
||||
@echo "*!! !!*"
|
||||
@@ -171,6 +189,7 @@ clean:
|
||||
cd $(DEV_HANDLERS_DIR) && $(MAKE) $@
|
||||
|
||||
extraclean: clean
|
||||
rm -f $(SCST_INTF_VER_FILE)
|
||||
cd $(DEV_HANDLERS_DIR) && $(MAKE) $@
|
||||
rm -f *.orig *.rej
|
||||
|
||||
|
||||
@@ -174,6 +174,9 @@ struct scst_vdisk_dev {
|
||||
|
||||
struct file *fd;
|
||||
struct block_device *bdev;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
struct bio_set *vdisk_bioset;
|
||||
#endif
|
||||
|
||||
uint64_t format_progress_to_do, format_progress_done;
|
||||
|
||||
@@ -199,6 +202,10 @@ struct scst_vdisk_dev {
|
||||
char prod_rev_lvl[4 + 1];
|
||||
char scsi_device_name[256 + 1];
|
||||
char t10_dev_id[16+8+2]; /* T10 device ID */
|
||||
int eui64_id_len;
|
||||
uint8_t eui64_id[16];
|
||||
int naa_id_len;
|
||||
uint8_t naa_id[16];
|
||||
char usn[MAX_USN_LEN];
|
||||
uint8_t inq_vend_specific[MAX_INQ_VEND_SPECIFIC_LEN];
|
||||
int inq_vend_specific_len;
|
||||
@@ -389,6 +396,14 @@ static ssize_t vdev_sysfs_t10_dev_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_t10_dev_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_eui64_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_eui64_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_naa_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_naa_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf);
|
||||
static ssize_t vdev_sysfs_usn_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count);
|
||||
static ssize_t vdev_sysfs_usn_show(struct kobject *kobj,
|
||||
@@ -459,6 +474,12 @@ static struct kobj_attribute vdev_scsi_device_name_attr =
|
||||
static struct kobj_attribute vdev_t10_dev_id_attr =
|
||||
__ATTR(t10_dev_id, S_IWUSR|S_IRUGO, vdev_sysfs_t10_dev_id_show,
|
||||
vdev_sysfs_t10_dev_id_store);
|
||||
static struct kobj_attribute vdev_eui64_id_attr =
|
||||
__ATTR(eui64_id, S_IWUSR|S_IRUGO, vdev_sysfs_eui64_id_show,
|
||||
vdev_sysfs_eui64_id_store);
|
||||
static struct kobj_attribute vdev_naa_id_attr =
|
||||
__ATTR(naa_id, S_IWUSR|S_IRUGO, vdev_sysfs_naa_id_show,
|
||||
vdev_sysfs_naa_id_store);
|
||||
static struct kobj_attribute vdev_usn_attr =
|
||||
__ATTR(usn, S_IWUSR|S_IRUGO, vdev_sysfs_usn_show, vdev_sysfs_usn_store);
|
||||
static struct kobj_attribute vdev_inq_vend_specific_attr =
|
||||
@@ -492,6 +513,8 @@ static const struct attribute *vdisk_fileio_attrs[] = {
|
||||
&vdev_prod_rev_lvl_attr.attr,
|
||||
&vdev_scsi_device_name_attr.attr,
|
||||
&vdev_t10_dev_id_attr.attr,
|
||||
&vdev_naa_id_attr.attr,
|
||||
&vdev_eui64_id_attr.attr,
|
||||
&vdev_usn_attr.attr,
|
||||
&vdev_inq_vend_specific_attr.attr,
|
||||
&vdev_zero_copy_attr.attr,
|
||||
@@ -516,6 +539,8 @@ static const struct attribute *vdisk_blockio_attrs[] = {
|
||||
&vdev_prod_rev_lvl_attr.attr,
|
||||
&vdev_scsi_device_name_attr.attr,
|
||||
&vdev_t10_dev_id_attr.attr,
|
||||
&vdev_naa_id_attr.attr,
|
||||
&vdev_eui64_id_attr.attr,
|
||||
&vdev_usn_attr.attr,
|
||||
&vdev_inq_vend_specific_attr.attr,
|
||||
&vdisk_tp_attr.attr,
|
||||
@@ -537,6 +562,8 @@ static const struct attribute *vdisk_nullio_attrs[] = {
|
||||
&vdev_prod_rev_lvl_attr.attr,
|
||||
&vdev_scsi_device_name_attr.attr,
|
||||
&vdev_t10_dev_id_attr.attr,
|
||||
&vdev_naa_id_attr.attr,
|
||||
&vdev_eui64_id_attr.attr,
|
||||
&vdev_usn_attr.attr,
|
||||
&vdev_inq_vend_specific_attr.attr,
|
||||
&vdisk_rotational_attr.attr,
|
||||
@@ -554,6 +581,8 @@ static const struct attribute *vcdrom_attrs[] = {
|
||||
&vdev_prod_rev_lvl_attr.attr,
|
||||
&vdev_scsi_device_name_attr.attr,
|
||||
&vdev_t10_dev_id_attr.attr,
|
||||
&vdev_naa_id_attr.attr,
|
||||
&vdev_eui64_id_attr.attr,
|
||||
&vdev_usn_attr.attr,
|
||||
&vdev_inq_vend_specific_attr.attr,
|
||||
NULL,
|
||||
@@ -566,7 +595,8 @@ static DEFINE_MUTEX(scst_vdisk_mutex);
|
||||
|
||||
/*
|
||||
* Protects the device attributes t10_vend_id, vend_specific_id, prod_id,
|
||||
* prod_rev_lvl, scsi_device_name, t10_dev_id, usn and inq_vend_specific.
|
||||
* prod_rev_lvl, scsi_device_name, t10_dev_id, eui64_id, naa_id, usn and
|
||||
* inq_vend_specific.
|
||||
*/
|
||||
static DEFINE_RWLOCK(vdisk_serial_rwlock);
|
||||
|
||||
@@ -2221,6 +2251,24 @@ static int vcdrom_get_supported_opcodes(struct scst_cmd *cmd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool vdisk_use_zero_copy(const struct scst_cmd *cmd)
|
||||
{
|
||||
struct scst_vdisk_dev *virt_dev = cmd->dev->dh_priv;
|
||||
|
||||
if (!virt_dev->zero_copy)
|
||||
return false;
|
||||
|
||||
switch (cmd->cdb[0]) {
|
||||
case READ_6:
|
||||
case READ_10:
|
||||
case READ_12:
|
||||
case READ_16:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*
|
||||
* Compute p->loff and p->fua.
|
||||
* Returns true for success or false otherwise and set error in the commeand.
|
||||
@@ -2234,7 +2282,7 @@ static bool vdisk_parse_offset(struct vdisk_cmd_params *p, struct scst_cmd *cmd)
|
||||
loff_t loff;
|
||||
struct scst_device *dev = cmd->dev;
|
||||
struct scst_vdisk_dev *virt_dev = dev->dh_priv;
|
||||
bool use_zero_copy = false, res;
|
||||
bool res;
|
||||
int fua = 0;
|
||||
|
||||
TRACE_ENTRY();
|
||||
@@ -2295,15 +2343,6 @@ static bool vdisk_parse_offset(struct vdisk_cmd_params *p, struct scst_cmd *cmd)
|
||||
goto out;
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case READ_6:
|
||||
case READ_10:
|
||||
case READ_12:
|
||||
case READ_16:
|
||||
use_zero_copy = true;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (opcode) {
|
||||
case WRITE_10:
|
||||
case WRITE_12:
|
||||
@@ -2320,7 +2359,7 @@ static bool vdisk_parse_offset(struct vdisk_cmd_params *p, struct scst_cmd *cmd)
|
||||
|
||||
p->loff = loff;
|
||||
p->fua = fua;
|
||||
p->use_zero_copy = use_zero_copy && virt_dev->zero_copy;
|
||||
p->use_zero_copy = vdisk_use_zero_copy(cmd);
|
||||
|
||||
res = true;
|
||||
|
||||
@@ -3247,20 +3286,21 @@ out:
|
||||
static int vdisk_sup_vpd(uint8_t *buf, struct scst_cmd *cmd,
|
||||
struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
buf[3] = 4;
|
||||
buf[4] = 0x0; /* this page */
|
||||
buf[5] = 0x80; /* unit serial number */
|
||||
buf[6] = 0x83; /* device identification */
|
||||
buf[7] = 0x86; /* extended inquiry */
|
||||
char *page_list = &buf[4], *p = page_list;
|
||||
|
||||
*p++ = 0x0; /* this page */
|
||||
*p++ = 0x80; /* unit serial number */
|
||||
*p++ = 0x83; /* device identification */
|
||||
*p++ = 0x86; /* extended inquiry */
|
||||
if (cmd->dev->type == TYPE_DISK) {
|
||||
buf[3] += 2;
|
||||
buf[8] = 0xB0; /* block limits */
|
||||
buf[9] = 0xB1; /* block device charachteristics */
|
||||
*p++ = 0xB0; /* block limits */
|
||||
*p++ = 0xB1; /* block device charachteristics */
|
||||
if (virt_dev->thin_provisioned) {
|
||||
buf[3] += 1;
|
||||
buf[10] = 0xB2; /* thin provisioning */
|
||||
*p++ = 0xB2; /* thin provisioning */
|
||||
}
|
||||
}
|
||||
buf[3] = p - page_list; /* page length */
|
||||
|
||||
return buf[3] + 4;
|
||||
}
|
||||
|
||||
@@ -3288,8 +3328,9 @@ static int vdisk_usn_vpd(uint8_t *buf, struct scst_cmd *cmd,
|
||||
static int vdisk_dev_id_vpd(uint8_t *buf, struct scst_cmd *cmd,
|
||||
struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
int i, resp_len, num = 4;
|
||||
int i, eui64_len = 0, naa_len = 0, resp_len, num = 4;
|
||||
uint16_t tg_id;
|
||||
u8 *eui64_id = NULL, *naa_id = NULL;
|
||||
|
||||
buf[1] = 0x83;
|
||||
|
||||
@@ -3353,30 +3394,48 @@ static int vdisk_dev_id_vpd(uint8_t *buf, struct scst_cmd *cmd,
|
||||
num += 4 + buf[num + 3];
|
||||
}
|
||||
|
||||
/*
|
||||
* IEEE id
|
||||
*/
|
||||
buf[num + 0] = 0x01; /* binary */
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
|
||||
/* EUI-64 */
|
||||
buf[num + 1] = 0x02;
|
||||
buf[num + 2] = 0x00;
|
||||
buf[num + 3] = 0x08;
|
||||
if (virt_dev->eui64_id_len == 0 && virt_dev->naa_id_len == 0) {
|
||||
/*
|
||||
* Compatibility mode: export the first eight bytes of the
|
||||
* t10_dev_id as an EUI-64 ID. This is not entirely standards
|
||||
* compliant since t10_dev_id contains an ASCII string and the
|
||||
* first three bytes of an eight-byte EUI-64 ID are a OUI.
|
||||
*/
|
||||
eui64_len = 8;
|
||||
eui64_id = virt_dev->t10_dev_id;
|
||||
} else {
|
||||
if (virt_dev->eui64_id_len) {
|
||||
eui64_len = virt_dev->eui64_id_len;
|
||||
eui64_id = virt_dev->eui64_id;
|
||||
}
|
||||
if (virt_dev->naa_id_len) {
|
||||
naa_len = virt_dev->naa_id_len;
|
||||
naa_id = virt_dev->naa_id;
|
||||
}
|
||||
}
|
||||
if (eui64_len) {
|
||||
buf[num + 0] = 0x01; /* binary */
|
||||
buf[num + 1] = 0x02; /* EUI-64 */
|
||||
buf[num + 2] = 0x00; /* reserved */
|
||||
buf[num + 3] = eui64_len;
|
||||
memcpy(&buf[num + 4], eui64_id, eui64_len);
|
||||
num += 4 + eui64_len;
|
||||
}
|
||||
if (naa_len) {
|
||||
buf[num + 0] = 0x01; /* binary */
|
||||
buf[num + 1] = 0x03; /* NAA */
|
||||
buf[num + 2] = 0x00; /* reserved */
|
||||
buf[num + 3] = naa_len;
|
||||
memcpy(&buf[num + 4], naa_id, naa_len);
|
||||
num += 4 + naa_len;
|
||||
}
|
||||
|
||||
/* IEEE id */
|
||||
buf[num + 4] = virt_dev->t10_dev_id[0];
|
||||
buf[num + 5] = virt_dev->t10_dev_id[1];
|
||||
buf[num + 6] = virt_dev->t10_dev_id[2];
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
/* IEEE ext id */
|
||||
buf[num + 7] = virt_dev->t10_dev_id[3];
|
||||
buf[num + 8] = virt_dev->t10_dev_id[4];
|
||||
buf[num + 9] = virt_dev->t10_dev_id[5];
|
||||
buf[num + 10] = virt_dev->t10_dev_id[6];
|
||||
buf[num + 11] = virt_dev->t10_dev_id[7];
|
||||
num += buf[num + 3];
|
||||
resp_len = num - 4;
|
||||
|
||||
resp_len = num;
|
||||
put_unaligned_be16(resp_len, &buf[2]);
|
||||
resp_len += 4;
|
||||
|
||||
@@ -5094,6 +5153,10 @@ out_nomem:
|
||||
struct scst_blockio_work {
|
||||
atomic_t bios_inflight;
|
||||
struct scst_cmd *cmd;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
/* just to avoid extra dereferences */
|
||||
struct bio_set *bioset;
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline void blockio_check_finish(struct scst_blockio_work *blockio_work)
|
||||
@@ -5108,6 +5171,15 @@ static inline void blockio_check_finish(struct scst_blockio_work *blockio_work)
|
||||
return;
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
static void blockio_bio_destructor(struct bio *bio)
|
||||
{
|
||||
struct scst_blockio_work *blockio_work = bio->bi_private;
|
||||
bio_free(bio, blockio_work->bioset);
|
||||
blockio_check_finish(blockio_work);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
static int blockio_endio(struct bio *bio, unsigned int bytes_done, int error)
|
||||
#else
|
||||
@@ -5153,7 +5225,9 @@ static void blockio_endio(struct bio *bio, int error)
|
||||
spin_unlock_irqrestore(&blockio_endio_lock, flags);
|
||||
}
|
||||
|
||||
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)) || (LINUX_VERSION_CODE > KERNEL_VERSION(3, 6, 0))
|
||||
blockio_check_finish(blockio_work);
|
||||
#endif
|
||||
|
||||
bio_put(bio);
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
@@ -5163,15 +5237,6 @@ static void blockio_endio(struct bio *bio, int error)
|
||||
#endif
|
||||
}
|
||||
|
||||
static struct bio *vdisk_bio_alloc(gfp_t gfp_mask, int max_nr_vecs)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
return bio_kmalloc(gfp_mask, max_nr_vecs);
|
||||
#else
|
||||
return bio_alloc(gfp_mask, max_nr_vecs);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void vdisk_bio_set_failfast(struct bio *bio)
|
||||
{
|
||||
#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 27)
|
||||
@@ -5223,6 +5288,9 @@ static void blockio_exec_rw(struct vdisk_cmd_params *p, bool write, bool fua)
|
||||
struct scst_vdisk_dev *virt_dev = cmd->dev->dh_priv;
|
||||
int block_shift = cmd->dev->block_shift;
|
||||
struct block_device *bdev = virt_dev->bdev;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
struct bio_set *bs = virt_dev->vdisk_bioset;
|
||||
#endif
|
||||
struct request_queue *q = bdev_get_queue(bdev);
|
||||
int length, max_nr_vecs = 0, offset;
|
||||
struct page *page;
|
||||
@@ -5255,6 +5323,9 @@ static void blockio_exec_rw(struct vdisk_cmd_params *p, bool write, bool fua)
|
||||
#endif
|
||||
|
||||
blockio_work->cmd = cmd;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
blockio_work->bioset = bs;
|
||||
#endif
|
||||
|
||||
if (q)
|
||||
max_nr_vecs = min(bio_get_nr_vecs(bdev), BIO_MAX_PAGES);
|
||||
@@ -5279,7 +5350,12 @@ static void blockio_exec_rw(struct vdisk_cmd_params *p, bool write, bool fua)
|
||||
int rc;
|
||||
|
||||
if (need_new_bio) {
|
||||
bio = vdisk_bio_alloc(gfp_mask, max_nr_vecs);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
bio = bio_alloc_bioset(gfp_mask, max_nr_vecs, bs);
|
||||
#else
|
||||
bio = bio_alloc(gfp_mask, max_nr_vecs);
|
||||
#endif
|
||||
|
||||
if (!bio) {
|
||||
PRINT_ERROR("Failed to create bio "
|
||||
"for data segment %d (cmd %p)",
|
||||
@@ -5297,6 +5373,9 @@ static void blockio_exec_rw(struct vdisk_cmd_params *p, bool write, bool fua)
|
||||
#endif
|
||||
bio->bi_bdev = bdev;
|
||||
bio->bi_private = blockio_work;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
bio->bi_destructor = blockio_bio_destructor;
|
||||
#endif
|
||||
/*
|
||||
* Better to fail fast w/o any local recovery
|
||||
* and retries.
|
||||
@@ -5465,6 +5544,24 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
struct bio_priv_sync {
|
||||
struct completion c;
|
||||
int error;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
struct bio_set *bs;
|
||||
struct completion c1;
|
||||
#endif
|
||||
};
|
||||
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
static void blockio_bio_destructor_sync(struct bio *bio)
|
||||
{
|
||||
struct bio_priv_sync *s = bio->bi_private;
|
||||
bio_free(bio, s->bs);
|
||||
complete(&s->c1);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
static int blockio_end_sync_io(struct bio *bio, unsigned int bytes_done,
|
||||
int error)
|
||||
@@ -5472,7 +5569,7 @@ static int blockio_end_sync_io(struct bio *bio, unsigned int bytes_done,
|
||||
static void blockio_end_sync_io(struct bio *bio, int error)
|
||||
#endif
|
||||
{
|
||||
struct completion *c = bio->bi_private;
|
||||
struct bio_priv_sync *s = bio->bi_private;
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
if (bio->bi_size)
|
||||
@@ -5484,8 +5581,8 @@ static void blockio_end_sync_io(struct bio *bio, int error)
|
||||
error = -EIO;
|
||||
}
|
||||
|
||||
bio->bi_private = (void *)(unsigned long)error;
|
||||
complete(c);
|
||||
s->error = error;
|
||||
complete(&s->c);
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 24)
|
||||
return 0;
|
||||
@@ -5497,7 +5594,13 @@ static void blockio_end_sync_io(struct bio *bio, int error)
|
||||
static ssize_t blockio_rw_sync(struct scst_vdisk_dev *virt_dev, void *buf,
|
||||
size_t len, loff_t *loff, unsigned rw)
|
||||
{
|
||||
DECLARE_COMPLETION_ONSTACK(c);
|
||||
struct bio_priv_sync s = {
|
||||
COMPLETION_INITIALIZER_ONSTACK(s.c), 0,
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
virt_dev->vdisk_bioset,
|
||||
COMPLETION_INITIALIZER_ONSTACK(s.c1)
|
||||
#endif
|
||||
};
|
||||
struct block_device *bdev = virt_dev->bdev;
|
||||
const bool is_vmalloc = is_vmalloc_addr(buf);
|
||||
struct bio *bio;
|
||||
@@ -5506,11 +5609,14 @@ static ssize_t blockio_rw_sync(struct scst_vdisk_dev *virt_dev, void *buf,
|
||||
int max_nr_vecs, rc;
|
||||
unsigned bytes, off;
|
||||
ssize_t ret = -ENOMEM;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
bool submitted = false;
|
||||
#endif
|
||||
|
||||
max_nr_vecs = min(bio_get_nr_vecs(bdev), BIO_MAX_PAGES);
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
bio = bio_kmalloc(GFP_KERNEL, max_nr_vecs);
|
||||
bio = bio_alloc_bioset(GFP_KERNEL, max_nr_vecs, virt_dev->vdisk_bioset);
|
||||
#else
|
||||
bio = bio_alloc(GFP_KERNEL, max_nr_vecs);
|
||||
#endif
|
||||
@@ -5521,7 +5627,10 @@ static ssize_t blockio_rw_sync(struct scst_vdisk_dev *virt_dev, void *buf,
|
||||
bio->bi_rw = rw;
|
||||
bio->bi_bdev = bdev;
|
||||
bio->bi_end_io = blockio_end_sync_io;
|
||||
bio->bi_private = &c;
|
||||
bio->bi_private = &s;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
bio->bi_destructor = blockio_bio_destructor_sync;
|
||||
#endif
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0)
|
||||
bio->bi_sector = *loff >> 9;
|
||||
#else
|
||||
@@ -5536,11 +5645,18 @@ static ssize_t blockio_rw_sync(struct scst_vdisk_dev *virt_dev, void *buf,
|
||||
goto free;
|
||||
}
|
||||
submit_bio(rw, bio);
|
||||
wait_for_completion(&c);
|
||||
ret = (unsigned long)bio->bi_private ? : len;
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
submitted = true;
|
||||
#endif
|
||||
wait_for_completion(&s.c);
|
||||
ret = (unsigned long)s.error ? : len;
|
||||
|
||||
free:
|
||||
bio_put(bio);
|
||||
#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 6, 0))
|
||||
if (submitted)
|
||||
wait_for_completion(&s.c1);
|
||||
#endif
|
||||
|
||||
out:
|
||||
return ret;
|
||||
@@ -5986,6 +6102,34 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
static int vdisk_create_bioset(struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
int res;
|
||||
|
||||
EXTRACHECKS_BUG_ON(virt_dev->vdisk_bioset || !virt_dev->blockio);
|
||||
|
||||
/* Pool size doesn't really matter */
|
||||
virt_dev->vdisk_bioset = bioset_create(2, 0);
|
||||
if (virt_dev->vdisk_bioset == NULL) {
|
||||
PRINT_ERROR("Failed to create bioset (dev %s)", virt_dev->name);
|
||||
res = -ENOMEM;
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = 0;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static void vdisk_free_bioset(struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
if (virt_dev->vdisk_bioset != NULL)
|
||||
bioset_free(virt_dev->vdisk_bioset);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* scst_vdisk_mutex supposed to be held */
|
||||
static int vdev_create(struct scst_dev_type *devt,
|
||||
const char *name, struct scst_vdisk_dev **res_virt_dev)
|
||||
@@ -6050,6 +6194,9 @@ static int vdev_create(struct scst_dev_type *devt,
|
||||
sprintf(virt_dev->scsi_device_name, "%.*s",
|
||||
(int)(sizeof(virt_dev->scsi_device_name) - 1), "");
|
||||
|
||||
virt_dev->eui64_id_len = 0;
|
||||
virt_dev->naa_id_len = 0;
|
||||
|
||||
scnprintf(virt_dev->usn, sizeof(virt_dev->usn), "%llx", dev_id_num);
|
||||
TRACE_DBG("usn %s", virt_dev->usn);
|
||||
|
||||
@@ -6075,6 +6222,9 @@ out_free:
|
||||
|
||||
static void vdev_destroy(struct scst_vdisk_dev *virt_dev)
|
||||
{
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
vdisk_free_bioset(virt_dev);
|
||||
#endif
|
||||
kfree(virt_dev->filename);
|
||||
kfree(virt_dev);
|
||||
return;
|
||||
@@ -6345,6 +6495,12 @@ static int vdev_blockio_add_device(const char *device_name, char *params)
|
||||
goto out_destroy;
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
res = vdisk_create_bioset(virt_dev);
|
||||
if (res != 0)
|
||||
goto out_destroy;
|
||||
#endif
|
||||
|
||||
list_add_tail(&virt_dev->vdev_list_entry, &vdev_list);
|
||||
|
||||
vdisk_report_registering(virt_dev);
|
||||
@@ -7706,6 +7862,161 @@ static ssize_t vdev_sysfs_t10_dev_id_show(struct kobject *kobj,
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_eui64_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int res = count;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
while (count > 0 && isspace((uint8_t)buf[0])) {
|
||||
buf++;
|
||||
count--;
|
||||
}
|
||||
while (count > 0 && isspace((uint8_t)buf[count - 1]))
|
||||
count--;
|
||||
if (count >= 2 && buf[0] == '0' && buf[1] == 'x') {
|
||||
buf += 2;
|
||||
count -= 2;
|
||||
}
|
||||
|
||||
switch (count) {
|
||||
case 0:
|
||||
case 2 * 8:
|
||||
case 2 * 12:
|
||||
case 2 * 16:
|
||||
break;
|
||||
default:
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
write_lock(&vdisk_serial_rwlock);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) || \
|
||||
defined(CONFIG_SUSE_KERNEL) && \
|
||||
LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 76)
|
||||
if (hex2bin(virt_dev->eui64_id, buf, count / 2) == 0)
|
||||
virt_dev->eui64_id_len = count / 2;
|
||||
else
|
||||
res = -EINVAL;
|
||||
#else
|
||||
memset(virt_dev->eui64_id, 0, sizeof(virt_dev->eui64_id));
|
||||
hex2bin(virt_dev->eui64_id, buf, count / 2);
|
||||
virt_dev->eui64_id_len = count / 2;
|
||||
#endif
|
||||
write_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_eui64_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
int i, pos = 0;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
if (virt_dev->eui64_id_len)
|
||||
pos += sprintf(buf + pos, "0x");
|
||||
for (i = 0; i < virt_dev->eui64_id_len; i++)
|
||||
pos += sprintf(buf + pos, "%02x", virt_dev->eui64_id[i]);
|
||||
pos += sprintf(buf + pos, "\n%s", virt_dev->eui64_id_len ?
|
||||
SCST_SYSFS_KEY_MARK "\n" : "");
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_naa_id_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr,
|
||||
const char *buf, size_t count)
|
||||
{
|
||||
int res = -EINVAL, c = count;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
while (c > 0 && isspace((uint8_t)buf[0])) {
|
||||
buf++;
|
||||
c--;
|
||||
}
|
||||
while (c > 0 && isspace((uint8_t)buf[c - 1]))
|
||||
c--;
|
||||
if (c >= 2 && buf[0] == '0' && buf[1] == 'x') {
|
||||
buf += 2;
|
||||
c -= 2;
|
||||
}
|
||||
|
||||
switch (c) {
|
||||
case 0:
|
||||
case 2 * 8:
|
||||
if (strchr("1235cCdDeEfF", buf[0]))
|
||||
break;
|
||||
else
|
||||
goto out;
|
||||
case 2 * 16:
|
||||
if (strchr("6", buf[0]))
|
||||
break;
|
||||
else
|
||||
goto out;
|
||||
default:
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = count;
|
||||
|
||||
write_lock(&vdisk_serial_rwlock);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) || \
|
||||
defined(CONFIG_SUSE_KERNEL) && \
|
||||
LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 76)
|
||||
if (hex2bin(virt_dev->naa_id, buf, c / 2) == 0)
|
||||
virt_dev->naa_id_len = c / 2;
|
||||
else
|
||||
res = -EINVAL;
|
||||
#else
|
||||
memset(virt_dev->naa_id, 0, sizeof(virt_dev->naa_id));
|
||||
hex2bin(virt_dev->naa_id, buf, c / 2);
|
||||
virt_dev->naa_id_len = c / 2;
|
||||
#endif
|
||||
write_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_naa_id_show(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
int i, pos = 0;
|
||||
struct scst_device *dev;
|
||||
struct scst_vdisk_dev *virt_dev;
|
||||
|
||||
dev = container_of(kobj, struct scst_device, dev_kobj);
|
||||
virt_dev = dev->dh_priv;
|
||||
|
||||
read_lock(&vdisk_serial_rwlock);
|
||||
if (virt_dev->naa_id_len)
|
||||
pos += sprintf(buf + pos, "0x");
|
||||
for (i = 0; i < virt_dev->naa_id_len; i++)
|
||||
pos += sprintf(buf + pos, "%02x", virt_dev->naa_id[i]);
|
||||
pos += sprintf(buf + pos, "\n%s", virt_dev->naa_id_len ?
|
||||
SCST_SYSFS_KEY_MARK "\n" : "");
|
||||
read_unlock(&vdisk_serial_rwlock);
|
||||
|
||||
return pos;
|
||||
}
|
||||
|
||||
static ssize_t vdev_sysfs_usn_store(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf, size_t count)
|
||||
{
|
||||
@@ -8068,6 +8379,11 @@ static int vdisk_write_proc(char *buffer, char **start, off_t offset,
|
||||
} else if (!strncmp("BLOCKIO", p, 7)) {
|
||||
p += 7;
|
||||
virt_dev->blockio = 1;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
|
||||
res = vdisk_create_bioset(virt_dev);
|
||||
if (res != 0)
|
||||
goto out_free_vdev;
|
||||
#endif
|
||||
/* Bad hack for anyway going out procfs */
|
||||
virt_dev->vdev_devt = &vdisk_blk_devtype;
|
||||
sprintf(virt_dev->t10_vend_id, "%.*s",
|
||||
|
||||
+22
-2
@@ -100,6 +100,23 @@ char *kvasprintf(gfp_t gfp, const char *fmt, va_list ap)
|
||||
}
|
||||
#endif
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 35)
|
||||
/*
|
||||
* See also "lib: introduce common method to convert hex digits" (commit
|
||||
* 903788892ea0fc7fcaf7e8e5fac9a77379fc215b).
|
||||
*/
|
||||
int hex_to_bin(char ch)
|
||||
{
|
||||
if (ch >= '0' && ch <= '9')
|
||||
return ch - '0';
|
||||
ch = tolower(ch);
|
||||
if (ch >= 'a' && ch <= 'f')
|
||||
return ch - 'a' + 10;
|
||||
return -1;
|
||||
}
|
||||
EXPORT_SYMBOL(hex_to_bin);
|
||||
#endif
|
||||
|
||||
#if !((LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)) && defined(SCSI_EXEC_REQ_FIFO_DEFINED)) && !defined(HAVE_SG_COPY)
|
||||
static int sg_copy(struct scatterlist *dst_sg, struct scatterlist *src_sg,
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0)
|
||||
@@ -5091,10 +5108,13 @@ static void scst_complete_request_sense(struct scst_cmd *req_cmd)
|
||||
len = scst_get_buf_full(req_cmd, &buf);
|
||||
|
||||
if (scsi_status_is_good(req_cmd->status) && (len > 0) &&
|
||||
scst_sense_valid(buf) && !scst_no_sense(buf)) {
|
||||
scst_sense_valid(buf)) {
|
||||
TRACE(TRACE_SCSI|TRACE_MGMT_DEBUG, "REQUEST SENSE %p returned "
|
||||
"valid sense", req_cmd);
|
||||
"valid sense (orig cmd %s)", req_cmd, orig_cmd->op_name);
|
||||
PRINT_BUFF_FLAG(TRACE_SCSI|TRACE_MGMT_DEBUG, "Sense", buf, len);
|
||||
if (scst_no_sense(buf))
|
||||
PRINT_WARNING("REQUEST SENSE returned NO SENSE (orig "
|
||||
"cmd %s)", orig_cmd->op_name);
|
||||
scst_alloc_set_sense(orig_cmd, scst_cmd_atomic(req_cmd),
|
||||
buf, len);
|
||||
} else {
|
||||
|
||||
+56
-25
@@ -1353,8 +1353,18 @@ static int scst_check_device_name(const char *dev_name)
|
||||
PRINT_ERROR("Dev name %s contains illegal character '/'",
|
||||
dev_name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* To prevent collision with saved PR and mode pages backup files */
|
||||
if (strchr(dev_name, '.') != NULL) {
|
||||
PRINT_ERROR("Dev name %s contains illegal character '.'",
|
||||
dev_name);
|
||||
res = -EINVAL;
|
||||
goto out;
|
||||
}
|
||||
|
||||
out:
|
||||
TRACE_EXIT_RES(res);
|
||||
return res;
|
||||
}
|
||||
@@ -1848,7 +1858,6 @@ void scst_unregister_virtual_dev_driver(struct scst_dev_type *dev_type)
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(scst_unregister_virtual_dev_driver);
|
||||
|
||||
/* scst_mutex supposed to be held */
|
||||
int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
struct scst_device *dev, struct scst_tgt_dev *tgt_dev, int num)
|
||||
{
|
||||
@@ -1863,9 +1872,9 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
goto out;
|
||||
}
|
||||
|
||||
list_for_each_entry(thr, &cmd_threads->threads_list, thread_list_entry) {
|
||||
n++;
|
||||
}
|
||||
spin_lock(&cmd_threads->thr_lock);
|
||||
n = cmd_threads->nr_threads;
|
||||
spin_unlock(&cmd_threads->thr_lock);
|
||||
|
||||
TRACE_DBG("cmd_threads %p, dev %s, tgt_dev %p, num %d, n %d",
|
||||
cmd_threads, dev ? dev->virt_name : NULL, tgt_dev, num, n);
|
||||
@@ -1881,7 +1890,7 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
}
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
thr = kmalloc(sizeof(*thr), GFP_KERNEL);
|
||||
thr = kzalloc(sizeof(*thr), GFP_KERNEL);
|
||||
if (!thr) {
|
||||
res = -ENOMEM;
|
||||
PRINT_ERROR("Fail to allocate thr %d", res);
|
||||
@@ -1912,20 +1921,17 @@ int scst_add_threads(struct scst_cmd_threads *cmd_threads,
|
||||
* sess->acg can be NULL here, if called from
|
||||
* scst_check_reassign_sess()!
|
||||
*/
|
||||
#if defined(RHEL_MAJOR) && RHEL_MAJOR -0 <= 5
|
||||
rc = set_cpus_allowed(thr->cmd_thread,
|
||||
tgt_dev->acg_dev->acg->acg_cpu_mask);
|
||||
#else
|
||||
rc = set_cpus_allowed_ptr(thr->cmd_thread,
|
||||
&tgt_dev->acg_dev->acg->acg_cpu_mask);
|
||||
#endif
|
||||
if (rc != 0)
|
||||
PRINT_ERROR("Setting CPU affinity failed: "
|
||||
"%d", rc);
|
||||
}
|
||||
|
||||
spin_lock(&cmd_threads->thr_lock);
|
||||
list_add(&thr->thread_list_entry, &cmd_threads->threads_list);
|
||||
cmd_threads->nr_threads++;
|
||||
spin_unlock(&cmd_threads->thr_lock);
|
||||
|
||||
TRACE_DBG("Added thr %p to threads list (nr_threads %d, n %d)",
|
||||
thr, cmd_threads->nr_threads, n);
|
||||
@@ -1955,43 +1961,67 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
/* scst_mutex supposed to be held */
|
||||
void scst_del_threads(struct scst_cmd_threads *cmd_threads, int num)
|
||||
{
|
||||
struct scst_cmd_thread_t *ct, *tmp;
|
||||
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (num == 0)
|
||||
goto out;
|
||||
|
||||
list_for_each_entry_safe_reverse(ct, tmp, &cmd_threads->threads_list,
|
||||
thread_list_entry) {
|
||||
for ( ; num != 0; num--) {
|
||||
struct scst_cmd_thread_t *ct = NULL, *ct2;
|
||||
int rc;
|
||||
|
||||
spin_lock(&cmd_threads->thr_lock);
|
||||
list_for_each_entry_reverse(ct2, &cmd_threads->threads_list,
|
||||
thread_list_entry) {
|
||||
if (!ct2->being_stopped) {
|
||||
ct = ct2;
|
||||
ct->being_stopped = true;
|
||||
cmd_threads->nr_threads--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&cmd_threads->thr_lock);
|
||||
|
||||
if (!ct)
|
||||
break;
|
||||
|
||||
rc = kthread_stop(ct->cmd_thread);
|
||||
if (rc != 0 && rc != -EINTR)
|
||||
TRACE_MGMT_DBG("kthread_stop() failed: %d", rc);
|
||||
|
||||
spin_lock(&cmd_threads->thr_lock);
|
||||
list_del(&ct->thread_list_entry);
|
||||
spin_unlock(&cmd_threads->thr_lock);
|
||||
|
||||
kfree(ct);
|
||||
|
||||
cmd_threads->nr_threads--;
|
||||
|
||||
--num;
|
||||
if (num == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
EXTRACHECKS_BUG_ON((cmd_threads->nr_threads == 0) &&
|
||||
(cmd_threads->io_context != NULL));
|
||||
|
||||
out:
|
||||
TRACE_EXIT();
|
||||
return;
|
||||
}
|
||||
|
||||
/* scst_mutex supposed to be held */
|
||||
int scst_set_thr_cpu_mask(struct scst_cmd_threads *cmd_threads,
|
||||
cpumask_t *cpu_mask)
|
||||
{
|
||||
struct scst_cmd_thread_t *thr;
|
||||
int rc = 0;
|
||||
|
||||
spin_lock(&cmd_threads->thr_lock);
|
||||
list_for_each_entry(thr, &cmd_threads->threads_list,
|
||||
thread_list_entry) {
|
||||
rc = set_cpus_allowed_ptr(thr->cmd_thread, cpu_mask);
|
||||
if (rc)
|
||||
break;
|
||||
}
|
||||
spin_unlock(&cmd_threads->thr_lock);
|
||||
|
||||
return rc;
|
||||
}
|
||||
EXPORT_SYMBOL(scst_set_thr_cpu_mask);
|
||||
|
||||
/* The activity supposed to be suspended and scst_mutex held */
|
||||
void scst_stop_dev_threads(struct scst_device *dev)
|
||||
{
|
||||
@@ -2177,6 +2207,7 @@ void scst_init_threads(struct scst_cmd_threads *cmd_threads)
|
||||
init_waitqueue_head(&cmd_threads->cmd_list_waitQ);
|
||||
INIT_LIST_HEAD(&cmd_threads->threads_list);
|
||||
mutex_init(&cmd_threads->io_context_mutex);
|
||||
spin_lock_init(&cmd_threads->thr_lock);
|
||||
|
||||
mutex_lock(&scst_cmd_threads_mutex);
|
||||
list_add_tail(&cmd_threads->lists_list_entry,
|
||||
|
||||
@@ -1111,19 +1111,21 @@ int scst_pr_set_file_name(struct scst_device *dev, char **prev,
|
||||
|
||||
res = -EINVAL;
|
||||
if (pr_file_name[0] != '/') {
|
||||
PRINT_ERROR("PR file name must be absolute!");
|
||||
PRINT_ERROR("PR file name %s must be absolute!", pr_file_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
file_mode = scst_get_file_mode(pr_file_name);
|
||||
if (file_mode >= 0 && !S_ISREG(file_mode) && !S_ISBLK(file_mode)) {
|
||||
PRINT_ERROR("PR file name must be file or block device!");
|
||||
PRINT_ERROR("PR file name %s must be file or block device!",
|
||||
pr_file_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
res = -ENOENT;
|
||||
if (!scst_parent_dir_exists(pr_file_name)) {
|
||||
PRINT_ERROR("PR file name parent directory doesn't exist");
|
||||
PRINT_ERROR("PR file name %s parent directory doesn't exist",
|
||||
pr_file_name);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
@@ -211,6 +211,7 @@ extern cpumask_t default_cpu_mask;
|
||||
struct scst_cmd_thread_t {
|
||||
struct task_struct *cmd_thread;
|
||||
struct list_head thread_list_entry;
|
||||
bool being_stopped;
|
||||
};
|
||||
|
||||
static inline bool scst_set_io_context(struct scst_cmd *cmd,
|
||||
|
||||
+8
-12
@@ -1916,18 +1916,14 @@ static int __scst_acg_process_cpu_mask_store(struct scst_tgt *tgt,
|
||||
struct list_head *head = &sess->sess_tgt_dev_list[i];
|
||||
list_for_each_entry(tgt_dev, head,
|
||||
sess_tgt_dev_list_entry) {
|
||||
struct scst_cmd_thread_t *thr;
|
||||
int rc;
|
||||
|
||||
if (tgt_dev->active_cmd_threads != &tgt_dev->tgt_dev_cmd_threads)
|
||||
continue;
|
||||
list_for_each_entry(thr,
|
||||
&tgt_dev->active_cmd_threads->threads_list,
|
||||
thread_list_entry) {
|
||||
int rc;
|
||||
rc = set_cpus_allowed_ptr(thr->cmd_thread, cpu_mask);
|
||||
if (rc != 0)
|
||||
PRINT_ERROR("Setting CPU "
|
||||
"affinity failed: %d", rc);
|
||||
}
|
||||
rc = scst_set_thr_cpu_mask(tgt_dev->active_cmd_threads, cpu_mask);
|
||||
if (rc != 0)
|
||||
PRINT_ERROR("Setting CPU affinity"
|
||||
" failed: %d", rc);
|
||||
}
|
||||
}
|
||||
if (tgt->tgtt->report_aen != NULL) {
|
||||
@@ -2576,7 +2572,7 @@ out: \
|
||||
} \
|
||||
\
|
||||
static struct kobj_attribute scst_tgt_##attr##_attr = \
|
||||
__ATTR(attr, S_IRUGO, scst_tgt_sysfs_##attr##_show, NULL);
|
||||
__ATTR(attr, S_IRUGO, scst_tgt_sysfs_##attr##_show, NULL)
|
||||
|
||||
SCST_TGT_SYSFS_STAT_ATTR(cmd_count, unknown_cmd_count, SCST_DATA_UNKNOWN, >> 0);
|
||||
SCST_TGT_SYSFS_STAT_ATTR(cmd_count, write_cmd_count, SCST_DATA_WRITE, >> 0);
|
||||
@@ -3971,7 +3967,7 @@ static ssize_t scst_sess_sysfs_##exported_name##_store(struct kobject *kobj, \
|
||||
static struct kobj_attribute session_##exported_name##_attr = \
|
||||
__ATTR(exported_name, S_IRUGO | S_IWUSR, \
|
||||
scst_sess_sysfs_##exported_name##_show, \
|
||||
scst_sess_sysfs_##exported_name##_store);
|
||||
scst_sess_sysfs_##exported_name##_store)
|
||||
|
||||
SCST_SESS_SYSFS_STAT_ATTR(cmd_count, unknown_cmd_count, SCST_DATA_UNKNOWN, 0);
|
||||
SCST_SESS_SYSFS_STAT_ATTR(cmd_count, write_cmd_count, SCST_DATA_WRITE, 0);
|
||||
|
||||
+41
-20
@@ -3380,11 +3380,21 @@ static int scst_check_sense(struct scst_cmd *cmd)
|
||||
|
||||
/* If we had internal bus reset behind us, set the command error UA */
|
||||
if ((dev->scsi_dev != NULL) &&
|
||||
unlikely(cmd->host_status == DID_RESET) &&
|
||||
((cmd->op_flags & SCST_SKIP_UA) == 0)) {
|
||||
TRACE(TRACE_MGMT, "DID_RESET: was_reset=%d host_status=%x",
|
||||
dev->scsi_dev->was_reset, cmd->host_status);
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_reset_UA));
|
||||
unlikely(cmd->host_status == DID_RESET)) {
|
||||
if ((cmd->op_flags & SCST_SKIP_UA) == 0) {
|
||||
TRACE(TRACE_MGMT, "DID_RESET: was_reset=%d host_status=%x",
|
||||
dev->scsi_dev->was_reset, cmd->host_status);
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_reset_UA));
|
||||
} else {
|
||||
int sl;
|
||||
uint8_t sense[SCST_STANDARD_SENSE_LEN];
|
||||
TRACE(TRACE_MGMT, "DID_RESET received for device %s, "
|
||||
"triggering reset UA", dev->virt_name);
|
||||
sl = scst_set_sense(sense, sizeof(sense), dev->d_sense,
|
||||
SCST_LOAD_SENSE(scst_sense_reset_UA));
|
||||
scst_dev_check_set_UA(dev, NULL, sense, sl);
|
||||
scst_abort_cmd(cmd, NULL, false, false);
|
||||
}
|
||||
/* It looks like it is safe to clear was_reset here */
|
||||
dev->scsi_dev->was_reset = 0;
|
||||
}
|
||||
@@ -3465,7 +3475,7 @@ static bool scst_check_auto_sense(struct scst_cmd *cmd)
|
||||
TRACE_ENTRY();
|
||||
|
||||
if (unlikely(cmd->status == SAM_STAT_CHECK_CONDITION) &&
|
||||
(!scst_sense_valid(cmd->sense) || scst_no_sense(cmd->sense))) {
|
||||
!scst_sense_valid(cmd->sense)) {
|
||||
if (!test_bit(SCST_CMD_ABORTED, &cmd->cmd_flags)) {
|
||||
TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG,
|
||||
"CHECK_CONDITION, but no sense: cmd->status=%x, "
|
||||
@@ -3479,8 +3489,23 @@ static bool scst_check_auto_sense(struct scst_cmd *cmd)
|
||||
if ((cmd->host_status == DID_REQUEUE) ||
|
||||
(cmd->host_status == DID_IMM_RETRY) ||
|
||||
(cmd->host_status == DID_SOFT_ERROR) ||
|
||||
(cmd->host_status == DID_ABORT)) {
|
||||
(cmd->host_status == DID_BUS_BUSY) ||
|
||||
(cmd->host_status == DID_TRANSPORT_DISRUPTED) ||
|
||||
(cmd->host_status == DID_TRANSPORT_FAILFAST) ||
|
||||
(cmd->host_status == DID_ALLOC_FAILURE)) {
|
||||
scst_set_busy(cmd);
|
||||
} else if (cmd->host_status == DID_RESET) {
|
||||
/* Postpone handling to scst_check_sense() */
|
||||
} else if ((cmd->host_status == DID_ABORT) ||
|
||||
(cmd->host_status == DID_NO_CONNECT) ||
|
||||
(cmd->host_status == DID_TIME_OUT) ||
|
||||
(cmd->host_status == DID_NEXUS_FAILURE)) {
|
||||
scst_abort_cmd(cmd, NULL, false, false);
|
||||
} else if (cmd->host_status == DID_MEDIUM_ERROR) {
|
||||
if (cmd->data_direction & SCST_DATA_WRITE)
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_write_error));
|
||||
else
|
||||
scst_set_cmd_error(cmd, SCST_LOAD_SENSE(scst_sense_read_error));
|
||||
} else {
|
||||
TRACE(TRACE_SCSI|TRACE_MINOR_AND_MGMT_DBG, "Host "
|
||||
"status 0x%x received, returning HARDWARE ERROR "
|
||||
@@ -4845,7 +4870,6 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
|
||||
if (res == SCST_CMD_STATE_RES_CONT_NEXT) {
|
||||
/* None */
|
||||
} else if (res == SCST_CMD_STATE_RES_NEED_THREAD) {
|
||||
spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
switch (cmd->state) {
|
||||
case SCST_CMD_STATE_PARSE:
|
||||
@@ -4858,22 +4882,18 @@ void scst_process_active_cmd(struct scst_cmd *cmd, bool atomic)
|
||||
case SCST_CMD_STATE_REAL_EXEC:
|
||||
case SCST_CMD_STATE_DEV_DONE:
|
||||
case SCST_CMD_STATE_XMIT_RESP:
|
||||
#endif
|
||||
TRACE_DBG("Adding cmd %p to head of active cmd list",
|
||||
cmd);
|
||||
list_add(&cmd->cmd_list_entry,
|
||||
&cmd->cmd_threads->active_cmd_list);
|
||||
#ifdef CONFIG_SCST_EXTRACHECKS
|
||||
break;
|
||||
default:
|
||||
PRINT_CRIT_ERROR("cmd %p is in invalid state %d)", cmd,
|
||||
cmd->state);
|
||||
#if !defined(__CHECKER__)
|
||||
spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
|
||||
#endif
|
||||
sBUG();
|
||||
}
|
||||
#endif
|
||||
TRACE_DBG("Adding cmd %p to head of active cmd list", cmd);
|
||||
|
||||
spin_lock_irq(&cmd->cmd_threads->cmd_list_lock);
|
||||
list_add(&cmd->cmd_list_entry,
|
||||
&cmd->cmd_threads->active_cmd_list);
|
||||
wake_up(&cmd->cmd_threads->cmd_list_waitQ);
|
||||
spin_unlock_irq(&cmd->cmd_threads->cmd_list_lock);
|
||||
} else
|
||||
@@ -5404,13 +5424,14 @@ void scst_abort_cmd(struct scst_cmd *cmd, struct scst_mgmt_cmd *mcmd,
|
||||
"op %s, proc time %ld sec., timeout %d sec.), "
|
||||
"deferring ABORT (cmd_done_wait_count %d, "
|
||||
"cmd_finish_wait_count %d, internal %d, mcmd "
|
||||
"fn %d (mcmd %p))", cmd,
|
||||
(long long unsigned int)cmd->tag,
|
||||
"fn %d (mcmd %p), initiator %s, target %s)",
|
||||
cmd, (long long unsigned int)cmd->tag,
|
||||
cmd->sn, cmd->state, scst_get_opcode_name(cmd),
|
||||
(long)(jiffies - cmd->start_time) / HZ,
|
||||
cmd->timeout / HZ, mcmd->cmd_done_wait_count,
|
||||
mcmd->cmd_finish_wait_count, cmd->internal,
|
||||
mcmd->fn, mcmd);
|
||||
mcmd->fn, mcmd, mcmd->sess->initiator_name,
|
||||
mcmd->sess->tgt->tgt_name);
|
||||
/*
|
||||
* cmd can't die here or sess_list_lock already taken
|
||||
* and cmd is in the sess list
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
obj-$(CONFIG_SCST_LOCAL) += scst_local.o
|
||||
|
||||
@@ -4708,6 +4708,9 @@ sub sessions {
|
||||
}
|
||||
} else {
|
||||
my $mode = (stat($pPath))[2];
|
||||
if (!$mode) {
|
||||
$mode = 0;
|
||||
}
|
||||
if (-d $pPath) {
|
||||
# Skip directories
|
||||
} else {
|
||||
|
||||
+15
-14
@@ -11,7 +11,6 @@ SCST_INC_DIR := $(shell if [ -e "$$PWD/../scst" ]; \
|
||||
SCST_SYMVERS_DIR := $(shell if [ -e $$PWD/../scst ]; then \
|
||||
echo $$PWD/../scst/src; \
|
||||
else echo $(DESTDIR)$(PREFIX)/include/scst; fi)
|
||||
SUBDIRS := $(shell pwd)
|
||||
|
||||
ifeq ($(KVER),)
|
||||
ifeq ($(KDIR),)
|
||||
@@ -61,18 +60,21 @@ ifeq ($(OFED_KERNEL_IB_RPM),compat-rdma)
|
||||
OFED_KERNEL_DIR:=/usr/src/compat-rdma
|
||||
OFED_CFLAGS:=-I$(OFED_KERNEL_DIR)/include
|
||||
else
|
||||
OFED_KERNEL_DIR:=/usr/src/ofa_kernel
|
||||
ifeq ($(OFED_FLAVOR),MOFED)
|
||||
# Mellanox OFED with or without kernel-ib RPM
|
||||
OFED_CFLAGS:=-I$(OFED_KERNEL_DIR)/include
|
||||
# Mellanox OFED with or without kernel-ib RPM. Since several MOFED backport
|
||||
# header files use the LINUX_BACKPORT() macro without including
|
||||
# <linux/compat-2.6.h>, include that header file explicitly.
|
||||
OFED_KERNEL_DIR:=/usr/src/ofa_kernel/default
|
||||
OFED_CFLAGS:=-I$(OFED_KERNEL_DIR)/include -include linux/compat-2.6.h
|
||||
else
|
||||
# OFED 1.5
|
||||
OFED_KERNEL_DIR:=/usr/src/ofa_kernel
|
||||
include $(OFED_KERNEL_DIR)/config.mk
|
||||
OFED_CFLAGS:=$(BACKPORT_INCLUDES) -I$(OFED_KERNEL_DIR)/include
|
||||
endif
|
||||
endif
|
||||
# Any OFED version
|
||||
OFED_MODULE_SYMVERS:=$(OFED_KERNEL_DIR)/Module.symvers
|
||||
OFED_MODULE_SYMVERS:=$(OFED_KERNEL_DIR)/$(MODULE_SYMVERS)
|
||||
endif
|
||||
|
||||
HAVE_KCFLAGS = $(shell $(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd)/conftest/kcflags KCFLAGS=-DKCFLAGS_MACRO=1 >/dev/null 2>&1 && echo true || echo false)
|
||||
@@ -98,7 +100,8 @@ uninstall:
|
||||
rm -f $(INSTALL_DIR)/ib_srpt.ko
|
||||
-/sbin/depmod -b $(INSTALL_MOD_PATH)/ -a $(KVER)
|
||||
|
||||
src/Module.symvers src/Modules.symvers: $(SCST_SYMVERS_DIR)/$(MODULE_SYMVERS)
|
||||
src/$(MODULE_SYMVERS): $(SCST_SYMVERS_DIR)/$(MODULE_SYMVERS) \
|
||||
$(OFED_MODULE_SYMVERS)
|
||||
@if [ "$(HAVE_KCFLAGS)" = false -a "$(HAVE_PRE_CFLAGS)" = false -a \
|
||||
-n "$(AUTOCONF_FLAGS)" ]; then \
|
||||
echo "Error: the kernel build system has not yet been patched.";\
|
||||
@@ -109,11 +112,6 @@ src/Module.symvers src/Modules.symvers: $(SCST_SYMVERS_DIR)/$(MODULE_SYMVERS)
|
||||
echo "Error: the OFED package $(OFED_KERNEL_IB_RPM)-devel has" \
|
||||
"not yet been installed."; \
|
||||
false; \
|
||||
elif [ -e /lib/modules/$(KVER)/kernel/drivers/infiniband ]; then \
|
||||
echo "Error: the distro-provided InfiniBand kernel drivers" \
|
||||
"must be removed first" \
|
||||
" (/lib/modules/$(KVER)/kernel/drivers/infiniband)."; \
|
||||
false; \
|
||||
elif [ "$(HAVE_PRE_CFLAGS)" = false ]; then \
|
||||
echo "Error: the kernel build system has not yet been patched.";\
|
||||
false; \
|
||||
@@ -121,7 +119,11 @@ src/Module.symvers src/Modules.symvers: $(SCST_SYMVERS_DIR)/$(MODULE_SYMVERS)
|
||||
echo " Building against $(OFED_FLAVOR) $(OFED_KERNEL_IB_RPM)" \
|
||||
"InfiniBand kernel headers."; \
|
||||
( \
|
||||
grep -v drivers/infiniband/ $<; \
|
||||
cat $(SCST_SYMVERS_DIR)/$(MODULE_SYMVERS) | \
|
||||
grep -v 'drivers/infiniband/' | \
|
||||
grep -v 'net/sunrpc/xprtrdma/' | \
|
||||
grep -v 'net/rds/' | \
|
||||
grep -v 'extra/ib_srpt'; \
|
||||
cat $(OFED_MODULE_SYMVERS) \
|
||||
) >$@; \
|
||||
fi \
|
||||
@@ -138,8 +140,7 @@ src/Module.symvers src/Modules.symvers: $(SCST_SYMVERS_DIR)/$(MODULE_SYMVERS)
|
||||
|
||||
clean:
|
||||
$(MAKE) -C $(KDIR) SUBDIRS=$(shell pwd)/src clean
|
||||
rm -f src/Modules.symvers src/Module.symvers src/Module.markers \
|
||||
src/modules.order
|
||||
rm -f src/$(MODULE_SYMVERS) src/Module.markers src/modules.order
|
||||
|
||||
extraclean: clean
|
||||
rm -f *.orig *.rej
|
||||
|
||||
+1
-1
@@ -61,7 +61,7 @@ the variable PRE_CFLAGS:
|
||||
if [ -e /lib/modules/$(uname -r)/build/scripts/Makefile.lib ]; then
|
||||
cd /lib/modules/$(uname -r)/build
|
||||
else
|
||||
cd /usr/src/linux-$(uname -r)
|
||||
cd /usr/src/linux-$(uname -r | sed 's/\(-default\|-trace\|-xen\)$//;s/\.[0-9]\+\.[0-9]\+\.[0-9]\+\.PTF$//')
|
||||
fi
|
||||
patch -p1 < ${SCST_DIR}/srpt/patches/kernel-${KV}-pre-cflags.patch
|
||||
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
diff --git a/Makefile b/Makefile
|
||||
index 540f7b2..078307f 100644
|
||||
--- a/Makefile
|
||||
+++ b/Makefile
|
||||
@@ -361,6 +361,7 @@ USERINCLUDE := \
|
||||
# Use LINUXINCLUDE when you must reference the include/ directory.
|
||||
# Needed to be compatible with the O= option
|
||||
LINUXINCLUDE := \
|
||||
+ $(PRE_CFLAGS) \
|
||||
-I$(srctree)/arch/$(hdr-arch)/include \
|
||||
-Iarch/$(hdr-arch)/include/generated \
|
||||
$(if $(KBUILD_SRC), -I$(srctree)/include) \
|
||||
+153
-31
@@ -348,8 +348,8 @@ static const char *get_ch_state_name(enum rdma_ch_state s)
|
||||
*/
|
||||
static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
|
||||
{
|
||||
TRACE_DBG("QP event %d on ch=%p sess_name=%s state=%s",
|
||||
event->event, ch, ch->sess_name,
|
||||
TRACE_DBG("QP event %d on ch=%p sess_name=%s-%d state=%s",
|
||||
event->event, ch, ch->sess_name, ch->qp->qp_num,
|
||||
get_ch_state_name(ch->state));
|
||||
|
||||
switch (event->event) {
|
||||
@@ -366,8 +366,9 @@ static void srpt_qp_event(struct ib_event *event, struct srpt_rdma_ch *ch)
|
||||
#endif
|
||||
break;
|
||||
case IB_EVENT_QP_LAST_WQE_REACHED:
|
||||
TRACE_DBG("%s, state %s: received Last WQE event.",
|
||||
ch->sess_name, get_ch_state_name(ch->state));
|
||||
TRACE_DBG("%s-%d, state %s: received Last WQE event.",
|
||||
ch->sess_name, ch->qp->qp_num,
|
||||
get_ch_state_name(ch->state));
|
||||
break;
|
||||
default:
|
||||
PRINT_ERROR("received unrecognized IB QP event %d",
|
||||
@@ -690,7 +691,11 @@ static int srpt_refresh_port(struct srpt_port *sport)
|
||||
®_req, 0,
|
||||
srpt_mad_send_handler,
|
||||
srpt_mad_recv_handler,
|
||||
sport);
|
||||
sport
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0)
|
||||
, 0
|
||||
#endif
|
||||
);
|
||||
if (IS_ERR(sport->mad_agent)) {
|
||||
ret = PTR_ERR(sport->mad_agent);
|
||||
sport->mad_agent = NULL;
|
||||
@@ -1941,8 +1946,8 @@ static void srpt_process_send_completion(struct ib_cq *cq,
|
||||
srpt_handle_rdma_comp(ch, ch->ioctx_ring[index], opcode,
|
||||
srpt_xmt_rsp_context);
|
||||
} else if (opcode == SRPT_RDMA_ZEROLENGTH_WRITE) {
|
||||
WARN_ONCE(true, "%s: QP not in error state\n",
|
||||
ch->sess_name);
|
||||
WARN_ONCE(true, "%s-%d: QP not in error state\n",
|
||||
ch->sess_name, ch->qp->qp_num);
|
||||
WARN_ON_ONCE(!srpt_set_ch_state(ch, CH_DISCONNECTED));
|
||||
} else {
|
||||
WARN(true, "unexpected opcode %d\n", opcode);
|
||||
@@ -2096,8 +2101,8 @@ static int srpt_compl_thread(void *arg)
|
||||
}
|
||||
set_current_state(TASK_RUNNING);
|
||||
|
||||
TRACE_DBG("ch %s: about to invoke scst_unregister_session()",
|
||||
ch->sess_name);
|
||||
TRACE_DBG("%s-%d: about to invoke scst_unregister_session()",
|
||||
ch->sess_name, ch->qp->qp_num);
|
||||
scst_unregister_session(ch->scst_sess, false, srpt_unreg_sess);
|
||||
|
||||
while (!kthread_should_stop())
|
||||
@@ -2128,12 +2133,12 @@ static int srpt_create_ch_ib(struct srpt_rdma_ch *ch)
|
||||
ch->rq_size + srpt_sq_size);
|
||||
#else
|
||||
ch->cq = ib_create_cq(sdev->device, srpt_completion, NULL, ch,
|
||||
ch->rq_size + srpt_sq_size, 0);
|
||||
ch->rq_size + srpt_sq_size, ch->comp_vector);
|
||||
#endif
|
||||
if (IS_ERR(ch->cq)) {
|
||||
ret = PTR_ERR(ch->cq);
|
||||
PRINT_ERROR("failed to create CQ cqe= %d ret= %d",
|
||||
ch->rq_size + srpt_sq_size, ret);
|
||||
PRINT_ERROR("failed to create CQ: cqe %d; c.v. %d; ret %d",
|
||||
ch->rq_size + srpt_sq_size, ch->comp_vector, ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
@@ -2227,13 +2232,13 @@ static bool srpt_close_ch(struct srpt_rdma_ch *ch)
|
||||
|
||||
ret = srpt_ch_qp_err(ch);
|
||||
if (ret < 0)
|
||||
PRINT_ERROR("%s: changing queue pair into error state"
|
||||
" failed: %d", ch->sess_name, ret);
|
||||
PRINT_ERROR("%s-%d: changing queue pair into error state"
|
||||
" failed: %d", ch->sess_name, ch->qp->qp_num, ret);
|
||||
|
||||
ret = srpt_zerolength_write(ch);
|
||||
if (ret < 0) {
|
||||
PRINT_ERROR("%s: queuing zero-length write failed: %d",
|
||||
ch->sess_name, ret);
|
||||
PRINT_ERROR("%s-%d: queuing zero-length write failed: %d",
|
||||
ch->sess_name, ch->qp->qp_num, ret);
|
||||
WARN_ON_ONCE(!srpt_set_ch_state(ch, CH_DISCONNECTED));
|
||||
}
|
||||
|
||||
@@ -2281,15 +2286,28 @@ static void __srpt_close_all_ch(struct srpt_tgt *srpt_tgt)
|
||||
|
||||
list_for_each_entry(nexus, &srpt_tgt->nexus_list, entry) {
|
||||
list_for_each_entry(ch, &nexus->ch_list, list) {
|
||||
if (srpt_disconnect_ch(ch) < 0)
|
||||
continue;
|
||||
PRINT_INFO("Closing channel %s because target %s has"
|
||||
" been disabled", ch->sess_name,
|
||||
srpt_tgt->scst_tgt->tgt_name);
|
||||
if (srpt_disconnect_ch(ch) >= 0)
|
||||
PRINT_INFO("Closing channel %s-%d because"
|
||||
" target %s has been disabled",
|
||||
ch->sess_name, ch->qp->qp_num,
|
||||
srpt_tgt->scst_tgt->tgt_name);
|
||||
srpt_close_ch(ch);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static struct srpt_device *srpt_convert_to_sdev(struct scst_tgt *scst_tgt)
|
||||
{
|
||||
struct srpt_port *sport;
|
||||
|
||||
if (one_target_per_port) {
|
||||
sport = scst_tgt_get_tgt_priv(scst_tgt);
|
||||
return sport ? sport->sdev : NULL;
|
||||
} else {
|
||||
return scst_tgt_get_tgt_priv(scst_tgt);
|
||||
}
|
||||
}
|
||||
|
||||
static struct srpt_tgt *srpt_convert_scst_tgt(struct scst_tgt *scst_tgt)
|
||||
{
|
||||
struct srpt_device *sdev;
|
||||
@@ -2388,6 +2406,26 @@ static bool srpt_is_target_enabled(struct scst_tgt *scst_tgt)
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* srpt_next_comp_vector() - Next completion vector >= srpt_tgt->comp_vector
|
||||
*/
|
||||
static u8 srpt_next_comp_vector(struct srpt_tgt *srpt_tgt)
|
||||
{
|
||||
u8 comp_vector;
|
||||
|
||||
mutex_lock(&srpt_tgt->mutex);
|
||||
comp_vector = find_next_bit(srpt_tgt->comp_v_mask, COMP_V_MASK_SIZE,
|
||||
srpt_tgt->comp_vector);
|
||||
if (comp_vector >= COMP_V_MASK_SIZE)
|
||||
comp_vector = find_next_bit(srpt_tgt->comp_v_mask,
|
||||
COMP_V_MASK_SIZE, 0);
|
||||
sBUG_ON(comp_vector >= COMP_V_MASK_SIZE);
|
||||
srpt_tgt->comp_vector = comp_vector + 1;
|
||||
mutex_unlock(&srpt_tgt->mutex);
|
||||
|
||||
return comp_vector;
|
||||
}
|
||||
|
||||
/**
|
||||
* srpt_cm_req_recv() - Process the event IB_CM_REQ_RECEIVED.
|
||||
*
|
||||
@@ -2550,6 +2588,8 @@ static int srpt_cm_req_recv(struct srpt_device *const sdev,
|
||||
list_add_tail(&ch->ioctx_ring[i]->free_list, &ch->free_list);
|
||||
}
|
||||
|
||||
ch->comp_vector = srpt_next_comp_vector(srpt_tgt);
|
||||
|
||||
ret = srpt_create_ch_ib(ch);
|
||||
if (ret) {
|
||||
rej->reason = cpu_to_be32(SRP_LOGIN_REJ_INSUFFICIENT_RESOURCES);
|
||||
@@ -2829,7 +2869,8 @@ static int srpt_rdma_cm_req_recv(struct rdma_cm_id *cm_id,
|
||||
|
||||
static void srpt_cm_rej_recv(struct srpt_rdma_ch *ch)
|
||||
{
|
||||
PRINT_INFO("Received CM REJ for ch %s.", ch->sess_name);
|
||||
PRINT_INFO("Received CM REJ for ch %s-%d.", ch->sess_name,
|
||||
ch->qp->qp_num);
|
||||
}
|
||||
|
||||
static void srpt_check_timeout(struct srpt_rdma_ch *ch)
|
||||
@@ -2856,9 +2897,9 @@ static void srpt_check_timeout(struct srpt_rdma_ch *ch)
|
||||
do_div(max_compl_time_ms, 1000000);
|
||||
T_tr_ms = T_tr_ns;
|
||||
do_div(T_tr_ms, 1000000);
|
||||
TRACE_DBG("Session %s: QP local ack timeout = %d or T_tr ="
|
||||
TRACE_DBG("%s-%d: QP local ack timeout = %d or T_tr ="
|
||||
" %u ms; retry_cnt = %d; max compl. time = %d ms",
|
||||
ch->sess_name, attr.timeout, T_tr_ms,
|
||||
ch->sess_name, ch->qp->qp_num, attr.timeout, T_tr_ms,
|
||||
attr.retry_cnt, (unsigned)max_compl_time_ms);
|
||||
|
||||
if (max_compl_time_ms >= RDMA_COMPL_TIMEOUT_S * 1000) {
|
||||
@@ -2882,7 +2923,8 @@ static void srpt_cm_rtu_recv(struct srpt_rdma_ch *ch)
|
||||
|
||||
ret = ch->using_rdma_cm ? 0 : srpt_ch_qp_rts(ch, ch->qp);
|
||||
if (ret < 0) {
|
||||
PRINT_ERROR("%s: QP transition to RTS failed", ch->sess_name);
|
||||
PRINT_ERROR("%s-%d: QP transition to RTS failed",
|
||||
ch->sess_name, ch->qp->qp_num);
|
||||
srpt_close_ch(ch);
|
||||
return;
|
||||
}
|
||||
@@ -2895,19 +2937,21 @@ static void srpt_cm_rtu_recv(struct srpt_rdma_ch *ch)
|
||||
* already been invoked from another thread.
|
||||
*/
|
||||
if (!srpt_set_ch_state(ch, CH_LIVE))
|
||||
PRINT_ERROR("%s: Channel transition to LIVE state failed",
|
||||
ch->sess_name);
|
||||
PRINT_ERROR("%s-%d: channel transition to LIVE state failed",
|
||||
ch->sess_name, ch->qp->qp_num);
|
||||
}
|
||||
|
||||
static void srpt_cm_timewait_exit(struct srpt_rdma_ch *ch)
|
||||
{
|
||||
PRINT_INFO("Received CM TimeWait exit for ch %s.", ch->sess_name);
|
||||
PRINT_INFO("Received CM TimeWait exit for ch %s-%d.", ch->sess_name,
|
||||
ch->qp->qp_num);
|
||||
srpt_close_ch(ch);
|
||||
}
|
||||
|
||||
static void srpt_cm_rep_error(struct srpt_rdma_ch *ch)
|
||||
{
|
||||
PRINT_INFO("Received CM REP error for ch %s.", ch->sess_name);
|
||||
PRINT_INFO("Received CM REP error for ch %s-%d.", ch->sess_name,
|
||||
ch->qp->qp_num);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2924,7 +2968,8 @@ static int srpt_cm_dreq_recv(struct srpt_rdma_ch *ch)
|
||||
*/
|
||||
static void srpt_cm_drep_recv(struct srpt_rdma_ch *ch)
|
||||
{
|
||||
PRINT_INFO("Received CM DREP message for ch %s.", ch->sess_name);
|
||||
PRINT_INFO("Received CM DREP message for ch %s-%d.", ch->sess_name,
|
||||
ch->qp->qp_num);
|
||||
srpt_close_ch(ch);
|
||||
}
|
||||
|
||||
@@ -3714,8 +3759,9 @@ static int srpt_release_sport(struct srpt_tgt *srpt_tgt)
|
||||
mutex_lock(&srpt_tgt->mutex);
|
||||
list_for_each_entry(nexus, &srpt_tgt->nexus_list, entry) {
|
||||
list_for_each_entry(ch, &nexus->ch_list, list) {
|
||||
PRINT_INFO("%s: state %s; %d commands in"
|
||||
PRINT_INFO("%s-%d: state %s; %d commands in"
|
||||
" progress", ch->sess_name,
|
||||
ch->qp->qp_num,
|
||||
get_ch_state_name(ch->state),
|
||||
atomic_read(&ch->scst_sess->sess_cmd_count));
|
||||
}
|
||||
@@ -3770,6 +3816,57 @@ static uint16_t srpt_get_scsi_transport_version(struct scst_tgt *scst_tgt)
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_SCST_PROC)
|
||||
static ssize_t show_comp_v_mask(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct scst_tgt *scst_tgt = container_of(kobj, struct scst_tgt,
|
||||
tgt_kobj);
|
||||
struct srpt_tgt *srpt_tgt = srpt_convert_scst_tgt(scst_tgt);
|
||||
int res = -E_TGT_PRIV_NOT_YET_SET;
|
||||
|
||||
if (!srpt_tgt)
|
||||
goto out;
|
||||
res = sprintf(buf, "%#lx\n%s", srpt_tgt->comp_v_mask[0],
|
||||
SCST_SYSFS_KEY_MARK "\n");
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static ssize_t store_comp_v_mask(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, const char *buf,
|
||||
size_t count)
|
||||
{
|
||||
struct scst_tgt *scst_tgt = container_of(kobj, struct scst_tgt,
|
||||
tgt_kobj);
|
||||
struct srpt_tgt *srpt_tgt = srpt_convert_scst_tgt(scst_tgt);
|
||||
struct srpt_device *sdev = srpt_convert_to_sdev(scst_tgt);
|
||||
int res = -E_TGT_PRIV_NOT_YET_SET;
|
||||
unsigned long mask;
|
||||
|
||||
if (!srpt_tgt)
|
||||
goto out;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)
|
||||
res = kstrtoul(buf, 16, &mask);
|
||||
#else
|
||||
res = strict_strtoul(buf, 16, &mask);
|
||||
#endif
|
||||
if (res)
|
||||
goto out;
|
||||
res = -EINVAL;
|
||||
if (mask == 0 || mask >= (1ULL << sdev->device->num_comp_vectors))
|
||||
goto out;
|
||||
srpt_tgt->comp_v_mask[0] = mask;
|
||||
res = count;
|
||||
|
||||
out:
|
||||
return res;
|
||||
}
|
||||
|
||||
static struct kobj_attribute srpt_show_comp_v_mask_attr =
|
||||
__ATTR(comp_v_mask, S_IRUGO | S_IWUSR, show_comp_v_mask,
|
||||
store_comp_v_mask);
|
||||
|
||||
static ssize_t srpt_show_device(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
@@ -3861,6 +3958,7 @@ static struct kobj_attribute srpt_show_login_info_attr =
|
||||
__ATTR(login_info, S_IRUGO, show_login_info, NULL);
|
||||
|
||||
static const struct attribute *srpt_tgt_attrs[] = {
|
||||
&srpt_show_comp_v_mask_attr.attr,
|
||||
&srpt_device_attr.attr,
|
||||
&srpt_show_login_info_attr.attr,
|
||||
NULL
|
||||
@@ -3905,17 +4003,37 @@ static ssize_t show_ch_state(struct kobject *kobj, struct kobj_attribute *attr,
|
||||
return sprintf(buf, "%s\n", get_ch_state_name(ch->state));
|
||||
}
|
||||
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) || defined(RHEL_RELEASE_CODE)
|
||||
static ssize_t show_comp_vector(struct kobject *kobj,
|
||||
struct kobj_attribute *attr, char *buf)
|
||||
{
|
||||
struct scst_session *scst_sess;
|
||||
struct srpt_rdma_ch *ch;
|
||||
|
||||
scst_sess = container_of(kobj, struct scst_session, sess_kobj);
|
||||
ch = scst_sess_get_tgt_priv(scst_sess);
|
||||
return ch ? sprintf(buf, "%u\n", ch->comp_vector) : -ENOENT;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct kobj_attribute srpt_req_lim_attr =
|
||||
__ATTR(req_lim, S_IRUGO, show_req_lim, NULL);
|
||||
static const struct kobj_attribute srpt_req_lim_delta_attr =
|
||||
__ATTR(req_lim_delta, S_IRUGO, show_req_lim_delta, NULL);
|
||||
static const struct kobj_attribute srpt_ch_state_attr =
|
||||
__ATTR(ch_state, S_IRUGO, show_ch_state, NULL);
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) || defined(RHEL_RELEASE_CODE)
|
||||
static const struct kobj_attribute srpt_comp_vector_attr =
|
||||
__ATTR(comp_vector, S_IRUGO, show_comp_vector, NULL);
|
||||
#endif
|
||||
|
||||
static const struct attribute *srpt_sess_attrs[] = {
|
||||
&srpt_req_lim_attr.attr,
|
||||
&srpt_req_lim_delta_attr.attr,
|
||||
&srpt_ch_state_attr.attr,
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) || defined(RHEL_RELEASE_CODE)
|
||||
&srpt_comp_vector_attr.attr,
|
||||
#endif
|
||||
NULL
|
||||
};
|
||||
#endif
|
||||
@@ -3974,9 +4092,13 @@ static struct scst_proc_data srpt_log_proc_data = {
|
||||
/* Note: the caller must have zero-initialized *@srpt_tgt. */
|
||||
static void srpt_init_tgt(struct srpt_tgt *srpt_tgt)
|
||||
{
|
||||
int i;
|
||||
|
||||
INIT_LIST_HEAD(&srpt_tgt->nexus_list);
|
||||
init_waitqueue_head(&srpt_tgt->ch_releaseQ);
|
||||
mutex_init(&srpt_tgt->mutex);
|
||||
for (i = 0; i < COMP_V_MASK_SIZE; i++)
|
||||
__set_bit(i, srpt_tgt->comp_v_mask);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -139,6 +139,8 @@ enum {
|
||||
DEFAULT_MAX_RDMA_SIZE = 65536,
|
||||
|
||||
RDMA_COMPL_TIMEOUT_S = 80,
|
||||
|
||||
COMP_V_MASK_SIZE = 64,
|
||||
};
|
||||
|
||||
#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 1, 0) && \
|
||||
@@ -334,6 +336,7 @@ enum rdma_ch_state {
|
||||
* list contains struct srpt_ioctx elements and is protected
|
||||
* against concurrent modification by the cm_id spinlock.
|
||||
* @pkey: P_Key of the IB partition for this SRP channel.
|
||||
* @comp_vector: Completion vector assigned to the QP.
|
||||
* @scst_sess: SCST session information associated with this SRP channel.
|
||||
* @sess_name: SCST session name.
|
||||
*/
|
||||
@@ -368,6 +371,9 @@ struct srpt_rdma_ch {
|
||||
struct list_head list;
|
||||
struct list_head cmd_wait_list;
|
||||
uint16_t pkey;
|
||||
#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 20) || defined(RHEL_RELEASE_CODE)
|
||||
u8 comp_vector;
|
||||
#endif
|
||||
bool using_rdma_cm;
|
||||
bool processing_wait_list;
|
||||
|
||||
@@ -395,6 +401,8 @@ struct srpt_nexus {
|
||||
* @mutex: Protects @nexus_list and srpt_nexus.ch_list.
|
||||
* @nexus_list: Per-device I_T nexus list.
|
||||
* @scst_tgt: SCST target information associated with this HCA.
|
||||
* @comp_v_mask: Bitmask with one bit per allowed completion vector.
|
||||
* @comp_vector: Completion vector from where searching will start.
|
||||
* @enabled: Whether or not this SCST target is enabled.
|
||||
*/
|
||||
struct srpt_tgt {
|
||||
@@ -402,6 +410,8 @@ struct srpt_tgt {
|
||||
struct mutex mutex;
|
||||
struct list_head nexus_list;
|
||||
struct scst_tgt *scst_tgt;
|
||||
DECLARE_BITMAP(comp_v_mask, COMP_V_MASK_SIZE);
|
||||
u8 comp_vector;
|
||||
bool enabled;
|
||||
};
|
||||
|
||||
|
||||
+4
-3
@@ -152,12 +152,13 @@
|
||||
<p><a href="http://monklinux.blogspot.com/2012/02/scst-configuration-how-to-using-gentoo.html">Gentoo HOWTO</a></p>
|
||||
<p><a href="iscsi-scst-howto.txt">HOWTO For iSCSI-SCST</a></p>
|
||||
<p><a href="SCST_Gentoo_HOWTO.txt">Gentoo HOWTO For iSCSI-SCST</a></p>
|
||||
<p><a href="http://alpinelinux.org/wiki/High_performance_SCST_iSCSI_Target_on_Linux_software_Raid" class="readmore">Alpine Linux HOWTO</a></p>
|
||||
<p><a href="qla2x00t-howto.html">HOWTO For QLogic Target Driver</a></p>
|
||||
<p><a href="sgv_cache.html">SCST SGV Cache Description</a></p>
|
||||
<h1>Articles</h1>
|
||||
<p><a href="http://marcitland.blogspot.com/2011/03/accelerating-vdi-using-scst-and-ssds.html">Accelerating VDI Using SCST and SSDs</a>
|
||||
by Marc Smith</p>
|
||||
<p>By Marc Smith:</p>
|
||||
<p><a href="http://marcitland.blogspot.com/2011/03/accelerating-vdi-using-scst-and-ssds.html">Accelerating VDI Using SCST and SSDs</a></p>
|
||||
<p><a href="http://marcitland.blogspot.com/2013/04/building-using-highly-available-esos.html">Building & Using a Highly Available ESOS Disk Array</a></p>
|
||||
<p><a href="http://marcitland.blogspot.com/2014/07/open-storage-dual-controller-oss-disk.html">Open Storage: Dual-Controller OSS Disk Array</a></p>
|
||||
<h1>SCST 0.9.6 graphs</h1>
|
||||
<p><a href="images/init_scst.png">init_scst</a></p>
|
||||
<p><a href="images/scst_cmd_thread.png">scst_cmd_thread</a></p>
|
||||
|
||||
@@ -58,17 +58,20 @@
|
||||
<div id="main">
|
||||
<h1>Target driver qla2x00t for QLogic FC adapters</h1>
|
||||
<p><img src="images/t_qlogic.gif" width="100" height="120" class="float-left" alt="SCST QLogic">
|
||||
This is target driver for QLogic qla2xxx (22xx/23xx/24xx/25xx) Fibre Channel adapters. It is stable and well tested.</p>
|
||||
This is target driver for QLogic qla2xxx (22xx++) Fibre Channel adapters.</p>
|
||||
|
||||
<p>The latest stable version is 2.2.0. Requires Linux kernel version 2.6.26.x or higher and
|
||||
SCST version 2.2.0 or higher.</p>
|
||||
<p>The latest stable version is 3.0.0. Requires Linux kernel version 2.6.26.x or higher and
|
||||
SCST version 3.0.0 or higher.</p>
|
||||
|
||||
<p>Driver for the latest QLogic 16Gb/10G FC/FCoE adapters you can find in git.qlogic.com/scst.git</p>
|
||||
<p>Driver in qla2x00t subdirectory is the old one, forked from qla2xxx from kernel 2.6.26. It is not maintained anymore.</p>
|
||||
|
||||
<p>You can find the latest version of this driver in
|
||||
git://git.qlogic.com/scst-qla2xxx.git. It is now maintained by QLogic, hence
|
||||
located in the QLogic's git. This driver also supports FCoE. See SVN root README for instructions how to integrate it
|
||||
into the SCST build tree.</p>
|
||||
|
||||
<p class="post-footer align-right">
|
||||
<a href="qla2x00t-howto.html" class="readmore">HOWTO</a>
|
||||
<a href="downloads.html" class="readmore">Download</a>
|
||||
<a href="http://sourceforge.net/p/scst/svn/HEAD/tree/" class="readmore">SCST SVN Repository</a>
|
||||
</p>
|
||||
<table border=0><tr><td height="300px"> </td></tr></table>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user