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:
Yan Burman
2014-08-27 13:26:02 +00:00
parent e4c7d430c1
commit d7e6569b1a
45 changed files with 3060 additions and 310 deletions
+40 -33
View File
@@ -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 \
+33
View File
@@ -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
+2
View File
@@ -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);
+6 -5
View File
@@ -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);
+2
View File
@@ -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
View File
@@ -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,
+3 -3
View File
@@ -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);
+6 -5
View File
@@ -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
+6 -2
View File
@@ -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
+25 -11
View File
@@ -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
{
+95 -56
View File
@@ -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
+98
View File
@@ -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
View File
@@ -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
View File
@@ -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.
+27
View File
@@ -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
View File
@@ -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
+26 -1
View File
@@ -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
*************************************************************/
+1 -1
View File
@@ -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
+13
View File
@@ -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);
+524
View File
@@ -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
View File
@@ -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
+377 -61
View File
@@ -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
View File
@@ -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
View File
@@ -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,
+5 -3
View File
@@ -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;
}
+1
View File
@@ -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
View File
@@ -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
View File
@@ -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
+2
View File
@@ -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
View File
@@ -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
View File
@@ -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
+12
View File
@@ -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
View File
@@ -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)
&reg_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);
}
/**
+10
View File
@@ -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
View File
@@ -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 &amp 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>
+9 -6
View File
@@ -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">&nbsp;</td></tr></table>
</div>